diff --git a/plugins/snes9x_gx/Makefile b/plugins/snes9x_gx/Makefile new file mode 100644 index 00000000..7e9faa14 --- /dev/null +++ b/plugins/snes9x_gx/Makefile @@ -0,0 +1,163 @@ +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif + +include $(DEVKITPPC)/wii_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := snes9xgx-wii +TARGETDIR := executables +BUILD := build_wii +SOURCES := source source/images source/sounds source/fonts source/lang \ + source/gui source/utils source/utils/sz source/utils/unzip \ + source/snes9x source/snes9x/apu +INCLUDES := source source/snes9x + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- + +CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \ + -DZLIB -DRIGHTSHIFT_IS_SAR -DCPU_SHUTDOWN -DCORRECT_VRAM_READS \ + -D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \ + -fomit-frame-pointer \ + -Wno-unused-parameter -Wno-strict-aliasing \ + -Wno-write-strings -Wno-parentheses +CXXFLAGS = $(CFLAGS) +LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map,-wrap,wiiuse_register + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := -ldi -liso9660 -lpng -lmxml \ + -lfat -lwiiuse -lwupc -lz -lbte -lasnd -logc -lvorbisidec -lfreetype -ltinysmb +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(CURDIR)/portlibs + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) +export DEPSDIR := $(CURDIR)/$(BUILD) + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) +TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf))) +LANGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.lang))) +PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png))) +OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg))) +PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) + export LD := $(CC) +else + export LD := $(CXX) +endif + +export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ + $(sFILES:.s=.o) $(SFILES:.S=.o) \ + $(TTFFILES:.ttf=.ttf.o) $(LANGFILES:.lang=.lang.o) \ + $(PNGFILES:.png=.png.o) \ + $(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o) +#--------------------------------------------------------------------------------- +# build a list of include paths +#--------------------------------------------------------------------------------- +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) \ + -I$(LIBOGC_INC) -I$(CURDIR)/portlibs/include/freetype2 + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + -L$(LIBOGC_LIB) + +export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @[ -d $(TARGETDIR) ] || mkdir -p $(TARGETDIR) + @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol + +#--------------------------------------------------------------------------------- +run: + wiiload $(OUTPUT).dol + +#--------------------------------------------------------------------------------- +reload: + wiiload -r $(OUTPUT).dol + + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).dol: $(OUTPUT).elf +$(OUTPUT).elf: $(OFILES) + +#--------------------------------------------------------------------------------- +# This rule links in binary data with these extensions: ttf lang png ogg pcm +#--------------------------------------------------------------------------------- +%.ttf.o : %.ttf + @echo $(notdir $<) + $(bin2o) + +%.lang.o : %.lang + @echo $(notdir $<) + $(bin2o) + +%.png.o : %.png + @echo $(notdir $<) + $(bin2o) + +%.ogg.o : %.ogg + @echo $(notdir $<) + $(bin2o) + +%.pcm.o : %.pcm + @echo $(notdir $<) + $(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/plugins/snes9x_gx/Makefile.gc b/plugins/snes9x_gx/Makefile.gc new file mode 100644 index 00000000..d3a870b2 --- /dev/null +++ b/plugins/snes9x_gx/Makefile.gc @@ -0,0 +1,159 @@ +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif + +include $(DEVKITPPC)/gamecube_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := snes9xgx-gc +TARGETDIR := executables +BUILD := build_gc +SOURCES := source source/images source/sounds source/fonts source/lang \ + source/gui source/utils source/utils/sz \ + source/snes9x source/snes9x/apu +INCLUDES := source source/snes9x + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- + +CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) -DNO_SOUND \ + -DZLIB -DRIGHTSHIFT_IS_SAR -DCPU_SHUTDOWN -DCORRECT_VRAM_READS \ + -D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \ + -fomit-frame-pointer \ + -Wno-unused-parameter -Wno-strict-aliasing \ + -Wno-write-strings -Wno-parentheses +CXXFLAGS = $(CFLAGS) +LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := -lpng -lmxml -ltinysmb -lbba -lfat -liso9660 -lz -logc -lfreetype + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) +export DEPSDIR := $(CURDIR)/$(BUILD) + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) +TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf))) +LANGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.lang))) +PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png))) +PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) + export LD := $(CC) +else + export LD := $(CXX) +endif + +export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ + $(sFILES:.s=.o) $(SFILES:.S=.o) \ + $(TTFFILES:.ttf=.ttf.o) $(LANGFILES:.lang=.lang.o) \ + $(PNGFILES:.png=.png.o) \ + $(PCMFILES:.pcm=.pcm.o) + +#--------------------------------------------------------------------------------- +# build a list of include paths +#--------------------------------------------------------------------------------- +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) \ + -I$(LIBOGC_INC) -I$(PORTLIBS)/include/freetype2 + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + -L$(LIBOGC_LIB) + +export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @[ -d $(TARGETDIR) ] || mkdir -p $(TARGETDIR) + @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.gc + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol + +#--------------------------------------------------------------------------------- +run: + psoload $(OUTPUT).dol + +#--------------------------------------------------------------------------------- +reload: + psoload -r $(OUTPUT).dol + + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).dol: $(OUTPUT).elf +$(OUTPUT).elf: $(OFILES) + +#--------------------------------------------------------------------------------- +# This rule links in binary data with these extensions: ttf lang png pcm +#--------------------------------------------------------------------------------- +%.ttf.o : %.ttf + @echo $(notdir $<) + $(bin2o) + +%.lang.o : %.lang + @echo $(notdir $<) + $(bin2o) + +%.png.o : %.png + @echo $(notdir $<) + $(bin2o) + +%.pcm.o : %.pcm + @echo $(notdir $<) + $(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/plugins/snes9x_gx/Makefile.xenon b/plugins/snes9x_gx/Makefile.xenon new file mode 100644 index 00000000..f97ab717 --- /dev/null +++ b/plugins/snes9x_gx/Makefile.xenon @@ -0,0 +1,161 @@ +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITXENON)),) +$(error "Please set DEVKITXENON in your environment. export DEVKITXENON=devkitxenon") +endif + +include $(DEVKITXENON)/rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := snes9xgx-xenon +TARGETDIR := executables +BUILD := build_xenon +SOURCES := source/xenon source/snes9x source/utils/sz +INCLUDES := source/snes9x source/xenon + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- + +CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \ + -DNGC -DNO_SOUND \ + -DNO_ASM -DRIGHTSHIFT_IS_SAR \ + -DCPU_SHUTDOWN -DSPC700_SHUTDOWN \ + -DSPC700_C -DSDD1_DECOMP \ + -DCORRECT_VRAM_READS -DNEW_COLOUR_BLENDING \ + -D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \ + -fomit-frame-pointer \ + -Wno-unused-parameter -Wno-strict-aliasing + +CXXFLAGS = -save-temps -Xassembler -aln=$@.lst $(CFLAGS) + +LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS = -lm -lxenon + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(CURDIR) + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) +export DEPSDIR := $(CURDIR)/$(BUILD) + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) +TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf))) +PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png))) +OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg))) +PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) + export LD := $(CC) +else + export LD := $(CXX) +endif + +export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ + $(sFILES:.s=.o) $(SFILES:.S=.o) \ + $(TTFFILES:.ttf=.ttf.o) $(PNGFILES:.png=.png.o) \ + $(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o) + +#--------------------------------------------------------------------------------- +# build a list of include paths +#--------------------------------------------------------------------------------- +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) \ + -I$(LIBXENON_INC) + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + -L$(LIBXENON_LIB) + +export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @[ -d $(TARGETDIR) ] || mkdir -p $(TARGETDIR) + @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.xenon + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).elf32 + +#--------------------------------------------------------------------------------- + +source/xenon/ffs_content.c: genffs.py data/ps.psu data/vs.vsu + python genffs.py > source/xenon/ffs_content.c + +run: $(OUTPUT).elf32 + cp $(OUTPUT).elf32 /tftpboot/xenon + /home/dev360/run + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).elf32: $(OUTPUT).elf +$(OUTPUT).elf: $(OFILES) + +#--------------------------------------------------------------------------------- +# This rule links in binary data with .ttf, .png, and .mp3 extensions +#--------------------------------------------------------------------------------- +%.ttf.o : %.ttf + @echo $(notdir $<) + $(bin2o) + +%.png.o : %.png + @echo $(notdir $<) + $(bin2o) + +%.ogg.o : %.ogg + @echo $(notdir $<) + $(bin2o) + +%.pcm.o : %.pcm + @echo $(notdir $<) + $(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/plugins/snes9x_gx/Makefile1 b/plugins/snes9x_gx/Makefile1 new file mode 100644 index 00000000..9b2ee1d6 --- /dev/null +++ b/plugins/snes9x_gx/Makefile1 @@ -0,0 +1,25 @@ +.PHONY = all wii gc wii-clean gc-clean wii-run gc-run + +all: wii gc + +run: wii-run + +clean: wii-clean gc-clean + +wii: + $(MAKE) -f Makefile.wii + +wii-clean: + $(MAKE) -f Makefile.wii clean + +wii-run: wii + $(MAKE) -f Makefile.wii run + +gc: + $(MAKE) -f Makefile.gc + +gc-clean: + $(MAKE) -f Makefile.gc clean + +gc-run: gc + $(MAKE) -f Makefile.gc run diff --git a/plugins/snes9x_gx/hbc/icon.png b/plugins/snes9x_gx/hbc/icon.png new file mode 100644 index 00000000..c095f638 Binary files /dev/null and b/plugins/snes9x_gx/hbc/icon.png differ diff --git a/plugins/snes9x_gx/hbc/meta.xml b/plugins/snes9x_gx/hbc/meta.xml new file mode 100644 index 00000000..1323becd --- /dev/null +++ b/plugins/snes9x_gx/hbc/meta.xml @@ -0,0 +1,10 @@ + + + Snes9x GX + Tantric + 4.3.4 + 20121109 + Super Nintendo Emulator + A port of Snes9x to the Wii. + + diff --git a/plugins/snes9x_gx/portlibs/include/ext2.h b/plugins/snes9x_gx/portlibs/include/ext2.h new file mode 100644 index 00000000..1f1f58c5 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/ext2.h @@ -0,0 +1,106 @@ +/******************************************************************************** + * ext2.h - devoptab file routines for EXT2/3/4-based devices. * + * * + * Copyright (c) 2010 Dimok * + * * + * This program/include file 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/include file 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + ********************************************************************************/ +#ifndef __EXT2_H_ +#define __EXT2_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/** + * EXT2 cache options + * + * It is recommended to use more pages instead of large page sizes for cache due to the sporadic write behaviour of ext file system. + * It will significantly increase the speed. A page size of 32 is mostly suffiecient. The larger the page count the faster the + * read/write between smaller files will be. Larger page sizes result in faster read/write of single big files. + */ +#define EXT2_CACHE_DEFAULT_PAGE_COUNT 64 /* The default number of pages in the cache */ +#define EXT2_CACHE_DEFAULT_PAGE_SIZE 32 /* The default number of sectors per cache page */ + +/* EXT2 mount flags */ +#define EXT2_FLAG_RW 0x00001 /* Open the filesystem for reading and writing. Without this flag, the filesystem is opened for reading only. */ +#define EXT2_FLAG_FORCE 0x00400 /* Open the filesystem regardless of the feature sets listed in the superblock */ +#define EXT2_FLAG_JOURNAL_DEV_OK 0x01000 /* Only open external journal devices if this flag is set (e.g. ext3/ext4) */ +#define EXT2_FLAG_64BITS 0x20000 /* Allow 64-bit bitfields (needed for large filesystems) */ +#define EXT2_FLAG_PRINT_PROGRESS 0x40000 /* If this flag is set the progress of file operations will be printed to stdout */ +#define EXT2_FLAG_SKIP_MMP 0x100000 /* Open without multi-mount protection check. */ +#define EXT2_FLAG_DEFAULT (EXT2_FLAG_RW | EXT2_FLAG_64BITS | EXT2_FLAG_JOURNAL_DEV_OK | EXT2_FLAG_SKIP_MMP) + +/** + * Find all EXT2/3/4 partitions on a block device. + * + * @param INTERFACE The block device to search + * @param PARTITIONS (out) A pointer to receive the array of partition start sectors + * + * @return The number of entries in PARTITIONS or -1 if an error occurred (see errno) + * @note The caller is responsible for freeing PARTITIONS when finished with it + */ +int ext2FindPartitions(const DISC_INTERFACE *interface, sec_t **partitions); + +/** + * Mount a EXT2/3/4 partition from a specific sector on a block device. + * + * @param NAME The name to mount the device under (can then be accessed as "NAME:/") + * @param INTERFACE The block device to mount + * @param STARTSECTOR The sector the partition begins at + * @param CACHEPAGECOUNT The total number of pages in the device cache + * @param CACHEPAGESIZE The number of sectors per cache page + * @param FLAGS Additional mounting flags (see above) + * + * @return True if mount was successful, false if no partition was found or an error occurred (see errno) + */ +bool ext2Mount(const char *name, const DISC_INTERFACE *interface, sec_t startSector, u32 cachePageCount, u32 cachePageSize, u32 flags); + +/** + * Unmount a EXT2/3/4 partition. + * + * @param NAME The name of mount used in ext2Mount() + */ +void ext2Unmount(const char *name); + +/** + * Get the volume name of a mounted EXT2/3/4 partition. + * + * @param NAME The name of mount + * + * @return The volumes name if successful or NULL if an error occurred (see errno) + */ +const char *ext2GetVolumeName (const char *name); + +/** + * Set the volume name of a mounted EXT2/3/4 partition. + * + * @param NAME The name of mount + * @param VOLUMENAME The new volume name + * + * @return True if mount was successful, false if an error occurred (see errno) + * @note The mount must be write-enabled else this will fail + */ +bool ext2SetVolumeName (const char *name, const char *volumeName); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/config/ftconfig.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/config/ftconfig.h new file mode 100644 index 00000000..9ceab5c2 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/config/ftconfig.h @@ -0,0 +1,477 @@ +/* ftconfig.h. Generated from ftconfig.in by configure. */ +/***************************************************************************/ +/* */ +/* ftconfig.in */ +/* */ +/* UNIX-specific configuration file (specification only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This header file contains a number of macro definitions that are used */ + /* by the rest of the engine. Most of the macros here are automatically */ + /* determined at compile time, and you should not need to change it to */ + /* port FreeType, except to compile the library with a non-ANSI */ + /* compiler. */ + /* */ + /* Note however that if some specific modifications are needed, we */ + /* advise you to place a modified copy in your build directory. */ + /* */ + /* The build directory is usually `freetype/builds/', and */ + /* contains system-specific files that are always included first when */ + /* building the library. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTCONFIG_H__ +#define __FTCONFIG_H__ + +#include +#include FT_CONFIG_OPTIONS_H +#include FT_CONFIG_STANDARD_LIBRARY_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* PLATFORM-SPECIFIC CONFIGURATION MACROS */ + /* */ + /* These macros can be toggled to suit a specific system. The current */ + /* ones are defaults used to compile FreeType in an ANSI C environment */ + /* (16bit compilers are also supported). Copy this file to your own */ + /* `freetype/builds/' directory, and edit it to port the engine. */ + /* */ + /*************************************************************************/ + + +#define HAVE_UNISTD_H 1 +#define HAVE_FCNTL_H 1 +#define HAVE_STDINT_H 1 + + + /* There are systems (like the Texas Instruments 'C54x) where a `char' */ + /* has 16 bits. ANSI C says that sizeof(char) is always 1. Since an */ + /* `int' has 16 bits also for this system, sizeof(int) gives 1 which */ + /* is probably unexpected. */ + /* */ + /* `CHAR_BIT' (defined in limits.h) gives the number of bits in a */ + /* `char' type. */ + +#ifndef FT_CHAR_BIT +#define FT_CHAR_BIT CHAR_BIT +#endif + + +/* #undef FT_USE_AUTOCONF_SIZEOF_TYPES */ +#ifdef FT_USE_AUTOCONF_SIZEOF_TYPES + +#define SIZEOF_INT 4 +#define SIZEOF_LONG 4 +#define FT_SIZEOF_INT SIZEOF_INT +#define FT_SIZEOF_LONG SIZEOF_LONG + +#else /* !FT_USE_AUTOCONF_SIZEOF_TYPES */ + + /* Following cpp computation of the bit length of int and long */ + /* is copied from default include/freetype/config/ftconfig.h. */ + /* If any improvement is required for this file, it should be */ + /* applied to the original header file for the builders that */ + /* does not use configure script. */ + + /* The size of an `int' type. */ +#if FT_UINT_MAX == 0xFFFFUL +#define FT_SIZEOF_INT (16 / FT_CHAR_BIT) +#elif FT_UINT_MAX == 0xFFFFFFFFUL +#define FT_SIZEOF_INT (32 / FT_CHAR_BIT) +#elif FT_UINT_MAX > 0xFFFFFFFFUL && FT_UINT_MAX == 0xFFFFFFFFFFFFFFFFUL +#define FT_SIZEOF_INT (64 / FT_CHAR_BIT) +#else +#error "Unsupported size of `int' type!" +#endif + + /* The size of a `long' type. A five-byte `long' (as used e.g. on the */ + /* DM642) is recognized but avoided. */ +#if FT_ULONG_MAX == 0xFFFFFFFFUL +#define FT_SIZEOF_LONG (32 / FT_CHAR_BIT) +#elif FT_ULONG_MAX > 0xFFFFFFFFUL && FT_ULONG_MAX == 0xFFFFFFFFFFUL +#define FT_SIZEOF_LONG (32 / FT_CHAR_BIT) +#elif FT_ULONG_MAX > 0xFFFFFFFFUL && FT_ULONG_MAX == 0xFFFFFFFFFFFFFFFFUL +#define FT_SIZEOF_LONG (64 / FT_CHAR_BIT) +#else +#error "Unsupported size of `long' type!" +#endif + +#endif /* !FT_USE_AUTOCONF_SIZEOF_TYPES */ + + + /* Preferred alignment of data */ +#define FT_ALIGNMENT 8 + + + /* FT_UNUSED is a macro used to indicate that a given parameter is not */ + /* used -- this is only used to get rid of unpleasant compiler warnings */ +#ifndef FT_UNUSED +#define FT_UNUSED( arg ) ( (arg) = (arg) ) +#endif + + + /*************************************************************************/ + /* */ + /* AUTOMATIC CONFIGURATION MACROS */ + /* */ + /* These macros are computed from the ones defined above. Don't touch */ + /* their definition, unless you know precisely what you are doing. No */ + /* porter should need to mess with them. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Mac support */ + /* */ + /* This is the only necessary change, so it is defined here instead */ + /* providing a new configuration file. */ + /* */ +#if ( defined( __APPLE__ ) && !defined( DARWIN_NO_CARBON ) ) || \ + ( defined( __MWERKS__ ) && defined( macintosh ) ) + /* no Carbon frameworks for 64bit 10.4.x */ +#include "AvailabilityMacros.h" +#if defined( __LP64__ ) && \ + ( MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 ) +#define DARWIN_NO_CARBON 1 +#else +#define FT_MACINTOSH 1 +#endif + +#elif defined( __SC__ ) || defined( __MRC__ ) + /* Classic MacOS compilers */ +#include "ConditionalMacros.h" +#if TARGET_OS_MAC +#define FT_MACINTOSH 1 +#endif + +#endif + + + /* Fix compiler warning with sgi compiler */ +#if defined( __sgi ) && !defined( __GNUC__ ) +#if defined( _COMPILER_VERSION ) && ( _COMPILER_VERSION >= 730 ) +#pragma set woff 3505 +#endif +#endif + + + /*************************************************************************/ + /* */ + /* IntN types */ + /* */ + /* Used to guarantee the size of some specific integers. */ + /* */ + typedef signed short FT_Int16; + typedef unsigned short FT_UInt16; + +#if FT_SIZEOF_INT == 4 + + typedef signed int FT_Int32; + typedef unsigned int FT_UInt32; + +#elif FT_SIZEOF_LONG == 4 + + typedef signed long FT_Int32; + typedef unsigned long FT_UInt32; + +#else +#error "no 32bit type found -- please check your configuration files" +#endif + + + /* look up an integer type that is at least 32 bits */ +#if FT_SIZEOF_INT >= 4 + + typedef int FT_Fast; + typedef unsigned int FT_UFast; + +#elif FT_SIZEOF_LONG >= 4 + + typedef long FT_Fast; + typedef unsigned long FT_UFast; + +#endif + + + /* determine whether we have a 64-bit int type for platforms without */ + /* Autoconf */ +#if FT_SIZEOF_LONG == 8 + + /* FT_LONG64 must be defined if a 64-bit type is available */ +#define FT_LONG64 +#define FT_INT64 long + +#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */ + + /* this compiler provides the __int64 type */ +#define FT_LONG64 +#define FT_INT64 __int64 + +#elif defined( __BORLANDC__ ) /* Borland C++ */ + + /* XXXX: We should probably check the value of __BORLANDC__ in order */ + /* to test the compiler version. */ + + /* this compiler provides the __int64 type */ +#define FT_LONG64 +#define FT_INT64 __int64 + +#elif defined( __WATCOMC__ ) /* Watcom C++ */ + + /* Watcom doesn't provide 64-bit data types */ + +#elif defined( __MWERKS__ ) /* Metrowerks CodeWarrior */ + +#define FT_LONG64 +#define FT_INT64 long long int + +#elif defined( __GNUC__ ) + + /* GCC provides the `long long' type */ +#define FT_LONG64 +#define FT_INT64 long long int + +#endif /* FT_SIZEOF_LONG == 8 */ + + + /*************************************************************************/ + /* */ + /* A 64-bit data type will create compilation problems if you compile */ + /* in strict ANSI mode. To avoid them, we disable its use if __STDC__ */ + /* is defined. You can however ignore this rule by defining the */ + /* FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */ + /* */ +#if defined( FT_LONG64 ) && !defined( FT_CONFIG_OPTION_FORCE_INT64 ) + +#ifdef __STDC__ + + /* Undefine the 64-bit macros in strict ANSI compilation mode. */ + /* Since `#undef' doesn't survive in configuration header files */ + /* we use the postprocessing facility of AC_CONFIG_HEADERS to */ + /* replace the leading `/' with `#'. */ +#undef FT_LONG64 +#undef FT_INT64 + +#endif /* __STDC__ */ + +#endif /* FT_LONG64 && !FT_CONFIG_OPTION_FORCE_INT64 */ + + +#define FT_BEGIN_STMNT do { +#define FT_END_STMNT } while ( 0 ) +#define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT + + +#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER + /* Provide assembler fragments for performance-critical functions. */ + /* These must be defined `static __inline__' with GCC. */ + +#ifdef __GNUC__ + +#if defined( __arm__ ) && !defined( __thumb__ ) +#define FT_MULFIX_ASSEMBLER FT_MulFix_arm + + static __inline__ FT_Int32 + FT_MulFix_arm( FT_Int32 a, + FT_Int32 b ) + { + register FT_Int32 t, t2; + + + __asm__ __volatile__ ( + "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */ + "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */ + "add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */ + "adds %1, %1, %0\n\t" /* %1 += %0 */ + "adc %2, %2, #0\n\t" /* %2 += carry */ + "mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */ + "orr %0, %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */ + : "=r"(a), "=&r"(t2), "=&r"(t) + : "r"(a), "r"(b) ); + return a; + } + +#endif /* __arm__ && !__thumb__ */ + +#if defined( __i386__ ) +#define FT_MULFIX_ASSEMBLER FT_MulFix_i386 + + static __inline__ FT_Int32 + FT_MulFix_i386( FT_Int32 a, + FT_Int32 b ) + { + register FT_Int32 result; + + + __asm__ __volatile__ ( + "imul %%edx\n" + "movl %%edx, %%ecx\n" + "sarl $31, %%ecx\n" + "addl $0x8000, %%ecx\n" + "addl %%ecx, %%eax\n" + "adcl $0, %%edx\n" + "shrl $16, %%eax\n" + "shll $16, %%edx\n" + "addl %%edx, %%eax\n" + : "=a"(result), "+d"(b) + : "a"(a) + : "%ecx" ); + return result; + } + +#endif /* i386 */ + +#endif /* __GNUC__ */ + +#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ + + +#ifdef FT_CONFIG_OPTION_INLINE_MULFIX +#ifdef FT_MULFIX_ASSEMBLER +#define FT_MULFIX_INLINED FT_MULFIX_ASSEMBLER +#endif +#endif + + +#ifdef FT_MAKE_OPTION_SINGLE_OBJECT + +#define FT_LOCAL( x ) static x +#define FT_LOCAL_DEF( x ) static x + +#else + +#ifdef __cplusplus +#define FT_LOCAL( x ) extern "C" x +#define FT_LOCAL_DEF( x ) extern "C" x +#else +#define FT_LOCAL( x ) extern x +#define FT_LOCAL_DEF( x ) x +#endif + +#endif /* FT_MAKE_OPTION_SINGLE_OBJECT */ + + +#ifndef FT_BASE + +#ifdef __cplusplus +#define FT_BASE( x ) extern "C" x +#else +#define FT_BASE( x ) extern x +#endif + +#endif /* !FT_BASE */ + + +#ifndef FT_BASE_DEF + +#ifdef __cplusplus +#define FT_BASE_DEF( x ) x +#else +#define FT_BASE_DEF( x ) x +#endif + +#endif /* !FT_BASE_DEF */ + + +#ifndef FT_EXPORT + +#ifdef __cplusplus +#define FT_EXPORT( x ) extern "C" x +#else +#define FT_EXPORT( x ) extern x +#endif + +#endif /* !FT_EXPORT */ + + +#ifndef FT_EXPORT_DEF + +#ifdef __cplusplus +#define FT_EXPORT_DEF( x ) extern "C" x +#else +#define FT_EXPORT_DEF( x ) extern x +#endif + +#endif /* !FT_EXPORT_DEF */ + + +#ifndef FT_EXPORT_VAR + +#ifdef __cplusplus +#define FT_EXPORT_VAR( x ) extern "C" x +#else +#define FT_EXPORT_VAR( x ) extern x +#endif + +#endif /* !FT_EXPORT_VAR */ + + /* The following macros are needed to compile the library with a */ + /* C++ compiler and with 16bit compilers. */ + /* */ + + /* This is special. Within C++, you must specify `extern "C"' for */ + /* functions which are used via function pointers, and you also */ + /* must do that for structures which contain function pointers to */ + /* assure C linkage -- it's not possible to have (local) anonymous */ + /* functions which are accessed by (global) function pointers. */ + /* */ + /* */ + /* FT_CALLBACK_DEF is used to _define_ a callback function. */ + /* */ + /* FT_CALLBACK_TABLE is used to _declare_ a constant variable that */ + /* contains pointers to callback functions. */ + /* */ + /* FT_CALLBACK_TABLE_DEF is used to _define_ a constant variable */ + /* that contains pointers to callback functions. */ + /* */ + /* */ + /* Some 16bit compilers have to redefine these macros to insert */ + /* the infamous `_cdecl' or `__fastcall' declarations. */ + /* */ +#ifndef FT_CALLBACK_DEF +#ifdef __cplusplus +#define FT_CALLBACK_DEF( x ) extern "C" x +#else +#define FT_CALLBACK_DEF( x ) static x +#endif +#endif /* FT_CALLBACK_DEF */ + +#ifndef FT_CALLBACK_TABLE +#ifdef __cplusplus +#define FT_CALLBACK_TABLE extern "C" +#define FT_CALLBACK_TABLE_DEF extern "C" +#else +#define FT_CALLBACK_TABLE extern +#define FT_CALLBACK_TABLE_DEF /* nothing */ +#endif +#endif /* FT_CALLBACK_TABLE */ + + +FT_END_HEADER + + +#endif /* __FTCONFIG_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/config/ftheader.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/config/ftheader.h new file mode 100644 index 00000000..b63945dc --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/config/ftheader.h @@ -0,0 +1,780 @@ +/***************************************************************************/ +/* */ +/* ftheader.h */ +/* */ +/* Build macros of the FreeType 2 library. */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +#ifndef __FT_HEADER_H__ +#define __FT_HEADER_H__ + + + /*@***********************************************************************/ + /* */ + /* */ + /* FT_BEGIN_HEADER */ + /* */ + /* */ + /* This macro is used in association with @FT_END_HEADER in header */ + /* files to ensure that the declarations within are properly */ + /* encapsulated in an `extern "C" { .. }' block when included from a */ + /* C++ compiler. */ + /* */ +#ifdef __cplusplus +#define FT_BEGIN_HEADER extern "C" { +#else +#define FT_BEGIN_HEADER /* nothing */ +#endif + + + /*@***********************************************************************/ + /* */ + /* */ + /* FT_END_HEADER */ + /* */ + /* */ + /* This macro is used in association with @FT_BEGIN_HEADER in header */ + /* files to ensure that the declarations within are properly */ + /* encapsulated in an `extern "C" { .. }' block when included from a */ + /* C++ compiler. */ + /* */ +#ifdef __cplusplus +#define FT_END_HEADER } +#else +#define FT_END_HEADER /* nothing */ +#endif + + + /*************************************************************************/ + /* */ + /* Aliases for the FreeType 2 public and configuration files. */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /*
*/ + /* header_file_macros */ + /* */ + /* */ + /* Header File Macros */ + /* */ + /* <Abstract> */ + /* Macro definitions used to #include specific header files. */ + /* */ + /* <Description> */ + /* The following macros are defined to the name of specific */ + /* FreeType~2 header files. They can be used directly in #include */ + /* statements as in: */ + /* */ + /* { */ + /* #include FT_FREETYPE_H */ + /* #include FT_MULTIPLE_MASTERS_H */ + /* #include FT_GLYPH_H */ + /* } */ + /* */ + /* There are several reasons why we are now using macros to name */ + /* public header files. The first one is that such macros are not */ + /* limited to the infamous 8.3~naming rule required by DOS (and */ + /* `FT_MULTIPLE_MASTERS_H' is a lot more meaningful than `ftmm.h'). */ + /* */ + /* The second reason is that it allows for more flexibility in the */ + /* way FreeType~2 is installed on a given system. */ + /* */ + /*************************************************************************/ + + + /* configuration files */ + + /************************************************************************* + * + * @macro: + * FT_CONFIG_CONFIG_H + * + * @description: + * A macro used in #include statements to name the file containing + * FreeType~2 configuration data. + * + */ +#ifndef FT_CONFIG_CONFIG_H +#define FT_CONFIG_CONFIG_H <freetype/config/ftconfig.h> +#endif + + + /************************************************************************* + * + * @macro: + * FT_CONFIG_STANDARD_LIBRARY_H + * + * @description: + * A macro used in #include statements to name the file containing + * FreeType~2 interface to the standard C library functions. + * + */ +#ifndef FT_CONFIG_STANDARD_LIBRARY_H +#define FT_CONFIG_STANDARD_LIBRARY_H <freetype/config/ftstdlib.h> +#endif + + + /************************************************************************* + * + * @macro: + * FT_CONFIG_OPTIONS_H + * + * @description: + * A macro used in #include statements to name the file containing + * FreeType~2 project-specific configuration options. + * + */ +#ifndef FT_CONFIG_OPTIONS_H +#define FT_CONFIG_OPTIONS_H <freetype/config/ftoption.h> +#endif + + + /************************************************************************* + * + * @macro: + * FT_CONFIG_MODULES_H + * + * @description: + * A macro used in #include statements to name the file containing the + * list of FreeType~2 modules that are statically linked to new library + * instances in @FT_Init_FreeType. + * + */ +#ifndef FT_CONFIG_MODULES_H +#define FT_CONFIG_MODULES_H <freetype/config/ftmodule.h> +#endif + + /* */ + + /* public headers */ + + /************************************************************************* + * + * @macro: + * FT_FREETYPE_H + * + * @description: + * A macro used in #include statements to name the file containing the + * base FreeType~2 API. + * + */ +#define FT_FREETYPE_H <freetype/freetype.h> + + + /************************************************************************* + * + * @macro: + * FT_ERRORS_H + * + * @description: + * A macro used in #include statements to name the file containing the + * list of FreeType~2 error codes (and messages). + * + * It is included by @FT_FREETYPE_H. + * + */ +#define FT_ERRORS_H <freetype/fterrors.h> + + + /************************************************************************* + * + * @macro: + * FT_MODULE_ERRORS_H + * + * @description: + * A macro used in #include statements to name the file containing the + * list of FreeType~2 module error offsets (and messages). + * + */ +#define FT_MODULE_ERRORS_H <freetype/ftmoderr.h> + + + /************************************************************************* + * + * @macro: + * FT_SYSTEM_H + * + * @description: + * A macro used in #include statements to name the file containing the + * FreeType~2 interface to low-level operations (i.e., memory management + * and stream i/o). + * + * It is included by @FT_FREETYPE_H. + * + */ +#define FT_SYSTEM_H <freetype/ftsystem.h> + + + /************************************************************************* + * + * @macro: + * FT_IMAGE_H + * + * @description: + * A macro used in #include statements to name the file containing type + * definitions related to glyph images (i.e., bitmaps, outlines, + * scan-converter parameters). + * + * It is included by @FT_FREETYPE_H. + * + */ +#define FT_IMAGE_H <freetype/ftimage.h> + + + /************************************************************************* + * + * @macro: + * FT_TYPES_H + * + * @description: + * A macro used in #include statements to name the file containing the + * basic data types defined by FreeType~2. + * + * It is included by @FT_FREETYPE_H. + * + */ +#define FT_TYPES_H <freetype/fttypes.h> + + + /************************************************************************* + * + * @macro: + * FT_LIST_H + * + * @description: + * A macro used in #include statements to name the file containing the + * list management API of FreeType~2. + * + * (Most applications will never need to include this file.) + * + */ +#define FT_LIST_H <freetype/ftlist.h> + + + /************************************************************************* + * + * @macro: + * FT_OUTLINE_H + * + * @description: + * A macro used in #include statements to name the file containing the + * scalable outline management API of FreeType~2. + * + */ +#define FT_OUTLINE_H <freetype/ftoutln.h> + + + /************************************************************************* + * + * @macro: + * FT_SIZES_H + * + * @description: + * A macro used in #include statements to name the file containing the + * API which manages multiple @FT_Size objects per face. + * + */ +#define FT_SIZES_H <freetype/ftsizes.h> + + + /************************************************************************* + * + * @macro: + * FT_MODULE_H + * + * @description: + * A macro used in #include statements to name the file containing the + * module management API of FreeType~2. + * + */ +#define FT_MODULE_H <freetype/ftmodapi.h> + + + /************************************************************************* + * + * @macro: + * FT_RENDER_H + * + * @description: + * A macro used in #include statements to name the file containing the + * renderer module management API of FreeType~2. + * + */ +#define FT_RENDER_H <freetype/ftrender.h> + + + /************************************************************************* + * + * @macro: + * FT_TYPE1_TABLES_H + * + * @description: + * A macro used in #include statements to name the file containing the + * types and API specific to the Type~1 format. + * + */ +#define FT_TYPE1_TABLES_H <freetype/t1tables.h> + + + /************************************************************************* + * + * @macro: + * FT_TRUETYPE_IDS_H + * + * @description: + * A macro used in #include statements to name the file containing the + * enumeration values which identify name strings, languages, encodings, + * etc. This file really contains a _large_ set of constant macro + * definitions, taken from the TrueType and OpenType specifications. + * + */ +#define FT_TRUETYPE_IDS_H <freetype/ttnameid.h> + + + /************************************************************************* + * + * @macro: + * FT_TRUETYPE_TABLES_H + * + * @description: + * A macro used in #include statements to name the file containing the + * types and API specific to the TrueType (as well as OpenType) format. + * + */ +#define FT_TRUETYPE_TABLES_H <freetype/tttables.h> + + + /************************************************************************* + * + * @macro: + * FT_TRUETYPE_TAGS_H + * + * @description: + * A macro used in #include statements to name the file containing the + * definitions of TrueType four-byte `tags' which identify blocks in + * SFNT-based font formats (i.e., TrueType and OpenType). + * + */ +#define FT_TRUETYPE_TAGS_H <freetype/tttags.h> + + + /************************************************************************* + * + * @macro: + * FT_BDF_H + * + * @description: + * A macro used in #include statements to name the file containing the + * definitions of an API which accesses BDF-specific strings from a + * face. + * + */ +#define FT_BDF_H <freetype/ftbdf.h> + + + /************************************************************************* + * + * @macro: + * FT_CID_H + * + * @description: + * A macro used in #include statements to name the file containing the + * definitions of an API which access CID font information from a + * face. + * + */ +#define FT_CID_H <freetype/ftcid.h> + + + /************************************************************************* + * + * @macro: + * FT_GZIP_H + * + * @description: + * A macro used in #include statements to name the file containing the + * definitions of an API which supports gzip-compressed files. + * + */ +#define FT_GZIP_H <freetype/ftgzip.h> + + + /************************************************************************* + * + * @macro: + * FT_LZW_H + * + * @description: + * A macro used in #include statements to name the file containing the + * definitions of an API which supports LZW-compressed files. + * + */ +#define FT_LZW_H <freetype/ftlzw.h> + + + /************************************************************************* + * + * @macro: + * FT_WINFONTS_H + * + * @description: + * A macro used in #include statements to name the file containing the + * definitions of an API which supports Windows FNT files. + * + */ +#define FT_WINFONTS_H <freetype/ftwinfnt.h> + + + /************************************************************************* + * + * @macro: + * FT_GLYPH_H + * + * @description: + * A macro used in #include statements to name the file containing the + * API of the optional glyph management component. + * + */ +#define FT_GLYPH_H <freetype/ftglyph.h> + + + /************************************************************************* + * + * @macro: + * FT_BITMAP_H + * + * @description: + * A macro used in #include statements to name the file containing the + * API of the optional bitmap conversion component. + * + */ +#define FT_BITMAP_H <freetype/ftbitmap.h> + + + /************************************************************************* + * + * @macro: + * FT_BBOX_H + * + * @description: + * A macro used in #include statements to name the file containing the + * API of the optional exact bounding box computation routines. + * + */ +#define FT_BBOX_H <freetype/ftbbox.h> + + + /************************************************************************* + * + * @macro: + * FT_CACHE_H + * + * @description: + * A macro used in #include statements to name the file containing the + * API of the optional FreeType~2 cache sub-system. + * + */ +#define FT_CACHE_H <freetype/ftcache.h> + + + /************************************************************************* + * + * @macro: + * FT_CACHE_IMAGE_H + * + * @description: + * A macro used in #include statements to name the file containing the + * `glyph image' API of the FreeType~2 cache sub-system. + * + * It is used to define a cache for @FT_Glyph elements. You can also + * use the API defined in @FT_CACHE_SMALL_BITMAPS_H if you only need to + * store small glyph bitmaps, as it will use less memory. + * + * This macro is deprecated. Simply include @FT_CACHE_H to have all + * glyph image-related cache declarations. + * + */ +#define FT_CACHE_IMAGE_H FT_CACHE_H + + + /************************************************************************* + * + * @macro: + * FT_CACHE_SMALL_BITMAPS_H + * + * @description: + * A macro used in #include statements to name the file containing the + * `small bitmaps' API of the FreeType~2 cache sub-system. + * + * It is used to define a cache for small glyph bitmaps in a relatively + * memory-efficient way. You can also use the API defined in + * @FT_CACHE_IMAGE_H if you want to cache arbitrary glyph images, + * including scalable outlines. + * + * This macro is deprecated. Simply include @FT_CACHE_H to have all + * small bitmaps-related cache declarations. + * + */ +#define FT_CACHE_SMALL_BITMAPS_H FT_CACHE_H + + + /************************************************************************* + * + * @macro: + * FT_CACHE_CHARMAP_H + * + * @description: + * A macro used in #include statements to name the file containing the + * `charmap' API of the FreeType~2 cache sub-system. + * + * This macro is deprecated. Simply include @FT_CACHE_H to have all + * charmap-based cache declarations. + * + */ +#define FT_CACHE_CHARMAP_H FT_CACHE_H + + + /************************************************************************* + * + * @macro: + * FT_MAC_H + * + * @description: + * A macro used in #include statements to name the file containing the + * Macintosh-specific FreeType~2 API. The latter is used to access + * fonts embedded in resource forks. + * + * This header file must be explicitly included by client applications + * compiled on the Mac (note that the base API still works though). + * + */ +#define FT_MAC_H <freetype/ftmac.h> + + + /************************************************************************* + * + * @macro: + * FT_MULTIPLE_MASTERS_H + * + * @description: + * A macro used in #include statements to name the file containing the + * optional multiple-masters management API of FreeType~2. + * + */ +#define FT_MULTIPLE_MASTERS_H <freetype/ftmm.h> + + + /************************************************************************* + * + * @macro: + * FT_SFNT_NAMES_H + * + * @description: + * A macro used in #include statements to name the file containing the + * optional FreeType~2 API which accesses embedded `name' strings in + * SFNT-based font formats (i.e., TrueType and OpenType). + * + */ +#define FT_SFNT_NAMES_H <freetype/ftsnames.h> + + + /************************************************************************* + * + * @macro: + * FT_OPENTYPE_VALIDATE_H + * + * @description: + * A macro used in #include statements to name the file containing the + * optional FreeType~2 API which validates OpenType tables (BASE, GDEF, + * GPOS, GSUB, JSTF). + * + */ +#define FT_OPENTYPE_VALIDATE_H <freetype/ftotval.h> + + + /************************************************************************* + * + * @macro: + * FT_GX_VALIDATE_H + * + * @description: + * A macro used in #include statements to name the file containing the + * optional FreeType~2 API which validates TrueTypeGX/AAT tables (feat, + * mort, morx, bsln, just, kern, opbd, trak, prop). + * + */ +#define FT_GX_VALIDATE_H <freetype/ftgxval.h> + + + /************************************************************************* + * + * @macro: + * FT_PFR_H + * + * @description: + * A macro used in #include statements to name the file containing the + * FreeType~2 API which accesses PFR-specific data. + * + */ +#define FT_PFR_H <freetype/ftpfr.h> + + + /************************************************************************* + * + * @macro: + * FT_STROKER_H + * + * @description: + * A macro used in #include statements to name the file containing the + * FreeType~2 API which provides functions to stroke outline paths. + */ +#define FT_STROKER_H <freetype/ftstroke.h> + + + /************************************************************************* + * + * @macro: + * FT_SYNTHESIS_H + * + * @description: + * A macro used in #include statements to name the file containing the + * FreeType~2 API which performs artificial obliquing and emboldening. + */ +#define FT_SYNTHESIS_H <freetype/ftsynth.h> + + + /************************************************************************* + * + * @macro: + * FT_XFREE86_H + * + * @description: + * A macro used in #include statements to name the file containing the + * FreeType~2 API which provides functions specific to the XFree86 and + * X.Org X11 servers. + */ +#define FT_XFREE86_H <freetype/ftxf86.h> + + + /************************************************************************* + * + * @macro: + * FT_TRIGONOMETRY_H + * + * @description: + * A macro used in #include statements to name the file containing the + * FreeType~2 API which performs trigonometric computations (e.g., + * cosines and arc tangents). + */ +#define FT_TRIGONOMETRY_H <freetype/fttrigon.h> + + + /************************************************************************* + * + * @macro: + * FT_LCD_FILTER_H + * + * @description: + * A macro used in #include statements to name the file containing the + * FreeType~2 API which performs color filtering for subpixel rendering. + */ +#define FT_LCD_FILTER_H <freetype/ftlcdfil.h> + + + /************************************************************************* + * + * @macro: + * FT_UNPATENTED_HINTING_H + * + * @description: + * A macro used in #include statements to name the file containing the + * FreeType~2 API which performs color filtering for subpixel rendering. + */ +#define FT_UNPATENTED_HINTING_H <freetype/ttunpat.h> + + + /************************************************************************* + * + * @macro: + * FT_INCREMENTAL_H + * + * @description: + * A macro used in #include statements to name the file containing the + * FreeType~2 API which performs color filtering for subpixel rendering. + */ +#define FT_INCREMENTAL_H <freetype/ftincrem.h> + + + /************************************************************************* + * + * @macro: + * FT_GASP_H + * + * @description: + * A macro used in #include statements to name the file containing the + * FreeType~2 API which returns entries from the TrueType GASP table. + */ +#define FT_GASP_H <freetype/ftgasp.h> + + + /************************************************************************* + * + * @macro: + * FT_ADVANCES_H + * + * @description: + * A macro used in #include statements to name the file containing the + * FreeType~2 API which returns individual and ranged glyph advances. + */ +#define FT_ADVANCES_H <freetype/ftadvanc.h> + + + /* */ + +#define FT_ERROR_DEFINITIONS_H <freetype/fterrdef.h> + + + /* The internals of the cache sub-system are no longer exposed. We */ + /* default to FT_CACHE_H at the moment just in case, but we know of */ + /* no rogue client that uses them. */ + /* */ +#define FT_CACHE_MANAGER_H <freetype/ftcache.h> +#define FT_CACHE_INTERNAL_MRU_H <freetype/ftcache.h> +#define FT_CACHE_INTERNAL_MANAGER_H <freetype/ftcache.h> +#define FT_CACHE_INTERNAL_CACHE_H <freetype/ftcache.h> +#define FT_CACHE_INTERNAL_GLYPH_H <freetype/ftcache.h> +#define FT_CACHE_INTERNAL_IMAGE_H <freetype/ftcache.h> +#define FT_CACHE_INTERNAL_SBITS_H <freetype/ftcache.h> + + +#define FT_INCREMENTAL_H <freetype/ftincrem.h> + +#define FT_TRUETYPE_UNPATENTED_H <freetype/ttunpat.h> + + + /* + * Include internal headers definitions from <freetype/internal/...> + * only when building the library. + */ +#ifdef FT2_BUILD_LIBRARY +#define FT_INTERNAL_INTERNAL_H <freetype/internal/internal.h> +#include FT_INTERNAL_INTERNAL_H +#endif /* FT2_BUILD_LIBRARY */ + + +#endif /* __FT2_BUILD_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/config/ftmodule.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/config/ftmodule.h new file mode 100644 index 00000000..b7299779 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/config/ftmodule.h @@ -0,0 +1,20 @@ +/* This is a generated file. */ +FT_USE_MODULE( FT_Driver_ClassRec, tt_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, cff_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, t1cid_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, pfr_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class ) +FT_USE_MODULE( FT_Module_Class, sfnt_module_class ) +FT_USE_MODULE( FT_Module_Class, autofit_module_class ) +FT_USE_MODULE( FT_Module_Class, pshinter_module_class ) +FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class ) +FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class ) +FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcd_renderer_class ) +FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcdv_renderer_class ) +FT_USE_MODULE( FT_Module_Class, psaux_module_class ) +FT_USE_MODULE( FT_Module_Class, psnames_module_class ) +/* EOF */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/config/ftoption.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/config/ftoption.h new file mode 100644 index 00000000..2b46259c --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/config/ftoption.h @@ -0,0 +1,733 @@ +/***************************************************************************/ +/* */ +/* ftoption.h */ +/* */ +/* User-selectable configuration macros (specification only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ +/* 2010 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTOPTION_H__ +#define __FTOPTION_H__ + + +#include <ft2build.h> + + +FT_BEGIN_HEADER + + /*************************************************************************/ + /* */ + /* USER-SELECTABLE CONFIGURATION MACROS */ + /* */ + /* This file contains the default configuration macro definitions for */ + /* a standard build of the FreeType library. There are three ways to */ + /* use this file to build project-specific versions of the library: */ + /* */ + /* - You can modify this file by hand, but this is not recommended in */ + /* cases where you would like to build several versions of the */ + /* library from a single source directory. */ + /* */ + /* - You can put a copy of this file in your build directory, more */ + /* precisely in `$BUILD/freetype/config/ftoption.h', where `$BUILD' */ + /* is the name of a directory that is included _before_ the FreeType */ + /* include path during compilation. */ + /* */ + /* The default FreeType Makefiles and Jamfiles use the build */ + /* directory `builds/<system>' by default, but you can easily change */ + /* that for your own projects. */ + /* */ + /* - Copy the file <ft2build.h> to `$BUILD/ft2build.h' and modify it */ + /* slightly to pre-define the macro FT_CONFIG_OPTIONS_H used to */ + /* locate this file during the build. For example, */ + /* */ + /* #define FT_CONFIG_OPTIONS_H <myftoptions.h> */ + /* #include <freetype/config/ftheader.h> */ + /* */ + /* will use `$BUILD/myftoptions.h' instead of this file for macro */ + /* definitions. */ + /* */ + /* Note also that you can similarly pre-define the macro */ + /* FT_CONFIG_MODULES_H used to locate the file listing of the modules */ + /* that are statically linked to the library at compile time. By */ + /* default, this file is <freetype/config/ftmodule.h>. */ + /* */ + /* We highly recommend using the third method whenever possible. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** G E N E R A L F R E E T Y P E 2 C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Uncomment the line below if you want to activate sub-pixel rendering */ + /* (a.k.a. LCD rendering, or ClearType) in this build of the library. */ + /* */ + /* Note that this feature is covered by several Microsoft patents */ + /* and should not be activated in any default build of the library. */ + /* */ + /* This macro has no impact on the FreeType API, only on its */ + /* _implementation_. For example, using FT_RENDER_MODE_LCD when calling */ + /* FT_Render_Glyph still generates a bitmap that is 3 times wider than */ + /* the original size in case this macro isn't defined; however, each */ + /* triplet of subpixels has R=G=B. */ + /* */ + /* This is done to allow FreeType clients to run unmodified, forcing */ + /* them to display normal gray-level anti-aliased glyphs. */ + /* */ +/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ + + + /*************************************************************************/ + /* */ + /* Many compilers provide a non-ANSI 64-bit data type that can be used */ + /* by FreeType to speed up some computations. However, this will create */ + /* some problems when compiling the library in strict ANSI mode. */ + /* */ + /* For this reason, the use of 64-bit integers is normally disabled when */ + /* the __STDC__ macro is defined. You can however disable this by */ + /* defining the macro FT_CONFIG_OPTION_FORCE_INT64 here. */ + /* */ + /* For most compilers, this will only create compilation warnings when */ + /* building the library. */ + /* */ + /* ObNote: The compiler-specific 64-bit integers are detected in the */ + /* file `ftconfig.h' either statically or through the */ + /* `configure' script on supported platforms. */ + /* */ +#undef FT_CONFIG_OPTION_FORCE_INT64 + + + /*************************************************************************/ + /* */ + /* If this macro is defined, do not try to use an assembler version of */ + /* performance-critical functions (e.g. FT_MulFix). You should only do */ + /* that to verify that the assembler function works properly, or to */ + /* execute benchmark tests of the various implementations. */ +/* #define FT_CONFIG_OPTION_NO_ASSEMBLER */ + + + /*************************************************************************/ + /* */ + /* If this macro is defined, try to use an inlined assembler version of */ + /* the `FT_MulFix' function, which is a `hotspot' when loading and */ + /* hinting glyphs, and which should be executed as fast as possible. */ + /* */ + /* Note that if your compiler or CPU is not supported, this will default */ + /* to the standard and portable implementation found in `ftcalc.c'. */ + /* */ +#define FT_CONFIG_OPTION_INLINE_MULFIX + + + /*************************************************************************/ + /* */ + /* LZW-compressed file support. */ + /* */ + /* FreeType now handles font files that have been compressed with the */ + /* `compress' program. This is mostly used to parse many of the PCF */ + /* files that come with various X11 distributions. The implementation */ + /* uses NetBSD's `zopen' to partially uncompress the file on the fly */ + /* (see src/lzw/ftgzip.c). */ + /* */ + /* Define this macro if you want to enable this `feature'. */ + /* */ +#define FT_CONFIG_OPTION_USE_LZW + + + /*************************************************************************/ + /* */ + /* Gzip-compressed file support. */ + /* */ + /* FreeType now handles font files that have been compressed with the */ + /* `gzip' program. This is mostly used to parse many of the PCF files */ + /* that come with XFree86. The implementation uses `zlib' to */ + /* partially uncompress the file on the fly (see src/gzip/ftgzip.c). */ + /* */ + /* Define this macro if you want to enable this `feature'. See also */ + /* the macro FT_CONFIG_OPTION_SYSTEM_ZLIB below. */ + /* */ +#define FT_CONFIG_OPTION_USE_ZLIB + + + /*************************************************************************/ + /* */ + /* ZLib library selection */ + /* */ + /* This macro is only used when FT_CONFIG_OPTION_USE_ZLIB is defined. */ + /* It allows FreeType's `ftgzip' component to link to the system's */ + /* installation of the ZLib library. This is useful on systems like */ + /* Unix or VMS where it generally is already available. */ + /* */ + /* If you let it undefined, the component will use its own copy */ + /* of the zlib sources instead. These have been modified to be */ + /* included directly within the component and *not* export external */ + /* function names. This allows you to link any program with FreeType */ + /* _and_ ZLib without linking conflicts. */ + /* */ + /* Do not #undef this macro here since the build system might define */ + /* it for certain configurations only. */ + /* */ +/* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */ + + + /*************************************************************************/ + /* */ + /* DLL export compilation */ + /* */ + /* When compiling FreeType as a DLL, some systems/compilers need a */ + /* special keyword in front OR after the return type of function */ + /* declarations. */ + /* */ + /* Two macros are used within the FreeType source code to define */ + /* exported library functions: FT_EXPORT and FT_EXPORT_DEF. */ + /* */ + /* FT_EXPORT( return_type ) */ + /* */ + /* is used in a function declaration, as in */ + /* */ + /* FT_EXPORT( FT_Error ) */ + /* FT_Init_FreeType( FT_Library* alibrary ); */ + /* */ + /* */ + /* FT_EXPORT_DEF( return_type ) */ + /* */ + /* is used in a function definition, as in */ + /* */ + /* FT_EXPORT_DEF( FT_Error ) */ + /* FT_Init_FreeType( FT_Library* alibrary ) */ + /* { */ + /* ... some code ... */ + /* return FT_Err_Ok; */ + /* } */ + /* */ + /* You can provide your own implementation of FT_EXPORT and */ + /* FT_EXPORT_DEF here if you want. If you leave them undefined, they */ + /* will be later automatically defined as `extern return_type' to */ + /* allow normal compilation. */ + /* */ + /* Do not #undef these macros here since the build system might define */ + /* them for certain configurations only. */ + /* */ +/* #define FT_EXPORT(x) extern x */ +/* #define FT_EXPORT_DEF(x) x */ + + + /*************************************************************************/ + /* */ + /* Glyph Postscript Names handling */ + /* */ + /* By default, FreeType 2 is compiled with the `psnames' module. This */ + /* module is in charge of converting a glyph name string into a */ + /* Unicode value, or return a Macintosh standard glyph name for the */ + /* use with the TrueType `post' table. */ + /* */ + /* Undefine this macro if you do not want `psnames' compiled in your */ + /* build of FreeType. This has the following effects: */ + /* */ + /* - The TrueType driver will provide its own set of glyph names, */ + /* if you build it to support postscript names in the TrueType */ + /* `post' table. */ + /* */ + /* - The Type 1 driver will not be able to synthesize a Unicode */ + /* charmap out of the glyphs found in the fonts. */ + /* */ + /* You would normally undefine this configuration macro when building */ + /* a version of FreeType that doesn't contain a Type 1 or CFF driver. */ + /* */ +#define FT_CONFIG_OPTION_POSTSCRIPT_NAMES + + + /*************************************************************************/ + /* */ + /* Postscript Names to Unicode Values support */ + /* */ + /* By default, FreeType 2 is built with the `PSNames' module compiled */ + /* in. Among other things, the module is used to convert a glyph name */ + /* into a Unicode value. This is especially useful in order to */ + /* synthesize on the fly a Unicode charmap from the CFF/Type 1 driver */ + /* through a big table named the `Adobe Glyph List' (AGL). */ + /* */ + /* Undefine this macro if you do not want the Adobe Glyph List */ + /* compiled in your `PSNames' module. The Type 1 driver will not be */ + /* able to synthesize a Unicode charmap out of the glyphs found in the */ + /* fonts. */ + /* */ +#define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + + + /*************************************************************************/ + /* */ + /* Support for Mac fonts */ + /* */ + /* Define this macro if you want support for outline fonts in Mac */ + /* format (mac dfont, mac resource, macbinary containing a mac */ + /* resource) on non-Mac platforms. */ + /* */ + /* Note that the `FOND' resource isn't checked. */ + /* */ +#define FT_CONFIG_OPTION_MAC_FONTS + + + /*************************************************************************/ + /* */ + /* Guessing methods to access embedded resource forks */ + /* */ + /* Enable extra Mac fonts support on non-Mac platforms (e.g. */ + /* GNU/Linux). */ + /* */ + /* Resource forks which include fonts data are stored sometimes in */ + /* locations which users or developers don't expected. In some cases, */ + /* resource forks start with some offset from the head of a file. In */ + /* other cases, the actual resource fork is stored in file different */ + /* from what the user specifies. If this option is activated, */ + /* FreeType tries to guess whether such offsets or different file */ + /* names must be used. */ + /* */ + /* Note that normal, direct access of resource forks is controlled via */ + /* the FT_CONFIG_OPTION_MAC_FONTS option. */ + /* */ +#ifdef FT_CONFIG_OPTION_MAC_FONTS +#define FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK +#endif + + + /*************************************************************************/ + /* */ + /* Allow the use of FT_Incremental_Interface to load typefaces that */ + /* contain no glyph data, but supply it via a callback function. */ + /* This is required by clients supporting document formats which */ + /* supply font data incrementally as the document is parsed, such */ + /* as the Ghostscript interpreter for the PostScript language. */ + /* */ +#define FT_CONFIG_OPTION_INCREMENTAL + + + /*************************************************************************/ + /* */ + /* The size in bytes of the render pool used by the scan-line converter */ + /* to do all of its work. */ + /* */ + /* This must be greater than 4KByte if you use FreeType to rasterize */ + /* glyphs; otherwise, you may set it to zero to avoid unnecessary */ + /* allocation of the render pool. */ + /* */ +#define FT_RENDER_POOL_SIZE 16384L + + + /*************************************************************************/ + /* */ + /* FT_MAX_MODULES */ + /* */ + /* The maximum number of modules that can be registered in a single */ + /* FreeType library object. 32 is the default. */ + /* */ +#define FT_MAX_MODULES 32 + + + /*************************************************************************/ + /* */ + /* Debug level */ + /* */ + /* FreeType can be compiled in debug or trace mode. In debug mode, */ + /* errors are reported through the `ftdebug' component. In trace */ + /* mode, additional messages are sent to the standard output during */ + /* execution. */ + /* */ + /* Define FT_DEBUG_LEVEL_ERROR to build the library in debug mode. */ + /* Define FT_DEBUG_LEVEL_TRACE to build it in trace mode. */ + /* */ + /* Don't define any of these macros to compile in `release' mode! */ + /* */ + /* Do not #undef these macros here since the build system might define */ + /* them for certain configurations only. */ + /* */ +/* #define FT_DEBUG_LEVEL_ERROR */ +/* #define FT_DEBUG_LEVEL_TRACE */ + + + /*************************************************************************/ + /* */ + /* Memory Debugging */ + /* */ + /* FreeType now comes with an integrated memory debugger that is */ + /* capable of detecting simple errors like memory leaks or double */ + /* deletes. To compile it within your build of the library, you */ + /* should define FT_DEBUG_MEMORY here. */ + /* */ + /* Note that the memory debugger is only activated at runtime when */ + /* when the _environment_ variable `FT2_DEBUG_MEMORY' is defined also! */ + /* */ + /* Do not #undef this macro here since the build system might define */ + /* it for certain configurations only. */ + /* */ +/* #define FT_DEBUG_MEMORY */ + + + /*************************************************************************/ + /* */ + /* Module errors */ + /* */ + /* If this macro is set (which is _not_ the default), the higher byte */ + /* of an error code gives the module in which the error has occurred, */ + /* while the lower byte is the real error code. */ + /* */ + /* Setting this macro makes sense for debugging purposes only, since */ + /* it would break source compatibility of certain programs that use */ + /* FreeType 2. */ + /* */ + /* More details can be found in the files ftmoderr.h and fterrors.h. */ + /* */ +#undef FT_CONFIG_OPTION_USE_MODULE_ERRORS + + + /*************************************************************************/ + /* */ + /* Position Independent Code */ + /* */ + /* If this macro is set (which is _not_ the default), FreeType2 will */ + /* avoid creating constants that require address fixups. Instead the */ + /* constants will be moved into a struct and additional intialization */ + /* code will be used. */ + /* */ + /* Setting this macro is needed for systems that prohibit address */ + /* fixups, such as BREW. */ + /* */ +/* #define FT_CONFIG_OPTION_PIC */ + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** S F N T D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_EMBEDDED_BITMAPS if you want to support */ + /* embedded bitmaps in all formats using the SFNT module (namely */ + /* TrueType & OpenType). */ + /* */ +#define TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to */ + /* load and enumerate the glyph Postscript names in a TrueType or */ + /* OpenType file. */ + /* */ + /* Note that when you do not compile the `PSNames' module by undefining */ + /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will */ + /* contain additional code used to read the PS Names table from a font. */ + /* */ + /* (By default, the module uses `PSNames' to extract glyph names.) */ + /* */ +#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_SFNT_NAMES if your applications need to */ + /* access the internal name table in a SFNT-based format like TrueType */ + /* or OpenType. The name table contains various strings used to */ + /* describe the font, like family name, copyright, version, etc. It */ + /* does not contain any glyph name though. */ + /* */ + /* Accessing SFNT names is done through the functions declared in */ + /* `freetype/ftsnames.h'. */ + /* */ +#define TT_CONFIG_OPTION_SFNT_NAMES + + + /*************************************************************************/ + /* */ + /* TrueType CMap support */ + /* */ + /* Here you can fine-tune which TrueType CMap table format shall be */ + /* supported. */ +#define TT_CONFIG_CMAP_FORMAT_0 +#define TT_CONFIG_CMAP_FORMAT_2 +#define TT_CONFIG_CMAP_FORMAT_4 +#define TT_CONFIG_CMAP_FORMAT_6 +#define TT_CONFIG_CMAP_FORMAT_8 +#define TT_CONFIG_CMAP_FORMAT_10 +#define TT_CONFIG_CMAP_FORMAT_12 +#define TT_CONFIG_CMAP_FORMAT_13 +#define TT_CONFIG_CMAP_FORMAT_14 + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** T R U E T Y P E D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_BYTECODE_INTERPRETER if you want to compile */ + /* a bytecode interpreter in the TrueType driver. */ + /* */ + /* By undefining this, you will only compile the code necessary to load */ + /* TrueType glyphs without hinting. */ + /* */ + /* Do not #undef this macro here, since the build system might */ + /* define it for certain configurations only. */ + /* */ +#define TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + + /*************************************************************************/ + /* */ + /* If you define TT_CONFIG_OPTION_UNPATENTED_HINTING, a special version */ + /* of the TrueType bytecode interpreter is used that doesn't implement */ + /* any of the patented opcodes and algorithms. The patents related to */ + /* TrueType hinting have expired worldwide since May 2010; this option */ + /* is now deprecated. */ + /* */ + /* Note that the TT_CONFIG_OPTION_UNPATENTED_HINTING macro is *ignored* */ + /* if you define TT_CONFIG_OPTION_BYTECODE_INTERPRETER; in other words, */ + /* either define TT_CONFIG_OPTION_BYTECODE_INTERPRETER or */ + /* TT_CONFIG_OPTION_UNPATENTED_HINTING but not both at the same time. */ + /* */ + /* This macro is only useful for a small number of font files (mostly */ + /* for Asian scripts) that require bytecode interpretation to properly */ + /* load glyphs. For all other fonts, this produces unpleasant results, */ + /* thus the unpatented interpreter is never used to load glyphs from */ + /* TrueType fonts unless one of the following two options is used. */ + /* */ + /* - The unpatented interpreter is explicitly activated by the user */ + /* through the FT_PARAM_TAG_UNPATENTED_HINTING parameter tag */ + /* when opening the FT_Face. */ + /* */ + /* - FreeType detects that the FT_Face corresponds to one of the */ + /* `trick' fonts (e.g., `Mingliu') it knows about. The font engine */ + /* contains a hard-coded list of font names and other matching */ + /* parameters (see function `tt_face_init' in file */ + /* `src/truetype/ttobjs.c'). */ + /* */ + /* Here a sample code snippet for using FT_PARAM_TAG_UNPATENTED_HINTING. */ + /* */ + /* { */ + /* FT_Parameter parameter; */ + /* FT_Open_Args open_args; */ + /* */ + /* */ + /* parameter.tag = FT_PARAM_TAG_UNPATENTED_HINTING; */ + /* */ + /* open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS; */ + /* open_args.pathname = my_font_pathname; */ + /* open_args.num_params = 1; */ + /* open_args.params = ¶meter; */ + /* */ + /* error = FT_Open_Face( library, &open_args, index, &face ); */ + /* ... */ + /* } */ + /* */ +/* #define TT_CONFIG_OPTION_UNPATENTED_HINTING */ + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_INTERPRETER_SWITCH to compile the TrueType */ + /* bytecode interpreter with a huge switch statement, rather than a call */ + /* table. This results in smaller and faster code for a number of */ + /* architectures. */ + /* */ + /* Note however that on some compiler/processor combinations, undefining */ + /* this macro will generate faster, though larger, code. */ + /* */ +#define TT_CONFIG_OPTION_INTERPRETER_SWITCH + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED to compile the */ + /* TrueType glyph loader to use Apple's definition of how to handle */ + /* component offsets in composite glyphs. */ + /* */ + /* Apple and MS disagree on the default behavior of component offsets */ + /* in composites. Apple says that they should be scaled by the scaling */ + /* factors in the transformation matrix (roughly, it's more complex) */ + /* while MS says they should not. OpenType defines two bits in the */ + /* composite flags array which can be used to disambiguate, but old */ + /* fonts will not have them. */ + /* */ + /* http://partners.adobe.com/asn/developer/opentype/glyf.html */ + /* http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html */ + /* */ +#undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_GX_VAR_SUPPORT if you want to include */ + /* support for Apple's distortable font technology (fvar, gvar, cvar, */ + /* and avar tables). This has many similarities to Type 1 Multiple */ + /* Masters support. */ + /* */ +#define TT_CONFIG_OPTION_GX_VAR_SUPPORT + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_BDF if you want to include support for */ + /* an embedded `BDF ' table within SFNT-based bitmap formats. */ + /* */ +#define TT_CONFIG_OPTION_BDF + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** T Y P E 1 D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* T1_MAX_DICT_DEPTH is the maximal depth of nest dictionaries and */ + /* arrays in the Type 1 stream (see t1load.c). A minimum of 4 is */ + /* required. */ + /* */ +#define T1_MAX_DICT_DEPTH 5 + + + /*************************************************************************/ + /* */ + /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */ + /* calls during glyph loading. */ + /* */ +#define T1_MAX_SUBRS_CALLS 16 + + + /*************************************************************************/ + /* */ + /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. A */ + /* minimum of 16 is required. */ + /* */ + /* The Chinese font MingTiEG-Medium (CNS 11643 character set) needs 256. */ + /* */ +#define T1_MAX_CHARSTRINGS_OPERANDS 256 + + + /*************************************************************************/ + /* */ + /* Define this configuration macro if you want to prevent the */ + /* compilation of `t1afm', which is in charge of reading Type 1 AFM */ + /* files into an existing face. Note that if set, the T1 driver will be */ + /* unable to produce kerning distances. */ + /* */ +#undef T1_CONFIG_OPTION_NO_AFM + + + /*************************************************************************/ + /* */ + /* Define this configuration macro if you want to prevent the */ + /* compilation of the Multiple Masters font support in the Type 1 */ + /* driver. */ + /* */ +#undef T1_CONFIG_OPTION_NO_MM_SUPPORT + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** A U T O F I T M O D U L E C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Compile autofit module with CJK (Chinese, Japanese, Korean) script */ + /* support. */ + /* */ +#define AF_CONFIG_OPTION_CJK + + /*************************************************************************/ + /* */ + /* Compile autofit module with Indic script support. */ + /* */ +#define AF_CONFIG_OPTION_INDIC + + /* */ + + + /* + * Define this variable if you want to keep the layout of internal + * structures that was used prior to FreeType 2.2. This also compiles in + * a few obsolete functions to avoid linking problems on typical Unix + * distributions. + * + * For embedded systems or building a new distribution from scratch, it + * is recommended to disable the macro since it reduces the library's code + * size and activates a few memory-saving optimizations as well. + */ +#define FT_CONFIG_OPTION_OLD_INTERNALS + + + /* + * To detect legacy cache-lookup call from a rogue client (<= 2.1.7), + * we restrict the number of charmaps in a font. The current API of + * FTC_CMapCache_Lookup() takes cmap_index & charcode, but old API + * takes charcode only. To determine the passed value is for cmap_index + * or charcode, the possible cmap_index is restricted not to exceed + * the minimum possible charcode by a rogue client. It is also very + * unlikely that a rogue client is interested in Unicode values 0 to 15. + * + * NOTE: The original threshold was 4 deduced from popular number of + * cmap subtables in UCS-4 TrueType fonts, but now it is not + * irregular for OpenType fonts to have more than 4 subtables, + * because variation selector subtables are available for Apple + * and Microsoft platforms. + */ + +#ifdef FT_CONFIG_OPTION_OLD_INTERNALS +#define FT_MAX_CHARMAP_CACHEABLE 15 +#endif + + + /* + * This macro is defined if either unpatented or native TrueType + * hinting is requested by the definitions above. + */ +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#define TT_USE_BYTECODE_INTERPRETER +#undef TT_CONFIG_OPTION_UNPATENTED_HINTING +#elif defined TT_CONFIG_OPTION_UNPATENTED_HINTING +#define TT_USE_BYTECODE_INTERPRETER +#endif + +FT_END_HEADER + + +#endif /* __FTOPTION_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/config/ftstdlib.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/config/ftstdlib.h new file mode 100644 index 00000000..30ec14e7 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/config/ftstdlib.h @@ -0,0 +1,173 @@ +/***************************************************************************/ +/* */ +/* ftstdlib.h */ +/* */ +/* ANSI-specific library and header configuration file (specification */ +/* only). */ +/* */ +/* Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2009 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to group all #includes to the ANSI C library that */ + /* FreeType normally requires. It also defines macros to rename the */ + /* standard functions within the FreeType source code. */ + /* */ + /* Load a file which defines __FTSTDLIB_H__ before this one to override */ + /* it. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTSTDLIB_H__ +#define __FTSTDLIB_H__ + + +#include <stddef.h> + +#define ft_ptrdiff_t ptrdiff_t + + + /**********************************************************************/ + /* */ + /* integer limits */ + /* */ + /* UINT_MAX and ULONG_MAX are used to automatically compute the size */ + /* of `int' and `long' in bytes at compile-time. So far, this works */ + /* for all platforms the library has been tested on. */ + /* */ + /* Note that on the extremely rare platforms that do not provide */ + /* integer types that are _exactly_ 16 and 32 bits wide (e.g. some */ + /* old Crays where `int' is 36 bits), we do not make any guarantee */ + /* about the correct behaviour of FT2 with all fonts. */ + /* */ + /* In these case, `ftconfig.h' will refuse to compile anyway with a */ + /* message like `couldn't find 32-bit type' or something similar. */ + /* */ + /**********************************************************************/ + + +#include <limits.h> + +#define FT_CHAR_BIT CHAR_BIT +#define FT_INT_MAX INT_MAX +#define FT_INT_MIN INT_MIN +#define FT_UINT_MAX UINT_MAX +#define FT_ULONG_MAX ULONG_MAX + + + /**********************************************************************/ + /* */ + /* character and string processing */ + /* */ + /**********************************************************************/ + + +#include <string.h> + +#define ft_memchr memchr +#define ft_memcmp memcmp +#define ft_memcpy memcpy +#define ft_memmove memmove +#define ft_memset memset +#define ft_strcat strcat +#define ft_strcmp strcmp +#define ft_strcpy strcpy +#define ft_strlen strlen +#define ft_strncmp strncmp +#define ft_strncpy strncpy +#define ft_strrchr strrchr +#define ft_strstr strstr + + + /**********************************************************************/ + /* */ + /* file handling */ + /* */ + /**********************************************************************/ + + +#include <stdio.h> + +#define FT_FILE FILE +#define ft_fclose fclose +#define ft_fopen fopen +#define ft_fread fread +#define ft_fseek fseek +#define ft_ftell ftell +#define ft_sprintf sprintf + + + /**********************************************************************/ + /* */ + /* sorting */ + /* */ + /**********************************************************************/ + + +#include <stdlib.h> + +#define ft_qsort qsort + + + /**********************************************************************/ + /* */ + /* memory allocation */ + /* */ + /**********************************************************************/ + + +#define ft_scalloc calloc +#define ft_sfree free +#define ft_smalloc malloc +#define ft_srealloc realloc + + + /**********************************************************************/ + /* */ + /* miscellaneous */ + /* */ + /**********************************************************************/ + + +#define ft_atol atol +#define ft_labs labs + + + /**********************************************************************/ + /* */ + /* execution control */ + /* */ + /**********************************************************************/ + + +#include <setjmp.h> + +#define ft_jmp_buf jmp_buf /* note: this cannot be a typedef since */ + /* jmp_buf is defined as a macro */ + /* on certain platforms */ + +#define ft_longjmp longjmp +#define ft_setjmp( b ) setjmp( *(jmp_buf*) &(b) ) /* same thing here */ + + + /* the following is only used for debugging purposes, i.e., if */ + /* FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE are defined */ + +#include <stdarg.h> + + +#endif /* __FTSTDLIB_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/freetype.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/freetype.h new file mode 100644 index 00000000..7799b70b --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/freetype.h @@ -0,0 +1,3919 @@ +/***************************************************************************/ +/* */ +/* freetype.h */ +/* */ +/* FreeType high-level API and common types (specification only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ +/* 2010 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FT_FREETYPE_H +#error "`ft2build.h' hasn't been included yet!" +#error "Please always use macros to include FreeType header files." +#error "Example:" +#error " #include <ft2build.h>" +#error " #include FT_FREETYPE_H" +#endif + + +#ifndef __FREETYPE_H__ +#define __FREETYPE_H__ + + +#include <ft2build.h> +#include FT_CONFIG_CONFIG_H +#include FT_ERRORS_H +#include FT_TYPES_H + + +FT_BEGIN_HEADER + + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* user_allocation */ + /* */ + /* <Title> */ + /* User allocation */ + /* */ + /* <Abstract> */ + /* How client applications should allocate FreeType data structures. */ + /* */ + /* <Description> */ + /* FreeType assumes that structures allocated by the user and passed */ + /* as arguments are zeroed out except for the actual data. In other */ + /* words, it is recommended to use `calloc' (or variants of it) */ + /* instead of `malloc' for allocation. */ + /* */ + /*************************************************************************/ + + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* B A S I C T Y P E S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* base_interface */ + /* */ + /* <Title> */ + /* Base Interface */ + /* */ + /* <Abstract> */ + /* The FreeType~2 base font interface. */ + /* */ + /* <Description> */ + /* This section describes the public high-level API of FreeType~2. */ + /* */ + /* <Order> */ + /* FT_Library */ + /* FT_Face */ + /* FT_Size */ + /* FT_GlyphSlot */ + /* FT_CharMap */ + /* FT_Encoding */ + /* */ + /* FT_FaceRec */ + /* */ + /* FT_FACE_FLAG_SCALABLE */ + /* FT_FACE_FLAG_FIXED_SIZES */ + /* FT_FACE_FLAG_FIXED_WIDTH */ + /* FT_FACE_FLAG_HORIZONTAL */ + /* FT_FACE_FLAG_VERTICAL */ + /* FT_FACE_FLAG_SFNT */ + /* FT_FACE_FLAG_KERNING */ + /* FT_FACE_FLAG_MULTIPLE_MASTERS */ + /* FT_FACE_FLAG_GLYPH_NAMES */ + /* FT_FACE_FLAG_EXTERNAL_STREAM */ + /* FT_FACE_FLAG_FAST_GLYPHS */ + /* FT_FACE_FLAG_HINTER */ + /* */ + /* FT_STYLE_FLAG_BOLD */ + /* FT_STYLE_FLAG_ITALIC */ + /* */ + /* FT_SizeRec */ + /* FT_Size_Metrics */ + /* */ + /* FT_GlyphSlotRec */ + /* FT_Glyph_Metrics */ + /* FT_SubGlyph */ + /* */ + /* FT_Bitmap_Size */ + /* */ + /* FT_Init_FreeType */ + /* FT_Done_FreeType */ + /* */ + /* FT_New_Face */ + /* FT_Done_Face */ + /* FT_New_Memory_Face */ + /* FT_Open_Face */ + /* FT_Open_Args */ + /* FT_Parameter */ + /* FT_Attach_File */ + /* FT_Attach_Stream */ + /* */ + /* FT_Set_Char_Size */ + /* FT_Set_Pixel_Sizes */ + /* FT_Request_Size */ + /* FT_Select_Size */ + /* FT_Size_Request_Type */ + /* FT_Size_Request */ + /* FT_Set_Transform */ + /* FT_Load_Glyph */ + /* FT_Get_Char_Index */ + /* FT_Get_Name_Index */ + /* FT_Load_Char */ + /* */ + /* FT_OPEN_MEMORY */ + /* FT_OPEN_STREAM */ + /* FT_OPEN_PATHNAME */ + /* FT_OPEN_DRIVER */ + /* FT_OPEN_PARAMS */ + /* */ + /* FT_LOAD_DEFAULT */ + /* FT_LOAD_RENDER */ + /* FT_LOAD_MONOCHROME */ + /* FT_LOAD_LINEAR_DESIGN */ + /* FT_LOAD_NO_SCALE */ + /* FT_LOAD_NO_HINTING */ + /* FT_LOAD_NO_BITMAP */ + /* FT_LOAD_CROP_BITMAP */ + /* */ + /* FT_LOAD_VERTICAL_LAYOUT */ + /* FT_LOAD_IGNORE_TRANSFORM */ + /* FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */ + /* FT_LOAD_FORCE_AUTOHINT */ + /* FT_LOAD_NO_RECURSE */ + /* FT_LOAD_PEDANTIC */ + /* */ + /* FT_LOAD_TARGET_NORMAL */ + /* FT_LOAD_TARGET_LIGHT */ + /* FT_LOAD_TARGET_MONO */ + /* FT_LOAD_TARGET_LCD */ + /* FT_LOAD_TARGET_LCD_V */ + /* */ + /* FT_Render_Glyph */ + /* FT_Render_Mode */ + /* FT_Get_Kerning */ + /* FT_Kerning_Mode */ + /* FT_Get_Track_Kerning */ + /* FT_Get_Glyph_Name */ + /* FT_Get_Postscript_Name */ + /* */ + /* FT_CharMapRec */ + /* FT_Select_Charmap */ + /* FT_Set_Charmap */ + /* FT_Get_Charmap_Index */ + /* */ + /* FT_FSTYPE_INSTALLABLE_EMBEDDING */ + /* FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING */ + /* FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING */ + /* FT_FSTYPE_EDITABLE_EMBEDDING */ + /* FT_FSTYPE_NO_SUBSETTING */ + /* FT_FSTYPE_BITMAP_EMBEDDING_ONLY */ + /* */ + /* FT_Get_FSType_Flags */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Glyph_Metrics */ + /* */ + /* <Description> */ + /* A structure used to model the metrics of a single glyph. The */ + /* values are expressed in 26.6 fractional pixel format; if the flag */ + /* @FT_LOAD_NO_SCALE has been used while loading the glyph, values */ + /* are expressed in font units instead. */ + /* */ + /* <Fields> */ + /* width :: */ + /* The glyph's width. */ + /* */ + /* height :: */ + /* The glyph's height. */ + /* */ + /* horiBearingX :: */ + /* Left side bearing for horizontal layout. */ + /* */ + /* horiBearingY :: */ + /* Top side bearing for horizontal layout. */ + /* */ + /* horiAdvance :: */ + /* Advance width for horizontal layout. */ + /* */ + /* vertBearingX :: */ + /* Left side bearing for vertical layout. */ + /* */ + /* vertBearingY :: */ + /* Top side bearing for vertical layout. */ + /* */ + /* vertAdvance :: */ + /* Advance height for vertical layout. */ + /* */ + /* <Note> */ + /* If not disabled with @FT_LOAD_NO_HINTING, the values represent */ + /* dimensions of the hinted glyph (in case hinting is applicable). */ + /* */ + typedef struct FT_Glyph_Metrics_ + { + FT_Pos width; + FT_Pos height; + + FT_Pos horiBearingX; + FT_Pos horiBearingY; + FT_Pos horiAdvance; + + FT_Pos vertBearingX; + FT_Pos vertBearingY; + FT_Pos vertAdvance; + + } FT_Glyph_Metrics; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Bitmap_Size */ + /* */ + /* <Description> */ + /* This structure models the metrics of a bitmap strike (i.e., a set */ + /* of glyphs for a given point size and resolution) in a bitmap font. */ + /* It is used for the `available_sizes' field of @FT_Face. */ + /* */ + /* <Fields> */ + /* height :: The vertical distance, in pixels, between two */ + /* consecutive baselines. It is always positive. */ + /* */ + /* width :: The average width, in pixels, of all glyphs in the */ + /* strike. */ + /* */ + /* size :: The nominal size of the strike in 26.6 fractional */ + /* points. This field is not very useful. */ + /* */ + /* x_ppem :: The horizontal ppem (nominal width) in 26.6 fractional */ + /* pixels. */ + /* */ + /* y_ppem :: The vertical ppem (nominal height) in 26.6 fractional */ + /* pixels. */ + /* */ + /* <Note> */ + /* Windows FNT: */ + /* The nominal size given in a FNT font is not reliable. Thus when */ + /* the driver finds it incorrect, it sets `size' to some calculated */ + /* values and sets `x_ppem' and `y_ppem' to the pixel width and */ + /* height given in the font, respectively. */ + /* */ + /* TrueType embedded bitmaps: */ + /* `size', `width', and `height' values are not contained in the */ + /* bitmap strike itself. They are computed from the global font */ + /* parameters. */ + /* */ + typedef struct FT_Bitmap_Size_ + { + FT_Short height; + FT_Short width; + + FT_Pos size; + + FT_Pos x_ppem; + FT_Pos y_ppem; + + } FT_Bitmap_Size; + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* O B J E C T C L A S S E S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Library */ + /* */ + /* <Description> */ + /* A handle to a FreeType library instance. Each `library' is */ + /* completely independent from the others; it is the `root' of a set */ + /* of objects like fonts, faces, sizes, etc. */ + /* */ + /* It also embeds a memory manager (see @FT_Memory), as well as a */ + /* scan-line converter object (see @FT_Raster). */ + /* */ + /* For multi-threading applications each thread should have its own */ + /* FT_Library object. */ + /* */ + /* <Note> */ + /* Library objects are normally created by @FT_Init_FreeType, and */ + /* destroyed with @FT_Done_FreeType. */ + /* */ + typedef struct FT_LibraryRec_ *FT_Library; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Module */ + /* */ + /* <Description> */ + /* A handle to a given FreeType module object. Each module can be a */ + /* font driver, a renderer, or anything else that provides services */ + /* to the formers. */ + /* */ + typedef struct FT_ModuleRec_* FT_Module; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Driver */ + /* */ + /* <Description> */ + /* A handle to a given FreeType font driver object. Each font driver */ + /* is a special module capable of creating faces from font files. */ + /* */ + typedef struct FT_DriverRec_* FT_Driver; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Renderer */ + /* */ + /* <Description> */ + /* A handle to a given FreeType renderer. A renderer is a special */ + /* module in charge of converting a glyph image to a bitmap, when */ + /* necessary. Each renderer supports a given glyph image format, and */ + /* one or more target surface depths. */ + /* */ + typedef struct FT_RendererRec_* FT_Renderer; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Face */ + /* */ + /* <Description> */ + /* A handle to a given typographic face object. A face object models */ + /* a given typeface, in a given style. */ + /* */ + /* <Note> */ + /* Each face object also owns a single @FT_GlyphSlot object, as well */ + /* as one or more @FT_Size objects. */ + /* */ + /* Use @FT_New_Face or @FT_Open_Face to create a new face object from */ + /* a given filepathname or a custom input stream. */ + /* */ + /* Use @FT_Done_Face to destroy it (along with its slot and sizes). */ + /* */ + /* <Also> */ + /* See @FT_FaceRec for the publicly accessible fields of a given face */ + /* object. */ + /* */ + typedef struct FT_FaceRec_* FT_Face; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Size */ + /* */ + /* <Description> */ + /* A handle to an object used to model a face scaled to a given */ + /* character size. */ + /* */ + /* <Note> */ + /* Each @FT_Face has an _active_ @FT_Size object that is used by */ + /* functions like @FT_Load_Glyph to determine the scaling */ + /* transformation which is used to load and hint glyphs and metrics. */ + /* */ + /* You can use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes, */ + /* @FT_Request_Size or even @FT_Select_Size to change the content */ + /* (i.e., the scaling values) of the active @FT_Size. */ + /* */ + /* You can use @FT_New_Size to create additional size objects for a */ + /* given @FT_Face, but they won't be used by other functions until */ + /* you activate it through @FT_Activate_Size. Only one size can be */ + /* activated at any given time per face. */ + /* */ + /* <Also> */ + /* See @FT_SizeRec for the publicly accessible fields of a given size */ + /* object. */ + /* */ + typedef struct FT_SizeRec_* FT_Size; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_GlyphSlot */ + /* */ + /* <Description> */ + /* A handle to a given `glyph slot'. A slot is a container where it */ + /* is possible to load any of the glyphs contained in its parent */ + /* face. */ + /* */ + /* In other words, each time you call @FT_Load_Glyph or */ + /* @FT_Load_Char, the slot's content is erased by the new glyph data, */ + /* i.e., the glyph's metrics, its image (bitmap or outline), and */ + /* other control information. */ + /* */ + /* <Also> */ + /* See @FT_GlyphSlotRec for the publicly accessible glyph fields. */ + /* */ + typedef struct FT_GlyphSlotRec_* FT_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_CharMap */ + /* */ + /* <Description> */ + /* A handle to a given character map. A charmap is used to translate */ + /* character codes in a given encoding into glyph indexes for its */ + /* parent's face. Some font formats may provide several charmaps per */ + /* font. */ + /* */ + /* Each face object owns zero or more charmaps, but only one of them */ + /* can be `active' and used by @FT_Get_Char_Index or @FT_Load_Char. */ + /* */ + /* The list of available charmaps in a face is available through the */ + /* `face->num_charmaps' and `face->charmaps' fields of @FT_FaceRec. */ + /* */ + /* The currently active charmap is available as `face->charmap'. */ + /* You should call @FT_Set_Charmap to change it. */ + /* */ + /* <Note> */ + /* When a new face is created (either through @FT_New_Face or */ + /* @FT_Open_Face), the library looks for a Unicode charmap within */ + /* the list and automatically activates it. */ + /* */ + /* <Also> */ + /* See @FT_CharMapRec for the publicly accessible fields of a given */ + /* character map. */ + /* */ + typedef struct FT_CharMapRec_* FT_CharMap; + + + /*************************************************************************/ + /* */ + /* <Macro> */ + /* FT_ENC_TAG */ + /* */ + /* <Description> */ + /* This macro converts four-letter tags into an unsigned long. It is */ + /* used to define `encoding' identifiers (see @FT_Encoding). */ + /* */ + /* <Note> */ + /* Since many 16-bit compilers don't like 32-bit enumerations, you */ + /* should redefine this macro in case of problems to something like */ + /* this: */ + /* */ + /* { */ + /* #define FT_ENC_TAG( value, a, b, c, d ) value */ + /* } */ + /* */ + /* to get a simple enumeration without assigning special numbers. */ + /* */ + +#ifndef FT_ENC_TAG +#define FT_ENC_TAG( value, a, b, c, d ) \ + value = ( ( (FT_UInt32)(a) << 24 ) | \ + ( (FT_UInt32)(b) << 16 ) | \ + ( (FT_UInt32)(c) << 8 ) | \ + (FT_UInt32)(d) ) + +#endif /* FT_ENC_TAG */ + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Encoding */ + /* */ + /* <Description> */ + /* An enumeration used to specify character sets supported by */ + /* charmaps. Used in the @FT_Select_Charmap API function. */ + /* */ + /* <Note> */ + /* Despite the name, this enumeration lists specific character */ + /* repertories (i.e., charsets), and not text encoding methods (e.g., */ + /* UTF-8, UTF-16, etc.). */ + /* */ + /* Other encodings might be defined in the future. */ + /* */ + /* <Values> */ + /* FT_ENCODING_NONE :: */ + /* The encoding value~0 is reserved. */ + /* */ + /* FT_ENCODING_UNICODE :: */ + /* Corresponds to the Unicode character set. This value covers */ + /* all versions of the Unicode repertoire, including ASCII and */ + /* Latin-1. Most fonts include a Unicode charmap, but not all */ + /* of them. */ + /* */ + /* For example, if you want to access Unicode value U+1F028 (and */ + /* the font contains it), use value 0x1F028 as the input value for */ + /* @FT_Get_Char_Index. */ + /* */ + /* FT_ENCODING_MS_SYMBOL :: */ + /* Corresponds to the Microsoft Symbol encoding, used to encode */ + /* mathematical symbols in the 32..255 character code range. For */ + /* more information, see `http://www.ceviz.net/symbol.htm'. */ + /* */ + /* FT_ENCODING_SJIS :: */ + /* Corresponds to Japanese SJIS encoding. More info at */ + /* at `http://langsupport.japanreference.com/encoding.shtml'. */ + /* See note on multi-byte encodings below. */ + /* */ + /* FT_ENCODING_GB2312 :: */ + /* Corresponds to an encoding system for Simplified Chinese as used */ + /* used in mainland China. */ + /* */ + /* FT_ENCODING_BIG5 :: */ + /* Corresponds to an encoding system for Traditional Chinese as */ + /* used in Taiwan and Hong Kong. */ + /* */ + /* FT_ENCODING_WANSUNG :: */ + /* Corresponds to the Korean encoding system known as Wansung. */ + /* For more information see */ + /* `http://www.microsoft.com/typography/unicode/949.txt'. */ + /* */ + /* FT_ENCODING_JOHAB :: */ + /* The Korean standard character set (KS~C 5601-1992), which */ + /* corresponds to MS Windows code page 1361. This character set */ + /* includes all possible Hangeul character combinations. */ + /* */ + /* FT_ENCODING_ADOBE_LATIN_1 :: */ + /* Corresponds to a Latin-1 encoding as defined in a Type~1 */ + /* PostScript font. It is limited to 256 character codes. */ + /* */ + /* FT_ENCODING_ADOBE_STANDARD :: */ + /* Corresponds to the Adobe Standard encoding, as found in Type~1, */ + /* CFF, and OpenType/CFF fonts. It is limited to 256 character */ + /* codes. */ + /* */ + /* FT_ENCODING_ADOBE_EXPERT :: */ + /* Corresponds to the Adobe Expert encoding, as found in Type~1, */ + /* CFF, and OpenType/CFF fonts. It is limited to 256 character */ + /* codes. */ + /* */ + /* FT_ENCODING_ADOBE_CUSTOM :: */ + /* Corresponds to a custom encoding, as found in Type~1, CFF, and */ + /* OpenType/CFF fonts. It is limited to 256 character codes. */ + /* */ + /* FT_ENCODING_APPLE_ROMAN :: */ + /* Corresponds to the 8-bit Apple roman encoding. Many TrueType */ + /* and OpenType fonts contain a charmap for this encoding, since */ + /* older versions of Mac OS are able to use it. */ + /* */ + /* FT_ENCODING_OLD_LATIN_2 :: */ + /* This value is deprecated and was never used nor reported by */ + /* FreeType. Don't use or test for it. */ + /* */ + /* FT_ENCODING_MS_SJIS :: */ + /* Same as FT_ENCODING_SJIS. Deprecated. */ + /* */ + /* FT_ENCODING_MS_GB2312 :: */ + /* Same as FT_ENCODING_GB2312. Deprecated. */ + /* */ + /* FT_ENCODING_MS_BIG5 :: */ + /* Same as FT_ENCODING_BIG5. Deprecated. */ + /* */ + /* FT_ENCODING_MS_WANSUNG :: */ + /* Same as FT_ENCODING_WANSUNG. Deprecated. */ + /* */ + /* FT_ENCODING_MS_JOHAB :: */ + /* Same as FT_ENCODING_JOHAB. Deprecated. */ + /* */ + /* <Note> */ + /* By default, FreeType automatically synthesizes a Unicode charmap */ + /* for PostScript fonts, using their glyph names dictionaries. */ + /* However, it also reports the encodings defined explicitly in the */ + /* font file, for the cases when they are needed, with the Adobe */ + /* values as well. */ + /* */ + /* FT_ENCODING_NONE is set by the BDF and PCF drivers if the charmap */ + /* is neither Unicode nor ISO-8859-1 (otherwise it is set to */ + /* FT_ENCODING_UNICODE). Use @FT_Get_BDF_Charset_ID to find out */ + /* which encoding is really present. If, for example, the */ + /* `cs_registry' field is `KOI8' and the `cs_encoding' field is `R', */ + /* the font is encoded in KOI8-R. */ + /* */ + /* FT_ENCODING_NONE is always set (with a single exception) by the */ + /* winfonts driver. Use @FT_Get_WinFNT_Header and examine the */ + /* `charset' field of the @FT_WinFNT_HeaderRec structure to find out */ + /* which encoding is really present. For example, */ + /* @FT_WinFNT_ID_CP1251 (204) means Windows code page 1251 (for */ + /* Russian). */ + /* */ + /* FT_ENCODING_NONE is set if `platform_id' is @TT_PLATFORM_MACINTOSH */ + /* and `encoding_id' is not @TT_MAC_ID_ROMAN (otherwise it is set to */ + /* FT_ENCODING_APPLE_ROMAN). */ + /* */ + /* If `platform_id' is @TT_PLATFORM_MACINTOSH, use the function */ + /* @FT_Get_CMap_Language_ID to query the Mac language ID which may */ + /* be needed to be able to distinguish Apple encoding variants. See */ + /* */ + /* http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/README.TXT */ + /* */ + /* to get an idea how to do that. Basically, if the language ID */ + /* is~0, don't use it, otherwise subtract 1 from the language ID. */ + /* Then examine `encoding_id'. If, for example, `encoding_id' is */ + /* @TT_MAC_ID_ROMAN and the language ID (minus~1) is */ + /* `TT_MAC_LANGID_GREEK', it is the Greek encoding, not Roman. */ + /* @TT_MAC_ID_ARABIC with `TT_MAC_LANGID_FARSI' means the Farsi */ + /* variant the Arabic encoding. */ + /* */ + typedef enum FT_Encoding_ + { + FT_ENC_TAG( FT_ENCODING_NONE, 0, 0, 0, 0 ), + + FT_ENC_TAG( FT_ENCODING_MS_SYMBOL, 's', 'y', 'm', 'b' ), + FT_ENC_TAG( FT_ENCODING_UNICODE, 'u', 'n', 'i', 'c' ), + + FT_ENC_TAG( FT_ENCODING_SJIS, 's', 'j', 'i', 's' ), + FT_ENC_TAG( FT_ENCODING_GB2312, 'g', 'b', ' ', ' ' ), + FT_ENC_TAG( FT_ENCODING_BIG5, 'b', 'i', 'g', '5' ), + FT_ENC_TAG( FT_ENCODING_WANSUNG, 'w', 'a', 'n', 's' ), + FT_ENC_TAG( FT_ENCODING_JOHAB, 'j', 'o', 'h', 'a' ), + + /* for backwards compatibility */ + FT_ENCODING_MS_SJIS = FT_ENCODING_SJIS, + FT_ENCODING_MS_GB2312 = FT_ENCODING_GB2312, + FT_ENCODING_MS_BIG5 = FT_ENCODING_BIG5, + FT_ENCODING_MS_WANSUNG = FT_ENCODING_WANSUNG, + FT_ENCODING_MS_JOHAB = FT_ENCODING_JOHAB, + + FT_ENC_TAG( FT_ENCODING_ADOBE_STANDARD, 'A', 'D', 'O', 'B' ), + FT_ENC_TAG( FT_ENCODING_ADOBE_EXPERT, 'A', 'D', 'B', 'E' ), + FT_ENC_TAG( FT_ENCODING_ADOBE_CUSTOM, 'A', 'D', 'B', 'C' ), + FT_ENC_TAG( FT_ENCODING_ADOBE_LATIN_1, 'l', 'a', 't', '1' ), + + FT_ENC_TAG( FT_ENCODING_OLD_LATIN_2, 'l', 'a', 't', '2' ), + + FT_ENC_TAG( FT_ENCODING_APPLE_ROMAN, 'a', 'r', 'm', 'n' ) + + } FT_Encoding; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* ft_encoding_xxx */ + /* */ + /* <Description> */ + /* These constants are deprecated; use the corresponding @FT_Encoding */ + /* values instead. */ + /* */ +#define ft_encoding_none FT_ENCODING_NONE +#define ft_encoding_unicode FT_ENCODING_UNICODE +#define ft_encoding_symbol FT_ENCODING_MS_SYMBOL +#define ft_encoding_latin_1 FT_ENCODING_ADOBE_LATIN_1 +#define ft_encoding_latin_2 FT_ENCODING_OLD_LATIN_2 +#define ft_encoding_sjis FT_ENCODING_SJIS +#define ft_encoding_gb2312 FT_ENCODING_GB2312 +#define ft_encoding_big5 FT_ENCODING_BIG5 +#define ft_encoding_wansung FT_ENCODING_WANSUNG +#define ft_encoding_johab FT_ENCODING_JOHAB + +#define ft_encoding_adobe_standard FT_ENCODING_ADOBE_STANDARD +#define ft_encoding_adobe_expert FT_ENCODING_ADOBE_EXPERT +#define ft_encoding_adobe_custom FT_ENCODING_ADOBE_CUSTOM +#define ft_encoding_apple_roman FT_ENCODING_APPLE_ROMAN + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_CharMapRec */ + /* */ + /* <Description> */ + /* The base charmap structure. */ + /* */ + /* <Fields> */ + /* face :: A handle to the parent face object. */ + /* */ + /* encoding :: An @FT_Encoding tag identifying the charmap. Use */ + /* this with @FT_Select_Charmap. */ + /* */ + /* platform_id :: An ID number describing the platform for the */ + /* following encoding ID. This comes directly from */ + /* the TrueType specification and should be emulated */ + /* for other formats. */ + /* */ + /* encoding_id :: A platform specific encoding number. This also */ + /* comes from the TrueType specification and should be */ + /* emulated similarly. */ + /* */ + typedef struct FT_CharMapRec_ + { + FT_Face face; + FT_Encoding encoding; + FT_UShort platform_id; + FT_UShort encoding_id; + + } FT_CharMapRec; + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* B A S E O B J E C T C L A S S E S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Face_Internal */ + /* */ + /* <Description> */ + /* An opaque handle to an `FT_Face_InternalRec' structure, used to */ + /* model private data of a given @FT_Face object. */ + /* */ + /* This structure might change between releases of FreeType~2 and is */ + /* not generally available to client applications. */ + /* */ + typedef struct FT_Face_InternalRec_* FT_Face_Internal; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_FaceRec */ + /* */ + /* <Description> */ + /* FreeType root face class structure. A face object models a */ + /* typeface in a font file. */ + /* */ + /* <Fields> */ + /* num_faces :: The number of faces in the font file. Some */ + /* font formats can have multiple faces in */ + /* a font file. */ + /* */ + /* face_index :: The index of the face in the font file. It */ + /* is set to~0 if there is only one face in */ + /* the font file. */ + /* */ + /* face_flags :: A set of bit flags that give important */ + /* information about the face; see */ + /* @FT_FACE_FLAG_XXX for the details. */ + /* */ + /* style_flags :: A set of bit flags indicating the style of */ + /* the face; see @FT_STYLE_FLAG_XXX for the */ + /* details. */ + /* */ + /* num_glyphs :: The number of glyphs in the face. If the */ + /* face is scalable and has sbits (see */ + /* `num_fixed_sizes'), it is set to the number */ + /* of outline glyphs. */ + /* */ + /* For CID-keyed fonts, this value gives the */ + /* highest CID used in the font. */ + /* */ + /* family_name :: The face's family name. This is an ASCII */ + /* string, usually in English, which describes */ + /* the typeface's family (like `Times New */ + /* Roman', `Bodoni', `Garamond', etc). This */ + /* is a least common denominator used to list */ + /* fonts. Some formats (TrueType & OpenType) */ + /* provide localized and Unicode versions of */ + /* this string. Applications should use the */ + /* format specific interface to access them. */ + /* Can be NULL (e.g., in fonts embedded in a */ + /* PDF file). */ + /* */ + /* style_name :: The face's style name. This is an ASCII */ + /* string, usually in English, which describes */ + /* the typeface's style (like `Italic', */ + /* `Bold', `Condensed', etc). Not all font */ + /* formats provide a style name, so this field */ + /* is optional, and can be set to NULL. As */ + /* for `family_name', some formats provide */ + /* localized and Unicode versions of this */ + /* string. Applications should use the format */ + /* specific interface to access them. */ + /* */ + /* num_fixed_sizes :: The number of bitmap strikes in the face. */ + /* Even if the face is scalable, there might */ + /* still be bitmap strikes, which are called */ + /* `sbits' in that case. */ + /* */ + /* available_sizes :: An array of @FT_Bitmap_Size for all bitmap */ + /* strikes in the face. It is set to NULL if */ + /* there is no bitmap strike. */ + /* */ + /* num_charmaps :: The number of charmaps in the face. */ + /* */ + /* charmaps :: An array of the charmaps of the face. */ + /* */ + /* generic :: A field reserved for client uses. See the */ + /* @FT_Generic type description. */ + /* */ + /* bbox :: The font bounding box. Coordinates are */ + /* expressed in font units (see */ + /* `units_per_EM'). The box is large enough */ + /* to contain any glyph from the font. Thus, */ + /* `bbox.yMax' can be seen as the `maximal */ + /* ascender', and `bbox.yMin' as the `minimal */ + /* descender'. Only relevant for scalable */ + /* formats. */ + /* */ + /* Note that the bounding box might be off by */ + /* (at least) one pixel for hinted fonts. See */ + /* @FT_Size_Metrics for further discussion. */ + /* */ + /* units_per_EM :: The number of font units per EM square for */ + /* this face. This is typically 2048 for */ + /* TrueType fonts, and 1000 for Type~1 fonts. */ + /* Only relevant for scalable formats. */ + /* */ + /* ascender :: The typographic ascender of the face, */ + /* expressed in font units. For font formats */ + /* not having this information, it is set to */ + /* `bbox.yMax'. Only relevant for scalable */ + /* formats. */ + /* */ + /* descender :: The typographic descender of the face, */ + /* expressed in font units. For font formats */ + /* not having this information, it is set to */ + /* `bbox.yMin'. Note that this field is */ + /* usually negative. Only relevant for */ + /* scalable formats. */ + /* */ + /* height :: The height is the vertical distance */ + /* between two consecutive baselines, */ + /* expressed in font units. It is always */ + /* positive. Only relevant for scalable */ + /* formats. */ + /* */ + /* max_advance_width :: The maximal advance width, in font units, */ + /* for all glyphs in this face. This can be */ + /* used to make word wrapping computations */ + /* faster. Only relevant for scalable */ + /* formats. */ + /* */ + /* max_advance_height :: The maximal advance height, in font units, */ + /* for all glyphs in this face. This is only */ + /* relevant for vertical layouts, and is set */ + /* to `height' for fonts that do not provide */ + /* vertical metrics. Only relevant for */ + /* scalable formats. */ + /* */ + /* underline_position :: The position, in font units, of the */ + /* underline line for this face. It is the */ + /* center of the underlining stem. Only */ + /* relevant for scalable formats. */ + /* */ + /* underline_thickness :: The thickness, in font units, of the */ + /* underline for this face. Only relevant for */ + /* scalable formats. */ + /* */ + /* glyph :: The face's associated glyph slot(s). */ + /* */ + /* size :: The current active size for this face. */ + /* */ + /* charmap :: The current active charmap for this face. */ + /* */ + /* <Note> */ + /* Fields may be changed after a call to @FT_Attach_File or */ + /* @FT_Attach_Stream. */ + /* */ + typedef struct FT_FaceRec_ + { + FT_Long num_faces; + FT_Long face_index; + + FT_Long face_flags; + FT_Long style_flags; + + FT_Long num_glyphs; + + FT_String* family_name; + FT_String* style_name; + + FT_Int num_fixed_sizes; + FT_Bitmap_Size* available_sizes; + + FT_Int num_charmaps; + FT_CharMap* charmaps; + + FT_Generic generic; + + /*# The following member variables (down to `underline_thickness') */ + /*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */ + /*# for bitmap fonts. */ + FT_BBox bbox; + + FT_UShort units_per_EM; + FT_Short ascender; + FT_Short descender; + FT_Short height; + + FT_Short max_advance_width; + FT_Short max_advance_height; + + FT_Short underline_position; + FT_Short underline_thickness; + + FT_GlyphSlot glyph; + FT_Size size; + FT_CharMap charmap; + + /*@private begin */ + + FT_Driver driver; + FT_Memory memory; + FT_Stream stream; + + FT_ListRec sizes_list; + + FT_Generic autohint; + void* extensions; + + FT_Face_Internal internal; + + /*@private end */ + + } FT_FaceRec; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_FACE_FLAG_XXX */ + /* */ + /* <Description> */ + /* A list of bit flags used in the `face_flags' field of the */ + /* @FT_FaceRec structure. They inform client applications of */ + /* properties of the corresponding face. */ + /* */ + /* <Values> */ + /* FT_FACE_FLAG_SCALABLE :: */ + /* Indicates that the face contains outline glyphs. This doesn't */ + /* prevent bitmap strikes, i.e., a face can have both this and */ + /* and @FT_FACE_FLAG_FIXED_SIZES set. */ + /* */ + /* FT_FACE_FLAG_FIXED_SIZES :: */ + /* Indicates that the face contains bitmap strikes. See also the */ + /* `num_fixed_sizes' and `available_sizes' fields of @FT_FaceRec. */ + /* */ + /* FT_FACE_FLAG_FIXED_WIDTH :: */ + /* Indicates that the face contains fixed-width characters (like */ + /* Courier, Lucido, MonoType, etc.). */ + /* */ + /* FT_FACE_FLAG_SFNT :: */ + /* Indicates that the face uses the `sfnt' storage scheme. For */ + /* now, this means TrueType and OpenType. */ + /* */ + /* FT_FACE_FLAG_HORIZONTAL :: */ + /* Indicates that the face contains horizontal glyph metrics. This */ + /* should be set for all common formats. */ + /* */ + /* FT_FACE_FLAG_VERTICAL :: */ + /* Indicates that the face contains vertical glyph metrics. This */ + /* is only available in some formats, not all of them. */ + /* */ + /* FT_FACE_FLAG_KERNING :: */ + /* Indicates that the face contains kerning information. If set, */ + /* the kerning distance can be retrieved through the function */ + /* @FT_Get_Kerning. Otherwise the function always return the */ + /* vector (0,0). Note that FreeType doesn't handle kerning data */ + /* from the `GPOS' table (as present in some OpenType fonts). */ + /* */ + /* FT_FACE_FLAG_FAST_GLYPHS :: */ + /* THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT. */ + /* */ + /* FT_FACE_FLAG_MULTIPLE_MASTERS :: */ + /* Indicates that the font contains multiple masters and is capable */ + /* of interpolating between them. See the multiple-masters */ + /* specific API for details. */ + /* */ + /* FT_FACE_FLAG_GLYPH_NAMES :: */ + /* Indicates that the font contains glyph names that can be */ + /* retrieved through @FT_Get_Glyph_Name. Note that some TrueType */ + /* fonts contain broken glyph name tables. Use the function */ + /* @FT_Has_PS_Glyph_Names when needed. */ + /* */ + /* FT_FACE_FLAG_EXTERNAL_STREAM :: */ + /* Used internally by FreeType to indicate that a face's stream was */ + /* provided by the client application and should not be destroyed */ + /* when @FT_Done_Face is called. Don't read or test this flag. */ + /* */ + /* FT_FACE_FLAG_HINTER :: */ + /* Set if the font driver has a hinting machine of its own. For */ + /* example, with TrueType fonts, it makes sense to use data from */ + /* the SFNT `gasp' table only if the native TrueType hinting engine */ + /* (with the bytecode interpreter) is available and active. */ + /* */ + /* FT_FACE_FLAG_CID_KEYED :: */ + /* Set if the font is CID-keyed. In that case, the font is not */ + /* accessed by glyph indices but by CID values. For subsetted */ + /* CID-keyed fonts this has the consequence that not all index */ + /* values are a valid argument to FT_Load_Glyph. Only the CID */ + /* values for which corresponding glyphs in the subsetted font */ + /* exist make FT_Load_Glyph return successfully; in all other cases */ + /* you get an `FT_Err_Invalid_Argument' error. */ + /* */ + /* Note that CID-keyed fonts which are in an SFNT wrapper don't */ + /* have this flag set since the glyphs are accessed in the normal */ + /* way (using contiguous indices); the `CID-ness' isn't visible to */ + /* the application. */ + /* */ + /* FT_FACE_FLAG_TRICKY :: */ + /* Set if the font is `tricky', this is, it always needs the */ + /* font format's native hinting engine to get a reasonable result. */ + /* A typical example is the Chinese font `mingli.ttf' which uses */ + /* TrueType bytecode instructions to move and scale all of its */ + /* subglyphs. */ + /* */ + /* It is not possible to autohint such fonts using */ + /* @FT_LOAD_FORCE_AUTOHINT; it will also ignore */ + /* @FT_LOAD_NO_HINTING. You have to set both FT_LOAD_NO_HINTING */ + /* and @FT_LOAD_NO_AUTOHINT to really disable hinting; however, you */ + /* probably never want this except for demonstration purposes. */ + /* */ + /* Currently, there are six TrueType fonts in the list of tricky */ + /* fonts; they are hard-coded in file `ttobjs.c'. */ + /* */ +#define FT_FACE_FLAG_SCALABLE ( 1L << 0 ) +#define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 ) +#define FT_FACE_FLAG_FIXED_WIDTH ( 1L << 2 ) +#define FT_FACE_FLAG_SFNT ( 1L << 3 ) +#define FT_FACE_FLAG_HORIZONTAL ( 1L << 4 ) +#define FT_FACE_FLAG_VERTICAL ( 1L << 5 ) +#define FT_FACE_FLAG_KERNING ( 1L << 6 ) +#define FT_FACE_FLAG_FAST_GLYPHS ( 1L << 7 ) +#define FT_FACE_FLAG_MULTIPLE_MASTERS ( 1L << 8 ) +#define FT_FACE_FLAG_GLYPH_NAMES ( 1L << 9 ) +#define FT_FACE_FLAG_EXTERNAL_STREAM ( 1L << 10 ) +#define FT_FACE_FLAG_HINTER ( 1L << 11 ) +#define FT_FACE_FLAG_CID_KEYED ( 1L << 12 ) +#define FT_FACE_FLAG_TRICKY ( 1L << 13 ) + + + /************************************************************************* + * + * @macro: + * FT_HAS_HORIZONTAL( face ) + * + * @description: + * A macro that returns true whenever a face object contains + * horizontal metrics (this is true for all font formats though). + * + * @also: + * @FT_HAS_VERTICAL can be used to check for vertical metrics. + * + */ +#define FT_HAS_HORIZONTAL( face ) \ + ( face->face_flags & FT_FACE_FLAG_HORIZONTAL ) + + + /************************************************************************* + * + * @macro: + * FT_HAS_VERTICAL( face ) + * + * @description: + * A macro that returns true whenever a face object contains vertical + * metrics. + * + */ +#define FT_HAS_VERTICAL( face ) \ + ( face->face_flags & FT_FACE_FLAG_VERTICAL ) + + + /************************************************************************* + * + * @macro: + * FT_HAS_KERNING( face ) + * + * @description: + * A macro that returns true whenever a face object contains kerning + * data that can be accessed with @FT_Get_Kerning. + * + */ +#define FT_HAS_KERNING( face ) \ + ( face->face_flags & FT_FACE_FLAG_KERNING ) + + + /************************************************************************* + * + * @macro: + * FT_IS_SCALABLE( face ) + * + * @description: + * A macro that returns true whenever a face object contains a scalable + * font face (true for TrueType, Type~1, Type~42, CID, OpenType/CFF, + * and PFR font formats. + * + */ +#define FT_IS_SCALABLE( face ) \ + ( face->face_flags & FT_FACE_FLAG_SCALABLE ) + + + /************************************************************************* + * + * @macro: + * FT_IS_SFNT( face ) + * + * @description: + * A macro that returns true whenever a face object contains a font + * whose format is based on the SFNT storage scheme. This usually + * means: TrueType fonts, OpenType fonts, as well as SFNT-based embedded + * bitmap fonts. + * + * If this macro is true, all functions defined in @FT_SFNT_NAMES_H and + * @FT_TRUETYPE_TABLES_H are available. + * + */ +#define FT_IS_SFNT( face ) \ + ( face->face_flags & FT_FACE_FLAG_SFNT ) + + + /************************************************************************* + * + * @macro: + * FT_IS_FIXED_WIDTH( face ) + * + * @description: + * A macro that returns true whenever a face object contains a font face + * that contains fixed-width (or `monospace', `fixed-pitch', etc.) + * glyphs. + * + */ +#define FT_IS_FIXED_WIDTH( face ) \ + ( face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ) + + + /************************************************************************* + * + * @macro: + * FT_HAS_FIXED_SIZES( face ) + * + * @description: + * A macro that returns true whenever a face object contains some + * embedded bitmaps. See the `available_sizes' field of the + * @FT_FaceRec structure. + * + */ +#define FT_HAS_FIXED_SIZES( face ) \ + ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES ) + + + /************************************************************************* + * + * @macro: + * FT_HAS_FAST_GLYPHS( face ) + * + * @description: + * Deprecated. + * + */ +#define FT_HAS_FAST_GLYPHS( face ) 0 + + + /************************************************************************* + * + * @macro: + * FT_HAS_GLYPH_NAMES( face ) + * + * @description: + * A macro that returns true whenever a face object contains some glyph + * names that can be accessed through @FT_Get_Glyph_Name. + * + */ +#define FT_HAS_GLYPH_NAMES( face ) \ + ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) + + + /************************************************************************* + * + * @macro: + * FT_HAS_MULTIPLE_MASTERS( face ) + * + * @description: + * A macro that returns true whenever a face object contains some + * multiple masters. The functions provided by @FT_MULTIPLE_MASTERS_H + * are then available to choose the exact design you want. + * + */ +#define FT_HAS_MULTIPLE_MASTERS( face ) \ + ( face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) + + + /************************************************************************* + * + * @macro: + * FT_IS_CID_KEYED( face ) + * + * @description: + * A macro that returns true whenever a face object contains a CID-keyed + * font. See the discussion of @FT_FACE_FLAG_CID_KEYED for more + * details. + * + * If this macro is true, all functions defined in @FT_CID_H are + * available. + * + */ +#define FT_IS_CID_KEYED( face ) \ + ( face->face_flags & FT_FACE_FLAG_CID_KEYED ) + + + /************************************************************************* + * + * @macro: + * FT_IS_TRICKY( face ) + * + * @description: + * A macro that returns true whenever a face represents a `tricky' font. + * See the discussion of @FT_FACE_FLAG_TRICKY for more details. + * + */ +#define FT_IS_TRICKY( face ) \ + ( face->face_flags & FT_FACE_FLAG_TRICKY ) + + + /*************************************************************************/ + /* */ + /* <Const> */ + /* FT_STYLE_FLAG_XXX */ + /* */ + /* <Description> */ + /* A list of bit-flags used to indicate the style of a given face. */ + /* These are used in the `style_flags' field of @FT_FaceRec. */ + /* */ + /* <Values> */ + /* FT_STYLE_FLAG_ITALIC :: */ + /* Indicates that a given face style is italic or oblique. */ + /* */ + /* FT_STYLE_FLAG_BOLD :: */ + /* Indicates that a given face is bold. */ + /* */ + /* <Note> */ + /* The style information as provided by FreeType is very basic. More */ + /* details are beyond the scope and should be done on a higher level */ + /* (for example, by analyzing various fields of the `OS/2' table in */ + /* SFNT based fonts). */ + /* */ +#define FT_STYLE_FLAG_ITALIC ( 1 << 0 ) +#define FT_STYLE_FLAG_BOLD ( 1 << 1 ) + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Size_Internal */ + /* */ + /* <Description> */ + /* An opaque handle to an `FT_Size_InternalRec' structure, used to */ + /* model private data of a given @FT_Size object. */ + /* */ + typedef struct FT_Size_InternalRec_* FT_Size_Internal; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Size_Metrics */ + /* */ + /* <Description> */ + /* The size metrics structure gives the metrics of a size object. */ + /* */ + /* <Fields> */ + /* x_ppem :: The width of the scaled EM square in pixels, hence */ + /* the term `ppem' (pixels per EM). It is also */ + /* referred to as `nominal width'. */ + /* */ + /* y_ppem :: The height of the scaled EM square in pixels, */ + /* hence the term `ppem' (pixels per EM). It is also */ + /* referred to as `nominal height'. */ + /* */ + /* x_scale :: A 16.16 fractional scaling value used to convert */ + /* horizontal metrics from font units to 26.6 */ + /* fractional pixels. Only relevant for scalable */ + /* font formats. */ + /* */ + /* y_scale :: A 16.16 fractional scaling value used to convert */ + /* vertical metrics from font units to 26.6 */ + /* fractional pixels. Only relevant for scalable */ + /* font formats. */ + /* */ + /* ascender :: The ascender in 26.6 fractional pixels. See */ + /* @FT_FaceRec for the details. */ + /* */ + /* descender :: The descender in 26.6 fractional pixels. See */ + /* @FT_FaceRec for the details. */ + /* */ + /* height :: The height in 26.6 fractional pixels. See */ + /* @FT_FaceRec for the details. */ + /* */ + /* max_advance :: The maximal advance width in 26.6 fractional */ + /* pixels. See @FT_FaceRec for the details. */ + /* */ + /* <Note> */ + /* The scaling values, if relevant, are determined first during a */ + /* size changing operation. The remaining fields are then set by the */ + /* driver. For scalable formats, they are usually set to scaled */ + /* values of the corresponding fields in @FT_FaceRec. */ + /* */ + /* Note that due to glyph hinting, these values might not be exact */ + /* for certain fonts. Thus they must be treated as unreliable */ + /* with an error margin of at least one pixel! */ + /* */ + /* Indeed, the only way to get the exact metrics is to render _all_ */ + /* glyphs. As this would be a definite performance hit, it is up to */ + /* client applications to perform such computations. */ + /* */ + /* The FT_Size_Metrics structure is valid for bitmap fonts also. */ + /* */ + typedef struct FT_Size_Metrics_ + { + FT_UShort x_ppem; /* horizontal pixels per EM */ + FT_UShort y_ppem; /* vertical pixels per EM */ + + FT_Fixed x_scale; /* scaling values used to convert font */ + FT_Fixed y_scale; /* units to 26.6 fractional pixels */ + + FT_Pos ascender; /* ascender in 26.6 frac. pixels */ + FT_Pos descender; /* descender in 26.6 frac. pixels */ + FT_Pos height; /* text height in 26.6 frac. pixels */ + FT_Pos max_advance; /* max horizontal advance, in 26.6 pixels */ + + } FT_Size_Metrics; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_SizeRec */ + /* */ + /* <Description> */ + /* FreeType root size class structure. A size object models a face */ + /* object at a given size. */ + /* */ + /* <Fields> */ + /* face :: Handle to the parent face object. */ + /* */ + /* generic :: A typeless pointer, which is unused by the FreeType */ + /* library or any of its drivers. It can be used by */ + /* client applications to link their own data to each size */ + /* object. */ + /* */ + /* metrics :: Metrics for this size object. This field is read-only. */ + /* */ + typedef struct FT_SizeRec_ + { + FT_Face face; /* parent face object */ + FT_Generic generic; /* generic pointer for client uses */ + FT_Size_Metrics metrics; /* size metrics */ + FT_Size_Internal internal; + + } FT_SizeRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_SubGlyph */ + /* */ + /* <Description> */ + /* The subglyph structure is an internal object used to describe */ + /* subglyphs (for example, in the case of composites). */ + /* */ + /* <Note> */ + /* The subglyph implementation is not part of the high-level API, */ + /* hence the forward structure declaration. */ + /* */ + /* You can however retrieve subglyph information with */ + /* @FT_Get_SubGlyph_Info. */ + /* */ + typedef struct FT_SubGlyphRec_* FT_SubGlyph; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Slot_Internal */ + /* */ + /* <Description> */ + /* An opaque handle to an `FT_Slot_InternalRec' structure, used to */ + /* model private data of a given @FT_GlyphSlot object. */ + /* */ + typedef struct FT_Slot_InternalRec_* FT_Slot_Internal; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_GlyphSlotRec */ + /* */ + /* <Description> */ + /* FreeType root glyph slot class structure. A glyph slot is a */ + /* container where individual glyphs can be loaded, be they in */ + /* outline or bitmap format. */ + /* */ + /* <Fields> */ + /* library :: A handle to the FreeType library instance */ + /* this slot belongs to. */ + /* */ + /* face :: A handle to the parent face object. */ + /* */ + /* next :: In some cases (like some font tools), several */ + /* glyph slots per face object can be a good */ + /* thing. As this is rare, the glyph slots are */ + /* listed through a direct, single-linked list */ + /* using its `next' field. */ + /* */ + /* generic :: A typeless pointer which is unused by the */ + /* FreeType library or any of its drivers. It */ + /* can be used by client applications to link */ + /* their own data to each glyph slot object. */ + /* */ + /* metrics :: The metrics of the last loaded glyph in the */ + /* slot. The returned values depend on the last */ + /* load flags (see the @FT_Load_Glyph API */ + /* function) and can be expressed either in 26.6 */ + /* fractional pixels or font units. */ + /* */ + /* Note that even when the glyph image is */ + /* transformed, the metrics are not. */ + /* */ + /* linearHoriAdvance :: The advance width of the unhinted glyph. */ + /* Its value is expressed in 16.16 fractional */ + /* pixels, unless @FT_LOAD_LINEAR_DESIGN is set */ + /* when loading the glyph. This field can be */ + /* important to perform correct WYSIWYG layout. */ + /* Only relevant for outline glyphs. */ + /* */ + /* linearVertAdvance :: The advance height of the unhinted glyph. */ + /* Its value is expressed in 16.16 fractional */ + /* pixels, unless @FT_LOAD_LINEAR_DESIGN is set */ + /* when loading the glyph. This field can be */ + /* important to perform correct WYSIWYG layout. */ + /* Only relevant for outline glyphs. */ + /* */ + /* advance :: This shorthand is, depending on */ + /* @FT_LOAD_IGNORE_TRANSFORM, the transformed */ + /* advance width for the glyph (in 26.6 */ + /* fractional pixel format). As specified with */ + /* @FT_LOAD_VERTICAL_LAYOUT, it uses either the */ + /* `horiAdvance' or the `vertAdvance' value of */ + /* `metrics' field. */ + /* */ + /* format :: This field indicates the format of the image */ + /* contained in the glyph slot. Typically */ + /* @FT_GLYPH_FORMAT_BITMAP, */ + /* @FT_GLYPH_FORMAT_OUTLINE, or */ + /* @FT_GLYPH_FORMAT_COMPOSITE, but others are */ + /* possible. */ + /* */ + /* bitmap :: This field is used as a bitmap descriptor */ + /* when the slot format is */ + /* @FT_GLYPH_FORMAT_BITMAP. Note that the */ + /* address and content of the bitmap buffer can */ + /* change between calls of @FT_Load_Glyph and a */ + /* few other functions. */ + /* */ + /* bitmap_left :: This is the bitmap's left bearing expressed */ + /* in integer pixels. Of course, this is only */ + /* valid if the format is */ + /* @FT_GLYPH_FORMAT_BITMAP. */ + /* */ + /* bitmap_top :: This is the bitmap's top bearing expressed in */ + /* integer pixels. Remember that this is the */ + /* distance from the baseline to the top-most */ + /* glyph scanline, upwards y~coordinates being */ + /* *positive*. */ + /* */ + /* outline :: The outline descriptor for the current glyph */ + /* image if its format is */ + /* @FT_GLYPH_FORMAT_OUTLINE. Once a glyph is */ + /* loaded, `outline' can be transformed, */ + /* distorted, embolded, etc. However, it must */ + /* not be freed. */ + /* */ + /* num_subglyphs :: The number of subglyphs in a composite glyph. */ + /* This field is only valid for the composite */ + /* glyph format that should normally only be */ + /* loaded with the @FT_LOAD_NO_RECURSE flag. */ + /* For now this is internal to FreeType. */ + /* */ + /* subglyphs :: An array of subglyph descriptors for */ + /* composite glyphs. There are `num_subglyphs' */ + /* elements in there. Currently internal to */ + /* FreeType. */ + /* */ + /* control_data :: Certain font drivers can also return the */ + /* control data for a given glyph image (e.g. */ + /* TrueType bytecode, Type~1 charstrings, etc.). */ + /* This field is a pointer to such data. */ + /* */ + /* control_len :: This is the length in bytes of the control */ + /* data. */ + /* */ + /* other :: Really wicked formats can use this pointer to */ + /* present their own glyph image to client */ + /* applications. Note that the application */ + /* needs to know about the image format. */ + /* */ + /* lsb_delta :: The difference between hinted and unhinted */ + /* left side bearing while autohinting is */ + /* active. Zero otherwise. */ + /* */ + /* rsb_delta :: The difference between hinted and unhinted */ + /* right side bearing while autohinting is */ + /* active. Zero otherwise. */ + /* */ + /* <Note> */ + /* If @FT_Load_Glyph is called with default flags (see */ + /* @FT_LOAD_DEFAULT) the glyph image is loaded in the glyph slot in */ + /* its native format (e.g., an outline glyph for TrueType and Type~1 */ + /* formats). */ + /* */ + /* This image can later be converted into a bitmap by calling */ + /* @FT_Render_Glyph. This function finds the current renderer for */ + /* the native image's format, then invokes it. */ + /* */ + /* The renderer is in charge of transforming the native image through */ + /* the slot's face transformation fields, then converting it into a */ + /* bitmap that is returned in `slot->bitmap'. */ + /* */ + /* Note that `slot->bitmap_left' and `slot->bitmap_top' are also used */ + /* to specify the position of the bitmap relative to the current pen */ + /* position (e.g., coordinates (0,0) on the baseline). Of course, */ + /* `slot->format' is also changed to @FT_GLYPH_FORMAT_BITMAP. */ + /* */ + /* <Note> */ + /* Here a small pseudo code fragment which shows how to use */ + /* `lsb_delta' and `rsb_delta': */ + /* */ + /* { */ + /* FT_Pos origin_x = 0; */ + /* FT_Pos prev_rsb_delta = 0; */ + /* */ + /* */ + /* for all glyphs do */ + /* <compute kern between current and previous glyph and add it to */ + /* `origin_x'> */ + /* */ + /* <load glyph with `FT_Load_Glyph'> */ + /* */ + /* if ( prev_rsb_delta - face->glyph->lsb_delta >= 32 ) */ + /* origin_x -= 64; */ + /* else if ( prev_rsb_delta - face->glyph->lsb_delta < -32 ) */ + /* origin_x += 64; */ + /* */ + /* prev_rsb_delta = face->glyph->rsb_delta; */ + /* */ + /* <save glyph image, or render glyph, or ...> */ + /* */ + /* origin_x += face->glyph->advance.x; */ + /* endfor */ + /* } */ + /* */ + typedef struct FT_GlyphSlotRec_ + { + FT_Library library; + FT_Face face; + FT_GlyphSlot next; + FT_UInt reserved; /* retained for binary compatibility */ + FT_Generic generic; + + FT_Glyph_Metrics metrics; + FT_Fixed linearHoriAdvance; + FT_Fixed linearVertAdvance; + FT_Vector advance; + + FT_Glyph_Format format; + + FT_Bitmap bitmap; + FT_Int bitmap_left; + FT_Int bitmap_top; + + FT_Outline outline; + + FT_UInt num_subglyphs; + FT_SubGlyph subglyphs; + + void* control_data; + long control_len; + + FT_Pos lsb_delta; + FT_Pos rsb_delta; + + void* other; + + FT_Slot_Internal internal; + + } FT_GlyphSlotRec; + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* F U N C T I O N S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Init_FreeType */ + /* */ + /* <Description> */ + /* Initialize a new FreeType library object. The set of modules */ + /* that are registered by this function is determined at build time. */ + /* */ + /* <Output> */ + /* alibrary :: A handle to a new library object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* In case you want to provide your own memory allocating routines, */ + /* use @FT_New_Library instead, followed by a call to */ + /* @FT_Add_Default_Modules (or a series of calls to @FT_Add_Module). */ + /* */ + FT_EXPORT( FT_Error ) + FT_Init_FreeType( FT_Library *alibrary ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Done_FreeType */ + /* */ + /* <Description> */ + /* Destroy a given FreeType library object and all of its children, */ + /* including resources, drivers, faces, sizes, etc. */ + /* */ + /* <Input> */ + /* library :: A handle to the target library object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Done_FreeType( FT_Library library ); + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_OPEN_XXX */ + /* */ + /* <Description> */ + /* A list of bit-field constants used within the `flags' field of the */ + /* @FT_Open_Args structure. */ + /* */ + /* <Values> */ + /* FT_OPEN_MEMORY :: This is a memory-based stream. */ + /* */ + /* FT_OPEN_STREAM :: Copy the stream from the `stream' field. */ + /* */ + /* FT_OPEN_PATHNAME :: Create a new input stream from a C~path */ + /* name. */ + /* */ + /* FT_OPEN_DRIVER :: Use the `driver' field. */ + /* */ + /* FT_OPEN_PARAMS :: Use the `num_params' and `params' fields. */ + /* */ + /* ft_open_memory :: Deprecated; use @FT_OPEN_MEMORY instead. */ + /* */ + /* ft_open_stream :: Deprecated; use @FT_OPEN_STREAM instead. */ + /* */ + /* ft_open_pathname :: Deprecated; use @FT_OPEN_PATHNAME instead. */ + /* */ + /* ft_open_driver :: Deprecated; use @FT_OPEN_DRIVER instead. */ + /* */ + /* ft_open_params :: Deprecated; use @FT_OPEN_PARAMS instead. */ + /* */ + /* <Note> */ + /* The `FT_OPEN_MEMORY', `FT_OPEN_STREAM', and `FT_OPEN_PATHNAME' */ + /* flags are mutually exclusive. */ + /* */ +#define FT_OPEN_MEMORY 0x1 +#define FT_OPEN_STREAM 0x2 +#define FT_OPEN_PATHNAME 0x4 +#define FT_OPEN_DRIVER 0x8 +#define FT_OPEN_PARAMS 0x10 + +#define ft_open_memory FT_OPEN_MEMORY /* deprecated */ +#define ft_open_stream FT_OPEN_STREAM /* deprecated */ +#define ft_open_pathname FT_OPEN_PATHNAME /* deprecated */ +#define ft_open_driver FT_OPEN_DRIVER /* deprecated */ +#define ft_open_params FT_OPEN_PARAMS /* deprecated */ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Parameter */ + /* */ + /* <Description> */ + /* A simple structure used to pass more or less generic parameters to */ + /* @FT_Open_Face. */ + /* */ + /* <Fields> */ + /* tag :: A four-byte identification tag. */ + /* */ + /* data :: A pointer to the parameter data. */ + /* */ + /* <Note> */ + /* The ID and function of parameters are driver-specific. See the */ + /* various FT_PARAM_TAG_XXX flags for more information. */ + /* */ + typedef struct FT_Parameter_ + { + FT_ULong tag; + FT_Pointer data; + + } FT_Parameter; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Open_Args */ + /* */ + /* <Description> */ + /* A structure used to indicate how to open a new font file or */ + /* stream. A pointer to such a structure can be used as a parameter */ + /* for the functions @FT_Open_Face and @FT_Attach_Stream. */ + /* */ + /* <Fields> */ + /* flags :: A set of bit flags indicating how to use the */ + /* structure. */ + /* */ + /* memory_base :: The first byte of the file in memory. */ + /* */ + /* memory_size :: The size in bytes of the file in memory. */ + /* */ + /* pathname :: A pointer to an 8-bit file pathname. */ + /* */ + /* stream :: A handle to a source stream object. */ + /* */ + /* driver :: This field is exclusively used by @FT_Open_Face; */ + /* it simply specifies the font driver to use to open */ + /* the face. If set to~0, FreeType tries to load the */ + /* face with each one of the drivers in its list. */ + /* */ + /* num_params :: The number of extra parameters. */ + /* */ + /* params :: Extra parameters passed to the font driver when */ + /* opening a new face. */ + /* */ + /* <Note> */ + /* The stream type is determined by the contents of `flags' which */ + /* are tested in the following order by @FT_Open_Face: */ + /* */ + /* If the `FT_OPEN_MEMORY' bit is set, assume that this is a */ + /* memory file of `memory_size' bytes, located at `memory_address'. */ + /* The data are are not copied, and the client is responsible for */ + /* releasing and destroying them _after_ the corresponding call to */ + /* @FT_Done_Face. */ + /* */ + /* Otherwise, if the `FT_OPEN_STREAM' bit is set, assume that a */ + /* custom input stream `stream' is used. */ + /* */ + /* Otherwise, if the `FT_OPEN_PATHNAME' bit is set, assume that this */ + /* is a normal file and use `pathname' to open it. */ + /* */ + /* If the `FT_OPEN_DRIVER' bit is set, @FT_Open_Face only tries to */ + /* open the file with the driver whose handler is in `driver'. */ + /* */ + /* If the `FT_OPEN_PARAMS' bit is set, the parameters given by */ + /* `num_params' and `params' is used. They are ignored otherwise. */ + /* */ + /* Ideally, both the `pathname' and `params' fields should be tagged */ + /* as `const'; this is missing for API backwards compatibility. In */ + /* other words, applications should treat them as read-only. */ + /* */ + typedef struct FT_Open_Args_ + { + FT_UInt flags; + const FT_Byte* memory_base; + FT_Long memory_size; + FT_String* pathname; + FT_Stream stream; + FT_Module driver; + FT_Int num_params; + FT_Parameter* params; + + } FT_Open_Args; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Face */ + /* */ + /* <Description> */ + /* This function calls @FT_Open_Face to open a font by its pathname. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library resource. */ + /* */ + /* <Input> */ + /* pathname :: A path to the font file. */ + /* */ + /* face_index :: The index of the face within the font. The first */ + /* face has index~0. */ + /* */ + /* <Output> */ + /* aface :: A handle to a new face object. If `face_index' is */ + /* greater than or equal to zero, it must be non-NULL. */ + /* See @FT_Open_Face for more details. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_New_Face( FT_Library library, + const char* filepathname, + FT_Long face_index, + FT_Face *aface ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Memory_Face */ + /* */ + /* <Description> */ + /* This function calls @FT_Open_Face to open a font which has been */ + /* loaded into memory. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library resource. */ + /* */ + /* <Input> */ + /* file_base :: A pointer to the beginning of the font data. */ + /* */ + /* file_size :: The size of the memory chunk used by the font data. */ + /* */ + /* face_index :: The index of the face within the font. The first */ + /* face has index~0. */ + /* */ + /* <Output> */ + /* aface :: A handle to a new face object. If `face_index' is */ + /* greater than or equal to zero, it must be non-NULL. */ + /* See @FT_Open_Face for more details. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* You must not deallocate the memory before calling @FT_Done_Face. */ + /* */ + FT_EXPORT( FT_Error ) + FT_New_Memory_Face( FT_Library library, + const FT_Byte* file_base, + FT_Long file_size, + FT_Long face_index, + FT_Face *aface ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Open_Face */ + /* */ + /* <Description> */ + /* Create a face object from a given resource described by */ + /* @FT_Open_Args. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library resource. */ + /* */ + /* <Input> */ + /* args :: A pointer to an `FT_Open_Args' structure which must */ + /* be filled by the caller. */ + /* */ + /* face_index :: The index of the face within the font. The first */ + /* face has index~0. */ + /* */ + /* <Output> */ + /* aface :: A handle to a new face object. If `face_index' is */ + /* greater than or equal to zero, it must be non-NULL. */ + /* See note below. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* FT_Open_Face can be used to quickly check whether the font */ + /* format of a given font resource is supported by FreeType. If the */ + /* `face_index' field is negative, the function's return value is~0 */ + /* if the font format is recognized, or non-zero otherwise; */ + /* the function returns a more or less empty face handle in `*aface' */ + /* (if `aface' isn't NULL). The only useful field in this special */ + /* case is `face->num_faces' which gives the number of faces within */ + /* the font file. After examination, the returned @FT_Face structure */ + /* should be deallocated with a call to @FT_Done_Face. */ + /* */ + /* Each new face object created with this function also owns a */ + /* default @FT_Size object, accessible as `face->size'. */ + /* */ + /* See the discussion of reference counters in the description of */ + /* @FT_Reference_Face. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Open_Face( FT_Library library, + const FT_Open_Args* args, + FT_Long face_index, + FT_Face *aface ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Attach_File */ + /* */ + /* <Description> */ + /* This function calls @FT_Attach_Stream to attach a file. */ + /* */ + /* <InOut> */ + /* face :: The target face object. */ + /* */ + /* <Input> */ + /* filepathname :: The pathname. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Attach_File( FT_Face face, + const char* filepathname ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Attach_Stream */ + /* */ + /* <Description> */ + /* `Attach' data to a face object. Normally, this is used to read */ + /* additional information for the face object. For example, you can */ + /* attach an AFM file that comes with a Type~1 font to get the */ + /* kerning values and other metrics. */ + /* */ + /* <InOut> */ + /* face :: The target face object. */ + /* */ + /* <Input> */ + /* parameters :: A pointer to @FT_Open_Args which must be filled by */ + /* the caller. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* The meaning of the `attach' (i.e., what really happens when the */ + /* new file is read) is not fixed by FreeType itself. It really */ + /* depends on the font format (and thus the font driver). */ + /* */ + /* Client applications are expected to know what they are doing */ + /* when invoking this function. Most drivers simply do not implement */ + /* file attachments. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Attach_Stream( FT_Face face, + FT_Open_Args* parameters ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Reference_Face */ + /* */ + /* <Description> */ + /* A counter gets initialized to~1 at the time an @FT_Face structure */ + /* is created. This function increments the counter. @FT_Done_Face */ + /* then only destroys a face if the counter is~1, otherwise it simply */ + /* decrements the counter. */ + /* */ + /* This function helps in managing life-cycles of structures which */ + /* reference @FT_Face objects. */ + /* */ + /* <Input> */ + /* face :: A handle to a target face object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Since> */ + /* 2.4.2 */ + /* */ + FT_EXPORT( FT_Error ) + FT_Reference_Face( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Done_Face */ + /* */ + /* <Description> */ + /* Discard a given face object, as well as all of its child slots and */ + /* sizes. */ + /* */ + /* <Input> */ + /* face :: A handle to a target face object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* See the discussion of reference counters in the description of */ + /* @FT_Reference_Face. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Done_Face( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Select_Size */ + /* */ + /* <Description> */ + /* Select a bitmap strike. */ + /* */ + /* <InOut> */ + /* face :: A handle to a target face object. */ + /* */ + /* <Input> */ + /* strike_index :: The index of the bitmap strike in the */ + /* `available_sizes' field of @FT_FaceRec structure. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Select_Size( FT_Face face, + FT_Int strike_index ); + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Size_Request_Type */ + /* */ + /* <Description> */ + /* An enumeration type that lists the supported size request types. */ + /* */ + /* <Values> */ + /* FT_SIZE_REQUEST_TYPE_NOMINAL :: */ + /* The nominal size. The `units_per_EM' field of @FT_FaceRec is */ + /* used to determine both scaling values. */ + /* */ + /* FT_SIZE_REQUEST_TYPE_REAL_DIM :: */ + /* The real dimension. The sum of the the `Ascender' and (minus */ + /* of) the `Descender' fields of @FT_FaceRec are used to determine */ + /* both scaling values. */ + /* */ + /* FT_SIZE_REQUEST_TYPE_BBOX :: */ + /* The font bounding box. The width and height of the `bbox' field */ + /* of @FT_FaceRec are used to determine the horizontal and vertical */ + /* scaling value, respectively. */ + /* */ + /* FT_SIZE_REQUEST_TYPE_CELL :: */ + /* The `max_advance_width' field of @FT_FaceRec is used to */ + /* determine the horizontal scaling value; the vertical scaling */ + /* value is determined the same way as */ + /* @FT_SIZE_REQUEST_TYPE_REAL_DIM does. Finally, both scaling */ + /* values are set to the smaller one. This type is useful if you */ + /* want to specify the font size for, say, a window of a given */ + /* dimension and 80x24 cells. */ + /* */ + /* FT_SIZE_REQUEST_TYPE_SCALES :: */ + /* Specify the scaling values directly. */ + /* */ + /* <Note> */ + /* The above descriptions only apply to scalable formats. For bitmap */ + /* formats, the behaviour is up to the driver. */ + /* */ + /* See the note section of @FT_Size_Metrics if you wonder how size */ + /* requesting relates to scaling values. */ + /* */ + typedef enum FT_Size_Request_Type_ + { + FT_SIZE_REQUEST_TYPE_NOMINAL, + FT_SIZE_REQUEST_TYPE_REAL_DIM, + FT_SIZE_REQUEST_TYPE_BBOX, + FT_SIZE_REQUEST_TYPE_CELL, + FT_SIZE_REQUEST_TYPE_SCALES, + + FT_SIZE_REQUEST_TYPE_MAX + + } FT_Size_Request_Type; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Size_RequestRec */ + /* */ + /* <Description> */ + /* A structure used to model a size request. */ + /* */ + /* <Fields> */ + /* type :: See @FT_Size_Request_Type. */ + /* */ + /* width :: The desired width. */ + /* */ + /* height :: The desired height. */ + /* */ + /* horiResolution :: The horizontal resolution. If set to zero, */ + /* `width' is treated as a 26.6 fractional pixel */ + /* value. */ + /* */ + /* vertResolution :: The vertical resolution. If set to zero, */ + /* `height' is treated as a 26.6 fractional pixel */ + /* value. */ + /* */ + /* <Note> */ + /* If `width' is zero, then the horizontal scaling value is set equal */ + /* to the vertical scaling value, and vice versa. */ + /* */ + typedef struct FT_Size_RequestRec_ + { + FT_Size_Request_Type type; + FT_Long width; + FT_Long height; + FT_UInt horiResolution; + FT_UInt vertResolution; + + } FT_Size_RequestRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Size_Request */ + /* */ + /* <Description> */ + /* A handle to a size request structure. */ + /* */ + typedef struct FT_Size_RequestRec_ *FT_Size_Request; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Request_Size */ + /* */ + /* <Description> */ + /* Resize the scale of the active @FT_Size object in a face. */ + /* */ + /* <InOut> */ + /* face :: A handle to a target face object. */ + /* */ + /* <Input> */ + /* req :: A pointer to a @FT_Size_RequestRec. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* Although drivers may select the bitmap strike matching the */ + /* request, you should not rely on this if you intend to select a */ + /* particular bitmap strike. Use @FT_Select_Size instead in that */ + /* case. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Request_Size( FT_Face face, + FT_Size_Request req ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Char_Size */ + /* */ + /* <Description> */ + /* This function calls @FT_Request_Size to request the nominal size */ + /* (in points). */ + /* */ + /* <InOut> */ + /* face :: A handle to a target face object. */ + /* */ + /* <Input> */ + /* char_width :: The nominal width, in 26.6 fractional points. */ + /* */ + /* char_height :: The nominal height, in 26.6 fractional points. */ + /* */ + /* horz_resolution :: The horizontal resolution in dpi. */ + /* */ + /* vert_resolution :: The vertical resolution in dpi. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* If either the character width or height is zero, it is set equal */ + /* to the other value. */ + /* */ + /* If either the horizontal or vertical resolution is zero, it is set */ + /* equal to the other value. */ + /* */ + /* A character width or height smaller than 1pt is set to 1pt; if */ + /* both resolution values are zero, they are set to 72dpi. */ + /* */ + /* Don't use this function if you are using the FreeType cache API. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_Char_Size( FT_Face face, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Pixel_Sizes */ + /* */ + /* <Description> */ + /* This function calls @FT_Request_Size to request the nominal size */ + /* (in pixels). */ + /* */ + /* <InOut> */ + /* face :: A handle to the target face object. */ + /* */ + /* <Input> */ + /* pixel_width :: The nominal width, in pixels. */ + /* */ + /* pixel_height :: The nominal height, in pixels. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_Pixel_Sizes( FT_Face face, + FT_UInt pixel_width, + FT_UInt pixel_height ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Load_Glyph */ + /* */ + /* <Description> */ + /* A function used to load a single glyph into the glyph slot of a */ + /* face object. */ + /* */ + /* <InOut> */ + /* face :: A handle to the target face object where the glyph */ + /* is loaded. */ + /* */ + /* <Input> */ + /* glyph_index :: The index of the glyph in the font file. For */ + /* CID-keyed fonts (either in PS or in CFF format) */ + /* this argument specifies the CID value. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* @FT_LOAD_XXX constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* The loaded glyph may be transformed. See @FT_Set_Transform for */ + /* the details. */ + /* */ + /* For subsetted CID-keyed fonts, `FT_Err_Invalid_Argument' is */ + /* returned for invalid CID values (this is, for CID values which */ + /* don't have a corresponding glyph in the font). See the discussion */ + /* of the @FT_FACE_FLAG_CID_KEYED flag for more details. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Load_Glyph( FT_Face face, + FT_UInt glyph_index, + FT_Int32 load_flags ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Load_Char */ + /* */ + /* <Description> */ + /* A function used to load a single glyph into the glyph slot of a */ + /* face object, according to its character code. */ + /* */ + /* <InOut> */ + /* face :: A handle to a target face object where the glyph */ + /* is loaded. */ + /* */ + /* <Input> */ + /* char_code :: The glyph's character code, according to the */ + /* current charmap used in the face. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* @FT_LOAD_XXX constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* This function simply calls @FT_Get_Char_Index and @FT_Load_Glyph. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Load_Char( FT_Face face, + FT_ULong char_code, + FT_Int32 load_flags ); + + + /************************************************************************* + * + * @enum: + * FT_LOAD_XXX + * + * @description: + * A list of bit-field constants used with @FT_Load_Glyph to indicate + * what kind of operations to perform during glyph loading. + * + * @values: + * FT_LOAD_DEFAULT :: + * Corresponding to~0, this value is used as the default glyph load + * operation. In this case, the following happens: + * + * 1. FreeType looks for a bitmap for the glyph corresponding to the + * face's current size. If one is found, the function returns. + * The bitmap data can be accessed from the glyph slot (see note + * below). + * + * 2. If no embedded bitmap is searched or found, FreeType looks for a + * scalable outline. If one is found, it is loaded from the font + * file, scaled to device pixels, then `hinted' to the pixel grid + * in order to optimize it. The outline data can be accessed from + * the glyph slot (see note below). + * + * Note that by default, the glyph loader doesn't render outlines into + * bitmaps. The following flags are used to modify this default + * behaviour to more specific and useful cases. + * + * FT_LOAD_NO_SCALE :: + * Don't scale the outline glyph loaded, but keep it in font units. + * + * This flag implies @FT_LOAD_NO_HINTING and @FT_LOAD_NO_BITMAP, and + * unsets @FT_LOAD_RENDER. + * + * FT_LOAD_NO_HINTING :: + * Disable hinting. This generally generates `blurrier' bitmap glyph + * when the glyph is rendered in any of the anti-aliased modes. See + * also the note below. + * + * This flag is implied by @FT_LOAD_NO_SCALE. + * + * FT_LOAD_RENDER :: + * Call @FT_Render_Glyph after the glyph is loaded. By default, the + * glyph is rendered in @FT_RENDER_MODE_NORMAL mode. This can be + * overridden by @FT_LOAD_TARGET_XXX or @FT_LOAD_MONOCHROME. + * + * This flag is unset by @FT_LOAD_NO_SCALE. + * + * FT_LOAD_NO_BITMAP :: + * Ignore bitmap strikes when loading. Bitmap-only fonts ignore this + * flag. + * + * @FT_LOAD_NO_SCALE always sets this flag. + * + * FT_LOAD_VERTICAL_LAYOUT :: + * Load the glyph for vertical text layout. _Don't_ use it as it is + * problematic currently. + * + * FT_LOAD_FORCE_AUTOHINT :: + * Indicates that the auto-hinter is preferred over the font's native + * hinter. See also the note below. + * + * FT_LOAD_CROP_BITMAP :: + * Indicates that the font driver should crop the loaded bitmap glyph + * (i.e., remove all space around its black bits). Not all drivers + * implement this. + * + * FT_LOAD_PEDANTIC :: + * Indicates that the font driver should perform pedantic verifications + * during glyph loading. This is mostly used to detect broken glyphs + * in fonts. By default, FreeType tries to handle broken fonts also. + * + * FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH :: + * Indicates that the font driver should ignore the global advance + * width defined in the font. By default, that value is used as the + * advance width for all glyphs when the face has + * @FT_FACE_FLAG_FIXED_WIDTH set. + * + * This flag exists for historical reasons (to support buggy CJK + * fonts). + * + * FT_LOAD_NO_RECURSE :: + * This flag is only used internally. It merely indicates that the + * font driver should not load composite glyphs recursively. Instead, + * it should set the `num_subglyph' and `subglyphs' values of the + * glyph slot accordingly, and set `glyph->format' to + * @FT_GLYPH_FORMAT_COMPOSITE. + * + * The description of sub-glyphs is not available to client + * applications for now. + * + * This flag implies @FT_LOAD_NO_SCALE and @FT_LOAD_IGNORE_TRANSFORM. + * + * FT_LOAD_IGNORE_TRANSFORM :: + * Indicates that the transform matrix set by @FT_Set_Transform should + * be ignored. + * + * FT_LOAD_MONOCHROME :: + * This flag is used with @FT_LOAD_RENDER to indicate that you want to + * render an outline glyph to a 1-bit monochrome bitmap glyph, with + * 8~pixels packed into each byte of the bitmap data. + * + * Note that this has no effect on the hinting algorithm used. You + * should rather use @FT_LOAD_TARGET_MONO so that the + * monochrome-optimized hinting algorithm is used. + * + * FT_LOAD_LINEAR_DESIGN :: + * Indicates that the `linearHoriAdvance' and `linearVertAdvance' + * fields of @FT_GlyphSlotRec should be kept in font units. See + * @FT_GlyphSlotRec for details. + * + * FT_LOAD_NO_AUTOHINT :: + * Disable auto-hinter. See also the note below. + * + * @note: + * By default, hinting is enabled and the font's native hinter (see + * @FT_FACE_FLAG_HINTER) is preferred over the auto-hinter. You can + * disable hinting by setting @FT_LOAD_NO_HINTING or change the + * precedence by setting @FT_LOAD_FORCE_AUTOHINT. You can also set + * @FT_LOAD_NO_AUTOHINT in case you don't want the auto-hinter to be + * used at all. + * + * See the description of @FT_FACE_FLAG_TRICKY for a special exception + * (affecting only a handful of Asian fonts). + * + * Besides deciding which hinter to use, you can also decide which + * hinting algorithm to use. See @FT_LOAD_TARGET_XXX for details. + * + */ +#define FT_LOAD_DEFAULT 0x0 +#define FT_LOAD_NO_SCALE 0x1 +#define FT_LOAD_NO_HINTING 0x2 +#define FT_LOAD_RENDER 0x4 +#define FT_LOAD_NO_BITMAP 0x8 +#define FT_LOAD_VERTICAL_LAYOUT 0x10 +#define FT_LOAD_FORCE_AUTOHINT 0x20 +#define FT_LOAD_CROP_BITMAP 0x40 +#define FT_LOAD_PEDANTIC 0x80 +#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH 0x200 +#define FT_LOAD_NO_RECURSE 0x400 +#define FT_LOAD_IGNORE_TRANSFORM 0x800 +#define FT_LOAD_MONOCHROME 0x1000 +#define FT_LOAD_LINEAR_DESIGN 0x2000 +#define FT_LOAD_NO_AUTOHINT 0x8000U + + /* */ + + /* used internally only by certain font drivers! */ +#define FT_LOAD_ADVANCE_ONLY 0x100 +#define FT_LOAD_SBITS_ONLY 0x4000 + + + /************************************************************************** + * + * @enum: + * FT_LOAD_TARGET_XXX + * + * @description: + * A list of values that are used to select a specific hinting algorithm + * to use by the hinter. You should OR one of these values to your + * `load_flags' when calling @FT_Load_Glyph. + * + * Note that font's native hinters may ignore the hinting algorithm you + * have specified (e.g., the TrueType bytecode interpreter). You can set + * @FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used. + * + * Also note that @FT_LOAD_TARGET_LIGHT is an exception, in that it + * always implies @FT_LOAD_FORCE_AUTOHINT. + * + * @values: + * FT_LOAD_TARGET_NORMAL :: + * This corresponds to the default hinting algorithm, optimized for + * standard gray-level rendering. For monochrome output, use + * @FT_LOAD_TARGET_MONO instead. + * + * FT_LOAD_TARGET_LIGHT :: + * A lighter hinting algorithm for non-monochrome modes. Many + * generated glyphs are more fuzzy but better resemble its original + * shape. A bit like rendering on Mac OS~X. + * + * As a special exception, this target implies @FT_LOAD_FORCE_AUTOHINT. + * + * FT_LOAD_TARGET_MONO :: + * Strong hinting algorithm that should only be used for monochrome + * output. The result is probably unpleasant if the glyph is rendered + * in non-monochrome modes. + * + * FT_LOAD_TARGET_LCD :: + * A variant of @FT_LOAD_TARGET_NORMAL optimized for horizontally + * decimated LCD displays. + * + * FT_LOAD_TARGET_LCD_V :: + * A variant of @FT_LOAD_TARGET_NORMAL optimized for vertically + * decimated LCD displays. + * + * @note: + * You should use only _one_ of the FT_LOAD_TARGET_XXX values in your + * `load_flags'. They can't be ORed. + * + * If @FT_LOAD_RENDER is also set, the glyph is rendered in the + * corresponding mode (i.e., the mode which matches the used algorithm + * best) unless @FT_LOAD_MONOCHROME is set. + * + * You can use a hinting algorithm that doesn't correspond to the same + * rendering mode. As an example, it is possible to use the `light' + * hinting algorithm and have the results rendered in horizontal LCD + * pixel mode, with code like + * + * { + * FT_Load_Glyph( face, glyph_index, + * load_flags | FT_LOAD_TARGET_LIGHT ); + * + * FT_Render_Glyph( face->glyph, FT_RENDER_MODE_LCD ); + * } + * + */ +#define FT_LOAD_TARGET_( x ) ( (FT_Int32)( (x) & 15 ) << 16 ) + +#define FT_LOAD_TARGET_NORMAL FT_LOAD_TARGET_( FT_RENDER_MODE_NORMAL ) +#define FT_LOAD_TARGET_LIGHT FT_LOAD_TARGET_( FT_RENDER_MODE_LIGHT ) +#define FT_LOAD_TARGET_MONO FT_LOAD_TARGET_( FT_RENDER_MODE_MONO ) +#define FT_LOAD_TARGET_LCD FT_LOAD_TARGET_( FT_RENDER_MODE_LCD ) +#define FT_LOAD_TARGET_LCD_V FT_LOAD_TARGET_( FT_RENDER_MODE_LCD_V ) + + + /************************************************************************** + * + * @macro: + * FT_LOAD_TARGET_MODE + * + * @description: + * Return the @FT_Render_Mode corresponding to a given + * @FT_LOAD_TARGET_XXX value. + * + */ +#define FT_LOAD_TARGET_MODE( x ) ( (FT_Render_Mode)( ( (x) >> 16 ) & 15 ) ) + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Transform */ + /* */ + /* <Description> */ + /* A function used to set the transformation that is applied to glyph */ + /* images when they are loaded into a glyph slot through */ + /* @FT_Load_Glyph. */ + /* */ + /* <InOut> */ + /* face :: A handle to the source face object. */ + /* */ + /* <Input> */ + /* matrix :: A pointer to the transformation's 2x2 matrix. Use~0 for */ + /* the identity matrix. */ + /* delta :: A pointer to the translation vector. Use~0 for the null */ + /* vector. */ + /* */ + /* <Note> */ + /* The transformation is only applied to scalable image formats after */ + /* the glyph has been loaded. It means that hinting is unaltered by */ + /* the transformation and is performed on the character size given in */ + /* the last call to @FT_Set_Char_Size or @FT_Set_Pixel_Sizes. */ + /* */ + /* Note that this also transforms the `face.glyph.advance' field, but */ + /* *not* the values in `face.glyph.metrics'. */ + /* */ + FT_EXPORT( void ) + FT_Set_Transform( FT_Face face, + FT_Matrix* matrix, + FT_Vector* delta ); + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Render_Mode */ + /* */ + /* <Description> */ + /* An enumeration type that lists the render modes supported by */ + /* FreeType~2. Each mode corresponds to a specific type of scanline */ + /* conversion performed on the outline. */ + /* */ + /* For bitmap fonts and embedded bitmaps the `bitmap->pixel_mode' */ + /* field in the @FT_GlyphSlotRec structure gives the format of the */ + /* returned bitmap. */ + /* */ + /* All modes except @FT_RENDER_MODE_MONO use 256 levels of opacity. */ + /* */ + /* <Values> */ + /* FT_RENDER_MODE_NORMAL :: */ + /* This is the default render mode; it corresponds to 8-bit */ + /* anti-aliased bitmaps. */ + /* */ + /* FT_RENDER_MODE_LIGHT :: */ + /* This is equivalent to @FT_RENDER_MODE_NORMAL. It is only */ + /* defined as a separate value because render modes are also used */ + /* indirectly to define hinting algorithm selectors. See */ + /* @FT_LOAD_TARGET_XXX for details. */ + /* */ + /* FT_RENDER_MODE_MONO :: */ + /* This mode corresponds to 1-bit bitmaps (with 2~levels of */ + /* opacity). */ + /* */ + /* FT_RENDER_MODE_LCD :: */ + /* This mode corresponds to horizontal RGB and BGR sub-pixel */ + /* displays like LCD screens. It produces 8-bit bitmaps that are */ + /* 3~times the width of the original glyph outline in pixels, and */ + /* which use the @FT_PIXEL_MODE_LCD mode. */ + /* */ + /* FT_RENDER_MODE_LCD_V :: */ + /* This mode corresponds to vertical RGB and BGR sub-pixel displays */ + /* (like PDA screens, rotated LCD displays, etc.). It produces */ + /* 8-bit bitmaps that are 3~times the height of the original */ + /* glyph outline in pixels and use the @FT_PIXEL_MODE_LCD_V mode. */ + /* */ + /* <Note> */ + /* The LCD-optimized glyph bitmaps produced by FT_Render_Glyph can be */ + /* filtered to reduce color-fringes by using @FT_Library_SetLcdFilter */ + /* (not active in the default builds). It is up to the caller to */ + /* either call @FT_Library_SetLcdFilter (if available) or do the */ + /* filtering itself. */ + /* */ + /* The selected render mode only affects vector glyphs of a font. */ + /* Embedded bitmaps often have a different pixel mode like */ + /* @FT_PIXEL_MODE_MONO. You can use @FT_Bitmap_Convert to transform */ + /* them into 8-bit pixmaps. */ + /* */ + typedef enum FT_Render_Mode_ + { + FT_RENDER_MODE_NORMAL = 0, + FT_RENDER_MODE_LIGHT, + FT_RENDER_MODE_MONO, + FT_RENDER_MODE_LCD, + FT_RENDER_MODE_LCD_V, + + FT_RENDER_MODE_MAX + + } FT_Render_Mode; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* ft_render_mode_xxx */ + /* */ + /* <Description> */ + /* These constants are deprecated. Use the corresponding */ + /* @FT_Render_Mode values instead. */ + /* */ + /* <Values> */ + /* ft_render_mode_normal :: see @FT_RENDER_MODE_NORMAL */ + /* ft_render_mode_mono :: see @FT_RENDER_MODE_MONO */ + /* */ +#define ft_render_mode_normal FT_RENDER_MODE_NORMAL +#define ft_render_mode_mono FT_RENDER_MODE_MONO + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Render_Glyph */ + /* */ + /* <Description> */ + /* Convert a given glyph image to a bitmap. It does so by inspecting */ + /* the glyph image format, finding the relevant renderer, and */ + /* invoking it. */ + /* */ + /* <InOut> */ + /* slot :: A handle to the glyph slot containing the image to */ + /* convert. */ + /* */ + /* <Input> */ + /* render_mode :: This is the render mode used to render the glyph */ + /* image into a bitmap. See @FT_Render_Mode for a */ + /* list of possible values. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Render_Glyph( FT_GlyphSlot slot, + FT_Render_Mode render_mode ); + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Kerning_Mode */ + /* */ + /* <Description> */ + /* An enumeration used to specify which kerning values to return in */ + /* @FT_Get_Kerning. */ + /* */ + /* <Values> */ + /* FT_KERNING_DEFAULT :: Return scaled and grid-fitted kerning */ + /* distances (value is~0). */ + /* */ + /* FT_KERNING_UNFITTED :: Return scaled but un-grid-fitted kerning */ + /* distances. */ + /* */ + /* FT_KERNING_UNSCALED :: Return the kerning vector in original font */ + /* units. */ + /* */ + typedef enum FT_Kerning_Mode_ + { + FT_KERNING_DEFAULT = 0, + FT_KERNING_UNFITTED, + FT_KERNING_UNSCALED + + } FT_Kerning_Mode; + + + /*************************************************************************/ + /* */ + /* <Const> */ + /* ft_kerning_default */ + /* */ + /* <Description> */ + /* This constant is deprecated. Please use @FT_KERNING_DEFAULT */ + /* instead. */ + /* */ +#define ft_kerning_default FT_KERNING_DEFAULT + + + /*************************************************************************/ + /* */ + /* <Const> */ + /* ft_kerning_unfitted */ + /* */ + /* <Description> */ + /* This constant is deprecated. Please use @FT_KERNING_UNFITTED */ + /* instead. */ + /* */ +#define ft_kerning_unfitted FT_KERNING_UNFITTED + + + /*************************************************************************/ + /* */ + /* <Const> */ + /* ft_kerning_unscaled */ + /* */ + /* <Description> */ + /* This constant is deprecated. Please use @FT_KERNING_UNSCALED */ + /* instead. */ + /* */ +#define ft_kerning_unscaled FT_KERNING_UNSCALED + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Kerning */ + /* */ + /* <Description> */ + /* Return the kerning vector between two glyphs of a same face. */ + /* */ + /* <Input> */ + /* face :: A handle to a source face object. */ + /* */ + /* left_glyph :: The index of the left glyph in the kern pair. */ + /* */ + /* right_glyph :: The index of the right glyph in the kern pair. */ + /* */ + /* kern_mode :: See @FT_Kerning_Mode for more information. */ + /* Determines the scale and dimension of the returned */ + /* kerning vector. */ + /* */ + /* <Output> */ + /* akerning :: The kerning vector. This is either in font units */ + /* or in pixels (26.6 format) for scalable formats, */ + /* and in pixels for fixed-sizes formats. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* Only horizontal layouts (left-to-right & right-to-left) are */ + /* supported by this method. Other layouts, or more sophisticated */ + /* kernings, are out of the scope of this API function -- they can be */ + /* implemented through format-specific interfaces. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Kerning( FT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_UInt kern_mode, + FT_Vector *akerning ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Track_Kerning */ + /* */ + /* <Description> */ + /* Return the track kerning for a given face object at a given size. */ + /* */ + /* <Input> */ + /* face :: A handle to a source face object. */ + /* */ + /* point_size :: The point size in 16.16 fractional points. */ + /* */ + /* degree :: The degree of tightness. */ + /* */ + /* <Output> */ + /* akerning :: The kerning in 16.16 fractional points. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Track_Kerning( FT_Face face, + FT_Fixed point_size, + FT_Int degree, + FT_Fixed* akerning ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Glyph_Name */ + /* */ + /* <Description> */ + /* Retrieve the ASCII name of a given glyph in a face. This only */ + /* works for those faces where @FT_HAS_GLYPH_NAMES(face) returns~1. */ + /* */ + /* <Input> */ + /* face :: A handle to a source face object. */ + /* */ + /* glyph_index :: The glyph index. */ + /* */ + /* buffer_max :: The maximal number of bytes available in the */ + /* buffer. */ + /* */ + /* <Output> */ + /* buffer :: A pointer to a target buffer where the name is */ + /* copied to. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* An error is returned if the face doesn't provide glyph names or if */ + /* the glyph index is invalid. In all cases of failure, the first */ + /* byte of `buffer' is set to~0 to indicate an empty name. */ + /* */ + /* The glyph name is truncated to fit within the buffer if it is too */ + /* long. The returned string is always zero-terminated. */ + /* */ + /* This function is not compiled within the library if the config */ + /* macro `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is defined in */ + /* `include/freetype/config/ftoptions.h'. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Glyph_Name( FT_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Postscript_Name */ + /* */ + /* <Description> */ + /* Retrieve the ASCII PostScript name of a given face, if available. */ + /* This only works with PostScript and TrueType fonts. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* <Return> */ + /* A pointer to the face's PostScript name. NULL if unavailable. */ + /* */ + /* <Note> */ + /* The returned pointer is owned by the face and is destroyed with */ + /* it. */ + /* */ + FT_EXPORT( const char* ) + FT_Get_Postscript_Name( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Select_Charmap */ + /* */ + /* <Description> */ + /* Select a given charmap by its encoding tag (as listed in */ + /* `freetype.h'). */ + /* */ + /* <InOut> */ + /* face :: A handle to the source face object. */ + /* */ + /* <Input> */ + /* encoding :: A handle to the selected encoding. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* This function returns an error if no charmap in the face */ + /* corresponds to the encoding queried here. */ + /* */ + /* Because many fonts contain more than a single cmap for Unicode */ + /* encoding, this function has some special code to select the one */ + /* which covers Unicode best (`best' in the sense that a UCS-4 cmap */ + /* is preferred to a UCS-2 cmap). It is thus preferable to */ + /* @FT_Set_Charmap in this case. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Select_Charmap( FT_Face face, + FT_Encoding encoding ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Charmap */ + /* */ + /* <Description> */ + /* Select a given charmap for character code to glyph index mapping. */ + /* */ + /* <InOut> */ + /* face :: A handle to the source face object. */ + /* */ + /* <Input> */ + /* charmap :: A handle to the selected charmap. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* This function returns an error if the charmap is not part of */ + /* the face (i.e., if it is not listed in the `face->charmaps' */ + /* table). */ + /* */ + /* It also fails if a type~14 charmap is selected. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_Charmap( FT_Face face, + FT_CharMap charmap ); + + + /************************************************************************* + * + * @function: + * FT_Get_Charmap_Index + * + * @description: + * Retrieve index of a given charmap. + * + * @input: + * charmap :: + * A handle to a charmap. + * + * @return: + * The index into the array of character maps within the face to which + * `charmap' belongs. If an error occurs, -1 is returned. + * + */ + FT_EXPORT( FT_Int ) + FT_Get_Charmap_Index( FT_CharMap charmap ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Char_Index */ + /* */ + /* <Description> */ + /* Return the glyph index of a given character code. This function */ + /* uses a charmap object to do the mapping. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* charcode :: The character code. */ + /* */ + /* <Return> */ + /* The glyph index. 0~means `undefined character code'. */ + /* */ + /* <Note> */ + /* If you use FreeType to manipulate the contents of font files */ + /* directly, be aware that the glyph index returned by this function */ + /* doesn't always correspond to the internal indices used within */ + /* the file. This is done to ensure that value~0 always corresponds */ + /* to the `missing glyph'. */ + /* */ + FT_EXPORT( FT_UInt ) + FT_Get_Char_Index( FT_Face face, + FT_ULong charcode ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_First_Char */ + /* */ + /* <Description> */ + /* This function is used to return the first character code in the */ + /* current charmap of a given face. It also returns the */ + /* corresponding glyph index. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* <Output> */ + /* agindex :: Glyph index of first character code. 0~if charmap is */ + /* empty. */ + /* */ + /* <Return> */ + /* The charmap's first character code. */ + /* */ + /* <Note> */ + /* You should use this function with @FT_Get_Next_Char to be able to */ + /* parse all character codes available in a given charmap. The code */ + /* should look like this: */ + /* */ + /* { */ + /* FT_ULong charcode; */ + /* FT_UInt gindex; */ + /* */ + /* */ + /* charcode = FT_Get_First_Char( face, &gindex ); */ + /* while ( gindex != 0 ) */ + /* { */ + /* ... do something with (charcode,gindex) pair ... */ + /* */ + /* charcode = FT_Get_Next_Char( face, charcode, &gindex ); */ + /* } */ + /* } */ + /* */ + /* Note that `*agindex' is set to~0 if the charmap is empty. The */ + /* result itself can be~0 in two cases: if the charmap is empty or */ + /* if the value~0 is the first valid character code. */ + /* */ + FT_EXPORT( FT_ULong ) + FT_Get_First_Char( FT_Face face, + FT_UInt *agindex ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Next_Char */ + /* */ + /* <Description> */ + /* This function is used to return the next character code in the */ + /* current charmap of a given face following the value `char_code', */ + /* as well as the corresponding glyph index. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* char_code :: The starting character code. */ + /* */ + /* <Output> */ + /* agindex :: Glyph index of next character code. 0~if charmap */ + /* is empty. */ + /* */ + /* <Return> */ + /* The charmap's next character code. */ + /* */ + /* <Note> */ + /* You should use this function with @FT_Get_First_Char to walk */ + /* over all character codes available in a given charmap. See the */ + /* note for this function for a simple code example. */ + /* */ + /* Note that `*agindex' is set to~0 when there are no more codes in */ + /* the charmap. */ + /* */ + FT_EXPORT( FT_ULong ) + FT_Get_Next_Char( FT_Face face, + FT_ULong char_code, + FT_UInt *agindex ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Name_Index */ + /* */ + /* <Description> */ + /* Return the glyph index of a given glyph name. This function uses */ + /* driver specific objects to do the translation. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* glyph_name :: The glyph name. */ + /* */ + /* <Return> */ + /* The glyph index. 0~means `undefined character code'. */ + /* */ + FT_EXPORT( FT_UInt ) + FT_Get_Name_Index( FT_Face face, + FT_String* glyph_name ); + + + /************************************************************************* + * + * @macro: + * FT_SUBGLYPH_FLAG_XXX + * + * @description: + * A list of constants used to describe subglyphs. Please refer to the + * TrueType specification for the meaning of the various flags. + * + * @values: + * FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS :: + * FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES :: + * FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID :: + * FT_SUBGLYPH_FLAG_SCALE :: + * FT_SUBGLYPH_FLAG_XY_SCALE :: + * FT_SUBGLYPH_FLAG_2X2 :: + * FT_SUBGLYPH_FLAG_USE_MY_METRICS :: + * + */ +#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1 +#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2 +#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4 +#define FT_SUBGLYPH_FLAG_SCALE 8 +#define FT_SUBGLYPH_FLAG_XY_SCALE 0x40 +#define FT_SUBGLYPH_FLAG_2X2 0x80 +#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200 + + + /************************************************************************* + * + * @func: + * FT_Get_SubGlyph_Info + * + * @description: + * Retrieve a description of a given subglyph. Only use it if + * `glyph->format' is @FT_GLYPH_FORMAT_COMPOSITE; an error is + * returned otherwise. + * + * @input: + * glyph :: + * The source glyph slot. + * + * sub_index :: + * The index of the subglyph. Must be less than + * `glyph->num_subglyphs'. + * + * @output: + * p_index :: + * The glyph index of the subglyph. + * + * p_flags :: + * The subglyph flags, see @FT_SUBGLYPH_FLAG_XXX. + * + * p_arg1 :: + * The subglyph's first argument (if any). + * + * p_arg2 :: + * The subglyph's second argument (if any). + * + * p_transform :: + * The subglyph transformation (if any). + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * The values of `*p_arg1', `*p_arg2', and `*p_transform' must be + * interpreted depending on the flags returned in `*p_flags'. See the + * TrueType specification for details. + * + */ + FT_EXPORT( FT_Error ) + FT_Get_SubGlyph_Info( FT_GlyphSlot glyph, + FT_UInt sub_index, + FT_Int *p_index, + FT_UInt *p_flags, + FT_Int *p_arg1, + FT_Int *p_arg2, + FT_Matrix *p_transform ); + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_FSTYPE_XXX */ + /* */ + /* <Description> */ + /* A list of bit flags used in the `fsType' field of the OS/2 table */ + /* in a TrueType or OpenType font and the `FSType' entry in a */ + /* PostScript font. These bit flags are returned by */ + /* @FT_Get_FSType_Flags; they inform client applications of embedding */ + /* and subsetting restrictions associated with a font. */ + /* */ + /* See http://www.adobe.com/devnet/acrobat/pdfs/FontPolicies.pdf for */ + /* more details. */ + /* */ + /* <Values> */ + /* FT_FSTYPE_INSTALLABLE_EMBEDDING :: */ + /* Fonts with no fsType bit set may be embedded and permanently */ + /* installed on the remote system by an application. */ + /* */ + /* FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING :: */ + /* Fonts that have only this bit set must not be modified, embedded */ + /* or exchanged in any manner without first obtaining permission of */ + /* the font software copyright owner. */ + /* */ + /* FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING :: */ + /* If this bit is set, the font may be embedded and temporarily */ + /* loaded on the remote system. Documents containing Preview & */ + /* Print fonts must be opened `read-only'; no edits can be applied */ + /* to the document. */ + /* */ + /* FT_FSTYPE_EDITABLE_EMBEDDING :: */ + /* If this bit is set, the font may be embedded but must only be */ + /* installed temporarily on other systems. In contrast to Preview */ + /* & Print fonts, documents containing editable fonts may be opened */ + /* for reading, editing is permitted, and changes may be saved. */ + /* */ + /* FT_FSTYPE_NO_SUBSETTING :: */ + /* If this bit is set, the font may not be subsetted prior to */ + /* embedding. */ + /* */ + /* FT_FSTYPE_BITMAP_EMBEDDING_ONLY :: */ + /* If this bit is set, only bitmaps contained in the font may be */ + /* embedded; no outline data may be embedded. If there are no */ + /* bitmaps available in the font, then the font is unembeddable. */ + /* */ + /* <Note> */ + /* While the fsType flags can indicate that a font may be embedded, a */ + /* license with the font vendor may be separately required to use the */ + /* font in this way. */ + /* */ +#define FT_FSTYPE_INSTALLABLE_EMBEDDING 0x0000 +#define FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING 0x0002 +#define FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING 0x0004 +#define FT_FSTYPE_EDITABLE_EMBEDDING 0x0008 +#define FT_FSTYPE_NO_SUBSETTING 0x0100 +#define FT_FSTYPE_BITMAP_EMBEDDING_ONLY 0x0200 + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_FSType_Flags */ + /* */ + /* <Description> */ + /* Return the fsType flags for a font. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* <Return> */ + /* The fsType flags, @FT_FSTYPE_XXX. */ + /* */ + /* <Note> */ + /* Use this function rather than directly reading the `fs_type' field */ + /* in the @PS_FontInfoRec structure which is only guaranteed to */ + /* return the correct results for Type~1 fonts. */ + /* */ + FT_EXPORT( FT_UShort ) + FT_Get_FSType_Flags( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* glyph_variants */ + /* */ + /* <Title> */ + /* Glyph Variants */ + /* */ + /* <Abstract> */ + /* The FreeType~2 interface to Unicode Ideographic Variation */ + /* Sequences (IVS), using the SFNT cmap format~14. */ + /* */ + /* <Description> */ + /* Many CJK characters have variant forms. They are a sort of grey */ + /* area somewhere between being totally irrelevant and semantically */ + /* distinct; for this reason, the Unicode consortium decided to */ + /* introduce Ideographic Variation Sequences (IVS), consisting of a */ + /* Unicode base character and one of 240 variant selectors */ + /* (U+E0100-U+E01EF), instead of further extending the already huge */ + /* code range for CJK characters. */ + /* */ + /* An IVS is registered and unique; for further details please refer */ + /* to Unicode Technical Report #37, the Ideographic Variation */ + /* Database. To date (October 2007), the character with the most */ + /* variants is U+908A, having 8~such IVS. */ + /* */ + /* Adobe and MS decided to support IVS with a new cmap subtable */ + /* (format~14). It is an odd subtable because it is not a mapping of */ + /* input code points to glyphs, but contains lists of all variants */ + /* supported by the font. */ + /* */ + /* A variant may be either `default' or `non-default'. A default */ + /* variant is the one you will get for that code point if you look it */ + /* up in the standard Unicode cmap. A non-default variant is a */ + /* different glyph. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Face_GetCharVariantIndex */ + /* */ + /* <Description> */ + /* Return the glyph index of a given character code as modified by */ + /* the variation selector. */ + /* */ + /* <Input> */ + /* face :: */ + /* A handle to the source face object. */ + /* */ + /* charcode :: */ + /* The character code point in Unicode. */ + /* */ + /* variantSelector :: */ + /* The Unicode code point of the variation selector. */ + /* */ + /* <Return> */ + /* The glyph index. 0~means either `undefined character code', or */ + /* `undefined selector code', or `no variation selector cmap */ + /* subtable', or `current CharMap is not Unicode'. */ + /* */ + /* <Note> */ + /* If you use FreeType to manipulate the contents of font files */ + /* directly, be aware that the glyph index returned by this function */ + /* doesn't always correspond to the internal indices used within */ + /* the file. This is done to ensure that value~0 always corresponds */ + /* to the `missing glyph'. */ + /* */ + /* This function is only meaningful if */ + /* a) the font has a variation selector cmap sub table, */ + /* and */ + /* b) the current charmap has a Unicode encoding. */ + /* */ + /* <Since> */ + /* 2.3.6 */ + /* */ + FT_EXPORT( FT_UInt ) + FT_Face_GetCharVariantIndex( FT_Face face, + FT_ULong charcode, + FT_ULong variantSelector ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Face_GetCharVariantIsDefault */ + /* */ + /* <Description> */ + /* Check whether this variant of this Unicode character is the one to */ + /* be found in the `cmap'. */ + /* */ + /* <Input> */ + /* face :: */ + /* A handle to the source face object. */ + /* */ + /* charcode :: */ + /* The character codepoint in Unicode. */ + /* */ + /* variantSelector :: */ + /* The Unicode codepoint of the variation selector. */ + /* */ + /* <Return> */ + /* 1~if found in the standard (Unicode) cmap, 0~if found in the */ + /* variation selector cmap, or -1 if it is not a variant. */ + /* */ + /* <Note> */ + /* This function is only meaningful if the font has a variation */ + /* selector cmap subtable. */ + /* */ + /* <Since> */ + /* 2.3.6 */ + /* */ + FT_EXPORT( FT_Int ) + FT_Face_GetCharVariantIsDefault( FT_Face face, + FT_ULong charcode, + FT_ULong variantSelector ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Face_GetVariantSelectors */ + /* */ + /* <Description> */ + /* Return a zero-terminated list of Unicode variant selectors found */ + /* in the font. */ + /* */ + /* <Input> */ + /* face :: */ + /* A handle to the source face object. */ + /* */ + /* <Return> */ + /* A pointer to an array of selector code points, or NULL if there is */ + /* no valid variant selector cmap subtable. */ + /* */ + /* <Note> */ + /* The last item in the array is~0; the array is owned by the */ + /* @FT_Face object but can be overwritten or released on the next */ + /* call to a FreeType function. */ + /* */ + /* <Since> */ + /* 2.3.6 */ + /* */ + FT_EXPORT( FT_UInt32* ) + FT_Face_GetVariantSelectors( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Face_GetVariantsOfChar */ + /* */ + /* <Description> */ + /* Return a zero-terminated list of Unicode variant selectors found */ + /* for the specified character code. */ + /* */ + /* <Input> */ + /* face :: */ + /* A handle to the source face object. */ + /* */ + /* charcode :: */ + /* The character codepoint in Unicode. */ + /* */ + /* <Return> */ + /* A pointer to an array of variant selector code points which are */ + /* active for the given character, or NULL if the corresponding list */ + /* is empty. */ + /* */ + /* <Note> */ + /* The last item in the array is~0; the array is owned by the */ + /* @FT_Face object but can be overwritten or released on the next */ + /* call to a FreeType function. */ + /* */ + /* <Since> */ + /* 2.3.6 */ + /* */ + FT_EXPORT( FT_UInt32* ) + FT_Face_GetVariantsOfChar( FT_Face face, + FT_ULong charcode ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Face_GetCharsOfVariant */ + /* */ + /* <Description> */ + /* Return a zero-terminated list of Unicode character codes found for */ + /* the specified variant selector. */ + /* */ + /* <Input> */ + /* face :: */ + /* A handle to the source face object. */ + /* */ + /* variantSelector :: */ + /* The variant selector code point in Unicode. */ + /* */ + /* <Return> */ + /* A list of all the code points which are specified by this selector */ + /* (both default and non-default codes are returned) or NULL if there */ + /* is no valid cmap or the variant selector is invalid. */ + /* */ + /* <Note> */ + /* The last item in the array is~0; the array is owned by the */ + /* @FT_Face object but can be overwritten or released on the next */ + /* call to a FreeType function. */ + /* */ + /* <Since> */ + /* 2.3.6 */ + /* */ + FT_EXPORT( FT_UInt32* ) + FT_Face_GetCharsOfVariant( FT_Face face, + FT_ULong variantSelector ); + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* computations */ + /* */ + /* <Title> */ + /* Computations */ + /* */ + /* <Abstract> */ + /* Crunching fixed numbers and vectors. */ + /* */ + /* <Description> */ + /* This section contains various functions used to perform */ + /* computations on 16.16 fixed-float numbers or 2d vectors. */ + /* */ + /* <Order> */ + /* FT_MulDiv */ + /* FT_MulFix */ + /* FT_DivFix */ + /* FT_RoundFix */ + /* FT_CeilFix */ + /* FT_FloorFix */ + /* FT_Vector_Transform */ + /* FT_Matrix_Multiply */ + /* FT_Matrix_Invert */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_MulDiv */ + /* */ + /* <Description> */ + /* A very simple function used to perform the computation `(a*b)/c' */ + /* with maximal accuracy (it uses a 64-bit intermediate integer */ + /* whenever necessary). */ + /* */ + /* This function isn't necessarily as fast as some processor specific */ + /* operations, but is at least completely portable. */ + /* */ + /* <Input> */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. */ + /* c :: The divisor. */ + /* */ + /* <Return> */ + /* The result of `(a*b)/c'. This function never traps when trying to */ + /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */ + /* on the signs of `a' and `b'. */ + /* */ + FT_EXPORT( FT_Long ) + FT_MulDiv( FT_Long a, + FT_Long b, + FT_Long c ); + + + /* */ + + /* The following #if 0 ... #endif is for the documentation formatter, */ + /* hiding the internal `FT_MULFIX_INLINED' macro. */ + +#if 0 + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_MulFix */ + /* */ + /* <Description> */ + /* A very simple function used to perform the computation */ + /* `(a*b)/0x10000' with maximal accuracy. Most of the time this is */ + /* used to multiply a given value by a 16.16 fixed float factor. */ + /* */ + /* <Input> */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* <Return> */ + /* The result of `(a*b)/0x10000'. */ + /* */ + /* <Note> */ + /* This function has been optimized for the case where the absolute */ + /* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */ + /* As this happens mainly when scaling from notional units to */ + /* fractional pixels in FreeType, it resulted in noticeable speed */ + /* improvements between versions 2.x and 1.x. */ + /* */ + /* As a conclusion, always try to place a 16.16 factor as the */ + /* _second_ argument of this function; this can make a great */ + /* difference. */ + /* */ + FT_EXPORT( FT_Long ) + FT_MulFix( FT_Long a, + FT_Long b ); + + /* */ +#endif + +#ifdef FT_MULFIX_INLINED +#define FT_MulFix( a, b ) FT_MULFIX_INLINED( a, b ) +#else + FT_EXPORT( FT_Long ) + FT_MulFix( FT_Long a, + FT_Long b ); +#endif + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_DivFix */ + /* */ + /* <Description> */ + /* A very simple function used to perform the computation */ + /* `(a*0x10000)/b' with maximal accuracy. Most of the time, this is */ + /* used to divide a given value by a 16.16 fixed float factor. */ + /* */ + /* <Input> */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* <Return> */ + /* The result of `(a*0x10000)/b'. */ + /* */ + /* <Note> */ + /* The optimization for FT_DivFix() is simple: If (a~<<~16) fits in */ + /* 32~bits, then the division is computed directly. Otherwise, we */ + /* use a specialized version of @FT_MulDiv. */ + /* */ + FT_EXPORT( FT_Long ) + FT_DivFix( FT_Long a, + FT_Long b ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_RoundFix */ + /* */ + /* <Description> */ + /* A very simple function used to round a 16.16 fixed number. */ + /* */ + /* <Input> */ + /* a :: The number to be rounded. */ + /* */ + /* <Return> */ + /* The result of `(a + 0x8000) & -0x10000'. */ + /* */ + FT_EXPORT( FT_Fixed ) + FT_RoundFix( FT_Fixed a ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_CeilFix */ + /* */ + /* <Description> */ + /* A very simple function used to compute the ceiling function of a */ + /* 16.16 fixed number. */ + /* */ + /* <Input> */ + /* a :: The number for which the ceiling function is to be computed. */ + /* */ + /* <Return> */ + /* The result of `(a + 0x10000 - 1) & -0x10000'. */ + /* */ + FT_EXPORT( FT_Fixed ) + FT_CeilFix( FT_Fixed a ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_FloorFix */ + /* */ + /* <Description> */ + /* A very simple function used to compute the floor function of a */ + /* 16.16 fixed number. */ + /* */ + /* <Input> */ + /* a :: The number for which the floor function is to be computed. */ + /* */ + /* <Return> */ + /* The result of `a & -0x10000'. */ + /* */ + FT_EXPORT( FT_Fixed ) + FT_FloorFix( FT_Fixed a ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Vector_Transform */ + /* */ + /* <Description> */ + /* Transform a single vector through a 2x2 matrix. */ + /* */ + /* <InOut> */ + /* vector :: The target vector to transform. */ + /* */ + /* <Input> */ + /* matrix :: A pointer to the source 2x2 matrix. */ + /* */ + /* <Note> */ + /* The result is undefined if either `vector' or `matrix' is invalid. */ + /* */ + FT_EXPORT( void ) + FT_Vector_Transform( FT_Vector* vec, + const FT_Matrix* matrix ); + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* version */ + /* */ + /* <Title> */ + /* FreeType Version */ + /* */ + /* <Abstract> */ + /* Functions and macros related to FreeType versions. */ + /* */ + /* <Description> */ + /* Note that those functions and macros are of limited use because */ + /* even a new release of FreeType with only documentation changes */ + /* increases the version number. */ + /* */ + /*************************************************************************/ + + + /************************************************************************* + * + * @enum: + * FREETYPE_XXX + * + * @description: + * These three macros identify the FreeType source code version. + * Use @FT_Library_Version to access them at runtime. + * + * @values: + * FREETYPE_MAJOR :: The major version number. + * FREETYPE_MINOR :: The minor version number. + * FREETYPE_PATCH :: The patch level. + * + * @note: + * The version number of FreeType if built as a dynamic link library + * with the `libtool' package is _not_ controlled by these three + * macros. + * + */ +#define FREETYPE_MAJOR 2 +#define FREETYPE_MINOR 4 +#define FREETYPE_PATCH 2 + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Library_Version */ + /* */ + /* <Description> */ + /* Return the version of the FreeType library being used. This is */ + /* useful when dynamically linking to the library, since one cannot */ + /* use the macros @FREETYPE_MAJOR, @FREETYPE_MINOR, and */ + /* @FREETYPE_PATCH. */ + /* */ + /* <Input> */ + /* library :: A source library handle. */ + /* */ + /* <Output> */ + /* amajor :: The major version number. */ + /* */ + /* aminor :: The minor version number. */ + /* */ + /* apatch :: The patch version number. */ + /* */ + /* <Note> */ + /* The reason why this function takes a `library' argument is because */ + /* certain programs implement library initialization in a custom way */ + /* that doesn't use @FT_Init_FreeType. */ + /* */ + /* In such cases, the library version might not be available before */ + /* the library object has been created. */ + /* */ + FT_EXPORT( void ) + FT_Library_Version( FT_Library library, + FT_Int *amajor, + FT_Int *aminor, + FT_Int *apatch ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Face_CheckTrueTypePatents */ + /* */ + /* <Description> */ + /* Parse all bytecode instructions of a TrueType font file to check */ + /* whether any of the patented opcodes are used. This is only useful */ + /* if you want to be able to use the unpatented hinter with */ + /* fonts that do *not* use these opcodes. */ + /* */ + /* Note that this function parses *all* glyph instructions in the */ + /* font file, which may be slow. */ + /* */ + /* <Input> */ + /* face :: A face handle. */ + /* */ + /* <Return> */ + /* 1~if this is a TrueType font that uses one of the patented */ + /* opcodes, 0~otherwise. */ + /* */ + /* <Note> */ + /* Since May 2010, TrueType hinting is no longer patented. */ + /* */ + /* <Since> */ + /* 2.3.5 */ + /* */ + FT_EXPORT( FT_Bool ) + FT_Face_CheckTrueTypePatents( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Face_SetUnpatentedHinting */ + /* */ + /* <Description> */ + /* Enable or disable the unpatented hinter for a given face. */ + /* Only enable it if you have determined that the face doesn't */ + /* use any patented opcodes (see @FT_Face_CheckTrueTypePatents). */ + /* */ + /* <Input> */ + /* face :: A face handle. */ + /* */ + /* value :: New boolean setting. */ + /* */ + /* <Return> */ + /* The old setting value. This will always be false if this is not */ + /* an SFNT font, or if the unpatented hinter is not compiled in this */ + /* instance of the library. */ + /* */ + /* <Note> */ + /* Since May 2010, TrueType hinting is no longer patented. */ + /* */ + /* <Since> */ + /* 2.3.5 */ + /* */ + FT_EXPORT( FT_Bool ) + FT_Face_SetUnpatentedHinting( FT_Face face, + FT_Bool value ); + + /* */ + + +FT_END_HEADER + +#endif /* __FREETYPE_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftadvanc.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftadvanc.h new file mode 100644 index 00000000..b2451bec --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftadvanc.h @@ -0,0 +1,179 @@ +/***************************************************************************/ +/* */ +/* ftadvanc.h */ +/* */ +/* Quick computation of advance widths (specification only). */ +/* */ +/* Copyright 2008 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTADVANC_H__ +#define __FTADVANC_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /************************************************************************** + * + * @section: + * quick_advance + * + * @title: + * Quick retrieval of advance values + * + * @abstract: + * Retrieve horizontal and vertical advance values without processing + * glyph outlines, if possible. + * + * @description: + * This section contains functions to quickly extract advance values + * without handling glyph outlines, if possible. + */ + + + /*************************************************************************/ + /* */ + /* <Const> */ + /* FT_ADVANCE_FLAG_FAST_ONLY */ + /* */ + /* <Description> */ + /* A bit-flag to be OR-ed with the `flags' parameter of the */ + /* @FT_Get_Advance and @FT_Get_Advances functions. */ + /* */ + /* If set, it indicates that you want these functions to fail if the */ + /* corresponding hinting mode or font driver doesn't allow for very */ + /* quick advance computation. */ + /* */ + /* Typically, glyphs which are either unscaled, unhinted, bitmapped, */ + /* or light-hinted can have their advance width computed very */ + /* quickly. */ + /* */ + /* Normal and bytecode hinted modes, which require loading, scaling, */ + /* and hinting of the glyph outline, are extremely slow by */ + /* comparison. */ + /* */ +#define FT_ADVANCE_FLAG_FAST_ONLY 0x20000000UL + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Advance */ + /* */ + /* <Description> */ + /* Retrieve the advance value of a given glyph outline in an */ + /* @FT_Face. By default, the unhinted advance is returned in font */ + /* units. */ + /* */ + /* <Input> */ + /* face :: The source @FT_Face handle. */ + /* */ + /* gindex :: The glyph index. */ + /* */ + /* load_flags :: A set of bit flags similar to those used when */ + /* calling @FT_Load_Glyph, used to determine what kind */ + /* of advances you need. */ + /* <Output> */ + /* padvance :: The advance value, in either font units or 16.16 */ + /* format. */ + /* */ + /* If @FT_LOAD_VERTICAL_LAYOUT is set, this is the */ + /* vertical advance corresponding to a vertical layout. */ + /* Otherwise, it is the horizontal advance in a */ + /* horizontal layout. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* This function may fail if you use @FT_ADVANCE_FLAG_FAST_ONLY and */ + /* if the corresponding font backend doesn't have a quick way to */ + /* retrieve the advances. */ + /* */ + /* A scaled advance is returned in 16.16 format but isn't transformed */ + /* by the affine transformation specified by @FT_Set_Transform. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Advance( FT_Face face, + FT_UInt gindex, + FT_Int32 load_flags, + FT_Fixed *padvance ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Advances */ + /* */ + /* <Description> */ + /* Retrieve the advance values of several glyph outlines in an */ + /* @FT_Face. By default, the unhinted advances are returned in font */ + /* units. */ + /* */ + /* <Input> */ + /* face :: The source @FT_Face handle. */ + /* */ + /* start :: The first glyph index. */ + /* */ + /* count :: The number of advance values you want to retrieve. */ + /* */ + /* load_flags :: A set of bit flags similar to those used when */ + /* calling @FT_Load_Glyph. */ + /* */ + /* <Output> */ + /* padvance :: The advances, in either font units or 16.16 format. */ + /* This array must contain at least `count' elements. */ + /* */ + /* If @FT_LOAD_VERTICAL_LAYOUT is set, these are the */ + /* vertical advances corresponding to a vertical layout. */ + /* Otherwise, they are the horizontal advances in a */ + /* horizontal layout. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* This function may fail if you use @FT_ADVANCE_FLAG_FAST_ONLY and */ + /* if the corresponding font backend doesn't have a quick way to */ + /* retrieve the advances. */ + /* */ + /* Scaled advances are returned in 16.16 format but aren't */ + /* transformed by the affine transformation specified by */ + /* @FT_Set_Transform. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Advances( FT_Face face, + FT_UInt start, + FT_UInt count, + FT_Int32 load_flags, + FT_Fixed *padvances ); + +/* */ + + +FT_END_HEADER + +#endif /* __FTADVANC_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftbbox.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftbbox.h new file mode 100644 index 00000000..01fe3fb0 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftbbox.h @@ -0,0 +1,94 @@ +/***************************************************************************/ +/* */ +/* ftbbox.h */ +/* */ +/* FreeType exact bbox computation (specification). */ +/* */ +/* Copyright 1996-2001, 2003, 2007 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This component has a _single_ role: to compute exact outline bounding */ + /* boxes. */ + /* */ + /* It is separated from the rest of the engine for various technical */ + /* reasons. It may well be integrated in `ftoutln' later. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTBBOX_H__ +#define __FTBBOX_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* outline_processing */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Get_BBox */ + /* */ + /* <Description> */ + /* Compute the exact bounding box of an outline. This is slower */ + /* than computing the control box. However, it uses an advanced */ + /* algorithm which returns _very_ quickly when the two boxes */ + /* coincide. Otherwise, the outline Bézier arcs are traversed to */ + /* extract their extrema. */ + /* */ + /* <Input> */ + /* outline :: A pointer to the source outline. */ + /* */ + /* <Output> */ + /* abbox :: The outline's exact bounding box. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_Get_BBox( FT_Outline* outline, + FT_BBox *abbox ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTBBOX_H__ */ + + +/* END */ + + +/* Local Variables: */ +/* coding: utf-8 */ +/* End: */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftbdf.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftbdf.h new file mode 100644 index 00000000..4f8baf84 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftbdf.h @@ -0,0 +1,209 @@ +/***************************************************************************/ +/* */ +/* ftbdf.h */ +/* */ +/* FreeType API for accessing BDF-specific strings (specification). */ +/* */ +/* Copyright 2002, 2003, 2004, 2006, 2009 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTBDF_H__ +#define __FTBDF_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* bdf_fonts */ + /* */ + /* <Title> */ + /* BDF and PCF Files */ + /* */ + /* <Abstract> */ + /* BDF and PCF specific API. */ + /* */ + /* <Description> */ + /* This section contains the declaration of functions specific to BDF */ + /* and PCF fonts. */ + /* */ + /*************************************************************************/ + + + /********************************************************************** + * + * @enum: + * FT_PropertyType + * + * @description: + * A list of BDF property types. + * + * @values: + * BDF_PROPERTY_TYPE_NONE :: + * Value~0 is used to indicate a missing property. + * + * BDF_PROPERTY_TYPE_ATOM :: + * Property is a string atom. + * + * BDF_PROPERTY_TYPE_INTEGER :: + * Property is a 32-bit signed integer. + * + * BDF_PROPERTY_TYPE_CARDINAL :: + * Property is a 32-bit unsigned integer. + */ + typedef enum BDF_PropertyType_ + { + BDF_PROPERTY_TYPE_NONE = 0, + BDF_PROPERTY_TYPE_ATOM = 1, + BDF_PROPERTY_TYPE_INTEGER = 2, + BDF_PROPERTY_TYPE_CARDINAL = 3 + + } BDF_PropertyType; + + + /********************************************************************** + * + * @type: + * BDF_Property + * + * @description: + * A handle to a @BDF_PropertyRec structure to model a given + * BDF/PCF property. + */ + typedef struct BDF_PropertyRec_* BDF_Property; + + + /********************************************************************** + * + * @struct: + * BDF_PropertyRec + * + * @description: + * This structure models a given BDF/PCF property. + * + * @fields: + * type :: + * The property type. + * + * u.atom :: + * The atom string, if type is @BDF_PROPERTY_TYPE_ATOM. + * + * u.integer :: + * A signed integer, if type is @BDF_PROPERTY_TYPE_INTEGER. + * + * u.cardinal :: + * An unsigned integer, if type is @BDF_PROPERTY_TYPE_CARDINAL. + */ + typedef struct BDF_PropertyRec_ + { + BDF_PropertyType type; + union { + const char* atom; + FT_Int32 integer; + FT_UInt32 cardinal; + + } u; + + } BDF_PropertyRec; + + + /********************************************************************** + * + * @function: + * FT_Get_BDF_Charset_ID + * + * @description: + * Retrieve a BDF font character set identity, according to + * the BDF specification. + * + * @input: + * face :: + * A handle to the input face. + * + * @output: + * acharset_encoding :: + * Charset encoding, as a C~string, owned by the face. + * + * acharset_registry :: + * Charset registry, as a C~string, owned by the face. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * This function only works with BDF faces, returning an error otherwise. + */ + FT_EXPORT( FT_Error ) + FT_Get_BDF_Charset_ID( FT_Face face, + const char* *acharset_encoding, + const char* *acharset_registry ); + + + /********************************************************************** + * + * @function: + * FT_Get_BDF_Property + * + * @description: + * Retrieve a BDF property from a BDF or PCF font file. + * + * @input: + * face :: A handle to the input face. + * + * name :: The property name. + * + * @output: + * aproperty :: The property. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * This function works with BDF _and_ PCF fonts. It returns an error + * otherwise. It also returns an error if the property is not in the + * font. + * + * A `property' is a either key-value pair within the STARTPROPERTIES + * ... ENDPROPERTIES block of a BDF font or a key-value pair from the + * `info->props' array within a `FontRec' structure of a PCF font. + * + * Integer properties are always stored as `signed' within PCF fonts; + * consequently, @BDF_PROPERTY_TYPE_CARDINAL is a possible return value + * for BDF fonts only. + * + * In case of error, `aproperty->type' is always set to + * @BDF_PROPERTY_TYPE_NONE. + */ + FT_EXPORT( FT_Error ) + FT_Get_BDF_Property( FT_Face face, + const char* prop_name, + BDF_PropertyRec *aproperty ); + + /* */ + +FT_END_HEADER + +#endif /* __FTBDF_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftbitmap.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftbitmap.h new file mode 100644 index 00000000..92742369 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftbitmap.h @@ -0,0 +1,227 @@ +/***************************************************************************/ +/* */ +/* ftbitmap.h */ +/* */ +/* FreeType utility functions for bitmaps (specification). */ +/* */ +/* Copyright 2004, 2005, 2006, 2008 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTBITMAP_H__ +#define __FTBITMAP_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* bitmap_handling */ + /* */ + /* <Title> */ + /* Bitmap Handling */ + /* */ + /* <Abstract> */ + /* Handling FT_Bitmap objects. */ + /* */ + /* <Description> */ + /* This section contains functions for converting FT_Bitmap objects. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Bitmap_New */ + /* */ + /* <Description> */ + /* Initialize a pointer to an @FT_Bitmap structure. */ + /* */ + /* <InOut> */ + /* abitmap :: A pointer to the bitmap structure. */ + /* */ + FT_EXPORT( void ) + FT_Bitmap_New( FT_Bitmap *abitmap ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Bitmap_Copy */ + /* */ + /* <Description> */ + /* Copy a bitmap into another one. */ + /* */ + /* <Input> */ + /* library :: A handle to a library object. */ + /* */ + /* source :: A handle to the source bitmap. */ + /* */ + /* <Output> */ + /* target :: A handle to the target bitmap. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Bitmap_Copy( FT_Library library, + const FT_Bitmap *source, + FT_Bitmap *target); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Bitmap_Embolden */ + /* */ + /* <Description> */ + /* Embolden a bitmap. The new bitmap will be about `xStrength' */ + /* pixels wider and `yStrength' pixels higher. The left and bottom */ + /* borders are kept unchanged. */ + /* */ + /* <Input> */ + /* library :: A handle to a library object. */ + /* */ + /* xStrength :: How strong the glyph is emboldened horizontally. */ + /* Expressed in 26.6 pixel format. */ + /* */ + /* yStrength :: How strong the glyph is emboldened vertically. */ + /* Expressed in 26.6 pixel format. */ + /* */ + /* <InOut> */ + /* bitmap :: A handle to the target bitmap. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* The current implementation restricts `xStrength' to be less than */ + /* or equal to~8 if bitmap is of pixel_mode @FT_PIXEL_MODE_MONO. */ + /* */ + /* If you want to embolden the bitmap owned by a @FT_GlyphSlotRec, */ + /* you should call @FT_GlyphSlot_Own_Bitmap on the slot first. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Bitmap_Embolden( FT_Library library, + FT_Bitmap* bitmap, + FT_Pos xStrength, + FT_Pos yStrength ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Bitmap_Convert */ + /* */ + /* <Description> */ + /* Convert a bitmap object with depth 1bpp, 2bpp, 4bpp, or 8bpp to a */ + /* bitmap object with depth 8bpp, making the number of used bytes per */ + /* line (a.k.a. the `pitch') a multiple of `alignment'. */ + /* */ + /* <Input> */ + /* library :: A handle to a library object. */ + /* */ + /* source :: The source bitmap. */ + /* */ + /* alignment :: The pitch of the bitmap is a multiple of this */ + /* parameter. Common values are 1, 2, or 4. */ + /* */ + /* <Output> */ + /* target :: The target bitmap. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* It is possible to call @FT_Bitmap_Convert multiple times without */ + /* calling @FT_Bitmap_Done (the memory is simply reallocated). */ + /* */ + /* Use @FT_Bitmap_Done to finally remove the bitmap object. */ + /* */ + /* The `library' argument is taken to have access to FreeType's */ + /* memory handling functions. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Bitmap_Convert( FT_Library library, + const FT_Bitmap *source, + FT_Bitmap *target, + FT_Int alignment ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_GlyphSlot_Own_Bitmap */ + /* */ + /* <Description> */ + /* Make sure that a glyph slot owns `slot->bitmap'. */ + /* */ + /* <Input> */ + /* slot :: The glyph slot. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* This function is to be used in combination with */ + /* @FT_Bitmap_Embolden. */ + /* */ + FT_EXPORT( FT_Error ) + FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Bitmap_Done */ + /* */ + /* <Description> */ + /* Destroy a bitmap object created with @FT_Bitmap_New. */ + /* */ + /* <Input> */ + /* library :: A handle to a library object. */ + /* */ + /* bitmap :: The bitmap object to be freed. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* The `library' argument is taken to have access to FreeType's */ + /* memory handling functions. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Bitmap_Done( FT_Library library, + FT_Bitmap *bitmap ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTBITMAP_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftcache.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftcache.h new file mode 100644 index 00000000..a9e1237b --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftcache.h @@ -0,0 +1,1125 @@ +/***************************************************************************/ +/* */ +/* ftcache.h */ +/* */ +/* FreeType Cache subsystem (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTCACHE_H__ +#define __FTCACHE_H__ + + +#include <ft2build.h> +#include FT_GLYPH_H + + +FT_BEGIN_HEADER + + + /************************************************************************* + * + * <Section> + * cache_subsystem + * + * <Title> + * Cache Sub-System + * + * <Abstract> + * How to cache face, size, and glyph data with FreeType~2. + * + * <Description> + * This section describes the FreeType~2 cache sub-system, which is used + * to limit the number of concurrently opened @FT_Face and @FT_Size + * objects, as well as caching information like character maps and glyph + * images while limiting their maximum memory usage. + * + * Note that all types and functions begin with the `FTC_' prefix. + * + * The cache is highly portable and thus doesn't know anything about the + * fonts installed on your system, or how to access them. This implies + * the following scheme: + * + * First, available or installed font faces are uniquely identified by + * @FTC_FaceID values, provided to the cache by the client. Note that + * the cache only stores and compares these values, and doesn't try to + * interpret them in any way. + * + * Second, the cache calls, only when needed, a client-provided function + * to convert a @FTC_FaceID into a new @FT_Face object. The latter is + * then completely managed by the cache, including its termination + * through @FT_Done_Face. + * + * Clients are free to map face IDs to anything else. The most simple + * usage is to associate them to a (pathname,face_index) pair that is + * used to call @FT_New_Face. However, more complex schemes are also + * possible. + * + * Note that for the cache to work correctly, the face ID values must be + * *persistent*, which means that the contents they point to should not + * change at runtime, or that their value should not become invalid. + * + * If this is unavoidable (e.g., when a font is uninstalled at runtime), + * you should call @FTC_Manager_RemoveFaceID as soon as possible, to let + * the cache get rid of any references to the old @FTC_FaceID it may + * keep internally. Failure to do so will lead to incorrect behaviour + * or even crashes. + * + * To use the cache, start with calling @FTC_Manager_New to create a new + * @FTC_Manager object, which models a single cache instance. You can + * then look up @FT_Face and @FT_Size objects with + * @FTC_Manager_LookupFace and @FTC_Manager_LookupSize, respectively. + * + * If you want to use the charmap caching, call @FTC_CMapCache_New, then + * later use @FTC_CMapCache_Lookup to perform the equivalent of + * @FT_Get_Char_Index, only much faster. + * + * If you want to use the @FT_Glyph caching, call @FTC_ImageCache, then + * later use @FTC_ImageCache_Lookup to retrieve the corresponding + * @FT_Glyph objects from the cache. + * + * If you need lots of small bitmaps, it is much more memory efficient + * to call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This + * returns @FTC_SBitRec structures, which are used to store small + * bitmaps directly. (A small bitmap is one whose metrics and + * dimensions all fit into 8-bit integers). + * + * We hope to also provide a kerning cache in the near future. + * + * + * <Order> + * FTC_Manager + * FTC_FaceID + * FTC_Face_Requester + * + * FTC_Manager_New + * FTC_Manager_Reset + * FTC_Manager_Done + * FTC_Manager_LookupFace + * FTC_Manager_LookupSize + * FTC_Manager_RemoveFaceID + * + * FTC_Node + * FTC_Node_Unref + * + * FTC_ImageCache + * FTC_ImageCache_New + * FTC_ImageCache_Lookup + * + * FTC_SBit + * FTC_SBitCache + * FTC_SBitCache_New + * FTC_SBitCache_Lookup + * + * FTC_CMapCache + * FTC_CMapCache_New + * FTC_CMapCache_Lookup + * + *************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** BASIC TYPE DEFINITIONS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /************************************************************************* + * + * @type: FTC_FaceID + * + * @description: + * An opaque pointer type that is used to identity face objects. The + * contents of such objects is application-dependent. + * + * These pointers are typically used to point to a user-defined + * structure containing a font file path, and face index. + * + * @note: + * Never use NULL as a valid @FTC_FaceID. + * + * Face IDs are passed by the client to the cache manager, which calls, + * when needed, the @FTC_Face_Requester to translate them into new + * @FT_Face objects. + * + * If the content of a given face ID changes at runtime, or if the value + * becomes invalid (e.g., when uninstalling a font), you should + * immediately call @FTC_Manager_RemoveFaceID before any other cache + * function. + * + * Failure to do so will result in incorrect behaviour or even + * memory leaks and crashes. + */ + typedef FT_Pointer FTC_FaceID; + + + /************************************************************************ + * + * @functype: + * FTC_Face_Requester + * + * @description: + * A callback function provided by client applications. It is used by + * the cache manager to translate a given @FTC_FaceID into a new valid + * @FT_Face object, on demand. + * + * <Input> + * face_id :: + * The face ID to resolve. + * + * library :: + * A handle to a FreeType library object. + * + * req_data :: + * Application-provided request data (see note below). + * + * <Output> + * aface :: + * A new @FT_Face handle. + * + * <Return> + * FreeType error code. 0~means success. + * + * <Note> + * The third parameter `req_data' is the same as the one passed by the + * client when @FTC_Manager_New is called. + * + * The face requester should not perform funny things on the returned + * face object, like creating a new @FT_Size for it, or setting a + * transformation through @FT_Set_Transform! + */ + typedef FT_Error + (*FTC_Face_Requester)( FTC_FaceID face_id, + FT_Library library, + FT_Pointer request_data, + FT_Face* aface ); + + /* */ + +#define FT_POINTER_TO_ULONG( p ) ( (FT_ULong)(FT_Pointer)(p) ) + +#define FTC_FACE_ID_HASH( i ) \ + ((FT_UInt32)(( FT_POINTER_TO_ULONG( i ) >> 3 ) ^ \ + ( FT_POINTER_TO_ULONG( i ) << 7 ) ) ) + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** CACHE MANAGER OBJECT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FTC_Manager */ + /* */ + /* <Description> */ + /* This object corresponds to one instance of the cache-subsystem. */ + /* It is used to cache one or more @FT_Face objects, along with */ + /* corresponding @FT_Size objects. */ + /* */ + /* The manager intentionally limits the total number of opened */ + /* @FT_Face and @FT_Size objects to control memory usage. See the */ + /* `max_faces' and `max_sizes' parameters of @FTC_Manager_New. */ + /* */ + /* The manager is also used to cache `nodes' of various types while */ + /* limiting their total memory usage. */ + /* */ + /* All limitations are enforced by keeping lists of managed objects */ + /* in most-recently-used order, and flushing old nodes to make room */ + /* for new ones. */ + /* */ + typedef struct FTC_ManagerRec_* FTC_Manager; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FTC_Node */ + /* */ + /* <Description> */ + /* An opaque handle to a cache node object. Each cache node is */ + /* reference-counted. A node with a count of~0 might be flushed */ + /* out of a full cache whenever a lookup request is performed. */ + /* */ + /* If you look up nodes, you have the ability to `acquire' them, */ + /* i.e., to increment their reference count. This will prevent the */ + /* node from being flushed out of the cache until you explicitly */ + /* `release' it (see @FTC_Node_Unref). */ + /* */ + /* See also @FTC_SBitCache_Lookup and @FTC_ImageCache_Lookup. */ + /* */ + typedef struct FTC_NodeRec_* FTC_Node; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_Manager_New */ + /* */ + /* <Description> */ + /* Create a new cache manager. */ + /* */ + /* <Input> */ + /* library :: The parent FreeType library handle to use. */ + /* */ + /* max_faces :: Maximum number of opened @FT_Face objects managed by */ + /* this cache instance. Use~0 for defaults. */ + /* */ + /* max_sizes :: Maximum number of opened @FT_Size objects managed by */ + /* this cache instance. Use~0 for defaults. */ + /* */ + /* max_bytes :: Maximum number of bytes to use for cached data nodes. */ + /* Use~0 for defaults. Note that this value does not */ + /* account for managed @FT_Face and @FT_Size objects. */ + /* */ + /* requester :: An application-provided callback used to translate */ + /* face IDs into real @FT_Face objects. */ + /* */ + /* req_data :: A generic pointer that is passed to the requester */ + /* each time it is called (see @FTC_Face_Requester). */ + /* */ + /* <Output> */ + /* amanager :: A handle to a new manager object. 0~in case of */ + /* failure. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FTC_Manager_New( FT_Library library, + FT_UInt max_faces, + FT_UInt max_sizes, + FT_ULong max_bytes, + FTC_Face_Requester requester, + FT_Pointer req_data, + FTC_Manager *amanager ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_Manager_Reset */ + /* */ + /* <Description> */ + /* Empty a given cache manager. This simply gets rid of all the */ + /* currently cached @FT_Face and @FT_Size objects within the manager. */ + /* */ + /* <InOut> */ + /* manager :: A handle to the manager. */ + /* */ + FT_EXPORT( void ) + FTC_Manager_Reset( FTC_Manager manager ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_Manager_Done */ + /* */ + /* <Description> */ + /* Destroy a given manager after emptying it. */ + /* */ + /* <Input> */ + /* manager :: A handle to the target cache manager object. */ + /* */ + FT_EXPORT( void ) + FTC_Manager_Done( FTC_Manager manager ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_Manager_LookupFace */ + /* */ + /* <Description> */ + /* Retrieve the @FT_Face object that corresponds to a given face ID */ + /* through a cache manager. */ + /* */ + /* <Input> */ + /* manager :: A handle to the cache manager. */ + /* */ + /* face_id :: The ID of the face object. */ + /* */ + /* <Output> */ + /* aface :: A handle to the face object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* The returned @FT_Face object is always owned by the manager. You */ + /* should never try to discard it yourself. */ + /* */ + /* The @FT_Face object doesn't necessarily have a current size object */ + /* (i.e., face->size can be 0). If you need a specific `font size', */ + /* use @FTC_Manager_LookupSize instead. */ + /* */ + /* Never change the face's transformation matrix (i.e., never call */ + /* the @FT_Set_Transform function) on a returned face! If you need */ + /* to transform glyphs, do it yourself after glyph loading. */ + /* */ + /* When you perform a lookup, out-of-memory errors are detected */ + /* _within_ the lookup and force incremental flushes of the cache */ + /* until enough memory is released for the lookup to succeed. */ + /* */ + /* If a lookup fails with `FT_Err_Out_Of_Memory' the cache has */ + /* already been completely flushed, and still no memory was available */ + /* for the operation. */ + /* */ + FT_EXPORT( FT_Error ) + FTC_Manager_LookupFace( FTC_Manager manager, + FTC_FaceID face_id, + FT_Face *aface ); + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FTC_ScalerRec */ + /* */ + /* <Description> */ + /* A structure used to describe a given character size in either */ + /* pixels or points to the cache manager. See */ + /* @FTC_Manager_LookupSize. */ + /* */ + /* <Fields> */ + /* face_id :: The source face ID. */ + /* */ + /* width :: The character width. */ + /* */ + /* height :: The character height. */ + /* */ + /* pixel :: A Boolean. If 1, the `width' and `height' fields are */ + /* interpreted as integer pixel character sizes. */ + /* Otherwise, they are expressed as 1/64th of points. */ + /* */ + /* x_res :: Only used when `pixel' is value~0 to indicate the */ + /* horizontal resolution in dpi. */ + /* */ + /* y_res :: Only used when `pixel' is value~0 to indicate the */ + /* vertical resolution in dpi. */ + /* */ + /* <Note> */ + /* This type is mainly used to retrieve @FT_Size objects through the */ + /* cache manager. */ + /* */ + typedef struct FTC_ScalerRec_ + { + FTC_FaceID face_id; + FT_UInt width; + FT_UInt height; + FT_Int pixel; + FT_UInt x_res; + FT_UInt y_res; + + } FTC_ScalerRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FTC_Scaler */ + /* */ + /* <Description> */ + /* A handle to an @FTC_ScalerRec structure. */ + /* */ + typedef struct FTC_ScalerRec_* FTC_Scaler; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_Manager_LookupSize */ + /* */ + /* <Description> */ + /* Retrieve the @FT_Size object that corresponds to a given */ + /* @FTC_ScalerRec pointer through a cache manager. */ + /* */ + /* <Input> */ + /* manager :: A handle to the cache manager. */ + /* */ + /* scaler :: A scaler handle. */ + /* */ + /* <Output> */ + /* asize :: A handle to the size object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* The returned @FT_Size object is always owned by the manager. You */ + /* should never try to discard it by yourself. */ + /* */ + /* You can access the parent @FT_Face object simply as `size->face' */ + /* if you need it. Note that this object is also owned by the */ + /* manager. */ + /* */ + /* <Note> */ + /* When you perform a lookup, out-of-memory errors are detected */ + /* _within_ the lookup and force incremental flushes of the cache */ + /* until enough memory is released for the lookup to succeed. */ + /* */ + /* If a lookup fails with `FT_Err_Out_Of_Memory' the cache has */ + /* already been completely flushed, and still no memory is available */ + /* for the operation. */ + /* */ + FT_EXPORT( FT_Error ) + FTC_Manager_LookupSize( FTC_Manager manager, + FTC_Scaler scaler, + FT_Size *asize ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_Node_Unref */ + /* */ + /* <Description> */ + /* Decrement a cache node's internal reference count. When the count */ + /* reaches 0, it is not destroyed but becomes eligible for subsequent */ + /* cache flushes. */ + /* */ + /* <Input> */ + /* node :: The cache node handle. */ + /* */ + /* manager :: The cache manager handle. */ + /* */ + FT_EXPORT( void ) + FTC_Node_Unref( FTC_Node node, + FTC_Manager manager ); + + + /************************************************************************* + * + * @function: + * FTC_Manager_RemoveFaceID + * + * @description: + * A special function used to indicate to the cache manager that + * a given @FTC_FaceID is no longer valid, either because its + * content changed, or because it was deallocated or uninstalled. + * + * @input: + * manager :: + * The cache manager handle. + * + * face_id :: + * The @FTC_FaceID to be removed. + * + * @note: + * This function flushes all nodes from the cache corresponding to this + * `face_id', with the exception of nodes with a non-null reference + * count. + * + * Such nodes are however modified internally so as to never appear + * in later lookups with the same `face_id' value, and to be immediately + * destroyed when released by all their users. + * + */ + FT_EXPORT( void ) + FTC_Manager_RemoveFaceID( FTC_Manager manager, + FTC_FaceID face_id ); + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* cache_subsystem */ + /* */ + /*************************************************************************/ + + /************************************************************************* + * + * @type: + * FTC_CMapCache + * + * @description: + * An opaque handle used to model a charmap cache. This cache is to + * hold character codes -> glyph indices mappings. + * + */ + typedef struct FTC_CMapCacheRec_* FTC_CMapCache; + + + /************************************************************************* + * + * @function: + * FTC_CMapCache_New + * + * @description: + * Create a new charmap cache. + * + * @input: + * manager :: + * A handle to the cache manager. + * + * @output: + * acache :: + * A new cache handle. NULL in case of error. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * Like all other caches, this one will be destroyed with the cache + * manager. + * + */ + FT_EXPORT( FT_Error ) + FTC_CMapCache_New( FTC_Manager manager, + FTC_CMapCache *acache ); + + + /************************************************************************ + * + * @function: + * FTC_CMapCache_Lookup + * + * @description: + * Translate a character code into a glyph index, using the charmap + * cache. + * + * @input: + * cache :: + * A charmap cache handle. + * + * face_id :: + * The source face ID. + * + * cmap_index :: + * The index of the charmap in the source face. Any negative value + * means to use the cache @FT_Face's default charmap. + * + * char_code :: + * The character code (in the corresponding charmap). + * + * @return: + * Glyph index. 0~means `no glyph'. + * + */ + FT_EXPORT( FT_UInt ) + FTC_CMapCache_Lookup( FTC_CMapCache cache, + FTC_FaceID face_id, + FT_Int cmap_index, + FT_UInt32 char_code ); + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* cache_subsystem */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** IMAGE CACHE OBJECT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /************************************************************************* + * + * @struct: + * FTC_ImageTypeRec + * + * @description: + * A structure used to model the type of images in a glyph cache. + * + * @fields: + * face_id :: + * The face ID. + * + * width :: + * The width in pixels. + * + * height :: + * The height in pixels. + * + * flags :: + * The load flags, as in @FT_Load_Glyph. + * + */ + typedef struct FTC_ImageTypeRec_ + { + FTC_FaceID face_id; + FT_Int width; + FT_Int height; + FT_Int32 flags; + + } FTC_ImageTypeRec; + + + /************************************************************************* + * + * @type: + * FTC_ImageType + * + * @description: + * A handle to an @FTC_ImageTypeRec structure. + * + */ + typedef struct FTC_ImageTypeRec_* FTC_ImageType; + + + /* */ + + +#define FTC_IMAGE_TYPE_COMPARE( d1, d2 ) \ + ( (d1)->face_id == (d2)->face_id && \ + (d1)->width == (d2)->width && \ + (d1)->flags == (d2)->flags ) + +#define FTC_IMAGE_TYPE_HASH( d ) \ + (FT_UFast)( FTC_FACE_ID_HASH( (d)->face_id ) ^ \ + ( (d)->width << 8 ) ^ (d)->height ^ \ + ( (d)->flags << 4 ) ) + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FTC_ImageCache */ + /* */ + /* <Description> */ + /* A handle to an glyph image cache object. They are designed to */ + /* hold many distinct glyph images while not exceeding a certain */ + /* memory threshold. */ + /* */ + typedef struct FTC_ImageCacheRec_* FTC_ImageCache; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_ImageCache_New */ + /* */ + /* <Description> */ + /* Create a new glyph image cache. */ + /* */ + /* <Input> */ + /* manager :: The parent manager for the image cache. */ + /* */ + /* <Output> */ + /* acache :: A handle to the new glyph image cache object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FTC_ImageCache_New( FTC_Manager manager, + FTC_ImageCache *acache ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_ImageCache_Lookup */ + /* */ + /* <Description> */ + /* Retrieve a given glyph image from a glyph image cache. */ + /* */ + /* <Input> */ + /* cache :: A handle to the source glyph image cache. */ + /* */ + /* type :: A pointer to a glyph image type descriptor. */ + /* */ + /* gindex :: The glyph index to retrieve. */ + /* */ + /* <Output> */ + /* aglyph :: The corresponding @FT_Glyph object. 0~in case of */ + /* failure. */ + /* */ + /* anode :: Used to return the address of of the corresponding cache */ + /* node after incrementing its reference count (see note */ + /* below). */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* The returned glyph is owned and managed by the glyph image cache. */ + /* Never try to transform or discard it manually! You can however */ + /* create a copy with @FT_Glyph_Copy and modify the new one. */ + /* */ + /* If `anode' is _not_ NULL, it receives the address of the cache */ + /* node containing the glyph image, after increasing its reference */ + /* count. This ensures that the node (as well as the @FT_Glyph) will */ + /* always be kept in the cache until you call @FTC_Node_Unref to */ + /* `release' it. */ + /* */ + /* If `anode' is NULL, the cache node is left unchanged, which means */ + /* that the @FT_Glyph could be flushed out of the cache on the next */ + /* call to one of the caching sub-system APIs. Don't assume that it */ + /* is persistent! */ + /* */ + FT_EXPORT( FT_Error ) + FTC_ImageCache_Lookup( FTC_ImageCache cache, + FTC_ImageType type, + FT_UInt gindex, + FT_Glyph *aglyph, + FTC_Node *anode ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_ImageCache_LookupScaler */ + /* */ + /* <Description> */ + /* A variant of @FTC_ImageCache_Lookup that uses an @FTC_ScalerRec */ + /* to specify the face ID and its size. */ + /* */ + /* <Input> */ + /* cache :: A handle to the source glyph image cache. */ + /* */ + /* scaler :: A pointer to a scaler descriptor. */ + /* */ + /* load_flags :: The corresponding load flags. */ + /* */ + /* gindex :: The glyph index to retrieve. */ + /* */ + /* <Output> */ + /* aglyph :: The corresponding @FT_Glyph object. 0~in case of */ + /* failure. */ + /* */ + /* anode :: Used to return the address of of the corresponding */ + /* cache node after incrementing its reference count */ + /* (see note below). */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* The returned glyph is owned and managed by the glyph image cache. */ + /* Never try to transform or discard it manually! You can however */ + /* create a copy with @FT_Glyph_Copy and modify the new one. */ + /* */ + /* If `anode' is _not_ NULL, it receives the address of the cache */ + /* node containing the glyph image, after increasing its reference */ + /* count. This ensures that the node (as well as the @FT_Glyph) will */ + /* always be kept in the cache until you call @FTC_Node_Unref to */ + /* `release' it. */ + /* */ + /* If `anode' is NULL, the cache node is left unchanged, which means */ + /* that the @FT_Glyph could be flushed out of the cache on the next */ + /* call to one of the caching sub-system APIs. Don't assume that it */ + /* is persistent! */ + /* */ + /* Calls to @FT_Set_Char_Size and friends have no effect on cached */ + /* glyphs; you should always use the FreeType cache API instead. */ + /* */ + FT_EXPORT( FT_Error ) + FTC_ImageCache_LookupScaler( FTC_ImageCache cache, + FTC_Scaler scaler, + FT_ULong load_flags, + FT_UInt gindex, + FT_Glyph *aglyph, + FTC_Node *anode ); + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FTC_SBit */ + /* */ + /* <Description> */ + /* A handle to a small bitmap descriptor. See the @FTC_SBitRec */ + /* structure for details. */ + /* */ + typedef struct FTC_SBitRec_* FTC_SBit; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FTC_SBitRec */ + /* */ + /* <Description> */ + /* A very compact structure used to describe a small glyph bitmap. */ + /* */ + /* <Fields> */ + /* width :: The bitmap width in pixels. */ + /* */ + /* height :: The bitmap height in pixels. */ + /* */ + /* left :: The horizontal distance from the pen position to the */ + /* left bitmap border (a.k.a. `left side bearing', or */ + /* `lsb'). */ + /* */ + /* top :: The vertical distance from the pen position (on the */ + /* baseline) to the upper bitmap border (a.k.a. `top */ + /* side bearing'). The distance is positive for upwards */ + /* y~coordinates. */ + /* */ + /* format :: The format of the glyph bitmap (monochrome or gray). */ + /* */ + /* max_grays :: Maximum gray level value (in the range 1 to~255). */ + /* */ + /* pitch :: The number of bytes per bitmap line. May be positive */ + /* or negative. */ + /* */ + /* xadvance :: The horizontal advance width in pixels. */ + /* */ + /* yadvance :: The vertical advance height in pixels. */ + /* */ + /* buffer :: A pointer to the bitmap pixels. */ + /* */ + typedef struct FTC_SBitRec_ + { + FT_Byte width; + FT_Byte height; + FT_Char left; + FT_Char top; + + FT_Byte format; + FT_Byte max_grays; + FT_Short pitch; + FT_Char xadvance; + FT_Char yadvance; + + FT_Byte* buffer; + + } FTC_SBitRec; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FTC_SBitCache */ + /* */ + /* <Description> */ + /* A handle to a small bitmap cache. These are special cache objects */ + /* used to store small glyph bitmaps (and anti-aliased pixmaps) in a */ + /* much more efficient way than the traditional glyph image cache */ + /* implemented by @FTC_ImageCache. */ + /* */ + typedef struct FTC_SBitCacheRec_* FTC_SBitCache; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_SBitCache_New */ + /* */ + /* <Description> */ + /* Create a new cache to store small glyph bitmaps. */ + /* */ + /* <Input> */ + /* manager :: A handle to the source cache manager. */ + /* */ + /* <Output> */ + /* acache :: A handle to the new sbit cache. NULL in case of error. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FTC_SBitCache_New( FTC_Manager manager, + FTC_SBitCache *acache ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_SBitCache_Lookup */ + /* */ + /* <Description> */ + /* Look up a given small glyph bitmap in a given sbit cache and */ + /* `lock' it to prevent its flushing from the cache until needed. */ + /* */ + /* <Input> */ + /* cache :: A handle to the source sbit cache. */ + /* */ + /* type :: A pointer to the glyph image type descriptor. */ + /* */ + /* gindex :: The glyph index. */ + /* */ + /* <Output> */ + /* sbit :: A handle to a small bitmap descriptor. */ + /* */ + /* anode :: Used to return the address of of the corresponding cache */ + /* node after incrementing its reference count (see note */ + /* below). */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* The small bitmap descriptor and its bit buffer are owned by the */ + /* cache and should never be freed by the application. They might */ + /* as well disappear from memory on the next cache lookup, so don't */ + /* treat them as persistent data. */ + /* */ + /* The descriptor's `buffer' field is set to~0 to indicate a missing */ + /* glyph bitmap. */ + /* */ + /* If `anode' is _not_ NULL, it receives the address of the cache */ + /* node containing the bitmap, after increasing its reference count. */ + /* This ensures that the node (as well as the image) will always be */ + /* kept in the cache until you call @FTC_Node_Unref to `release' it. */ + /* */ + /* If `anode' is NULL, the cache node is left unchanged, which means */ + /* that the bitmap could be flushed out of the cache on the next */ + /* call to one of the caching sub-system APIs. Don't assume that it */ + /* is persistent! */ + /* */ + FT_EXPORT( FT_Error ) + FTC_SBitCache_Lookup( FTC_SBitCache cache, + FTC_ImageType type, + FT_UInt gindex, + FTC_SBit *sbit, + FTC_Node *anode ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_SBitCache_LookupScaler */ + /* */ + /* <Description> */ + /* A variant of @FTC_SBitCache_Lookup that uses an @FTC_ScalerRec */ + /* to specify the face ID and its size. */ + /* */ + /* <Input> */ + /* cache :: A handle to the source sbit cache. */ + /* */ + /* scaler :: A pointer to the scaler descriptor. */ + /* */ + /* load_flags :: The corresponding load flags. */ + /* */ + /* gindex :: The glyph index. */ + /* */ + /* <Output> */ + /* sbit :: A handle to a small bitmap descriptor. */ + /* */ + /* anode :: Used to return the address of of the corresponding */ + /* cache node after incrementing its reference count */ + /* (see note below). */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* The small bitmap descriptor and its bit buffer are owned by the */ + /* cache and should never be freed by the application. They might */ + /* as well disappear from memory on the next cache lookup, so don't */ + /* treat them as persistent data. */ + /* */ + /* The descriptor's `buffer' field is set to~0 to indicate a missing */ + /* glyph bitmap. */ + /* */ + /* If `anode' is _not_ NULL, it receives the address of the cache */ + /* node containing the bitmap, after increasing its reference count. */ + /* This ensures that the node (as well as the image) will always be */ + /* kept in the cache until you call @FTC_Node_Unref to `release' it. */ + /* */ + /* If `anode' is NULL, the cache node is left unchanged, which means */ + /* that the bitmap could be flushed out of the cache on the next */ + /* call to one of the caching sub-system APIs. Don't assume that it */ + /* is persistent! */ + /* */ + FT_EXPORT( FT_Error ) + FTC_SBitCache_LookupScaler( FTC_SBitCache cache, + FTC_Scaler scaler, + FT_ULong load_flags, + FT_UInt gindex, + FTC_SBit *sbit, + FTC_Node *anode ); + + + /* */ + +#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + + /*@***********************************************************************/ + /* */ + /* <Struct> */ + /* FTC_FontRec */ + /* */ + /* <Description> */ + /* A simple structure used to describe a given `font' to the cache */ + /* manager. Note that a `font' is the combination of a given face */ + /* with a given character size. */ + /* */ + /* <Fields> */ + /* face_id :: The ID of the face to use. */ + /* */ + /* pix_width :: The character width in integer pixels. */ + /* */ + /* pix_height :: The character height in integer pixels. */ + /* */ + typedef struct FTC_FontRec_ + { + FTC_FaceID face_id; + FT_UShort pix_width; + FT_UShort pix_height; + + } FTC_FontRec; + + + /* */ + + +#define FTC_FONT_COMPARE( f1, f2 ) \ + ( (f1)->face_id == (f2)->face_id && \ + (f1)->pix_width == (f2)->pix_width && \ + (f1)->pix_height == (f2)->pix_height ) + +#define FTC_FONT_HASH( f ) \ + (FT_UInt32)( FTC_FACE_ID_HASH((f)->face_id) ^ \ + ((f)->pix_width << 8) ^ \ + ((f)->pix_height) ) + + typedef FTC_FontRec* FTC_Font; + + + FT_EXPORT( FT_Error ) + FTC_Manager_Lookup_Face( FTC_Manager manager, + FTC_FaceID face_id, + FT_Face *aface ); + + FT_EXPORT( FT_Error ) + FTC_Manager_Lookup_Size( FTC_Manager manager, + FTC_Font font, + FT_Face *aface, + FT_Size *asize ); + +#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ + + + /* */ + +FT_END_HEADER + +#endif /* __FTCACHE_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftchapters.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftchapters.h new file mode 100644 index 00000000..7775a6bb --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftchapters.h @@ -0,0 +1,103 @@ +/***************************************************************************/ +/* */ +/* This file defines the structure of the FreeType reference. */ +/* It is used by the python script which generates the HTML files. */ +/* */ +/***************************************************************************/ + + +/***************************************************************************/ +/* */ +/* <Chapter> */ +/* general_remarks */ +/* */ +/* <Title> */ +/* General Remarks */ +/* */ +/* <Sections> */ +/* user_allocation */ +/* */ +/***************************************************************************/ + + +/***************************************************************************/ +/* */ +/* <Chapter> */ +/* core_api */ +/* */ +/* <Title> */ +/* Core API */ +/* */ +/* <Sections> */ +/* version */ +/* basic_types */ +/* base_interface */ +/* glyph_variants */ +/* glyph_management */ +/* mac_specific */ +/* sizes_management */ +/* header_file_macros */ +/* */ +/***************************************************************************/ + + +/***************************************************************************/ +/* */ +/* <Chapter> */ +/* format_specific */ +/* */ +/* <Title> */ +/* Format-Specific API */ +/* */ +/* <Sections> */ +/* multiple_masters */ +/* truetype_tables */ +/* type1_tables */ +/* sfnt_names */ +/* bdf_fonts */ +/* cid_fonts */ +/* pfr_fonts */ +/* winfnt_fonts */ +/* font_formats */ +/* gasp_table */ +/* */ +/***************************************************************************/ + + +/***************************************************************************/ +/* */ +/* <Chapter> */ +/* cache_subsystem */ +/* */ +/* <Title> */ +/* Cache Sub-System */ +/* */ +/* <Sections> */ +/* cache_subsystem */ +/* */ +/***************************************************************************/ + + +/***************************************************************************/ +/* */ +/* <Chapter> */ +/* support_api */ +/* */ +/* <Title> */ +/* Support API */ +/* */ +/* <Sections> */ +/* computations */ +/* list_processing */ +/* outline_processing */ +/* quick_advance */ +/* bitmap_handling */ +/* raster */ +/* glyph_stroker */ +/* system_interface */ +/* module_management */ +/* gzip */ +/* lzw */ +/* lcd_filtering */ +/* */ +/***************************************************************************/ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftcid.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftcid.h new file mode 100644 index 00000000..203a30ca --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftcid.h @@ -0,0 +1,166 @@ +/***************************************************************************/ +/* */ +/* ftcid.h */ +/* */ +/* FreeType API for accessing CID font information (specification). */ +/* */ +/* Copyright 2007, 2009 by Dereg Clegg, Michael Toftdal. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTCID_H__ +#define __FTCID_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* cid_fonts */ + /* */ + /* <Title> */ + /* CID Fonts */ + /* */ + /* <Abstract> */ + /* CID-keyed font specific API. */ + /* */ + /* <Description> */ + /* This section contains the declaration of CID-keyed font specific */ + /* functions. */ + /* */ + /*************************************************************************/ + + + /********************************************************************** + * + * @function: + * FT_Get_CID_Registry_Ordering_Supplement + * + * @description: + * Retrieve the Registry/Ordering/Supplement triple (also known as the + * "R/O/S") from a CID-keyed font. + * + * @input: + * face :: + * A handle to the input face. + * + * @output: + * registry :: + * The registry, as a C~string, owned by the face. + * + * ordering :: + * The ordering, as a C~string, owned by the face. + * + * supplement :: + * The supplement. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * This function only works with CID faces, returning an error + * otherwise. + * + * @since: + * 2.3.6 + */ + FT_EXPORT( FT_Error ) + FT_Get_CID_Registry_Ordering_Supplement( FT_Face face, + const char* *registry, + const char* *ordering, + FT_Int *supplement); + + + /********************************************************************** + * + * @function: + * FT_Get_CID_Is_Internally_CID_Keyed + * + * @description: + * Retrieve the type of the input face, CID keyed or not. In + * constrast to the @FT_IS_CID_KEYED macro this function returns + * successfully also for CID-keyed fonts in an SNFT wrapper. + * + * @input: + * face :: + * A handle to the input face. + * + * @output: + * is_cid :: + * The type of the face as an @FT_Bool. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * This function only works with CID faces and OpenType fonts, + * returning an error otherwise. + * + * @since: + * 2.3.9 + */ + FT_EXPORT( FT_Error ) + FT_Get_CID_Is_Internally_CID_Keyed( FT_Face face, + FT_Bool *is_cid ); + + + /********************************************************************** + * + * @function: + * FT_Get_CID_From_Glyph_Index + * + * @description: + * Retrieve the CID of the input glyph index. + * + * @input: + * face :: + * A handle to the input face. + * + * glyph_index :: + * The input glyph index. + * + * @output: + * cid :: + * The CID as an @FT_UInt. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * This function only works with CID faces and OpenType fonts, + * returning an error otherwise. + * + * @since: + * 2.3.9 + */ + FT_EXPORT( FT_Error ) + FT_Get_CID_From_Glyph_Index( FT_Face face, + FT_UInt glyph_index, + FT_UInt *cid ); + + /* */ + +FT_END_HEADER + +#endif /* __FTCID_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/fterrdef.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/fterrdef.h new file mode 100644 index 00000000..bf522206 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/fterrdef.h @@ -0,0 +1,244 @@ +/***************************************************************************/ +/* */ +/* fterrdef.h */ +/* */ +/* FreeType error codes (specification). */ +/* */ +/* Copyright 2002, 2004, 2006, 2007, 2010 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*******************************************************************/ + /*******************************************************************/ + /***** *****/ + /***** LIST OF ERROR CODES/MESSAGES *****/ + /***** *****/ + /*******************************************************************/ + /*******************************************************************/ + + + /* You need to define both FT_ERRORDEF_ and FT_NOERRORDEF_ before */ + /* including this file. */ + + + /* generic errors */ + + FT_NOERRORDEF_( Ok, 0x00, \ + "no error" ) + + FT_ERRORDEF_( Cannot_Open_Resource, 0x01, \ + "cannot open resource" ) + FT_ERRORDEF_( Unknown_File_Format, 0x02, \ + "unknown file format" ) + FT_ERRORDEF_( Invalid_File_Format, 0x03, \ + "broken file" ) + FT_ERRORDEF_( Invalid_Version, 0x04, \ + "invalid FreeType version" ) + FT_ERRORDEF_( Lower_Module_Version, 0x05, \ + "module version is too low" ) + FT_ERRORDEF_( Invalid_Argument, 0x06, \ + "invalid argument" ) + FT_ERRORDEF_( Unimplemented_Feature, 0x07, \ + "unimplemented feature" ) + FT_ERRORDEF_( Invalid_Table, 0x08, \ + "broken table" ) + FT_ERRORDEF_( Invalid_Offset, 0x09, \ + "broken offset within table" ) + FT_ERRORDEF_( Array_Too_Large, 0x0A, \ + "array allocation size too large" ) + + /* glyph/character errors */ + + FT_ERRORDEF_( Invalid_Glyph_Index, 0x10, \ + "invalid glyph index" ) + FT_ERRORDEF_( Invalid_Character_Code, 0x11, \ + "invalid character code" ) + FT_ERRORDEF_( Invalid_Glyph_Format, 0x12, \ + "unsupported glyph image format" ) + FT_ERRORDEF_( Cannot_Render_Glyph, 0x13, \ + "cannot render this glyph format" ) + FT_ERRORDEF_( Invalid_Outline, 0x14, \ + "invalid outline" ) + FT_ERRORDEF_( Invalid_Composite, 0x15, \ + "invalid composite glyph" ) + FT_ERRORDEF_( Too_Many_Hints, 0x16, \ + "too many hints" ) + FT_ERRORDEF_( Invalid_Pixel_Size, 0x17, \ + "invalid pixel size" ) + + /* handle errors */ + + FT_ERRORDEF_( Invalid_Handle, 0x20, \ + "invalid object handle" ) + FT_ERRORDEF_( Invalid_Library_Handle, 0x21, \ + "invalid library handle" ) + FT_ERRORDEF_( Invalid_Driver_Handle, 0x22, \ + "invalid module handle" ) + FT_ERRORDEF_( Invalid_Face_Handle, 0x23, \ + "invalid face handle" ) + FT_ERRORDEF_( Invalid_Size_Handle, 0x24, \ + "invalid size handle" ) + FT_ERRORDEF_( Invalid_Slot_Handle, 0x25, \ + "invalid glyph slot handle" ) + FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26, \ + "invalid charmap handle" ) + FT_ERRORDEF_( Invalid_Cache_Handle, 0x27, \ + "invalid cache manager handle" ) + FT_ERRORDEF_( Invalid_Stream_Handle, 0x28, \ + "invalid stream handle" ) + + /* driver errors */ + + FT_ERRORDEF_( Too_Many_Drivers, 0x30, \ + "too many modules" ) + FT_ERRORDEF_( Too_Many_Extensions, 0x31, \ + "too many extensions" ) + + /* memory errors */ + + FT_ERRORDEF_( Out_Of_Memory, 0x40, \ + "out of memory" ) + FT_ERRORDEF_( Unlisted_Object, 0x41, \ + "unlisted object" ) + + /* stream errors */ + + FT_ERRORDEF_( Cannot_Open_Stream, 0x51, \ + "cannot open stream" ) + FT_ERRORDEF_( Invalid_Stream_Seek, 0x52, \ + "invalid stream seek" ) + FT_ERRORDEF_( Invalid_Stream_Skip, 0x53, \ + "invalid stream skip" ) + FT_ERRORDEF_( Invalid_Stream_Read, 0x54, \ + "invalid stream read" ) + FT_ERRORDEF_( Invalid_Stream_Operation, 0x55, \ + "invalid stream operation" ) + FT_ERRORDEF_( Invalid_Frame_Operation, 0x56, \ + "invalid frame operation" ) + FT_ERRORDEF_( Nested_Frame_Access, 0x57, \ + "nested frame access" ) + FT_ERRORDEF_( Invalid_Frame_Read, 0x58, \ + "invalid frame read" ) + + /* raster errors */ + + FT_ERRORDEF_( Raster_Uninitialized, 0x60, \ + "raster uninitialized" ) + FT_ERRORDEF_( Raster_Corrupted, 0x61, \ + "raster corrupted" ) + FT_ERRORDEF_( Raster_Overflow, 0x62, \ + "raster overflow" ) + FT_ERRORDEF_( Raster_Negative_Height, 0x63, \ + "negative height while rastering" ) + + /* cache errors */ + + FT_ERRORDEF_( Too_Many_Caches, 0x70, \ + "too many registered caches" ) + + /* TrueType and SFNT errors */ + + FT_ERRORDEF_( Invalid_Opcode, 0x80, \ + "invalid opcode" ) + FT_ERRORDEF_( Too_Few_Arguments, 0x81, \ + "too few arguments" ) + FT_ERRORDEF_( Stack_Overflow, 0x82, \ + "stack overflow" ) + FT_ERRORDEF_( Code_Overflow, 0x83, \ + "code overflow" ) + FT_ERRORDEF_( Bad_Argument, 0x84, \ + "bad argument" ) + FT_ERRORDEF_( Divide_By_Zero, 0x85, \ + "division by zero" ) + FT_ERRORDEF_( Invalid_Reference, 0x86, \ + "invalid reference" ) + FT_ERRORDEF_( Debug_OpCode, 0x87, \ + "found debug opcode" ) + FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88, \ + "found ENDF opcode in execution stream" ) + FT_ERRORDEF_( Nested_DEFS, 0x89, \ + "nested DEFS" ) + FT_ERRORDEF_( Invalid_CodeRange, 0x8A, \ + "invalid code range" ) + FT_ERRORDEF_( Execution_Too_Long, 0x8B, \ + "execution context too long" ) + FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C, \ + "too many function definitions" ) + FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D, \ + "too many instruction definitions" ) + FT_ERRORDEF_( Table_Missing, 0x8E, \ + "SFNT font table missing" ) + FT_ERRORDEF_( Horiz_Header_Missing, 0x8F, \ + "horizontal header (hhea) table missing" ) + FT_ERRORDEF_( Locations_Missing, 0x90, \ + "locations (loca) table missing" ) + FT_ERRORDEF_( Name_Table_Missing, 0x91, \ + "name table missing" ) + FT_ERRORDEF_( CMap_Table_Missing, 0x92, \ + "character map (cmap) table missing" ) + FT_ERRORDEF_( Hmtx_Table_Missing, 0x93, \ + "horizontal metrics (hmtx) table missing" ) + FT_ERRORDEF_( Post_Table_Missing, 0x94, \ + "PostScript (post) table missing" ) + FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95, \ + "invalid horizontal metrics" ) + FT_ERRORDEF_( Invalid_CharMap_Format, 0x96, \ + "invalid character map (cmap) format" ) + FT_ERRORDEF_( Invalid_PPem, 0x97, \ + "invalid ppem value" ) + FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98, \ + "invalid vertical metrics" ) + FT_ERRORDEF_( Could_Not_Find_Context, 0x99, \ + "could not find context" ) + FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A, \ + "invalid PostScript (post) table format" ) + FT_ERRORDEF_( Invalid_Post_Table, 0x9B, \ + "invalid PostScript (post) table" ) + + /* CFF, CID, and Type 1 errors */ + + FT_ERRORDEF_( Syntax_Error, 0xA0, \ + "opcode syntax error" ) + FT_ERRORDEF_( Stack_Underflow, 0xA1, \ + "argument stack underflow" ) + FT_ERRORDEF_( Ignore, 0xA2, \ + "ignore" ) + FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3, \ + "no Unicode glyph name found" ) + + + /* BDF errors */ + + FT_ERRORDEF_( Missing_Startfont_Field, 0xB0, \ + "`STARTFONT' field missing" ) + FT_ERRORDEF_( Missing_Font_Field, 0xB1, \ + "`FONT' field missing" ) + FT_ERRORDEF_( Missing_Size_Field, 0xB2, \ + "`SIZE' field missing" ) + FT_ERRORDEF_( Missing_Fontboundingbox_Field, 0xB3, \ + "`FONTBOUNDINGBOX' field missing" ) + FT_ERRORDEF_( Missing_Chars_Field, 0xB4, \ + "`CHARS' field missing" ) + FT_ERRORDEF_( Missing_Startchar_Field, 0xB5, \ + "`STARTCHAR' field missing" ) + FT_ERRORDEF_( Missing_Encoding_Field, 0xB6, \ + "`ENCODING' field missing" ) + FT_ERRORDEF_( Missing_Bbx_Field, 0xB7, \ + "`BBX' field missing" ) + FT_ERRORDEF_( Bbx_Too_Big, 0xB8, \ + "`BBX' too big" ) + FT_ERRORDEF_( Corrupted_Font_Header, 0xB9, \ + "Font header corrupted or missing fields" ) + FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xBA, \ + "Font glyphs corrupted or missing fields" ) + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/fterrors.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/fterrors.h new file mode 100644 index 00000000..6600dadd --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/fterrors.h @@ -0,0 +1,206 @@ +/***************************************************************************/ +/* */ +/* fterrors.h */ +/* */ +/* FreeType error code handling (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2004, 2007 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This special header file is used to define the handling of FT2 */ + /* enumeration constants. It can also be used to generate error message */ + /* strings with a small macro trick explained below. */ + /* */ + /* I - Error Formats */ + /* ----------------- */ + /* */ + /* The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be */ + /* defined in ftoption.h in order to make the higher byte indicate */ + /* the module where the error has happened (this is not compatible */ + /* with standard builds of FreeType 2). You can then use the macro */ + /* FT_ERROR_BASE macro to extract the generic error code from an */ + /* FT_Error value. */ + /* */ + /* */ + /* II - Error Message strings */ + /* -------------------------- */ + /* */ + /* The error definitions below are made through special macros that */ + /* allow client applications to build a table of error message strings */ + /* if they need it. The strings are not included in a normal build of */ + /* FreeType 2 to save space (most client applications do not use */ + /* them). */ + /* */ + /* To do so, you have to define the following macros before including */ + /* this file: */ + /* */ + /* FT_ERROR_START_LIST :: */ + /* This macro is called before anything else to define the start of */ + /* the error list. It is followed by several FT_ERROR_DEF calls */ + /* (see below). */ + /* */ + /* FT_ERROR_DEF( e, v, s ) :: */ + /* This macro is called to define one single error. */ + /* `e' is the error code identifier (e.g. FT_Err_Invalid_Argument). */ + /* `v' is the error numerical value. */ + /* `s' is the corresponding error string. */ + /* */ + /* FT_ERROR_END_LIST :: */ + /* This macro ends the list. */ + /* */ + /* Additionally, you have to undefine __FTERRORS_H__ before #including */ + /* this file. */ + /* */ + /* Here is a simple example: */ + /* */ + /* { */ + /* #undef __FTERRORS_H__ */ + /* #define FT_ERRORDEF( e, v, s ) { e, s }, */ + /* #define FT_ERROR_START_LIST { */ + /* #define FT_ERROR_END_LIST { 0, 0 } }; */ + /* */ + /* const struct */ + /* { */ + /* int err_code; */ + /* const char* err_msg; */ + /* } ft_errors[] = */ + /* */ + /* #include FT_ERRORS_H */ + /* } */ + /* */ + /*************************************************************************/ + + +#ifndef __FTERRORS_H__ +#define __FTERRORS_H__ + + + /* include module base error codes */ +#include FT_MODULE_ERRORS_H + + + /*******************************************************************/ + /*******************************************************************/ + /***** *****/ + /***** SETUP MACROS *****/ + /***** *****/ + /*******************************************************************/ + /*******************************************************************/ + + +#undef FT_NEED_EXTERN_C + +#undef FT_ERR_XCAT +#undef FT_ERR_CAT + +#define FT_ERR_XCAT( x, y ) x ## y +#define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y ) + + + /* FT_ERR_PREFIX is used as a prefix for error identifiers. */ + /* By default, we use `FT_Err_'. */ + /* */ +#ifndef FT_ERR_PREFIX +#define FT_ERR_PREFIX FT_Err_ +#endif + + + /* FT_ERR_BASE is used as the base for module-specific errors. */ + /* */ +#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS + +#ifndef FT_ERR_BASE +#define FT_ERR_BASE FT_Mod_Err_Base +#endif + +#else + +#undef FT_ERR_BASE +#define FT_ERR_BASE 0 + +#endif /* FT_CONFIG_OPTION_USE_MODULE_ERRORS */ + + + /* If FT_ERRORDEF is not defined, we need to define a simple */ + /* enumeration type. */ + /* */ +#ifndef FT_ERRORDEF + +#define FT_ERRORDEF( e, v, s ) e = v, +#define FT_ERROR_START_LIST enum { +#define FT_ERROR_END_LIST FT_ERR_CAT( FT_ERR_PREFIX, Max ) }; + +#ifdef __cplusplus +#define FT_NEED_EXTERN_C + extern "C" { +#endif + +#endif /* !FT_ERRORDEF */ + + + /* this macro is used to define an error */ +#define FT_ERRORDEF_( e, v, s ) \ + FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v + FT_ERR_BASE, s ) + + /* this is only used for <module>_Err_Ok, which must be 0! */ +#define FT_NOERRORDEF_( e, v, s ) \ + FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v, s ) + + +#ifdef FT_ERROR_START_LIST + FT_ERROR_START_LIST +#endif + + + /* now include the error codes */ +#include FT_ERROR_DEFINITIONS_H + + +#ifdef FT_ERROR_END_LIST + FT_ERROR_END_LIST +#endif + + + /*******************************************************************/ + /*******************************************************************/ + /***** *****/ + /***** SIMPLE CLEANUP *****/ + /***** *****/ + /*******************************************************************/ + /*******************************************************************/ + +#ifdef FT_NEED_EXTERN_C + } +#endif + +#undef FT_ERROR_START_LIST +#undef FT_ERROR_END_LIST + +#undef FT_ERRORDEF +#undef FT_ERRORDEF_ +#undef FT_NOERRORDEF_ + +#undef FT_NEED_EXTERN_C +#undef FT_ERR_CONCAT +#undef FT_ERR_BASE + + /* FT_KEEP_ERR_PREFIX is needed for ftvalid.h */ +#ifndef FT_KEEP_ERR_PREFIX +#undef FT_ERR_PREFIX +#endif + +#endif /* __FTERRORS_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftgasp.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftgasp.h new file mode 100644 index 00000000..91a769e5 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftgasp.h @@ -0,0 +1,120 @@ +/***************************************************************************/ +/* */ +/* ftgasp.h */ +/* */ +/* Access of TrueType's `gasp' table (specification). */ +/* */ +/* Copyright 2007, 2008 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef _FT_GASP_H_ +#define _FT_GASP_H_ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + + /*************************************************************************** + * + * @section: + * gasp_table + * + * @title: + * Gasp Table + * + * @abstract: + * Retrieving TrueType `gasp' table entries. + * + * @description: + * The function @FT_Get_Gasp can be used to query a TrueType or OpenType + * font for specific entries in its `gasp' table, if any. This is + * mainly useful when implementing native TrueType hinting with the + * bytecode interpreter to duplicate the Windows text rendering results. + */ + + /************************************************************************* + * + * @enum: + * FT_GASP_XXX + * + * @description: + * A list of values and/or bit-flags returned by the @FT_Get_Gasp + * function. + * + * @values: + * FT_GASP_NO_TABLE :: + * This special value means that there is no GASP table in this face. + * It is up to the client to decide what to do. + * + * FT_GASP_DO_GRIDFIT :: + * Grid-fitting and hinting should be performed at the specified ppem. + * This *really* means TrueType bytecode interpretation. + * + * FT_GASP_DO_GRAY :: + * Anti-aliased rendering should be performed at the specified ppem. + * + * FT_GASP_SYMMETRIC_SMOOTHING :: + * Smoothing along multiple axes must be used with ClearType. + * + * FT_GASP_SYMMETRIC_GRIDFIT :: + * Grid-fitting must be used with ClearType's symmetric smoothing. + * + * @note: + * `ClearType' is Microsoft's implementation of LCD rendering, partly + * protected by patents. + * + * @since: + * 2.3.0 + */ +#define FT_GASP_NO_TABLE -1 +#define FT_GASP_DO_GRIDFIT 0x01 +#define FT_GASP_DO_GRAY 0x02 +#define FT_GASP_SYMMETRIC_SMOOTHING 0x08 +#define FT_GASP_SYMMETRIC_GRIDFIT 0x10 + + + /************************************************************************* + * + * @func: + * FT_Get_Gasp + * + * @description: + * Read the `gasp' table from a TrueType or OpenType font file and + * return the entry corresponding to a given character pixel size. + * + * @input: + * face :: The source face handle. + * ppem :: The vertical character pixel size. + * + * @return: + * Bit flags (see @FT_GASP_XXX), or @FT_GASP_NO_TABLE if there is no + * `gasp' table in the face. + * + * @since: + * 2.3.0 + */ + FT_EXPORT( FT_Int ) + FT_Get_Gasp( FT_Face face, + FT_UInt ppem ); + +/* */ + +#endif /* _FT_GASP_H_ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftglyph.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftglyph.h new file mode 100644 index 00000000..0b8f0c04 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftglyph.h @@ -0,0 +1,613 @@ +/***************************************************************************/ +/* */ +/* ftglyph.h */ +/* */ +/* FreeType convenience functions to handle glyphs (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2006, 2008, 2009 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file contains the definition of several convenience functions */ + /* that can be used by client applications to easily retrieve glyph */ + /* bitmaps and outlines from a given face. */ + /* */ + /* These functions should be optional if you are writing a font server */ + /* or text layout engine on top of FreeType. However, they are pretty */ + /* handy for many other simple uses of the library. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTGLYPH_H__ +#define __FTGLYPH_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* glyph_management */ + /* */ + /* <Title> */ + /* Glyph Management */ + /* */ + /* <Abstract> */ + /* Generic interface to manage individual glyph data. */ + /* */ + /* <Description> */ + /* This section contains definitions used to manage glyph data */ + /* through generic FT_Glyph objects. Each of them can contain a */ + /* bitmap, a vector outline, or even images in other formats. */ + /* */ + /*************************************************************************/ + + + /* forward declaration to a private type */ + typedef struct FT_Glyph_Class_ FT_Glyph_Class; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Glyph */ + /* */ + /* <Description> */ + /* Handle to an object used to model generic glyph images. It is a */ + /* pointer to the @FT_GlyphRec structure and can contain a glyph */ + /* bitmap or pointer. */ + /* */ + /* <Note> */ + /* Glyph objects are not owned by the library. You must thus release */ + /* them manually (through @FT_Done_Glyph) _before_ calling */ + /* @FT_Done_FreeType. */ + /* */ + typedef struct FT_GlyphRec_* FT_Glyph; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_GlyphRec */ + /* */ + /* <Description> */ + /* The root glyph structure contains a given glyph image plus its */ + /* advance width in 16.16 fixed float format. */ + /* */ + /* <Fields> */ + /* library :: A handle to the FreeType library object. */ + /* */ + /* clazz :: A pointer to the glyph's class. Private. */ + /* */ + /* format :: The format of the glyph's image. */ + /* */ + /* advance :: A 16.16 vector that gives the glyph's advance width. */ + /* */ + typedef struct FT_GlyphRec_ + { + FT_Library library; + const FT_Glyph_Class* clazz; + FT_Glyph_Format format; + FT_Vector advance; + + } FT_GlyphRec; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_BitmapGlyph */ + /* */ + /* <Description> */ + /* A handle to an object used to model a bitmap glyph image. This is */ + /* a sub-class of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec. */ + /* */ + typedef struct FT_BitmapGlyphRec_* FT_BitmapGlyph; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_BitmapGlyphRec */ + /* */ + /* <Description> */ + /* A structure used for bitmap glyph images. This really is a */ + /* `sub-class' of @FT_GlyphRec. */ + /* */ + /* <Fields> */ + /* root :: The root @FT_Glyph fields. */ + /* */ + /* left :: The left-side bearing, i.e., the horizontal distance */ + /* from the current pen position to the left border of the */ + /* glyph bitmap. */ + /* */ + /* top :: The top-side bearing, i.e., the vertical distance from */ + /* the current pen position to the top border of the glyph */ + /* bitmap. This distance is positive for upwards~y! */ + /* */ + /* bitmap :: A descriptor for the bitmap. */ + /* */ + /* <Note> */ + /* You can typecast an @FT_Glyph to @FT_BitmapGlyph if you have */ + /* `glyph->format == FT_GLYPH_FORMAT_BITMAP'. This lets you access */ + /* the bitmap's contents easily. */ + /* */ + /* The corresponding pixel buffer is always owned by @FT_BitmapGlyph */ + /* and is thus created and destroyed with it. */ + /* */ + typedef struct FT_BitmapGlyphRec_ + { + FT_GlyphRec root; + FT_Int left; + FT_Int top; + FT_Bitmap bitmap; + + } FT_BitmapGlyphRec; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_OutlineGlyph */ + /* */ + /* <Description> */ + /* A handle to an object used to model an outline glyph image. This */ + /* is a sub-class of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec. */ + /* */ + typedef struct FT_OutlineGlyphRec_* FT_OutlineGlyph; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_OutlineGlyphRec */ + /* */ + /* <Description> */ + /* A structure used for outline (vectorial) glyph images. This */ + /* really is a `sub-class' of @FT_GlyphRec. */ + /* */ + /* <Fields> */ + /* root :: The root @FT_Glyph fields. */ + /* */ + /* outline :: A descriptor for the outline. */ + /* */ + /* <Note> */ + /* You can typecast an @FT_Glyph to @FT_OutlineGlyph if you have */ + /* `glyph->format == FT_GLYPH_FORMAT_OUTLINE'. This lets you access */ + /* the outline's content easily. */ + /* */ + /* As the outline is extracted from a glyph slot, its coordinates are */ + /* expressed normally in 26.6 pixels, unless the flag */ + /* @FT_LOAD_NO_SCALE was used in @FT_Load_Glyph() or @FT_Load_Char(). */ + /* */ + /* The outline's tables are always owned by the object and are */ + /* destroyed with it. */ + /* */ + typedef struct FT_OutlineGlyphRec_ + { + FT_GlyphRec root; + FT_Outline outline; + + } FT_OutlineGlyphRec; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Glyph */ + /* */ + /* <Description> */ + /* A function used to extract a glyph image from a slot. Note that */ + /* the created @FT_Glyph object must be released with @FT_Done_Glyph. */ + /* */ + /* <Input> */ + /* slot :: A handle to the source glyph slot. */ + /* */ + /* <Output> */ + /* aglyph :: A handle to the glyph object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Glyph( FT_GlyphSlot slot, + FT_Glyph *aglyph ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Glyph_Copy */ + /* */ + /* <Description> */ + /* A function used to copy a glyph image. Note that the created */ + /* @FT_Glyph object must be released with @FT_Done_Glyph. */ + /* */ + /* <Input> */ + /* source :: A handle to the source glyph object. */ + /* */ + /* <Output> */ + /* target :: A handle to the target glyph object. 0~in case of */ + /* error. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Glyph_Copy( FT_Glyph source, + FT_Glyph *target ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Glyph_Transform */ + /* */ + /* <Description> */ + /* Transform a glyph image if its format is scalable. */ + /* */ + /* <InOut> */ + /* glyph :: A handle to the target glyph object. */ + /* */ + /* <Input> */ + /* matrix :: A pointer to a 2x2 matrix to apply. */ + /* */ + /* delta :: A pointer to a 2d vector to apply. Coordinates are */ + /* expressed in 1/64th of a pixel. */ + /* */ + /* <Return> */ + /* FreeType error code (if not 0, the glyph format is not scalable). */ + /* */ + /* <Note> */ + /* The 2x2 transformation matrix is also applied to the glyph's */ + /* advance vector. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Glyph_Transform( FT_Glyph glyph, + FT_Matrix* matrix, + FT_Vector* delta ); + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Glyph_BBox_Mode */ + /* */ + /* <Description> */ + /* The mode how the values of @FT_Glyph_Get_CBox are returned. */ + /* */ + /* <Values> */ + /* FT_GLYPH_BBOX_UNSCALED :: */ + /* Return unscaled font units. */ + /* */ + /* FT_GLYPH_BBOX_SUBPIXELS :: */ + /* Return unfitted 26.6 coordinates. */ + /* */ + /* FT_GLYPH_BBOX_GRIDFIT :: */ + /* Return grid-fitted 26.6 coordinates. */ + /* */ + /* FT_GLYPH_BBOX_TRUNCATE :: */ + /* Return coordinates in integer pixels. */ + /* */ + /* FT_GLYPH_BBOX_PIXELS :: */ + /* Return grid-fitted pixel coordinates. */ + /* */ + typedef enum FT_Glyph_BBox_Mode_ + { + FT_GLYPH_BBOX_UNSCALED = 0, + FT_GLYPH_BBOX_SUBPIXELS = 0, + FT_GLYPH_BBOX_GRIDFIT = 1, + FT_GLYPH_BBOX_TRUNCATE = 2, + FT_GLYPH_BBOX_PIXELS = 3 + + } FT_Glyph_BBox_Mode; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* ft_glyph_bbox_xxx */ + /* */ + /* <Description> */ + /* These constants are deprecated. Use the corresponding */ + /* @FT_Glyph_BBox_Mode values instead. */ + /* */ + /* <Values> */ + /* ft_glyph_bbox_unscaled :: See @FT_GLYPH_BBOX_UNSCALED. */ + /* ft_glyph_bbox_subpixels :: See @FT_GLYPH_BBOX_SUBPIXELS. */ + /* ft_glyph_bbox_gridfit :: See @FT_GLYPH_BBOX_GRIDFIT. */ + /* ft_glyph_bbox_truncate :: See @FT_GLYPH_BBOX_TRUNCATE. */ + /* ft_glyph_bbox_pixels :: See @FT_GLYPH_BBOX_PIXELS. */ + /* */ +#define ft_glyph_bbox_unscaled FT_GLYPH_BBOX_UNSCALED +#define ft_glyph_bbox_subpixels FT_GLYPH_BBOX_SUBPIXELS +#define ft_glyph_bbox_gridfit FT_GLYPH_BBOX_GRIDFIT +#define ft_glyph_bbox_truncate FT_GLYPH_BBOX_TRUNCATE +#define ft_glyph_bbox_pixels FT_GLYPH_BBOX_PIXELS + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Glyph_Get_CBox */ + /* */ + /* <Description> */ + /* Return a glyph's `control box'. The control box encloses all the */ + /* outline's points, including Bézier control points. Though it */ + /* coincides with the exact bounding box for most glyphs, it can be */ + /* slightly larger in some situations (like when rotating an outline */ + /* which contains Bézier outside arcs). */ + /* */ + /* Computing the control box is very fast, while getting the bounding */ + /* box can take much more time as it needs to walk over all segments */ + /* and arcs in the outline. To get the latter, you can use the */ + /* `ftbbox' component which is dedicated to this single task. */ + /* */ + /* <Input> */ + /* glyph :: A handle to the source glyph object. */ + /* */ + /* mode :: The mode which indicates how to interpret the returned */ + /* bounding box values. */ + /* */ + /* <Output> */ + /* acbox :: The glyph coordinate bounding box. Coordinates are */ + /* expressed in 1/64th of pixels if it is grid-fitted. */ + /* */ + /* <Note> */ + /* Coordinates are relative to the glyph origin, using the y~upwards */ + /* convention. */ + /* */ + /* If the glyph has been loaded with @FT_LOAD_NO_SCALE, `bbox_mode' */ + /* must be set to @FT_GLYPH_BBOX_UNSCALED to get unscaled font */ + /* units in 26.6 pixel format. The value @FT_GLYPH_BBOX_SUBPIXELS */ + /* is another name for this constant. */ + /* */ + /* Note that the maximum coordinates are exclusive, which means that */ + /* one can compute the width and height of the glyph image (be it in */ + /* integer or 26.6 pixels) as: */ + /* */ + /* { */ + /* width = bbox.xMax - bbox.xMin; */ + /* height = bbox.yMax - bbox.yMin; */ + /* } */ + /* */ + /* Note also that for 26.6 coordinates, if `bbox_mode' is set to */ + /* @FT_GLYPH_BBOX_GRIDFIT, the coordinates will also be grid-fitted, */ + /* which corresponds to: */ + /* */ + /* { */ + /* bbox.xMin = FLOOR(bbox.xMin); */ + /* bbox.yMin = FLOOR(bbox.yMin); */ + /* bbox.xMax = CEILING(bbox.xMax); */ + /* bbox.yMax = CEILING(bbox.yMax); */ + /* } */ + /* */ + /* To get the bbox in pixel coordinates, set `bbox_mode' to */ + /* @FT_GLYPH_BBOX_TRUNCATE. */ + /* */ + /* To get the bbox in grid-fitted pixel coordinates, set `bbox_mode' */ + /* to @FT_GLYPH_BBOX_PIXELS. */ + /* */ + FT_EXPORT( void ) + FT_Glyph_Get_CBox( FT_Glyph glyph, + FT_UInt bbox_mode, + FT_BBox *acbox ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Glyph_To_Bitmap */ + /* */ + /* <Description> */ + /* Convert a given glyph object to a bitmap glyph object. */ + /* */ + /* <InOut> */ + /* the_glyph :: A pointer to a handle to the target glyph. */ + /* */ + /* <Input> */ + /* render_mode :: An enumeration that describes how the data is */ + /* rendered. */ + /* */ + /* origin :: A pointer to a vector used to translate the glyph */ + /* image before rendering. Can be~0 (if no */ + /* translation). The origin is expressed in */ + /* 26.6 pixels. */ + /* */ + /* destroy :: A boolean that indicates that the original glyph */ + /* image should be destroyed by this function. It is */ + /* never destroyed in case of error. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* This function does nothing if the glyph format isn't scalable. */ + /* */ + /* The glyph image is translated with the `origin' vector before */ + /* rendering. */ + /* */ + /* The first parameter is a pointer to an @FT_Glyph handle, that will */ + /* be _replaced_ by this function (with newly allocated data). */ + /* Typically, you would use (omitting error handling): */ + /* */ + /* */ + /* { */ + /* FT_Glyph glyph; */ + /* FT_BitmapGlyph glyph_bitmap; */ + /* */ + /* */ + /* // load glyph */ + /* error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT ); */ + /* */ + /* // extract glyph image */ + /* error = FT_Get_Glyph( face->glyph, &glyph ); */ + /* */ + /* // convert to a bitmap (default render mode + destroying old) */ + /* if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) */ + /* { */ + /* error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, */ + /* 0, 1 ); */ + /* if ( error ) // `glyph' unchanged */ + /* ... */ + /* } */ + /* */ + /* // access bitmap content by typecasting */ + /* glyph_bitmap = (FT_BitmapGlyph)glyph; */ + /* */ + /* // do funny stuff with it, like blitting/drawing */ + /* ... */ + /* */ + /* // discard glyph image (bitmap or not) */ + /* FT_Done_Glyph( glyph ); */ + /* } */ + /* */ + /* */ + /* Here another example, again without error handling: */ + /* */ + /* */ + /* { */ + /* FT_Glyph glyphs[MAX_GLYPHS] */ + /* */ + /* */ + /* ... */ + /* */ + /* for ( idx = 0; i < MAX_GLYPHS; i++ ) */ + /* error = FT_Load_Glyph( face, idx, FT_LOAD_DEFAULT ) || */ + /* FT_Get_Glyph ( face->glyph, &glyph[idx] ); */ + /* */ + /* ... */ + /* */ + /* for ( idx = 0; i < MAX_GLYPHS; i++ ) */ + /* { */ + /* FT_Glyph bitmap = glyphs[idx]; */ + /* */ + /* */ + /* ... */ + /* */ + /* // after this call, `bitmap' no longer points into */ + /* // the `glyphs' array (and the old value isn't destroyed) */ + /* FT_Glyph_To_Bitmap( &bitmap, FT_RENDER_MODE_MONO, 0, 0 ); */ + /* */ + /* ... */ + /* */ + /* FT_Done_Glyph( bitmap ); */ + /* } */ + /* */ + /* ... */ + /* */ + /* for ( idx = 0; i < MAX_GLYPHS; i++ ) */ + /* FT_Done_Glyph( glyphs[idx] ); */ + /* } */ + /* */ + FT_EXPORT( FT_Error ) + FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, + FT_Render_Mode render_mode, + FT_Vector* origin, + FT_Bool destroy ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Done_Glyph */ + /* */ + /* <Description> */ + /* Destroy a given glyph. */ + /* */ + /* <Input> */ + /* glyph :: A handle to the target glyph object. */ + /* */ + FT_EXPORT( void ) + FT_Done_Glyph( FT_Glyph glyph ); + + /* */ + + + /* other helpful functions */ + + /*************************************************************************/ + /* */ + /* <Section> */ + /* computations */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Matrix_Multiply */ + /* */ + /* <Description> */ + /* Perform the matrix operation `b = a*b'. */ + /* */ + /* <Input> */ + /* a :: A pointer to matrix `a'. */ + /* */ + /* <InOut> */ + /* b :: A pointer to matrix `b'. */ + /* */ + /* <Note> */ + /* The result is undefined if either `a' or `b' is zero. */ + /* */ + FT_EXPORT( void ) + FT_Matrix_Multiply( const FT_Matrix* a, + FT_Matrix* b ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Matrix_Invert */ + /* */ + /* <Description> */ + /* Invert a 2x2 matrix. Return an error if it can't be inverted. */ + /* */ + /* <InOut> */ + /* matrix :: A pointer to the target matrix. Remains untouched in */ + /* case of error. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Matrix_Invert( FT_Matrix* matrix ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTGLYPH_H__ */ + + +/* END */ + + +/* Local Variables: */ +/* coding: utf-8 */ +/* End: */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftgxval.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftgxval.h new file mode 100644 index 00000000..497015c1 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftgxval.h @@ -0,0 +1,358 @@ +/***************************************************************************/ +/* */ +/* ftgxval.h */ +/* */ +/* FreeType API for validating TrueTypeGX/AAT tables (specification). */ +/* */ +/* Copyright 2004, 2005, 2006 by */ +/* Masatake YAMATO, Redhat K.K, */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +/***************************************************************************/ +/* */ +/* gxvalid is derived from both gxlayout module and otvalid module. */ +/* Development of gxlayout is supported by the Information-technology */ +/* Promotion Agency(IPA), Japan. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTGXVAL_H__ +#define __FTGXVAL_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* gx_validation */ + /* */ + /* <Title> */ + /* TrueTypeGX/AAT Validation */ + /* */ + /* <Abstract> */ + /* An API to validate TrueTypeGX/AAT tables. */ + /* */ + /* <Description> */ + /* This section contains the declaration of functions to validate */ + /* some TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd, */ + /* trak, prop, lcar). */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Warning: Use FT_VALIDATE_XXX to validate a table. */ + /* Following definitions are for gxvalid developers. */ + /* */ + /* */ + /*************************************************************************/ + +#define FT_VALIDATE_feat_INDEX 0 +#define FT_VALIDATE_mort_INDEX 1 +#define FT_VALIDATE_morx_INDEX 2 +#define FT_VALIDATE_bsln_INDEX 3 +#define FT_VALIDATE_just_INDEX 4 +#define FT_VALIDATE_kern_INDEX 5 +#define FT_VALIDATE_opbd_INDEX 6 +#define FT_VALIDATE_trak_INDEX 7 +#define FT_VALIDATE_prop_INDEX 8 +#define FT_VALIDATE_lcar_INDEX 9 +#define FT_VALIDATE_GX_LAST_INDEX FT_VALIDATE_lcar_INDEX + + + /************************************************************************* + * + * @macro: + * FT_VALIDATE_GX_LENGTH + * + * @description: + * The number of tables checked in this module. Use it as a parameter + * for the `table-length' argument of function @FT_TrueTypeGX_Validate. + */ +#define FT_VALIDATE_GX_LENGTH (FT_VALIDATE_GX_LAST_INDEX + 1) + + /* */ + + /* Up to 0x1000 is used by otvalid. + Ox2xxx is reserved for feature OT extension. */ +#define FT_VALIDATE_GX_START 0x4000 +#define FT_VALIDATE_GX_BITFIELD( tag ) \ + ( FT_VALIDATE_GX_START << FT_VALIDATE_##tag##_INDEX ) + + + /********************************************************************** + * + * @enum: + * FT_VALIDATE_GXXXX + * + * @description: + * A list of bit-field constants used with @FT_TrueTypeGX_Validate to + * indicate which TrueTypeGX/AAT Type tables should be validated. + * + * @values: + * FT_VALIDATE_feat :: + * Validate `feat' table. + * + * FT_VALIDATE_mort :: + * Validate `mort' table. + * + * FT_VALIDATE_morx :: + * Validate `morx' table. + * + * FT_VALIDATE_bsln :: + * Validate `bsln' table. + * + * FT_VALIDATE_just :: + * Validate `just' table. + * + * FT_VALIDATE_kern :: + * Validate `kern' table. + * + * FT_VALIDATE_opbd :: + * Validate `opbd' table. + * + * FT_VALIDATE_trak :: + * Validate `trak' table. + * + * FT_VALIDATE_prop :: + * Validate `prop' table. + * + * FT_VALIDATE_lcar :: + * Validate `lcar' table. + * + * FT_VALIDATE_GX :: + * Validate all TrueTypeGX tables (feat, mort, morx, bsln, just, kern, + * opbd, trak, prop and lcar). + * + */ + +#define FT_VALIDATE_feat FT_VALIDATE_GX_BITFIELD( feat ) +#define FT_VALIDATE_mort FT_VALIDATE_GX_BITFIELD( mort ) +#define FT_VALIDATE_morx FT_VALIDATE_GX_BITFIELD( morx ) +#define FT_VALIDATE_bsln FT_VALIDATE_GX_BITFIELD( bsln ) +#define FT_VALIDATE_just FT_VALIDATE_GX_BITFIELD( just ) +#define FT_VALIDATE_kern FT_VALIDATE_GX_BITFIELD( kern ) +#define FT_VALIDATE_opbd FT_VALIDATE_GX_BITFIELD( opbd ) +#define FT_VALIDATE_trak FT_VALIDATE_GX_BITFIELD( trak ) +#define FT_VALIDATE_prop FT_VALIDATE_GX_BITFIELD( prop ) +#define FT_VALIDATE_lcar FT_VALIDATE_GX_BITFIELD( lcar ) + +#define FT_VALIDATE_GX ( FT_VALIDATE_feat | \ + FT_VALIDATE_mort | \ + FT_VALIDATE_morx | \ + FT_VALIDATE_bsln | \ + FT_VALIDATE_just | \ + FT_VALIDATE_kern | \ + FT_VALIDATE_opbd | \ + FT_VALIDATE_trak | \ + FT_VALIDATE_prop | \ + FT_VALIDATE_lcar ) + + + /* */ + + /********************************************************************** + * + * @function: + * FT_TrueTypeGX_Validate + * + * @description: + * Validate various TrueTypeGX tables to assure that all offsets and + * indices are valid. The idea is that a higher-level library which + * actually does the text layout can access those tables without + * error checking (which can be quite time consuming). + * + * @input: + * face :: + * A handle to the input face. + * + * validation_flags :: + * A bit field which specifies the tables to be validated. See + * @FT_VALIDATE_GXXXX for possible values. + * + * table_length :: + * The size of the `tables' array. Normally, @FT_VALIDATE_GX_LENGTH + * should be passed. + * + * @output: + * tables :: + * The array where all validated sfnt tables are stored. + * The array itself must be allocated by a client. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * This function only works with TrueTypeGX fonts, returning an error + * otherwise. + * + * After use, the application should deallocate the buffers pointed to by + * each `tables' element, by calling @FT_TrueTypeGX_Free. A NULL value + * indicates that the table either doesn't exist in the font, the + * application hasn't asked for validation, or the validator doesn't have + * the ability to validate the sfnt table. + */ + FT_EXPORT( FT_Error ) + FT_TrueTypeGX_Validate( FT_Face face, + FT_UInt validation_flags, + FT_Bytes tables[FT_VALIDATE_GX_LENGTH], + FT_UInt table_length ); + + + /* */ + + /********************************************************************** + * + * @function: + * FT_TrueTypeGX_Free + * + * @description: + * Free the buffer allocated by TrueTypeGX validator. + * + * @input: + * face :: + * A handle to the input face. + * + * table :: + * The pointer to the buffer allocated by + * @FT_TrueTypeGX_Validate. + * + * @note: + * This function must be used to free the buffer allocated by + * @FT_TrueTypeGX_Validate only. + */ + FT_EXPORT( void ) + FT_TrueTypeGX_Free( FT_Face face, + FT_Bytes table ); + + + /* */ + + /********************************************************************** + * + * @enum: + * FT_VALIDATE_CKERNXXX + * + * @description: + * A list of bit-field constants used with @FT_ClassicKern_Validate + * to indicate the classic kern dialect or dialects. If the selected + * type doesn't fit, @FT_ClassicKern_Validate regards the table as + * invalid. + * + * @values: + * FT_VALIDATE_MS :: + * Handle the `kern' table as a classic Microsoft kern table. + * + * FT_VALIDATE_APPLE :: + * Handle the `kern' table as a classic Apple kern table. + * + * FT_VALIDATE_CKERN :: + * Handle the `kern' as either classic Apple or Microsoft kern table. + */ +#define FT_VALIDATE_MS ( FT_VALIDATE_GX_START << 0 ) +#define FT_VALIDATE_APPLE ( FT_VALIDATE_GX_START << 1 ) + +#define FT_VALIDATE_CKERN ( FT_VALIDATE_MS | FT_VALIDATE_APPLE ) + + + /* */ + + /********************************************************************** + * + * @function: + * FT_ClassicKern_Validate + * + * @description: + * Validate classic (16-bit format) kern table to assure that the offsets + * and indices are valid. The idea is that a higher-level library which + * actually does the text layout can access those tables without error + * checking (which can be quite time consuming). + * + * The `kern' table validator in @FT_TrueTypeGX_Validate deals with both + * the new 32-bit format and the classic 16-bit format, while + * FT_ClassicKern_Validate only supports the classic 16-bit format. + * + * @input: + * face :: + * A handle to the input face. + * + * validation_flags :: + * A bit field which specifies the dialect to be validated. See + * @FT_VALIDATE_CKERNXXX for possible values. + * + * @output: + * ckern_table :: + * A pointer to the kern table. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * After use, the application should deallocate the buffers pointed to by + * `ckern_table', by calling @FT_ClassicKern_Free. A NULL value + * indicates that the table doesn't exist in the font. + */ + FT_EXPORT( FT_Error ) + FT_ClassicKern_Validate( FT_Face face, + FT_UInt validation_flags, + FT_Bytes *ckern_table ); + + + /* */ + + /********************************************************************** + * + * @function: + * FT_ClassicKern_Free + * + * @description: + * Free the buffer allocated by classic Kern validator. + * + * @input: + * face :: + * A handle to the input face. + * + * table :: + * The pointer to the buffer that is allocated by + * @FT_ClassicKern_Validate. + * + * @note: + * This function must be used to free the buffer allocated by + * @FT_ClassicKern_Validate only. + */ + FT_EXPORT( void ) + FT_ClassicKern_Free( FT_Face face, + FT_Bytes table ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTGXVAL_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftgzip.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftgzip.h new file mode 100644 index 00000000..acbc4f03 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftgzip.h @@ -0,0 +1,102 @@ +/***************************************************************************/ +/* */ +/* ftgzip.h */ +/* */ +/* Gzip-compressed stream support. */ +/* */ +/* Copyright 2002, 2003, 2004, 2006 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTGZIP_H__ +#define __FTGZIP_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + /*************************************************************************/ + /* */ + /* <Section> */ + /* gzip */ + /* */ + /* <Title> */ + /* GZIP Streams */ + /* */ + /* <Abstract> */ + /* Using gzip-compressed font files. */ + /* */ + /* <Description> */ + /* This section contains the declaration of Gzip-specific functions. */ + /* */ + /*************************************************************************/ + + + /************************************************************************ + * + * @function: + * FT_Stream_OpenGzip + * + * @description: + * Open a new stream to parse gzip-compressed font files. This is + * mainly used to support the compressed `*.pcf.gz' fonts that come + * with XFree86. + * + * @input: + * stream :: + * The target embedding stream. + * + * source :: + * The source stream. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * The source stream must be opened _before_ calling this function. + * + * Calling the internal function `FT_Stream_Close' on the new stream will + * *not* call `FT_Stream_Close' on the source stream. None of the stream + * objects will be released to the heap. + * + * The stream implementation is very basic and resets the decompression + * process each time seeking backwards is needed within the stream. + * + * In certain builds of the library, gzip compression recognition is + * automatically handled when calling @FT_New_Face or @FT_Open_Face. + * This means that if no font driver is capable of handling the raw + * compressed file, the library will try to open a gzipped stream from + * it and re-open the face with it. + * + * This function may return `FT_Err_Unimplemented_Feature' if your build + * of FreeType was not compiled with zlib support. + */ + FT_EXPORT( FT_Error ) + FT_Stream_OpenGzip( FT_Stream stream, + FT_Stream source ); + + /* */ + + +FT_END_HEADER + +#endif /* __FTGZIP_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftimage.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftimage.h new file mode 100644 index 00000000..0272e92d --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftimage.h @@ -0,0 +1,1301 @@ +/***************************************************************************/ +/* */ +/* ftimage.h */ +/* */ +/* FreeType glyph image formats and default raster interface */ +/* (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ +/* 2010 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* Note: A `raster' is simply a scan-line converter, used to render */ + /* FT_Outlines into FT_Bitmaps. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTIMAGE_H__ +#define __FTIMAGE_H__ + + + /* _STANDALONE_ is from ftgrays.c */ +#ifndef _STANDALONE_ +#include <ft2build.h> +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* basic_types */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Pos */ + /* */ + /* <Description> */ + /* The type FT_Pos is used to store vectorial coordinates. Depending */ + /* on the context, these can represent distances in integer font */ + /* units, or 16.16, or 26.6 fixed float pixel coordinates. */ + /* */ + typedef signed long FT_Pos; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Vector */ + /* */ + /* <Description> */ + /* A simple structure used to store a 2D vector; coordinates are of */ + /* the FT_Pos type. */ + /* */ + /* <Fields> */ + /* x :: The horizontal coordinate. */ + /* y :: The vertical coordinate. */ + /* */ + typedef struct FT_Vector_ + { + FT_Pos x; + FT_Pos y; + + } FT_Vector; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_BBox */ + /* */ + /* <Description> */ + /* A structure used to hold an outline's bounding box, i.e., the */ + /* coordinates of its extrema in the horizontal and vertical */ + /* directions. */ + /* */ + /* <Fields> */ + /* xMin :: The horizontal minimum (left-most). */ + /* */ + /* yMin :: The vertical minimum (bottom-most). */ + /* */ + /* xMax :: The horizontal maximum (right-most). */ + /* */ + /* yMax :: The vertical maximum (top-most). */ + /* */ + /* <Note> */ + /* The bounding box is specified with the coordinates of the lower */ + /* left and the upper right corner. In PostScript, those values are */ + /* often called (llx,lly) and (urx,ury), respectively. */ + /* */ + /* If `yMin' is negative, this value gives the glyph's descender. */ + /* Otherwise, the glyph doesn't descend below the baseline. */ + /* Similarly, if `ymax' is positive, this value gives the glyph's */ + /* ascender. */ + /* */ + /* `xMin' gives the horizontal distance from the glyph's origin to */ + /* the left edge of the glyph's bounding box. If `xMin' is negative, */ + /* the glyph extends to the left of the origin. */ + /* */ + typedef struct FT_BBox_ + { + FT_Pos xMin, yMin; + FT_Pos xMax, yMax; + + } FT_BBox; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Pixel_Mode */ + /* */ + /* <Description> */ + /* An enumeration type used to describe the format of pixels in a */ + /* given bitmap. Note that additional formats may be added in the */ + /* future. */ + /* */ + /* <Values> */ + /* FT_PIXEL_MODE_NONE :: */ + /* Value~0 is reserved. */ + /* */ + /* FT_PIXEL_MODE_MONO :: */ + /* A monochrome bitmap, using 1~bit per pixel. Note that pixels */ + /* are stored in most-significant order (MSB), which means that */ + /* the left-most pixel in a byte has value 128. */ + /* */ + /* FT_PIXEL_MODE_GRAY :: */ + /* An 8-bit bitmap, generally used to represent anti-aliased glyph */ + /* images. Each pixel is stored in one byte. Note that the number */ + /* of `gray' levels is stored in the `num_grays' field of the */ + /* @FT_Bitmap structure (it generally is 256). */ + /* */ + /* FT_PIXEL_MODE_GRAY2 :: */ + /* A 2-bit per pixel bitmap, used to represent embedded */ + /* anti-aliased bitmaps in font files according to the OpenType */ + /* specification. We haven't found a single font using this */ + /* format, however. */ + /* */ + /* FT_PIXEL_MODE_GRAY4 :: */ + /* A 4-bit per pixel bitmap, representing embedded anti-aliased */ + /* bitmaps in font files according to the OpenType specification. */ + /* We haven't found a single font using this format, however. */ + /* */ + /* FT_PIXEL_MODE_LCD :: */ + /* An 8-bit bitmap, representing RGB or BGR decimated glyph images */ + /* used for display on LCD displays; the bitmap is three times */ + /* wider than the original glyph image. See also */ + /* @FT_RENDER_MODE_LCD. */ + /* */ + /* FT_PIXEL_MODE_LCD_V :: */ + /* An 8-bit bitmap, representing RGB or BGR decimated glyph images */ + /* used for display on rotated LCD displays; the bitmap is three */ + /* times taller than the original glyph image. See also */ + /* @FT_RENDER_MODE_LCD_V. */ + /* */ + typedef enum FT_Pixel_Mode_ + { + FT_PIXEL_MODE_NONE = 0, + FT_PIXEL_MODE_MONO, + FT_PIXEL_MODE_GRAY, + FT_PIXEL_MODE_GRAY2, + FT_PIXEL_MODE_GRAY4, + FT_PIXEL_MODE_LCD, + FT_PIXEL_MODE_LCD_V, + + FT_PIXEL_MODE_MAX /* do not remove */ + + } FT_Pixel_Mode; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* ft_pixel_mode_xxx */ + /* */ + /* <Description> */ + /* A list of deprecated constants. Use the corresponding */ + /* @FT_Pixel_Mode values instead. */ + /* */ + /* <Values> */ + /* ft_pixel_mode_none :: See @FT_PIXEL_MODE_NONE. */ + /* ft_pixel_mode_mono :: See @FT_PIXEL_MODE_MONO. */ + /* ft_pixel_mode_grays :: See @FT_PIXEL_MODE_GRAY. */ + /* ft_pixel_mode_pal2 :: See @FT_PIXEL_MODE_GRAY2. */ + /* ft_pixel_mode_pal4 :: See @FT_PIXEL_MODE_GRAY4. */ + /* */ +#define ft_pixel_mode_none FT_PIXEL_MODE_NONE +#define ft_pixel_mode_mono FT_PIXEL_MODE_MONO +#define ft_pixel_mode_grays FT_PIXEL_MODE_GRAY +#define ft_pixel_mode_pal2 FT_PIXEL_MODE_GRAY2 +#define ft_pixel_mode_pal4 FT_PIXEL_MODE_GRAY4 + + /* */ + +#if 0 + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Palette_Mode */ + /* */ + /* <Description> */ + /* THIS TYPE IS DEPRECATED. DO NOT USE IT! */ + /* */ + /* An enumeration type to describe the format of a bitmap palette, */ + /* used with ft_pixel_mode_pal4 and ft_pixel_mode_pal8. */ + /* */ + /* <Values> */ + /* ft_palette_mode_rgb :: The palette is an array of 3-byte RGB */ + /* records. */ + /* */ + /* ft_palette_mode_rgba :: The palette is an array of 4-byte RGBA */ + /* records. */ + /* */ + /* <Note> */ + /* As ft_pixel_mode_pal2, pal4 and pal8 are currently unused by */ + /* FreeType, these types are not handled by the library itself. */ + /* */ + typedef enum FT_Palette_Mode_ + { + ft_palette_mode_rgb = 0, + ft_palette_mode_rgba, + + ft_palette_mode_max /* do not remove */ + + } FT_Palette_Mode; + + /* */ + +#endif + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Bitmap */ + /* */ + /* <Description> */ + /* A structure used to describe a bitmap or pixmap to the raster. */ + /* Note that we now manage pixmaps of various depths through the */ + /* `pixel_mode' field. */ + /* */ + /* <Fields> */ + /* rows :: The number of bitmap rows. */ + /* */ + /* width :: The number of pixels in bitmap row. */ + /* */ + /* pitch :: The pitch's absolute value is the number of bytes */ + /* taken by one bitmap row, including padding. */ + /* However, the pitch is positive when the bitmap has */ + /* a `down' flow, and negative when it has an `up' */ + /* flow. In all cases, the pitch is an offset to add */ + /* to a bitmap pointer in order to go down one row. */ + /* */ + /* For the B/W rasterizer, `pitch' is always an even */ + /* number. */ + /* */ + /* buffer :: A typeless pointer to the bitmap buffer. This */ + /* value should be aligned on 32-bit boundaries in */ + /* most cases. */ + /* */ + /* num_grays :: This field is only used with */ + /* @FT_PIXEL_MODE_GRAY; it gives the number of gray */ + /* levels used in the bitmap. */ + /* */ + /* pixel_mode :: The pixel mode, i.e., how pixel bits are stored. */ + /* See @FT_Pixel_Mode for possible values. */ + /* */ + /* palette_mode :: This field is intended for paletted pixel modes; */ + /* it indicates how the palette is stored. Not */ + /* used currently. */ + /* */ + /* palette :: A typeless pointer to the bitmap palette; this */ + /* field is intended for paletted pixel modes. Not */ + /* used currently. */ + /* */ + /* <Note> */ + /* For now, the only pixel modes supported by FreeType are mono and */ + /* grays. However, drivers might be added in the future to support */ + /* more `colorful' options. */ + /* */ + typedef struct FT_Bitmap_ + { + int rows; + int width; + int pitch; + unsigned char* buffer; + short num_grays; + char pixel_mode; + char palette_mode; + void* palette; + + } FT_Bitmap; + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* outline_processing */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Outline */ + /* */ + /* <Description> */ + /* This structure is used to describe an outline to the scan-line */ + /* converter. */ + /* */ + /* <Fields> */ + /* n_contours :: The number of contours in the outline. */ + /* */ + /* n_points :: The number of points in the outline. */ + /* */ + /* points :: A pointer to an array of `n_points' @FT_Vector */ + /* elements, giving the outline's point coordinates. */ + /* */ + /* tags :: A pointer to an array of `n_points' chars, giving */ + /* each outline point's type. */ + /* */ + /* If bit~0 is unset, the point is `off' the curve, */ + /* i.e., a Bézier control point, while it is `on' if */ + /* set. */ + /* */ + /* Bit~1 is meaningful for `off' points only. If set, */ + /* it indicates a third-order Bézier arc control point; */ + /* and a second-order control point if unset. */ + /* */ + /* If bit~2 is set, bits 5-7 contain the drop-out mode */ + /* (as defined in the OpenType specification; the value */ + /* is the same as the argument to the SCANMODE */ + /* instruction). */ + /* */ + /* Bits 3 and~4 are reserved for internal purposes. */ + /* */ + /* contours :: An array of `n_contours' shorts, giving the end */ + /* point of each contour within the outline. For */ + /* example, the first contour is defined by the points */ + /* `0' to `contours[0]', the second one is defined by */ + /* the points `contours[0]+1' to `contours[1]', etc. */ + /* */ + /* flags :: A set of bit flags used to characterize the outline */ + /* and give hints to the scan-converter and hinter on */ + /* how to convert/grid-fit it. See @FT_OUTLINE_FLAGS. */ + /* */ + /* <Note> */ + /* The B/W rasterizer only checks bit~2 in the `tags' array for the */ + /* first point of each contour. The drop-out mode as given with */ + /* @FT_OUTLINE_IGNORE_DROPOUTS, @FT_OUTLINE_SMART_DROPOUTS, and */ + /* @FT_OUTLINE_INCLUDE_STUBS in `flags' is then overridden. */ + /* */ + typedef struct FT_Outline_ + { + short n_contours; /* number of contours in glyph */ + short n_points; /* number of points in the glyph */ + + FT_Vector* points; /* the outline's points */ + char* tags; /* the points flags */ + short* contours; /* the contour end points */ + + int flags; /* outline masks */ + + } FT_Outline; + + /* Following limits must be consistent with */ + /* FT_Outline.{n_contours,n_points} */ +#define FT_OUTLINE_CONTOURS_MAX SHRT_MAX +#define FT_OUTLINE_POINTS_MAX SHRT_MAX + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_OUTLINE_FLAGS */ + /* */ + /* <Description> */ + /* A list of bit-field constants use for the flags in an outline's */ + /* `flags' field. */ + /* */ + /* <Values> */ + /* FT_OUTLINE_NONE :: */ + /* Value~0 is reserved. */ + /* */ + /* FT_OUTLINE_OWNER :: */ + /* If set, this flag indicates that the outline's field arrays */ + /* (i.e., `points', `flags', and `contours') are `owned' by the */ + /* outline object, and should thus be freed when it is destroyed. */ + /* */ + /* FT_OUTLINE_EVEN_ODD_FILL :: */ + /* By default, outlines are filled using the non-zero winding rule. */ + /* If set to 1, the outline will be filled using the even-odd fill */ + /* rule (only works with the smooth rasterizer). */ + /* */ + /* FT_OUTLINE_REVERSE_FILL :: */ + /* By default, outside contours of an outline are oriented in */ + /* clock-wise direction, as defined in the TrueType specification. */ + /* This flag is set if the outline uses the opposite direction */ + /* (typically for Type~1 fonts). This flag is ignored by the scan */ + /* converter. */ + /* */ + /* FT_OUTLINE_IGNORE_DROPOUTS :: */ + /* By default, the scan converter will try to detect drop-outs in */ + /* an outline and correct the glyph bitmap to ensure consistent */ + /* shape continuity. If set, this flag hints the scan-line */ + /* converter to ignore such cases. See below for more information. */ + /* */ + /* FT_OUTLINE_SMART_DROPOUTS :: */ + /* Select smart dropout control. If unset, use simple dropout */ + /* control. Ignored if @FT_OUTLINE_IGNORE_DROPOUTS is set. See */ + /* below for more information. */ + /* */ + /* FT_OUTLINE_INCLUDE_STUBS :: */ + /* If set, turn pixels on for `stubs', otherwise exclude them. */ + /* Ignored if @FT_OUTLINE_IGNORE_DROPOUTS is set. See below for */ + /* more information. */ + /* */ + /* FT_OUTLINE_HIGH_PRECISION :: */ + /* This flag indicates that the scan-line converter should try to */ + /* convert this outline to bitmaps with the highest possible */ + /* quality. It is typically set for small character sizes. Note */ + /* that this is only a hint that might be completely ignored by a */ + /* given scan-converter. */ + /* */ + /* FT_OUTLINE_SINGLE_PASS :: */ + /* This flag is set to force a given scan-converter to only use a */ + /* single pass over the outline to render a bitmap glyph image. */ + /* Normally, it is set for very large character sizes. It is only */ + /* a hint that might be completely ignored by a given */ + /* scan-converter. */ + /* */ + /* <Note> */ + /* The flags @FT_OUTLINE_IGNORE_DROPOUTS, @FT_OUTLINE_SMART_DROPOUTS, */ + /* and @FT_OUTLINE_INCLUDE_STUBS are ignored by the smooth */ + /* rasterizer. */ + /* */ + /* There exists a second mechanism to pass the drop-out mode to the */ + /* B/W rasterizer; see the `tags' field in @FT_Outline. */ + /* */ + /* Please refer to the description of the `SCANTYPE' instruction in */ + /* the OpenType specification (in file `ttinst1.doc') how simple */ + /* drop-outs, smart drop-outs, and stubs are defined. */ + /* */ +#define FT_OUTLINE_NONE 0x0 +#define FT_OUTLINE_OWNER 0x1 +#define FT_OUTLINE_EVEN_ODD_FILL 0x2 +#define FT_OUTLINE_REVERSE_FILL 0x4 +#define FT_OUTLINE_IGNORE_DROPOUTS 0x8 +#define FT_OUTLINE_SMART_DROPOUTS 0x10 +#define FT_OUTLINE_INCLUDE_STUBS 0x20 + +#define FT_OUTLINE_HIGH_PRECISION 0x100 +#define FT_OUTLINE_SINGLE_PASS 0x200 + + + /************************************************************************* + * + * @enum: + * ft_outline_flags + * + * @description: + * These constants are deprecated. Please use the corresponding + * @FT_OUTLINE_FLAGS values. + * + * @values: + * ft_outline_none :: See @FT_OUTLINE_NONE. + * ft_outline_owner :: See @FT_OUTLINE_OWNER. + * ft_outline_even_odd_fill :: See @FT_OUTLINE_EVEN_ODD_FILL. + * ft_outline_reverse_fill :: See @FT_OUTLINE_REVERSE_FILL. + * ft_outline_ignore_dropouts :: See @FT_OUTLINE_IGNORE_DROPOUTS. + * ft_outline_high_precision :: See @FT_OUTLINE_HIGH_PRECISION. + * ft_outline_single_pass :: See @FT_OUTLINE_SINGLE_PASS. + */ +#define ft_outline_none FT_OUTLINE_NONE +#define ft_outline_owner FT_OUTLINE_OWNER +#define ft_outline_even_odd_fill FT_OUTLINE_EVEN_ODD_FILL +#define ft_outline_reverse_fill FT_OUTLINE_REVERSE_FILL +#define ft_outline_ignore_dropouts FT_OUTLINE_IGNORE_DROPOUTS +#define ft_outline_high_precision FT_OUTLINE_HIGH_PRECISION +#define ft_outline_single_pass FT_OUTLINE_SINGLE_PASS + + /* */ + +#define FT_CURVE_TAG( flag ) ( flag & 3 ) + +#define FT_CURVE_TAG_ON 1 +#define FT_CURVE_TAG_CONIC 0 +#define FT_CURVE_TAG_CUBIC 2 + +#define FT_CURVE_TAG_HAS_SCANMODE 4 + +#define FT_CURVE_TAG_TOUCH_X 8 /* reserved for the TrueType hinter */ +#define FT_CURVE_TAG_TOUCH_Y 16 /* reserved for the TrueType hinter */ + +#define FT_CURVE_TAG_TOUCH_BOTH ( FT_CURVE_TAG_TOUCH_X | \ + FT_CURVE_TAG_TOUCH_Y ) + +#define FT_Curve_Tag_On FT_CURVE_TAG_ON +#define FT_Curve_Tag_Conic FT_CURVE_TAG_CONIC +#define FT_Curve_Tag_Cubic FT_CURVE_TAG_CUBIC +#define FT_Curve_Tag_Touch_X FT_CURVE_TAG_TOUCH_X +#define FT_Curve_Tag_Touch_Y FT_CURVE_TAG_TOUCH_Y + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Outline_MoveToFunc */ + /* */ + /* <Description> */ + /* A function pointer type used to describe the signature of a `move */ + /* to' function during outline walking/decomposition. */ + /* */ + /* A `move to' is emitted to start a new contour in an outline. */ + /* */ + /* <Input> */ + /* to :: A pointer to the target point of the `move to'. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of the */ + /* decomposition function. */ + /* */ + /* <Return> */ + /* Error code. 0~means success. */ + /* */ + typedef int + (*FT_Outline_MoveToFunc)( const FT_Vector* to, + void* user ); + +#define FT_Outline_MoveTo_Func FT_Outline_MoveToFunc + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Outline_LineToFunc */ + /* */ + /* <Description> */ + /* A function pointer type used to describe the signature of a `line */ + /* to' function during outline walking/decomposition. */ + /* */ + /* A `line to' is emitted to indicate a segment in the outline. */ + /* */ + /* <Input> */ + /* to :: A pointer to the target point of the `line to'. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of the */ + /* decomposition function. */ + /* */ + /* <Return> */ + /* Error code. 0~means success. */ + /* */ + typedef int + (*FT_Outline_LineToFunc)( const FT_Vector* to, + void* user ); + +#define FT_Outline_LineTo_Func FT_Outline_LineToFunc + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Outline_ConicToFunc */ + /* */ + /* <Description> */ + /* A function pointer type used to describe the signature of a `conic */ + /* to' function during outline walking or decomposition. */ + /* */ + /* A `conic to' is emitted to indicate a second-order Bézier arc in */ + /* the outline. */ + /* */ + /* <Input> */ + /* control :: An intermediate control point between the last position */ + /* and the new target in `to'. */ + /* */ + /* to :: A pointer to the target end point of the conic arc. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of */ + /* the decomposition function. */ + /* */ + /* <Return> */ + /* Error code. 0~means success. */ + /* */ + typedef int + (*FT_Outline_ConicToFunc)( const FT_Vector* control, + const FT_Vector* to, + void* user ); + +#define FT_Outline_ConicTo_Func FT_Outline_ConicToFunc + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Outline_CubicToFunc */ + /* */ + /* <Description> */ + /* A function pointer type used to describe the signature of a `cubic */ + /* to' function during outline walking or decomposition. */ + /* */ + /* A `cubic to' is emitted to indicate a third-order Bézier arc. */ + /* */ + /* <Input> */ + /* control1 :: A pointer to the first Bézier control point. */ + /* */ + /* control2 :: A pointer to the second Bézier control point. */ + /* */ + /* to :: A pointer to the target end point. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of */ + /* the decomposition function. */ + /* */ + /* <Return> */ + /* Error code. 0~means success. */ + /* */ + typedef int + (*FT_Outline_CubicToFunc)( const FT_Vector* control1, + const FT_Vector* control2, + const FT_Vector* to, + void* user ); + +#define FT_Outline_CubicTo_Func FT_Outline_CubicToFunc + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Outline_Funcs */ + /* */ + /* <Description> */ + /* A structure to hold various function pointers used during outline */ + /* decomposition in order to emit segments, conic, and cubic Béziers. */ + /* */ + /* <Fields> */ + /* move_to :: The `move to' emitter. */ + /* */ + /* line_to :: The segment emitter. */ + /* */ + /* conic_to :: The second-order Bézier arc emitter. */ + /* */ + /* cubic_to :: The third-order Bézier arc emitter. */ + /* */ + /* shift :: The shift that is applied to coordinates before they */ + /* are sent to the emitter. */ + /* */ + /* delta :: The delta that is applied to coordinates before they */ + /* are sent to the emitter, but after the shift. */ + /* */ + /* <Note> */ + /* The point coordinates sent to the emitters are the transformed */ + /* version of the original coordinates (this is important for high */ + /* accuracy during scan-conversion). The transformation is simple: */ + /* */ + /* { */ + /* x' = (x << shift) - delta */ + /* y' = (x << shift) - delta */ + /* } */ + /* */ + /* Set the values of `shift' and `delta' to~0 to get the original */ + /* point coordinates. */ + /* */ + typedef struct FT_Outline_Funcs_ + { + FT_Outline_MoveToFunc move_to; + FT_Outline_LineToFunc line_to; + FT_Outline_ConicToFunc conic_to; + FT_Outline_CubicToFunc cubic_to; + + int shift; + FT_Pos delta; + + } FT_Outline_Funcs; + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* basic_types */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Macro> */ + /* FT_IMAGE_TAG */ + /* */ + /* <Description> */ + /* This macro converts four-letter tags to an unsigned long type. */ + /* */ + /* <Note> */ + /* Since many 16-bit compilers don't like 32-bit enumerations, you */ + /* should redefine this macro in case of problems to something like */ + /* this: */ + /* */ + /* { */ + /* #define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) value */ + /* } */ + /* */ + /* to get a simple enumeration without assigning special numbers. */ + /* */ +#ifndef FT_IMAGE_TAG +#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) \ + value = ( ( (unsigned long)_x1 << 24 ) | \ + ( (unsigned long)_x2 << 16 ) | \ + ( (unsigned long)_x3 << 8 ) | \ + (unsigned long)_x4 ) +#endif /* FT_IMAGE_TAG */ + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Glyph_Format */ + /* */ + /* <Description> */ + /* An enumeration type used to describe the format of a given glyph */ + /* image. Note that this version of FreeType only supports two image */ + /* formats, even though future font drivers will be able to register */ + /* their own format. */ + /* */ + /* <Values> */ + /* FT_GLYPH_FORMAT_NONE :: */ + /* The value~0 is reserved. */ + /* */ + /* FT_GLYPH_FORMAT_COMPOSITE :: */ + /* The glyph image is a composite of several other images. This */ + /* format is _only_ used with @FT_LOAD_NO_RECURSE, and is used to */ + /* report compound glyphs (like accented characters). */ + /* */ + /* FT_GLYPH_FORMAT_BITMAP :: */ + /* The glyph image is a bitmap, and can be described as an */ + /* @FT_Bitmap. You generally need to access the `bitmap' field of */ + /* the @FT_GlyphSlotRec structure to read it. */ + /* */ + /* FT_GLYPH_FORMAT_OUTLINE :: */ + /* The glyph image is a vectorial outline made of line segments */ + /* and Bézier arcs; it can be described as an @FT_Outline; you */ + /* generally want to access the `outline' field of the */ + /* @FT_GlyphSlotRec structure to read it. */ + /* */ + /* FT_GLYPH_FORMAT_PLOTTER :: */ + /* The glyph image is a vectorial path with no inside and outside */ + /* contours. Some Type~1 fonts, like those in the Hershey family, */ + /* contain glyphs in this format. These are described as */ + /* @FT_Outline, but FreeType isn't currently capable of rendering */ + /* them correctly. */ + /* */ + typedef enum FT_Glyph_Format_ + { + FT_IMAGE_TAG( FT_GLYPH_FORMAT_NONE, 0, 0, 0, 0 ), + + FT_IMAGE_TAG( FT_GLYPH_FORMAT_COMPOSITE, 'c', 'o', 'm', 'p' ), + FT_IMAGE_TAG( FT_GLYPH_FORMAT_BITMAP, 'b', 'i', 't', 's' ), + FT_IMAGE_TAG( FT_GLYPH_FORMAT_OUTLINE, 'o', 'u', 't', 'l' ), + FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER, 'p', 'l', 'o', 't' ) + + } FT_Glyph_Format; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* ft_glyph_format_xxx */ + /* */ + /* <Description> */ + /* A list of deprecated constants. Use the corresponding */ + /* @FT_Glyph_Format values instead. */ + /* */ + /* <Values> */ + /* ft_glyph_format_none :: See @FT_GLYPH_FORMAT_NONE. */ + /* ft_glyph_format_composite :: See @FT_GLYPH_FORMAT_COMPOSITE. */ + /* ft_glyph_format_bitmap :: See @FT_GLYPH_FORMAT_BITMAP. */ + /* ft_glyph_format_outline :: See @FT_GLYPH_FORMAT_OUTLINE. */ + /* ft_glyph_format_plotter :: See @FT_GLYPH_FORMAT_PLOTTER. */ + /* */ +#define ft_glyph_format_none FT_GLYPH_FORMAT_NONE +#define ft_glyph_format_composite FT_GLYPH_FORMAT_COMPOSITE +#define ft_glyph_format_bitmap FT_GLYPH_FORMAT_BITMAP +#define ft_glyph_format_outline FT_GLYPH_FORMAT_OUTLINE +#define ft_glyph_format_plotter FT_GLYPH_FORMAT_PLOTTER + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** R A S T E R D E F I N I T I O N S *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* A raster is a scan converter, in charge of rendering an outline into */ + /* a a bitmap. This section contains the public API for rasters. */ + /* */ + /* Note that in FreeType 2, all rasters are now encapsulated within */ + /* specific modules called `renderers'. See `freetype/ftrender.h' for */ + /* more details on renderers. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* raster */ + /* */ + /* <Title> */ + /* Scanline Converter */ + /* */ + /* <Abstract> */ + /* How vectorial outlines are converted into bitmaps and pixmaps. */ + /* */ + /* <Description> */ + /* This section contains technical definitions. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Raster */ + /* */ + /* <Description> */ + /* A handle (pointer) to a raster object. Each object can be used */ + /* independently to convert an outline into a bitmap or pixmap. */ + /* */ + typedef struct FT_RasterRec_* FT_Raster; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Span */ + /* */ + /* <Description> */ + /* A structure used to model a single span of gray (or black) pixels */ + /* when rendering a monochrome or anti-aliased bitmap. */ + /* */ + /* <Fields> */ + /* x :: The span's horizontal start position. */ + /* */ + /* len :: The span's length in pixels. */ + /* */ + /* coverage :: The span color/coverage, ranging from 0 (background) */ + /* to 255 (foreground). Only used for anti-aliased */ + /* rendering. */ + /* */ + /* <Note> */ + /* This structure is used by the span drawing callback type named */ + /* @FT_SpanFunc which takes the y~coordinate of the span as a */ + /* a parameter. */ + /* */ + /* The coverage value is always between 0 and 255. If you want less */ + /* gray values, the callback function has to reduce them. */ + /* */ + typedef struct FT_Span_ + { + short x; + unsigned short len; + unsigned char coverage; + + } FT_Span; + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_SpanFunc */ + /* */ + /* <Description> */ + /* A function used as a call-back by the anti-aliased renderer in */ + /* order to let client applications draw themselves the gray pixel */ + /* spans on each scan line. */ + /* */ + /* <Input> */ + /* y :: The scanline's y~coordinate. */ + /* */ + /* count :: The number of spans to draw on this scanline. */ + /* */ + /* spans :: A table of `count' spans to draw on the scanline. */ + /* */ + /* user :: User-supplied data that is passed to the callback. */ + /* */ + /* <Note> */ + /* This callback allows client applications to directly render the */ + /* gray spans of the anti-aliased bitmap to any kind of surfaces. */ + /* */ + /* This can be used to write anti-aliased outlines directly to a */ + /* given background bitmap, and even perform translucency. */ + /* */ + /* Note that the `count' field cannot be greater than a fixed value */ + /* defined by the `FT_MAX_GRAY_SPANS' configuration macro in */ + /* `ftoption.h'. By default, this value is set to~32, which means */ + /* that if there are more than 32~spans on a given scanline, the */ + /* callback is called several times with the same `y' parameter in */ + /* order to draw all callbacks. */ + /* */ + /* Otherwise, the callback is only called once per scan-line, and */ + /* only for those scanlines that do have `gray' pixels on them. */ + /* */ + typedef void + (*FT_SpanFunc)( int y, + int count, + const FT_Span* spans, + void* user ); + +#define FT_Raster_Span_Func FT_SpanFunc + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Raster_BitTest_Func */ + /* */ + /* <Description> */ + /* THIS TYPE IS DEPRECATED. DO NOT USE IT. */ + /* */ + /* A function used as a call-back by the monochrome scan-converter */ + /* to test whether a given target pixel is already set to the drawing */ + /* `color'. These tests are crucial to implement drop-out control */ + /* per-se the TrueType spec. */ + /* */ + /* <Input> */ + /* y :: The pixel's y~coordinate. */ + /* */ + /* x :: The pixel's x~coordinate. */ + /* */ + /* user :: User-supplied data that is passed to the callback. */ + /* */ + /* <Return> */ + /* 1~if the pixel is `set', 0~otherwise. */ + /* */ + typedef int + (*FT_Raster_BitTest_Func)( int y, + int x, + void* user ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Raster_BitSet_Func */ + /* */ + /* <Description> */ + /* THIS TYPE IS DEPRECATED. DO NOT USE IT. */ + /* */ + /* A function used as a call-back by the monochrome scan-converter */ + /* to set an individual target pixel. This is crucial to implement */ + /* drop-out control according to the TrueType specification. */ + /* */ + /* <Input> */ + /* y :: The pixel's y~coordinate. */ + /* */ + /* x :: The pixel's x~coordinate. */ + /* */ + /* user :: User-supplied data that is passed to the callback. */ + /* */ + /* <Return> */ + /* 1~if the pixel is `set', 0~otherwise. */ + /* */ + typedef void + (*FT_Raster_BitSet_Func)( int y, + int x, + void* user ); + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_RASTER_FLAG_XXX */ + /* */ + /* <Description> */ + /* A list of bit flag constants as used in the `flags' field of a */ + /* @FT_Raster_Params structure. */ + /* */ + /* <Values> */ + /* FT_RASTER_FLAG_DEFAULT :: This value is 0. */ + /* */ + /* FT_RASTER_FLAG_AA :: This flag is set to indicate that an */ + /* anti-aliased glyph image should be */ + /* generated. Otherwise, it will be */ + /* monochrome (1-bit). */ + /* */ + /* FT_RASTER_FLAG_DIRECT :: This flag is set to indicate direct */ + /* rendering. In this mode, client */ + /* applications must provide their own span */ + /* callback. This lets them directly */ + /* draw or compose over an existing bitmap. */ + /* If this bit is not set, the target */ + /* pixmap's buffer _must_ be zeroed before */ + /* rendering. */ + /* */ + /* Note that for now, direct rendering is */ + /* only possible with anti-aliased glyphs. */ + /* */ + /* FT_RASTER_FLAG_CLIP :: This flag is only used in direct */ + /* rendering mode. If set, the output will */ + /* be clipped to a box specified in the */ + /* `clip_box' field of the */ + /* @FT_Raster_Params structure. */ + /* */ + /* Note that by default, the glyph bitmap */ + /* is clipped to the target pixmap, except */ + /* in direct rendering mode where all spans */ + /* are generated if no clipping box is set. */ + /* */ +#define FT_RASTER_FLAG_DEFAULT 0x0 +#define FT_RASTER_FLAG_AA 0x1 +#define FT_RASTER_FLAG_DIRECT 0x2 +#define FT_RASTER_FLAG_CLIP 0x4 + + /* deprecated */ +#define ft_raster_flag_default FT_RASTER_FLAG_DEFAULT +#define ft_raster_flag_aa FT_RASTER_FLAG_AA +#define ft_raster_flag_direct FT_RASTER_FLAG_DIRECT +#define ft_raster_flag_clip FT_RASTER_FLAG_CLIP + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Raster_Params */ + /* */ + /* <Description> */ + /* A structure to hold the arguments used by a raster's render */ + /* function. */ + /* */ + /* <Fields> */ + /* target :: The target bitmap. */ + /* */ + /* source :: A pointer to the source glyph image (e.g., an */ + /* @FT_Outline). */ + /* */ + /* flags :: The rendering flags. */ + /* */ + /* gray_spans :: The gray span drawing callback. */ + /* */ + /* black_spans :: The black span drawing callback. UNIMPLEMENTED! */ + /* */ + /* bit_test :: The bit test callback. UNIMPLEMENTED! */ + /* */ + /* bit_set :: The bit set callback. UNIMPLEMENTED! */ + /* */ + /* user :: User-supplied data that is passed to each drawing */ + /* callback. */ + /* */ + /* clip_box :: An optional clipping box. It is only used in */ + /* direct rendering mode. Note that coordinates here */ + /* should be expressed in _integer_ pixels (and not in */ + /* 26.6 fixed-point units). */ + /* */ + /* <Note> */ + /* An anti-aliased glyph bitmap is drawn if the @FT_RASTER_FLAG_AA */ + /* bit flag is set in the `flags' field, otherwise a monochrome */ + /* bitmap is generated. */ + /* */ + /* If the @FT_RASTER_FLAG_DIRECT bit flag is set in `flags', the */ + /* raster will call the `gray_spans' callback to draw gray pixel */ + /* spans, in the case of an aa glyph bitmap, it will call */ + /* `black_spans', and `bit_test' and `bit_set' in the case of a */ + /* monochrome bitmap. This allows direct composition over a */ + /* pre-existing bitmap through user-provided callbacks to perform the */ + /* span drawing/composition. */ + /* */ + /* Note that the `bit_test' and `bit_set' callbacks are required when */ + /* rendering a monochrome bitmap, as they are crucial to implement */ + /* correct drop-out control as defined in the TrueType specification. */ + /* */ + typedef struct FT_Raster_Params_ + { + const FT_Bitmap* target; + const void* source; + int flags; + FT_SpanFunc gray_spans; + FT_SpanFunc black_spans; /* doesn't work! */ + FT_Raster_BitTest_Func bit_test; /* doesn't work! */ + FT_Raster_BitSet_Func bit_set; /* doesn't work! */ + void* user; + FT_BBox clip_box; + + } FT_Raster_Params; + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Raster_NewFunc */ + /* */ + /* <Description> */ + /* A function used to create a new raster object. */ + /* */ + /* <Input> */ + /* memory :: A handle to the memory allocator. */ + /* */ + /* <Output> */ + /* raster :: A handle to the new raster object. */ + /* */ + /* <Return> */ + /* Error code. 0~means success. */ + /* */ + /* <Note> */ + /* The `memory' parameter is a typeless pointer in order to avoid */ + /* un-wanted dependencies on the rest of the FreeType code. In */ + /* practice, it is an @FT_Memory object, i.e., a handle to the */ + /* standard FreeType memory allocator. However, this field can be */ + /* completely ignored by a given raster implementation. */ + /* */ + typedef int + (*FT_Raster_NewFunc)( void* memory, + FT_Raster* raster ); + +#define FT_Raster_New_Func FT_Raster_NewFunc + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Raster_DoneFunc */ + /* */ + /* <Description> */ + /* A function used to destroy a given raster object. */ + /* */ + /* <Input> */ + /* raster :: A handle to the raster object. */ + /* */ + typedef void + (*FT_Raster_DoneFunc)( FT_Raster raster ); + +#define FT_Raster_Done_Func FT_Raster_DoneFunc + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Raster_ResetFunc */ + /* */ + /* <Description> */ + /* FreeType provides an area of memory called the `render pool', */ + /* available to all registered rasters. This pool can be freely used */ + /* during a given scan-conversion but is shared by all rasters. Its */ + /* content is thus transient. */ + /* */ + /* This function is called each time the render pool changes, or just */ + /* after a new raster object is created. */ + /* */ + /* <Input> */ + /* raster :: A handle to the new raster object. */ + /* */ + /* pool_base :: The address in memory of the render pool. */ + /* */ + /* pool_size :: The size in bytes of the render pool. */ + /* */ + /* <Note> */ + /* Rasters can ignore the render pool and rely on dynamic memory */ + /* allocation if they want to (a handle to the memory allocator is */ + /* passed to the raster constructor). However, this is not */ + /* recommended for efficiency purposes. */ + /* */ + typedef void + (*FT_Raster_ResetFunc)( FT_Raster raster, + unsigned char* pool_base, + unsigned long pool_size ); + +#define FT_Raster_Reset_Func FT_Raster_ResetFunc + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Raster_SetModeFunc */ + /* */ + /* <Description> */ + /* This function is a generic facility to change modes or attributes */ + /* in a given raster. This can be used for debugging purposes, or */ + /* simply to allow implementation-specific `features' in a given */ + /* raster module. */ + /* */ + /* <Input> */ + /* raster :: A handle to the new raster object. */ + /* */ + /* mode :: A 4-byte tag used to name the mode or property. */ + /* */ + /* args :: A pointer to the new mode/property to use. */ + /* */ + typedef int + (*FT_Raster_SetModeFunc)( FT_Raster raster, + unsigned long mode, + void* args ); + +#define FT_Raster_Set_Mode_Func FT_Raster_SetModeFunc + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Raster_RenderFunc */ + /* */ + /* <Description> */ + /* Invoke a given raster to scan-convert a given glyph image into a */ + /* target bitmap. */ + /* */ + /* <Input> */ + /* raster :: A handle to the raster object. */ + /* */ + /* params :: A pointer to an @FT_Raster_Params structure used to */ + /* store the rendering parameters. */ + /* */ + /* <Return> */ + /* Error code. 0~means success. */ + /* */ + /* <Note> */ + /* The exact format of the source image depends on the raster's glyph */ + /* format defined in its @FT_Raster_Funcs structure. It can be an */ + /* @FT_Outline or anything else in order to support a large array of */ + /* glyph formats. */ + /* */ + /* Note also that the render function can fail and return a */ + /* `FT_Err_Unimplemented_Feature' error code if the raster used does */ + /* not support direct composition. */ + /* */ + /* XXX: For now, the standard raster doesn't support direct */ + /* composition but this should change for the final release (see */ + /* the files `demos/src/ftgrays.c' and `demos/src/ftgrays2.c' */ + /* for examples of distinct implementations which support direct */ + /* composition). */ + /* */ + typedef int + (*FT_Raster_RenderFunc)( FT_Raster raster, + const FT_Raster_Params* params ); + +#define FT_Raster_Render_Func FT_Raster_RenderFunc + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Raster_Funcs */ + /* */ + /* <Description> */ + /* A structure used to describe a given raster class to the library. */ + /* */ + /* <Fields> */ + /* glyph_format :: The supported glyph format for this raster. */ + /* */ + /* raster_new :: The raster constructor. */ + /* */ + /* raster_reset :: Used to reset the render pool within the raster. */ + /* */ + /* raster_render :: A function to render a glyph into a given bitmap. */ + /* */ + /* raster_done :: The raster destructor. */ + /* */ + typedef struct FT_Raster_Funcs_ + { + FT_Glyph_Format glyph_format; + FT_Raster_NewFunc raster_new; + FT_Raster_ResetFunc raster_reset; + FT_Raster_SetModeFunc raster_set_mode; + FT_Raster_RenderFunc raster_render; + FT_Raster_DoneFunc raster_done; + + } FT_Raster_Funcs; + + + /* */ + + +FT_END_HEADER + +#endif /* __FTIMAGE_H__ */ + + +/* END */ + + +/* Local Variables: */ +/* coding: utf-8 */ +/* End: */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftincrem.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftincrem.h new file mode 100644 index 00000000..aaf689ff --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftincrem.h @@ -0,0 +1,353 @@ +/***************************************************************************/ +/* */ +/* ftincrem.h */ +/* */ +/* FreeType incremental loading (specification). */ +/* */ +/* Copyright 2002, 2003, 2006, 2007, 2008, 2010 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTINCREM_H__ +#define __FTINCREM_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + /*************************************************************************** + * + * @section: + * incremental + * + * @title: + * Incremental Loading + * + * @abstract: + * Custom Glyph Loading. + * + * @description: + * This section contains various functions used to perform so-called + * `incremental' glyph loading. This is a mode where all glyphs loaded + * from a given @FT_Face are provided by the client application, + * + * Apart from that, all other tables are loaded normally from the font + * file. This mode is useful when FreeType is used within another + * engine, e.g., a PostScript Imaging Processor. + * + * To enable this mode, you must use @FT_Open_Face, passing an + * @FT_Parameter with the @FT_PARAM_TAG_INCREMENTAL tag and an + * @FT_Incremental_Interface value. See the comments for + * @FT_Incremental_InterfaceRec for an example. + * + */ + + + /*************************************************************************** + * + * @type: + * FT_Incremental + * + * @description: + * An opaque type describing a user-provided object used to implement + * `incremental' glyph loading within FreeType. This is used to support + * embedded fonts in certain environments (e.g., PostScript interpreters), + * where the glyph data isn't in the font file, or must be overridden by + * different values. + * + * @note: + * It is up to client applications to create and implement @FT_Incremental + * objects, as long as they provide implementations for the methods + * @FT_Incremental_GetGlyphDataFunc, @FT_Incremental_FreeGlyphDataFunc + * and @FT_Incremental_GetGlyphMetricsFunc. + * + * See the description of @FT_Incremental_InterfaceRec to understand how + * to use incremental objects with FreeType. + * + */ + typedef struct FT_IncrementalRec_* FT_Incremental; + + + /*************************************************************************** + * + * @struct: + * FT_Incremental_MetricsRec + * + * @description: + * A small structure used to contain the basic glyph metrics returned + * by the @FT_Incremental_GetGlyphMetricsFunc method. + * + * @fields: + * bearing_x :: + * Left bearing, in font units. + * + * bearing_y :: + * Top bearing, in font units. + * + * advance :: + * Horizontal component of glyph advance, in font units. + * + * advance_v :: + * Vertical component of glyph advance, in font units. + * + * @note: + * These correspond to horizontal or vertical metrics depending on the + * value of the `vertical' argument to the function + * @FT_Incremental_GetGlyphMetricsFunc. + * + */ + typedef struct FT_Incremental_MetricsRec_ + { + FT_Long bearing_x; + FT_Long bearing_y; + FT_Long advance; + FT_Long advance_v; /* since 2.3.12 */ + + } FT_Incremental_MetricsRec; + + + /*************************************************************************** + * + * @struct: + * FT_Incremental_Metrics + * + * @description: + * A handle to an @FT_Incremental_MetricsRec structure. + * + */ + typedef struct FT_Incremental_MetricsRec_* FT_Incremental_Metrics; + + + /*************************************************************************** + * + * @type: + * FT_Incremental_GetGlyphDataFunc + * + * @description: + * A function called by FreeType to access a given glyph's data bytes + * during @FT_Load_Glyph or @FT_Load_Char if incremental loading is + * enabled. + * + * Note that the format of the glyph's data bytes depends on the font + * file format. For TrueType, it must correspond to the raw bytes within + * the `glyf' table. For PostScript formats, it must correspond to the + * *unencrypted* charstring bytes, without any `lenIV' header. It is + * undefined for any other format. + * + * @input: + * incremental :: + * Handle to an opaque @FT_Incremental handle provided by the client + * application. + * + * glyph_index :: + * Index of relevant glyph. + * + * @output: + * adata :: + * A structure describing the returned glyph data bytes (which will be + * accessed as a read-only byte block). + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * If this function returns successfully the method + * @FT_Incremental_FreeGlyphDataFunc will be called later to release + * the data bytes. + * + * Nested calls to @FT_Incremental_GetGlyphDataFunc can happen for + * compound glyphs. + * + */ + typedef FT_Error + (*FT_Incremental_GetGlyphDataFunc)( FT_Incremental incremental, + FT_UInt glyph_index, + FT_Data* adata ); + + + /*************************************************************************** + * + * @type: + * FT_Incremental_FreeGlyphDataFunc + * + * @description: + * A function used to release the glyph data bytes returned by a + * successful call to @FT_Incremental_GetGlyphDataFunc. + * + * @input: + * incremental :: + * A handle to an opaque @FT_Incremental handle provided by the client + * application. + * + * data :: + * A structure describing the glyph data bytes (which will be accessed + * as a read-only byte block). + * + */ + typedef void + (*FT_Incremental_FreeGlyphDataFunc)( FT_Incremental incremental, + FT_Data* data ); + + + /*************************************************************************** + * + * @type: + * FT_Incremental_GetGlyphMetricsFunc + * + * @description: + * A function used to retrieve the basic metrics of a given glyph index + * before accessing its data. This is necessary because, in certain + * formats like TrueType, the metrics are stored in a different place from + * the glyph images proper. + * + * @input: + * incremental :: + * A handle to an opaque @FT_Incremental handle provided by the client + * application. + * + * glyph_index :: + * Index of relevant glyph. + * + * vertical :: + * If true, return vertical metrics. + * + * ametrics :: + * This parameter is used for both input and output. + * The original glyph metrics, if any, in font units. If metrics are + * not available all the values must be set to zero. + * + * @output: + * ametrics :: + * The replacement glyph metrics in font units. + * + */ + typedef FT_Error + (*FT_Incremental_GetGlyphMetricsFunc) + ( FT_Incremental incremental, + FT_UInt glyph_index, + FT_Bool vertical, + FT_Incremental_MetricsRec *ametrics ); + + + /************************************************************************** + * + * @struct: + * FT_Incremental_FuncsRec + * + * @description: + * A table of functions for accessing fonts that load data + * incrementally. Used in @FT_Incremental_InterfaceRec. + * + * @fields: + * get_glyph_data :: + * The function to get glyph data. Must not be null. + * + * free_glyph_data :: + * The function to release glyph data. Must not be null. + * + * get_glyph_metrics :: + * The function to get glyph metrics. May be null if the font does + * not provide overriding glyph metrics. + * + */ + typedef struct FT_Incremental_FuncsRec_ + { + FT_Incremental_GetGlyphDataFunc get_glyph_data; + FT_Incremental_FreeGlyphDataFunc free_glyph_data; + FT_Incremental_GetGlyphMetricsFunc get_glyph_metrics; + + } FT_Incremental_FuncsRec; + + + /*************************************************************************** + * + * @struct: + * FT_Incremental_InterfaceRec + * + * @description: + * A structure to be used with @FT_Open_Face to indicate that the user + * wants to support incremental glyph loading. You should use it with + * @FT_PARAM_TAG_INCREMENTAL as in the following example: + * + * { + * FT_Incremental_InterfaceRec inc_int; + * FT_Parameter parameter; + * FT_Open_Args open_args; + * + * + * // set up incremental descriptor + * inc_int.funcs = my_funcs; + * inc_int.object = my_object; + * + * // set up optional parameter + * parameter.tag = FT_PARAM_TAG_INCREMENTAL; + * parameter.data = &inc_int; + * + * // set up FT_Open_Args structure + * open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS; + * open_args.pathname = my_font_pathname; + * open_args.num_params = 1; + * open_args.params = ¶meter; // we use one optional argument + * + * // open the font + * error = FT_Open_Face( library, &open_args, index, &face ); + * ... + * } + * + */ + typedef struct FT_Incremental_InterfaceRec_ + { + const FT_Incremental_FuncsRec* funcs; + FT_Incremental object; + + } FT_Incremental_InterfaceRec; + + + /*************************************************************************** + * + * @type: + * FT_Incremental_Interface + * + * @description: + * A pointer to an @FT_Incremental_InterfaceRec structure. + * + */ + typedef FT_Incremental_InterfaceRec* FT_Incremental_Interface; + + + /*************************************************************************** + * + * @constant: + * FT_PARAM_TAG_INCREMENTAL + * + * @description: + * A constant used as the tag of @FT_Parameter structures to indicate + * an incremental loading object to be used by FreeType. + * + */ +#define FT_PARAM_TAG_INCREMENTAL FT_MAKE_TAG( 'i', 'n', 'c', 'r' ) + + /* */ + +FT_END_HEADER + +#endif /* __FTINCREM_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftlcdfil.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftlcdfil.h new file mode 100644 index 00000000..0b55ebee --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftlcdfil.h @@ -0,0 +1,213 @@ +/***************************************************************************/ +/* */ +/* ftlcdfil.h */ +/* */ +/* FreeType API for color filtering of subpixel bitmap glyphs */ +/* (specification). */ +/* */ +/* Copyright 2006, 2007, 2008, 2010 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FT_LCD_FILTER_H__ +#define __FT_LCD_FILTER_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + /*************************************************************************** + * + * @section: + * lcd_filtering + * + * @title: + * LCD Filtering + * + * @abstract: + * Reduce color fringes of LCD-optimized bitmaps. + * + * @description: + * The @FT_Library_SetLcdFilter API can be used to specify a low-pass + * filter which is then applied to LCD-optimized bitmaps generated + * through @FT_Render_Glyph. This is useful to reduce color fringes + * which would occur with unfiltered rendering. + * + * Note that no filter is active by default, and that this function is + * *not* implemented in default builds of the library. You need to + * #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your `ftoption.h' file + * in order to activate it. + */ + + + /**************************************************************************** + * + * @enum: + * FT_LcdFilter + * + * @description: + * A list of values to identify various types of LCD filters. + * + * @values: + * FT_LCD_FILTER_NONE :: + * Do not perform filtering. When used with subpixel rendering, this + * results in sometimes severe color fringes. + * + * FT_LCD_FILTER_DEFAULT :: + * The default filter reduces color fringes considerably, at the cost + * of a slight blurriness in the output. + * + * FT_LCD_FILTER_LIGHT :: + * The light filter is a variant that produces less blurriness at the + * cost of slightly more color fringes than the default one. It might + * be better, depending on taste, your monitor, or your personal vision. + * + * FT_LCD_FILTER_LEGACY :: + * This filter corresponds to the original libXft color filter. It + * provides high contrast output but can exhibit really bad color + * fringes if glyphs are not extremely well hinted to the pixel grid. + * In other words, it only works well if the TrueType bytecode + * interpreter is enabled *and* high-quality hinted fonts are used. + * + * This filter is only provided for comparison purposes, and might be + * disabled or stay unsupported in the future. + * + * @since: + * 2.3.0 + */ + typedef enum FT_LcdFilter_ + { + FT_LCD_FILTER_NONE = 0, + FT_LCD_FILTER_DEFAULT = 1, + FT_LCD_FILTER_LIGHT = 2, + FT_LCD_FILTER_LEGACY = 16, + + FT_LCD_FILTER_MAX /* do not remove */ + + } FT_LcdFilter; + + + /************************************************************************** + * + * @func: + * FT_Library_SetLcdFilter + * + * @description: + * This function is used to apply color filtering to LCD decimated + * bitmaps, like the ones used when calling @FT_Render_Glyph with + * @FT_RENDER_MODE_LCD or @FT_RENDER_MODE_LCD_V. + * + * @input: + * library :: + * A handle to the target library instance. + * + * filter :: + * The filter type. + * + * You can use @FT_LCD_FILTER_NONE here to disable this feature, or + * @FT_LCD_FILTER_DEFAULT to use a default filter that should work + * well on most LCD screens. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * This feature is always disabled by default. Clients must make an + * explicit call to this function with a `filter' value other than + * @FT_LCD_FILTER_NONE in order to enable it. + * + * Due to *PATENTS* covering subpixel rendering, this function doesn't + * do anything except returning `FT_Err_Unimplemented_Feature' if the + * configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not + * defined in your build of the library, which should correspond to all + * default builds of FreeType. + * + * The filter affects glyph bitmaps rendered through @FT_Render_Glyph, + * @FT_Outline_Get_Bitmap, @FT_Load_Glyph, and @FT_Load_Char. + * + * It does _not_ affect the output of @FT_Outline_Render and + * @FT_Outline_Get_Bitmap. + * + * If this feature is activated, the dimensions of LCD glyph bitmaps are + * either larger or taller than the dimensions of the corresponding + * outline with regards to the pixel grid. For example, for + * @FT_RENDER_MODE_LCD, the filter adds up to 3~pixels to the left, and + * up to 3~pixels to the right. + * + * The bitmap offset values are adjusted correctly, so clients shouldn't + * need to modify their layout and glyph positioning code when enabling + * the filter. + * + * @since: + * 2.3.0 + */ + FT_EXPORT( FT_Error ) + FT_Library_SetLcdFilter( FT_Library library, + FT_LcdFilter filter ); + + + /************************************************************************** + * + * @func: + * FT_Library_SetLcdFilterWeights + * + * @description: + * Use this function to override the filter weights selected by + * @FT_Library_SetLcdFilter. By default, FreeType uses the quintuple + * (0x00, 0x55, 0x56, 0x55, 0x00) for FT_LCD_FILTER_LIGHT, and (0x10, + * 0x40, 0x70, 0x40, 0x10) for FT_LCD_FILTER_DEFAULT and + * FT_LCD_FILTER_LEGACY. + * + * @input: + * library :: + * A handle to the target library instance. + * + * weights :: + * A pointer to an array; the function copies the first five bytes and + * uses them to specify the filter weights. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * Due to *PATENTS* covering subpixel rendering, this function doesn't + * do anything except returning `FT_Err_Unimplemented_Feature' if the + * configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not + * defined in your build of the library, which should correspond to all + * default builds of FreeType. + * + * This function must be called after @FT_Library_SetLcdFilter to have + * any effect. + * + * @since: + * 2.4.0 + */ + FT_EXPORT( FT_Error ) + FT_Library_SetLcdFilterWeights( FT_Library library, + unsigned char *weights ); + + /* */ + + +FT_END_HEADER + +#endif /* __FT_LCD_FILTER_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftlist.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftlist.h new file mode 100644 index 00000000..bb6f7f11 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftlist.h @@ -0,0 +1,277 @@ +/***************************************************************************/ +/* */ +/* ftlist.h */ +/* */ +/* Generic list support for FreeType (specification). */ +/* */ +/* Copyright 1996-2001, 2003, 2007, 2010 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file implements functions relative to list processing. Its */ + /* data structures are defined in `freetype.h'. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTLIST_H__ +#define __FTLIST_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* list_processing */ + /* */ + /* <Title> */ + /* List Processing */ + /* */ + /* <Abstract> */ + /* Simple management of lists. */ + /* */ + /* <Description> */ + /* This section contains various definitions related to list */ + /* processing using doubly-linked nodes. */ + /* */ + /* <Order> */ + /* FT_List */ + /* FT_ListNode */ + /* FT_ListRec */ + /* FT_ListNodeRec */ + /* */ + /* FT_List_Add */ + /* FT_List_Insert */ + /* FT_List_Find */ + /* FT_List_Remove */ + /* FT_List_Up */ + /* FT_List_Iterate */ + /* FT_List_Iterator */ + /* FT_List_Finalize */ + /* FT_List_Destructor */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_List_Find */ + /* */ + /* <Description> */ + /* Find the list node for a given listed object. */ + /* */ + /* <Input> */ + /* list :: A pointer to the parent list. */ + /* data :: The address of the listed object. */ + /* */ + /* <Return> */ + /* List node. NULL if it wasn't found. */ + /* */ + FT_EXPORT( FT_ListNode ) + FT_List_Find( FT_List list, + void* data ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_List_Add */ + /* */ + /* <Description> */ + /* Append an element to the end of a list. */ + /* */ + /* <InOut> */ + /* list :: A pointer to the parent list. */ + /* node :: The node to append. */ + /* */ + FT_EXPORT( void ) + FT_List_Add( FT_List list, + FT_ListNode node ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_List_Insert */ + /* */ + /* <Description> */ + /* Insert an element at the head of a list. */ + /* */ + /* <InOut> */ + /* list :: A pointer to parent list. */ + /* node :: The node to insert. */ + /* */ + FT_EXPORT( void ) + FT_List_Insert( FT_List list, + FT_ListNode node ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_List_Remove */ + /* */ + /* <Description> */ + /* Remove a node from a list. This function doesn't check whether */ + /* the node is in the list! */ + /* */ + /* <Input> */ + /* node :: The node to remove. */ + /* */ + /* <InOut> */ + /* list :: A pointer to the parent list. */ + /* */ + FT_EXPORT( void ) + FT_List_Remove( FT_List list, + FT_ListNode node ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_List_Up */ + /* */ + /* <Description> */ + /* Move a node to the head/top of a list. Used to maintain LRU */ + /* lists. */ + /* */ + /* <InOut> */ + /* list :: A pointer to the parent list. */ + /* node :: The node to move. */ + /* */ + FT_EXPORT( void ) + FT_List_Up( FT_List list, + FT_ListNode node ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_List_Iterator */ + /* */ + /* <Description> */ + /* An FT_List iterator function which is called during a list parse */ + /* by @FT_List_Iterate. */ + /* */ + /* <Input> */ + /* node :: The current iteration list node. */ + /* */ + /* user :: A typeless pointer passed to @FT_List_Iterate. */ + /* Can be used to point to the iteration's state. */ + /* */ + typedef FT_Error + (*FT_List_Iterator)( FT_ListNode node, + void* user ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_List_Iterate */ + /* */ + /* <Description> */ + /* Parse a list and calls a given iterator function on each element. */ + /* Note that parsing is stopped as soon as one of the iterator calls */ + /* returns a non-zero value. */ + /* */ + /* <Input> */ + /* list :: A handle to the list. */ + /* iterator :: An iterator function, called on each node of the list. */ + /* user :: A user-supplied field which is passed as the second */ + /* argument to the iterator. */ + /* */ + /* <Return> */ + /* The result (a FreeType error code) of the last iterator call. */ + /* */ + FT_EXPORT( FT_Error ) + FT_List_Iterate( FT_List list, + FT_List_Iterator iterator, + void* user ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_List_Destructor */ + /* */ + /* <Description> */ + /* An @FT_List iterator function which is called during a list */ + /* finalization by @FT_List_Finalize to destroy all elements in a */ + /* given list. */ + /* */ + /* <Input> */ + /* system :: The current system object. */ + /* */ + /* data :: The current object to destroy. */ + /* */ + /* user :: A typeless pointer passed to @FT_List_Iterate. It can */ + /* be used to point to the iteration's state. */ + /* */ + typedef void + (*FT_List_Destructor)( FT_Memory memory, + void* data, + void* user ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_List_Finalize */ + /* */ + /* <Description> */ + /* Destroy all elements in the list as well as the list itself. */ + /* */ + /* <Input> */ + /* list :: A handle to the list. */ + /* */ + /* destroy :: A list destructor that will be applied to each element */ + /* of the list. */ + /* */ + /* memory :: The current memory object which handles deallocation. */ + /* */ + /* user :: A user-supplied field which is passed as the last */ + /* argument to the destructor. */ + /* */ + /* <Note> */ + /* This function expects that all nodes added by @FT_List_Add or */ + /* @FT_List_Insert have been dynamically allocated. */ + /* */ + FT_EXPORT( void ) + FT_List_Finalize( FT_List list, + FT_List_Destructor destroy, + FT_Memory memory, + void* user ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTLIST_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftlzw.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftlzw.h new file mode 100644 index 00000000..00d40169 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftlzw.h @@ -0,0 +1,99 @@ +/***************************************************************************/ +/* */ +/* ftlzw.h */ +/* */ +/* LZW-compressed stream support. */ +/* */ +/* Copyright 2004, 2006 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTLZW_H__ +#define __FTLZW_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + /*************************************************************************/ + /* */ + /* <Section> */ + /* lzw */ + /* */ + /* <Title> */ + /* LZW Streams */ + /* */ + /* <Abstract> */ + /* Using LZW-compressed font files. */ + /* */ + /* <Description> */ + /* This section contains the declaration of LZW-specific functions. */ + /* */ + /*************************************************************************/ + + /************************************************************************ + * + * @function: + * FT_Stream_OpenLZW + * + * @description: + * Open a new stream to parse LZW-compressed font files. This is + * mainly used to support the compressed `*.pcf.Z' fonts that come + * with XFree86. + * + * @input: + * stream :: The target embedding stream. + * + * source :: The source stream. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * The source stream must be opened _before_ calling this function. + * + * Calling the internal function `FT_Stream_Close' on the new stream will + * *not* call `FT_Stream_Close' on the source stream. None of the stream + * objects will be released to the heap. + * + * The stream implementation is very basic and resets the decompression + * process each time seeking backwards is needed within the stream + * + * In certain builds of the library, LZW compression recognition is + * automatically handled when calling @FT_New_Face or @FT_Open_Face. + * This means that if no font driver is capable of handling the raw + * compressed file, the library will try to open a LZW stream from it + * and re-open the face with it. + * + * This function may return `FT_Err_Unimplemented_Feature' if your build + * of FreeType was not compiled with LZW support. + */ + FT_EXPORT( FT_Error ) + FT_Stream_OpenLZW( FT_Stream stream, + FT_Stream source ); + + /* */ + + +FT_END_HEADER + +#endif /* __FTLZW_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftmac.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftmac.h new file mode 100644 index 00000000..ab5bab51 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftmac.h @@ -0,0 +1,274 @@ +/***************************************************************************/ +/* */ +/* ftmac.h */ +/* */ +/* Additional Mac-specific API. */ +/* */ +/* Copyright 1996-2001, 2004, 2006, 2007 by */ +/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +/***************************************************************************/ +/* */ +/* NOTE: Include this file after <freetype/freetype.h> and after any */ +/* Mac-specific headers (because this header uses Mac types such as */ +/* Handle, FSSpec, FSRef, etc.) */ +/* */ +/***************************************************************************/ + + +#ifndef __FTMAC_H__ +#define __FTMAC_H__ + + +#include <ft2build.h> + + +FT_BEGIN_HEADER + + +/* gcc-3.4.1 and later can warn about functions tagged as deprecated */ +#ifndef FT_DEPRECATED_ATTRIBUTE +#if defined(__GNUC__) && \ + ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))) +#define FT_DEPRECATED_ATTRIBUTE __attribute__((deprecated)) +#else +#define FT_DEPRECATED_ATTRIBUTE +#endif +#endif + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* mac_specific */ + /* */ + /* <Title> */ + /* Mac Specific Interface */ + /* */ + /* <Abstract> */ + /* Only available on the Macintosh. */ + /* */ + /* <Description> */ + /* The following definitions are only available if FreeType is */ + /* compiled on a Macintosh. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Face_From_FOND */ + /* */ + /* <Description> */ + /* Create a new face object from a FOND resource. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library resource. */ + /* */ + /* <Input> */ + /* fond :: A FOND resource. */ + /* */ + /* face_index :: Only supported for the -1 `sanity check' special */ + /* case. */ + /* */ + /* <Output> */ + /* aface :: A handle to a new face object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Notes> */ + /* This function can be used to create @FT_Face objects from fonts */ + /* that are installed in the system as follows. */ + /* */ + /* { */ + /* fond = GetResource( 'FOND', fontName ); */ + /* error = FT_New_Face_From_FOND( library, fond, 0, &face ); */ + /* } */ + /* */ + FT_EXPORT( FT_Error ) + FT_New_Face_From_FOND( FT_Library library, + Handle fond, + FT_Long face_index, + FT_Face *aface ) + FT_DEPRECATED_ATTRIBUTE; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_GetFile_From_Mac_Name */ + /* */ + /* <Description> */ + /* Return an FSSpec for the disk file containing the named font. */ + /* */ + /* <Input> */ + /* fontName :: Mac OS name of the font (e.g., Times New Roman */ + /* Bold). */ + /* */ + /* <Output> */ + /* pathSpec :: FSSpec to the file. For passing to */ + /* @FT_New_Face_From_FSSpec. */ + /* */ + /* face_index :: Index of the face. For passing to */ + /* @FT_New_Face_From_FSSpec. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_GetFile_From_Mac_Name( const char* fontName, + FSSpec* pathSpec, + FT_Long* face_index ) + FT_DEPRECATED_ATTRIBUTE; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_GetFile_From_Mac_ATS_Name */ + /* */ + /* <Description> */ + /* Return an FSSpec for the disk file containing the named font. */ + /* */ + /* <Input> */ + /* fontName :: Mac OS name of the font in ATS framework. */ + /* */ + /* <Output> */ + /* pathSpec :: FSSpec to the file. For passing to */ + /* @FT_New_Face_From_FSSpec. */ + /* */ + /* face_index :: Index of the face. For passing to */ + /* @FT_New_Face_From_FSSpec. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_GetFile_From_Mac_ATS_Name( const char* fontName, + FSSpec* pathSpec, + FT_Long* face_index ) + FT_DEPRECATED_ATTRIBUTE; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_GetFilePath_From_Mac_ATS_Name */ + /* */ + /* <Description> */ + /* Return a pathname of the disk file and face index for given font */ + /* name which is handled by ATS framework. */ + /* */ + /* <Input> */ + /* fontName :: Mac OS name of the font in ATS framework. */ + /* */ + /* <Output> */ + /* path :: Buffer to store pathname of the file. For passing */ + /* to @FT_New_Face. The client must allocate this */ + /* buffer before calling this function. */ + /* */ + /* maxPathSize :: Lengths of the buffer `path' that client allocated. */ + /* */ + /* face_index :: Index of the face. For passing to @FT_New_Face. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_GetFilePath_From_Mac_ATS_Name( const char* fontName, + UInt8* path, + UInt32 maxPathSize, + FT_Long* face_index ) + FT_DEPRECATED_ATTRIBUTE; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Face_From_FSSpec */ + /* */ + /* <Description> */ + /* Create a new face object from a given resource and typeface index */ + /* using an FSSpec to the font file. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library resource. */ + /* */ + /* <Input> */ + /* spec :: FSSpec to the font file. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index~0. */ + /* <Output> */ + /* aface :: A handle to a new face object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* @FT_New_Face_From_FSSpec is identical to @FT_New_Face except */ + /* it accepts an FSSpec instead of a path. */ + /* */ + FT_EXPORT( FT_Error ) + FT_New_Face_From_FSSpec( FT_Library library, + const FSSpec *spec, + FT_Long face_index, + FT_Face *aface ) + FT_DEPRECATED_ATTRIBUTE; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Face_From_FSRef */ + /* */ + /* <Description> */ + /* Create a new face object from a given resource and typeface index */ + /* using an FSRef to the font file. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library resource. */ + /* */ + /* <Input> */ + /* spec :: FSRef to the font file. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index~0. */ + /* <Output> */ + /* aface :: A handle to a new face object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* @FT_New_Face_From_FSRef is identical to @FT_New_Face except */ + /* it accepts an FSRef instead of a path. */ + /* */ + FT_EXPORT( FT_Error ) + FT_New_Face_From_FSRef( FT_Library library, + const FSRef *ref, + FT_Long face_index, + FT_Face *aface ) + FT_DEPRECATED_ATTRIBUTE; + + /* */ + + +FT_END_HEADER + + +#endif /* __FTMAC_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftmm.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftmm.h new file mode 100644 index 00000000..3aefb9e4 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftmm.h @@ -0,0 +1,378 @@ +/***************************************************************************/ +/* */ +/* ftmm.h */ +/* */ +/* FreeType Multiple Master font interface (specification). */ +/* */ +/* Copyright 1996-2001, 2003, 2004, 2006, 2009 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTMM_H__ +#define __FTMM_H__ + + +#include <ft2build.h> +#include FT_TYPE1_TABLES_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* multiple_masters */ + /* */ + /* <Title> */ + /* Multiple Masters */ + /* */ + /* <Abstract> */ + /* How to manage Multiple Masters fonts. */ + /* */ + /* <Description> */ + /* The following types and functions are used to manage Multiple */ + /* Master fonts, i.e., the selection of specific design instances by */ + /* setting design axis coordinates. */ + /* */ + /* George Williams has extended this interface to make it work with */ + /* both Type~1 Multiple Masters fonts and GX distortable (var) */ + /* fonts. Some of these routines only work with MM fonts, others */ + /* will work with both types. They are similar enough that a */ + /* consistent interface makes sense. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_MM_Axis */ + /* */ + /* <Description> */ + /* A simple structure used to model a given axis in design space for */ + /* Multiple Masters fonts. */ + /* */ + /* This structure can't be used for GX var fonts. */ + /* */ + /* <Fields> */ + /* name :: The axis's name. */ + /* */ + /* minimum :: The axis's minimum design coordinate. */ + /* */ + /* maximum :: The axis's maximum design coordinate. */ + /* */ + typedef struct FT_MM_Axis_ + { + FT_String* name; + FT_Long minimum; + FT_Long maximum; + + } FT_MM_Axis; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Multi_Master */ + /* */ + /* <Description> */ + /* A structure used to model the axes and space of a Multiple Masters */ + /* font. */ + /* */ + /* This structure can't be used for GX var fonts. */ + /* */ + /* <Fields> */ + /* num_axis :: Number of axes. Cannot exceed~4. */ + /* */ + /* num_designs :: Number of designs; should be normally 2^num_axis */ + /* even though the Type~1 specification strangely */ + /* allows for intermediate designs to be present. This */ + /* number cannot exceed~16. */ + /* */ + /* axis :: A table of axis descriptors. */ + /* */ + typedef struct FT_Multi_Master_ + { + FT_UInt num_axis; + FT_UInt num_designs; + FT_MM_Axis axis[T1_MAX_MM_AXIS]; + + } FT_Multi_Master; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Var_Axis */ + /* */ + /* <Description> */ + /* A simple structure used to model a given axis in design space for */ + /* Multiple Masters and GX var fonts. */ + /* */ + /* <Fields> */ + /* name :: The axis's name. */ + /* Not always meaningful for GX. */ + /* */ + /* minimum :: The axis's minimum design coordinate. */ + /* */ + /* def :: The axis's default design coordinate. */ + /* FreeType computes meaningful default values for MM; it */ + /* is then an integer value, not in 16.16 format. */ + /* */ + /* maximum :: The axis's maximum design coordinate. */ + /* */ + /* tag :: The axis's tag (the GX equivalent to `name'). */ + /* FreeType provides default values for MM if possible. */ + /* */ + /* strid :: The entry in `name' table (another GX version of */ + /* `name'). */ + /* Not meaningful for MM. */ + /* */ + typedef struct FT_Var_Axis_ + { + FT_String* name; + + FT_Fixed minimum; + FT_Fixed def; + FT_Fixed maximum; + + FT_ULong tag; + FT_UInt strid; + + } FT_Var_Axis; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Var_Named_Style */ + /* */ + /* <Description> */ + /* A simple structure used to model a named style in a GX var font. */ + /* */ + /* This structure can't be used for MM fonts. */ + /* */ + /* <Fields> */ + /* coords :: The design coordinates for this style. */ + /* This is an array with one entry for each axis. */ + /* */ + /* strid :: The entry in `name' table identifying this style. */ + /* */ + typedef struct FT_Var_Named_Style_ + { + FT_Fixed* coords; + FT_UInt strid; + + } FT_Var_Named_Style; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_MM_Var */ + /* */ + /* <Description> */ + /* A structure used to model the axes and space of a Multiple Masters */ + /* or GX var distortable font. */ + /* */ + /* Some fields are specific to one format and not to the other. */ + /* */ + /* <Fields> */ + /* num_axis :: The number of axes. The maximum value is~4 for */ + /* MM; no limit in GX. */ + /* */ + /* num_designs :: The number of designs; should be normally */ + /* 2^num_axis for MM fonts. Not meaningful for GX */ + /* (where every glyph could have a different */ + /* number of designs). */ + /* */ + /* num_namedstyles :: The number of named styles; only meaningful for */ + /* GX which allows certain design coordinates to */ + /* have a string ID (in the `name' table) */ + /* associated with them. The font can tell the */ + /* user that, for example, Weight=1.5 is `Bold'. */ + /* */ + /* axis :: A table of axis descriptors. */ + /* GX fonts contain slightly more data than MM. */ + /* */ + /* namedstyles :: A table of named styles. */ + /* Only meaningful with GX. */ + /* */ + typedef struct FT_MM_Var_ + { + FT_UInt num_axis; + FT_UInt num_designs; + FT_UInt num_namedstyles; + FT_Var_Axis* axis; + FT_Var_Named_Style* namedstyle; + + } FT_MM_Var; + + + /* */ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Multi_Master */ + /* */ + /* <Description> */ + /* Retrieve the Multiple Master descriptor of a given font. */ + /* */ + /* This function can't be used with GX fonts. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face. */ + /* */ + /* <Output> */ + /* amaster :: The Multiple Masters descriptor. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Multi_Master( FT_Face face, + FT_Multi_Master *amaster ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_MM_Var */ + /* */ + /* <Description> */ + /* Retrieve the Multiple Master/GX var descriptor of a given font. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face. */ + /* */ + /* <Output> */ + /* amaster :: The Multiple Masters/GX var descriptor. */ + /* Allocates a data structure, which the user must free */ + /* (a single call to FT_FREE will do it). */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_MM_Var( FT_Face face, + FT_MM_Var* *amaster ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_MM_Design_Coordinates */ + /* */ + /* <Description> */ + /* For Multiple Masters fonts, choose an interpolated font design */ + /* through design coordinates. */ + /* */ + /* This function can't be used with GX fonts. */ + /* */ + /* <InOut> */ + /* face :: A handle to the source face. */ + /* */ + /* <Input> */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: An array of design coordinates. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_MM_Design_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Var_Design_Coordinates */ + /* */ + /* <Description> */ + /* For Multiple Master or GX Var fonts, choose an interpolated font */ + /* design through design coordinates. */ + /* */ + /* <InOut> */ + /* face :: A handle to the source face. */ + /* */ + /* <Input> */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: An array of design coordinates. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_Var_Design_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_MM_Blend_Coordinates */ + /* */ + /* <Description> */ + /* For Multiple Masters and GX var fonts, choose an interpolated font */ + /* design through normalized blend coordinates. */ + /* */ + /* <InOut> */ + /* face :: A handle to the source face. */ + /* */ + /* <Input> */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: The design coordinates array (each element must be */ + /* between 0 and 1.0). */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_MM_Blend_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Var_Blend_Coordinates */ + /* */ + /* <Description> */ + /* This is another name of @FT_Set_MM_Blend_Coordinates. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_Var_Blend_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTMM_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftmodapi.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftmodapi.h new file mode 100644 index 00000000..8f2e0179 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftmodapi.h @@ -0,0 +1,483 @@ +/***************************************************************************/ +/* */ +/* ftmodapi.h */ +/* */ +/* FreeType modules public interface (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2006, 2008, 2009, 2010 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTMODAPI_H__ +#define __FTMODAPI_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* module_management */ + /* */ + /* <Title> */ + /* Module Management */ + /* */ + /* <Abstract> */ + /* How to add, upgrade, and remove modules from FreeType. */ + /* */ + /* <Description> */ + /* The definitions below are used to manage modules within FreeType. */ + /* Modules can be added, upgraded, and removed at runtime. */ + /* */ + /*************************************************************************/ + + + /* module bit flags */ +#define FT_MODULE_FONT_DRIVER 1 /* this module is a font driver */ +#define FT_MODULE_RENDERER 2 /* this module is a renderer */ +#define FT_MODULE_HINTER 4 /* this module is a glyph hinter */ +#define FT_MODULE_STYLER 8 /* this module is a styler */ + +#define FT_MODULE_DRIVER_SCALABLE 0x100 /* the driver supports */ + /* scalable fonts */ +#define FT_MODULE_DRIVER_NO_OUTLINES 0x200 /* the driver does not */ + /* support vector outlines */ +#define FT_MODULE_DRIVER_HAS_HINTER 0x400 /* the driver provides its */ + /* own hinter */ + + + /* deprecated values */ +#define ft_module_font_driver FT_MODULE_FONT_DRIVER +#define ft_module_renderer FT_MODULE_RENDERER +#define ft_module_hinter FT_MODULE_HINTER +#define ft_module_styler FT_MODULE_STYLER + +#define ft_module_driver_scalable FT_MODULE_DRIVER_SCALABLE +#define ft_module_driver_no_outlines FT_MODULE_DRIVER_NO_OUTLINES +#define ft_module_driver_has_hinter FT_MODULE_DRIVER_HAS_HINTER + + + typedef FT_Pointer FT_Module_Interface; + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Module_Constructor */ + /* */ + /* <Description> */ + /* A function used to initialize (not create) a new module object. */ + /* */ + /* <Input> */ + /* module :: The module to initialize. */ + /* */ + typedef FT_Error + (*FT_Module_Constructor)( FT_Module module ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Module_Destructor */ + /* */ + /* <Description> */ + /* A function used to finalize (not destroy) a given module object. */ + /* */ + /* <Input> */ + /* module :: The module to finalize. */ + /* */ + typedef void + (*FT_Module_Destructor)( FT_Module module ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Module_Requester */ + /* */ + /* <Description> */ + /* A function used to query a given module for a specific interface. */ + /* */ + /* <Input> */ + /* module :: The module to finalize. */ + /* */ + /* name :: The name of the interface in the module. */ + /* */ + typedef FT_Module_Interface + (*FT_Module_Requester)( FT_Module module, + const char* name ); + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Module_Class */ + /* */ + /* <Description> */ + /* The module class descriptor. */ + /* */ + /* <Fields> */ + /* module_flags :: Bit flags describing the module. */ + /* */ + /* module_size :: The size of one module object/instance in */ + /* bytes. */ + /* */ + /* module_name :: The name of the module. */ + /* */ + /* module_version :: The version, as a 16.16 fixed number */ + /* (major.minor). */ + /* */ + /* module_requires :: The version of FreeType this module requires, */ + /* as a 16.16 fixed number (major.minor). Starts */ + /* at version 2.0, i.e., 0x20000. */ + /* */ + /* module_init :: The initializing function. */ + /* */ + /* module_done :: The finalizing function. */ + /* */ + /* get_interface :: The interface requesting function. */ + /* */ + typedef struct FT_Module_Class_ + { + FT_ULong module_flags; + FT_Long module_size; + const FT_String* module_name; + FT_Fixed module_version; + FT_Fixed module_requires; + + const void* module_interface; + + FT_Module_Constructor module_init; + FT_Module_Destructor module_done; + FT_Module_Requester get_interface; + + } FT_Module_Class; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Add_Module */ + /* */ + /* <Description> */ + /* Add a new module to a given library instance. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library object. */ + /* */ + /* <Input> */ + /* clazz :: A pointer to class descriptor for the module. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* An error will be returned if a module already exists by that name, */ + /* or if the module requires a version of FreeType that is too great. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Add_Module( FT_Library library, + const FT_Module_Class* clazz ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Module */ + /* */ + /* <Description> */ + /* Find a module by its name. */ + /* */ + /* <Input> */ + /* library :: A handle to the library object. */ + /* */ + /* module_name :: The module's name (as an ASCII string). */ + /* */ + /* <Return> */ + /* A module handle. 0~if none was found. */ + /* */ + /* <Note> */ + /* FreeType's internal modules aren't documented very well, and you */ + /* should look up the source code for details. */ + /* */ + FT_EXPORT( FT_Module ) + FT_Get_Module( FT_Library library, + const char* module_name ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Remove_Module */ + /* */ + /* <Description> */ + /* Remove a given module from a library instance. */ + /* */ + /* <InOut> */ + /* library :: A handle to a library object. */ + /* */ + /* <Input> */ + /* module :: A handle to a module object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* The module object is destroyed by the function in case of success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Remove_Module( FT_Library library, + FT_Module module ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Reference_Library */ + /* */ + /* <Description> */ + /* A counter gets initialized to~1 at the time an @FT_Library */ + /* structure is created. This function increments the counter. */ + /* @FT_Done_Library then only destroys a library if the counter is~1, */ + /* otherwise it simply decrements the counter. */ + /* */ + /* This function helps in managing life-cycles of structures which */ + /* reference @FT_Library objects. */ + /* */ + /* <Input> */ + /* library :: A handle to a target library object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Since> */ + /* 2.4.2 */ + /* */ + FT_EXPORT( FT_Error ) + FT_Reference_Library( FT_Library library ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Library */ + /* */ + /* <Description> */ + /* This function is used to create a new FreeType library instance */ + /* from a given memory object. It is thus possible to use libraries */ + /* with distinct memory allocators within the same program. */ + /* */ + /* Normally, you would call this function (followed by a call to */ + /* @FT_Add_Default_Modules or a series of calls to @FT_Add_Module) */ + /* instead of @FT_Init_FreeType to initialize the FreeType library. */ + /* */ + /* Don't use @FT_Done_FreeType but @FT_Done_Library to destroy a */ + /* library instance. */ + /* */ + /* <Input> */ + /* memory :: A handle to the original memory object. */ + /* */ + /* <Output> */ + /* alibrary :: A pointer to handle of a new library object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* See the discussion of reference counters in the description of */ + /* @FT_Reference_Library. */ + /* */ + FT_EXPORT( FT_Error ) + FT_New_Library( FT_Memory memory, + FT_Library *alibrary ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Done_Library */ + /* */ + /* <Description> */ + /* Discard a given library object. This closes all drivers and */ + /* discards all resource objects. */ + /* */ + /* <Input> */ + /* library :: A handle to the target library. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* See the discussion of reference counters in the description of */ + /* @FT_Reference_Library. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Done_Library( FT_Library library ); + +/* */ + + typedef void + (*FT_DebugHook_Func)( void* arg ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Debug_Hook */ + /* */ + /* <Description> */ + /* Set a debug hook function for debugging the interpreter of a font */ + /* format. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library object. */ + /* */ + /* <Input> */ + /* hook_index :: The index of the debug hook. You should use the */ + /* values defined in `ftobjs.h', e.g., */ + /* `FT_DEBUG_HOOK_TRUETYPE'. */ + /* */ + /* debug_hook :: The function used to debug the interpreter. */ + /* */ + /* <Note> */ + /* Currently, four debug hook slots are available, but only two (for */ + /* the TrueType and the Type~1 interpreter) are defined. */ + /* */ + /* Since the internal headers of FreeType are no longer installed, */ + /* the symbol `FT_DEBUG_HOOK_TRUETYPE' isn't available publicly. */ + /* This is a bug and will be fixed in a forthcoming release. */ + /* */ + FT_EXPORT( void ) + FT_Set_Debug_Hook( FT_Library library, + FT_UInt hook_index, + FT_DebugHook_Func debug_hook ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Add_Default_Modules */ + /* */ + /* <Description> */ + /* Add the set of default drivers to a given library object. */ + /* This is only useful when you create a library object with */ + /* @FT_New_Library (usually to plug a custom memory manager). */ + /* */ + /* <InOut> */ + /* library :: A handle to a new library object. */ + /* */ + FT_EXPORT( void ) + FT_Add_Default_Modules( FT_Library library ); + + + + /************************************************************************** + * + * @section: + * truetype_engine + * + * @title: + * The TrueType Engine + * + * @abstract: + * TrueType bytecode support. + * + * @description: + * This section contains a function used to query the level of TrueType + * bytecode support compiled in this version of the library. + * + */ + + + /************************************************************************** + * + * @enum: + * FT_TrueTypeEngineType + * + * @description: + * A list of values describing which kind of TrueType bytecode + * engine is implemented in a given FT_Library instance. It is used + * by the @FT_Get_TrueType_Engine_Type function. + * + * @values: + * FT_TRUETYPE_ENGINE_TYPE_NONE :: + * The library doesn't implement any kind of bytecode interpreter. + * + * FT_TRUETYPE_ENGINE_TYPE_UNPATENTED :: + * The library implements a bytecode interpreter that doesn't + * support the patented operations of the TrueType virtual machine. + * + * Its main use is to load certain Asian fonts which position and + * scale glyph components with bytecode instructions. It produces + * bad output for most other fonts. + * + * FT_TRUETYPE_ENGINE_TYPE_PATENTED :: + * The library implements a bytecode interpreter that covers + * the full instruction set of the TrueType virtual machine (this + * was governed by patents until May 2010, hence the name). + * + * @since: + * 2.2 + * + */ + typedef enum FT_TrueTypeEngineType_ + { + FT_TRUETYPE_ENGINE_TYPE_NONE = 0, + FT_TRUETYPE_ENGINE_TYPE_UNPATENTED, + FT_TRUETYPE_ENGINE_TYPE_PATENTED + + } FT_TrueTypeEngineType; + + + /************************************************************************** + * + * @func: + * FT_Get_TrueType_Engine_Type + * + * @description: + * Return an @FT_TrueTypeEngineType value to indicate which level of + * the TrueType virtual machine a given library instance supports. + * + * @input: + * library :: + * A library instance. + * + * @return: + * A value indicating which level is supported. + * + * @since: + * 2.2 + * + */ + FT_EXPORT( FT_TrueTypeEngineType ) + FT_Get_TrueType_Engine_Type( FT_Library library ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTMODAPI_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftmoderr.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftmoderr.h new file mode 100644 index 00000000..b0115dd0 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftmoderr.h @@ -0,0 +1,155 @@ +/***************************************************************************/ +/* */ +/* ftmoderr.h */ +/* */ +/* FreeType module error offsets (specification). */ +/* */ +/* Copyright 2001, 2002, 2003, 2004, 2005 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the FreeType module error offsets. */ + /* */ + /* The lower byte gives the error code, the higher byte gives the */ + /* module. The base module has error offset 0. For example, the error */ + /* `FT_Err_Invalid_File_Format' has value 0x003, the error */ + /* `TT_Err_Invalid_File_Format' has value 0x1103, the error */ + /* `T1_Err_Invalid_File_Format' has value 0x1203, etc. */ + /* */ + /* Undefine the macro FT_CONFIG_OPTION_USE_MODULE_ERRORS in ftoption.h */ + /* to make the higher byte always zero (disabling the module error */ + /* mechanism). */ + /* */ + /* It can also be used to create a module error message table easily */ + /* with something like */ + /* */ + /* { */ + /* #undef __FTMODERR_H__ */ + /* #define FT_MODERRDEF( e, v, s ) { FT_Mod_Err_ ## e, s }, */ + /* #define FT_MODERR_START_LIST { */ + /* #define FT_MODERR_END_LIST { 0, 0 } }; */ + /* */ + /* const struct */ + /* { */ + /* int mod_err_offset; */ + /* const char* mod_err_msg */ + /* } ft_mod_errors[] = */ + /* */ + /* #include FT_MODULE_ERRORS_H */ + /* } */ + /* */ + /* To use such a table, all errors must be ANDed with 0xFF00 to remove */ + /* the error code. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTMODERR_H__ +#define __FTMODERR_H__ + + + /*******************************************************************/ + /*******************************************************************/ + /***** *****/ + /***** SETUP MACROS *****/ + /***** *****/ + /*******************************************************************/ + /*******************************************************************/ + + +#undef FT_NEED_EXTERN_C + +#ifndef FT_MODERRDEF + +#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS +#define FT_MODERRDEF( e, v, s ) FT_Mod_Err_ ## e = v, +#else +#define FT_MODERRDEF( e, v, s ) FT_Mod_Err_ ## e = 0, +#endif + +#define FT_MODERR_START_LIST enum { +#define FT_MODERR_END_LIST FT_Mod_Err_Max }; + +#ifdef __cplusplus +#define FT_NEED_EXTERN_C + extern "C" { +#endif + +#endif /* !FT_MODERRDEF */ + + + /*******************************************************************/ + /*******************************************************************/ + /***** *****/ + /***** LIST MODULE ERROR BASES *****/ + /***** *****/ + /*******************************************************************/ + /*******************************************************************/ + + +#ifdef FT_MODERR_START_LIST + FT_MODERR_START_LIST +#endif + + + FT_MODERRDEF( Base, 0x000, "base module" ) + FT_MODERRDEF( Autofit, 0x100, "autofitter module" ) + FT_MODERRDEF( BDF, 0x200, "BDF module" ) + FT_MODERRDEF( Cache, 0x300, "cache module" ) + FT_MODERRDEF( CFF, 0x400, "CFF module" ) + FT_MODERRDEF( CID, 0x500, "CID module" ) + FT_MODERRDEF( Gzip, 0x600, "Gzip module" ) + FT_MODERRDEF( LZW, 0x700, "LZW module" ) + FT_MODERRDEF( OTvalid, 0x800, "OpenType validation module" ) + FT_MODERRDEF( PCF, 0x900, "PCF module" ) + FT_MODERRDEF( PFR, 0xA00, "PFR module" ) + FT_MODERRDEF( PSaux, 0xB00, "PS auxiliary module" ) + FT_MODERRDEF( PShinter, 0xC00, "PS hinter module" ) + FT_MODERRDEF( PSnames, 0xD00, "PS names module" ) + FT_MODERRDEF( Raster, 0xE00, "raster module" ) + FT_MODERRDEF( SFNT, 0xF00, "SFNT module" ) + FT_MODERRDEF( Smooth, 0x1000, "smooth raster module" ) + FT_MODERRDEF( TrueType, 0x1100, "TrueType module" ) + FT_MODERRDEF( Type1, 0x1200, "Type 1 module" ) + FT_MODERRDEF( Type42, 0x1300, "Type 42 module" ) + FT_MODERRDEF( Winfonts, 0x1400, "Windows FON/FNT module" ) + + +#ifdef FT_MODERR_END_LIST + FT_MODERR_END_LIST +#endif + + + /*******************************************************************/ + /*******************************************************************/ + /***** *****/ + /***** CLEANUP *****/ + /***** *****/ + /*******************************************************************/ + /*******************************************************************/ + + +#ifdef FT_NEED_EXTERN_C + } +#endif + +#undef FT_MODERR_START_LIST +#undef FT_MODERR_END_LIST +#undef FT_MODERRDEF +#undef FT_NEED_EXTERN_C + + +#endif /* __FTMODERR_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftotval.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftotval.h new file mode 100644 index 00000000..027f2e88 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftotval.h @@ -0,0 +1,203 @@ +/***************************************************************************/ +/* */ +/* ftotval.h */ +/* */ +/* FreeType API for validating OpenType tables (specification). */ +/* */ +/* Copyright 2004, 2005, 2006, 2007 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +/***************************************************************************/ +/* */ +/* */ +/* Warning: This module might be moved to a different library in the */ +/* future to avoid a tight dependency between FreeType and the */ +/* OpenType specification. */ +/* */ +/* */ +/***************************************************************************/ + + +#ifndef __FTOTVAL_H__ +#define __FTOTVAL_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* ot_validation */ + /* */ + /* <Title> */ + /* OpenType Validation */ + /* */ + /* <Abstract> */ + /* An API to validate OpenType tables. */ + /* */ + /* <Description> */ + /* This section contains the declaration of functions to validate */ + /* some OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH). */ + /* */ + /*************************************************************************/ + + + /********************************************************************** + * + * @enum: + * FT_VALIDATE_OTXXX + * + * @description: + * A list of bit-field constants used with @FT_OpenType_Validate to + * indicate which OpenType tables should be validated. + * + * @values: + * FT_VALIDATE_BASE :: + * Validate BASE table. + * + * FT_VALIDATE_GDEF :: + * Validate GDEF table. + * + * FT_VALIDATE_GPOS :: + * Validate GPOS table. + * + * FT_VALIDATE_GSUB :: + * Validate GSUB table. + * + * FT_VALIDATE_JSTF :: + * Validate JSTF table. + * + * FT_VALIDATE_MATH :: + * Validate MATH table. + * + * FT_VALIDATE_OT :: + * Validate all OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH). + * + */ +#define FT_VALIDATE_BASE 0x0100 +#define FT_VALIDATE_GDEF 0x0200 +#define FT_VALIDATE_GPOS 0x0400 +#define FT_VALIDATE_GSUB 0x0800 +#define FT_VALIDATE_JSTF 0x1000 +#define FT_VALIDATE_MATH 0x2000 + +#define FT_VALIDATE_OT FT_VALIDATE_BASE | \ + FT_VALIDATE_GDEF | \ + FT_VALIDATE_GPOS | \ + FT_VALIDATE_GSUB | \ + FT_VALIDATE_JSTF | \ + FT_VALIDATE_MATH + + /* */ + + /********************************************************************** + * + * @function: + * FT_OpenType_Validate + * + * @description: + * Validate various OpenType tables to assure that all offsets and + * indices are valid. The idea is that a higher-level library which + * actually does the text layout can access those tables without + * error checking (which can be quite time consuming). + * + * @input: + * face :: + * A handle to the input face. + * + * validation_flags :: + * A bit field which specifies the tables to be validated. See + * @FT_VALIDATE_OTXXX for possible values. + * + * @output: + * BASE_table :: + * A pointer to the BASE table. + * + * GDEF_table :: + * A pointer to the GDEF table. + * + * GPOS_table :: + * A pointer to the GPOS table. + * + * GSUB_table :: + * A pointer to the GSUB table. + * + * JSTF_table :: + * A pointer to the JSTF table. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * This function only works with OpenType fonts, returning an error + * otherwise. + * + * After use, the application should deallocate the five tables with + * @FT_OpenType_Free. A NULL value indicates that the table either + * doesn't exist in the font, or the application hasn't asked for + * validation. + */ + FT_EXPORT( FT_Error ) + FT_OpenType_Validate( FT_Face face, + FT_UInt validation_flags, + FT_Bytes *BASE_table, + FT_Bytes *GDEF_table, + FT_Bytes *GPOS_table, + FT_Bytes *GSUB_table, + FT_Bytes *JSTF_table ); + + /* */ + + /********************************************************************** + * + * @function: + * FT_OpenType_Free + * + * @description: + * Free the buffer allocated by OpenType validator. + * + * @input: + * face :: + * A handle to the input face. + * + * table :: + * The pointer to the buffer that is allocated by + * @FT_OpenType_Validate. + * + * @note: + * This function must be used to free the buffer allocated by + * @FT_OpenType_Validate only. + */ + FT_EXPORT( void ) + FT_OpenType_Free( FT_Face face, + FT_Bytes table ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTOTVAL_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftoutln.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftoutln.h new file mode 100644 index 00000000..2829a05c --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftoutln.h @@ -0,0 +1,537 @@ +/***************************************************************************/ +/* */ +/* ftoutln.h */ +/* */ +/* Support for the FT_Outline type used to store glyph shapes of */ +/* most scalable font formats (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTOUTLN_H__ +#define __FTOUTLN_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* outline_processing */ + /* */ + /* <Title> */ + /* Outline Processing */ + /* */ + /* <Abstract> */ + /* Functions to create, transform, and render vectorial glyph images. */ + /* */ + /* <Description> */ + /* This section contains routines used to create and destroy scalable */ + /* glyph images known as `outlines'. These can also be measured, */ + /* transformed, and converted into bitmaps and pixmaps. */ + /* */ + /* <Order> */ + /* FT_Outline */ + /* FT_OUTLINE_FLAGS */ + /* FT_Outline_New */ + /* FT_Outline_Done */ + /* FT_Outline_Copy */ + /* FT_Outline_Translate */ + /* FT_Outline_Transform */ + /* FT_Outline_Embolden */ + /* FT_Outline_Reverse */ + /* FT_Outline_Check */ + /* */ + /* FT_Outline_Get_CBox */ + /* FT_Outline_Get_BBox */ + /* */ + /* FT_Outline_Get_Bitmap */ + /* FT_Outline_Render */ + /* */ + /* FT_Outline_Decompose */ + /* FT_Outline_Funcs */ + /* FT_Outline_MoveTo_Func */ + /* FT_Outline_LineTo_Func */ + /* FT_Outline_ConicTo_Func */ + /* FT_Outline_CubicTo_Func */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Decompose */ + /* */ + /* <Description> */ + /* Walk over an outline's structure to decompose it into individual */ + /* segments and Bézier arcs. This function also emits `move to' */ + /* operations to indicate the start of new contours in the outline. */ + /* */ + /* <Input> */ + /* outline :: A pointer to the source target. */ + /* */ + /* func_interface :: A table of `emitters', i.e., function pointers */ + /* called during decomposition to indicate path */ + /* operations. */ + /* */ + /* <InOut> */ + /* user :: A typeless pointer which is passed to each */ + /* emitter during the decomposition. It can be */ + /* used to store the state during the */ + /* decomposition. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_Decompose( FT_Outline* outline, + const FT_Outline_Funcs* func_interface, + void* user ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_New */ + /* */ + /* <Description> */ + /* Create a new outline of a given size. */ + /* */ + /* <Input> */ + /* library :: A handle to the library object from where the */ + /* outline is allocated. Note however that the new */ + /* outline will *not* necessarily be *freed*, when */ + /* destroying the library, by @FT_Done_FreeType. */ + /* */ + /* numPoints :: The maximal number of points within the outline. */ + /* */ + /* numContours :: The maximal number of contours within the outline. */ + /* */ + /* <Output> */ + /* anoutline :: A handle to the new outline. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* The reason why this function takes a `library' parameter is simply */ + /* to use the library's memory allocator. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_New( FT_Library library, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline *anoutline ); + + + FT_EXPORT( FT_Error ) + FT_Outline_New_Internal( FT_Memory memory, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline *anoutline ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Done */ + /* */ + /* <Description> */ + /* Destroy an outline created with @FT_Outline_New. */ + /* */ + /* <Input> */ + /* library :: A handle of the library object used to allocate the */ + /* outline. */ + /* */ + /* outline :: A pointer to the outline object to be discarded. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* If the outline's `owner' field is not set, only the outline */ + /* descriptor will be released. */ + /* */ + /* The reason why this function takes an `library' parameter is */ + /* simply to use ft_mem_free(). */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_Done( FT_Library library, + FT_Outline* outline ); + + + FT_EXPORT( FT_Error ) + FT_Outline_Done_Internal( FT_Memory memory, + FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Check */ + /* */ + /* <Description> */ + /* Check the contents of an outline descriptor. */ + /* */ + /* <Input> */ + /* outline :: A handle to a source outline. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_Check( FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Get_CBox */ + /* */ + /* <Description> */ + /* Return an outline's `control box'. The control box encloses all */ + /* the outline's points, including Bézier control points. Though it */ + /* coincides with the exact bounding box for most glyphs, it can be */ + /* slightly larger in some situations (like when rotating an outline */ + /* which contains Bézier outside arcs). */ + /* */ + /* Computing the control box is very fast, while getting the bounding */ + /* box can take much more time as it needs to walk over all segments */ + /* and arcs in the outline. To get the latter, you can use the */ + /* `ftbbox' component which is dedicated to this single task. */ + /* */ + /* <Input> */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* <Output> */ + /* acbox :: The outline's control box. */ + /* */ + FT_EXPORT( void ) + FT_Outline_Get_CBox( const FT_Outline* outline, + FT_BBox *acbox ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Translate */ + /* */ + /* <Description> */ + /* Apply a simple translation to the points of an outline. */ + /* */ + /* <InOut> */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* <Input> */ + /* xOffset :: The horizontal offset. */ + /* */ + /* yOffset :: The vertical offset. */ + /* */ + FT_EXPORT( void ) + FT_Outline_Translate( const FT_Outline* outline, + FT_Pos xOffset, + FT_Pos yOffset ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Copy */ + /* */ + /* <Description> */ + /* Copy an outline into another one. Both objects must have the */ + /* same sizes (number of points & number of contours) when this */ + /* function is called. */ + /* */ + /* <Input> */ + /* source :: A handle to the source outline. */ + /* */ + /* <Output> */ + /* target :: A handle to the target outline. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_Copy( const FT_Outline* source, + FT_Outline *target ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Transform */ + /* */ + /* <Description> */ + /* Apply a simple 2x2 matrix to all of an outline's points. Useful */ + /* for applying rotations, slanting, flipping, etc. */ + /* */ + /* <InOut> */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* <Input> */ + /* matrix :: A pointer to the transformation matrix. */ + /* */ + /* <Note> */ + /* You can use @FT_Outline_Translate if you need to translate the */ + /* outline's points. */ + /* */ + FT_EXPORT( void ) + FT_Outline_Transform( const FT_Outline* outline, + const FT_Matrix* matrix ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Embolden */ + /* */ + /* <Description> */ + /* Embolden an outline. The new outline will be at most 4~times */ + /* `strength' pixels wider and higher. You may think of the left and */ + /* bottom borders as unchanged. */ + /* */ + /* Negative `strength' values to reduce the outline thickness are */ + /* possible also. */ + /* */ + /* <InOut> */ + /* outline :: A handle to the target outline. */ + /* */ + /* <Input> */ + /* strength :: How strong the glyph is emboldened. Expressed in */ + /* 26.6 pixel format. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* The used algorithm to increase or decrease the thickness of the */ + /* glyph doesn't change the number of points; this means that certain */ + /* situations like acute angles or intersections are sometimes */ + /* handled incorrectly. */ + /* */ + /* If you need `better' metrics values you should call */ + /* @FT_Outline_Get_CBox ot @FT_Outline_Get_BBox. */ + /* */ + /* Example call: */ + /* */ + /* { */ + /* FT_Load_Glyph( face, index, FT_LOAD_DEFAULT ); */ + /* if ( face->slot->format == FT_GLYPH_FORMAT_OUTLINE ) */ + /* FT_Outline_Embolden( &face->slot->outline, strength ); */ + /* } */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_Embolden( FT_Outline* outline, + FT_Pos strength ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Reverse */ + /* */ + /* <Description> */ + /* Reverse the drawing direction of an outline. This is used to */ + /* ensure consistent fill conventions for mirrored glyphs. */ + /* */ + /* <InOut> */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* <Note> */ + /* This function toggles the bit flag @FT_OUTLINE_REVERSE_FILL in */ + /* the outline's `flags' field. */ + /* */ + /* It shouldn't be used by a normal client application, unless it */ + /* knows what it is doing. */ + /* */ + FT_EXPORT( void ) + FT_Outline_Reverse( FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Get_Bitmap */ + /* */ + /* <Description> */ + /* Render an outline within a bitmap. The outline's image is simply */ + /* OR-ed to the target bitmap. */ + /* */ + /* <Input> */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* <InOut> */ + /* abitmap :: A pointer to the target bitmap descriptor. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* This function does NOT CREATE the bitmap, it only renders an */ + /* outline image within the one you pass to it! Consequently, the */ + /* various fields in `abitmap' should be set accordingly. */ + /* */ + /* It will use the raster corresponding to the default glyph format. */ + /* */ + /* The value of the `num_grays' field in `abitmap' is ignored. If */ + /* you select the gray-level rasterizer, and you want less than 256 */ + /* gray levels, you have to use @FT_Outline_Render directly. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_Get_Bitmap( FT_Library library, + FT_Outline* outline, + const FT_Bitmap *abitmap ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Render */ + /* */ + /* <Description> */ + /* Render an outline within a bitmap using the current scan-convert. */ + /* This function uses an @FT_Raster_Params structure as an argument, */ + /* allowing advanced features like direct composition, translucency, */ + /* etc. */ + /* */ + /* <Input> */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* <InOut> */ + /* params :: A pointer to an @FT_Raster_Params structure used to */ + /* describe the rendering operation. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* You should know what you are doing and how @FT_Raster_Params works */ + /* to use this function. */ + /* */ + /* The field `params.source' will be set to `outline' before the scan */ + /* converter is called, which means that the value you give to it is */ + /* actually ignored. */ + /* */ + /* The gray-level rasterizer always uses 256 gray levels. If you */ + /* want less gray levels, you have to provide your own span callback. */ + /* See the @FT_RASTER_FLAG_DIRECT value of the `flags' field in the */ + /* @FT_Raster_Params structure for more details. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_Render( FT_Library library, + FT_Outline* outline, + FT_Raster_Params* params ); + + + /************************************************************************** + * + * @enum: + * FT_Orientation + * + * @description: + * A list of values used to describe an outline's contour orientation. + * + * The TrueType and PostScript specifications use different conventions + * to determine whether outline contours should be filled or unfilled. + * + * @values: + * FT_ORIENTATION_TRUETYPE :: + * According to the TrueType specification, clockwise contours must + * be filled, and counter-clockwise ones must be unfilled. + * + * FT_ORIENTATION_POSTSCRIPT :: + * According to the PostScript specification, counter-clockwise contours + * must be filled, and clockwise ones must be unfilled. + * + * FT_ORIENTATION_FILL_RIGHT :: + * This is identical to @FT_ORIENTATION_TRUETYPE, but is used to + * remember that in TrueType, everything that is to the right of + * the drawing direction of a contour must be filled. + * + * FT_ORIENTATION_FILL_LEFT :: + * This is identical to @FT_ORIENTATION_POSTSCRIPT, but is used to + * remember that in PostScript, everything that is to the left of + * the drawing direction of a contour must be filled. + * + * FT_ORIENTATION_NONE :: + * The orientation cannot be determined. That is, different parts of + * the glyph have different orientation. + * + */ + typedef enum FT_Orientation_ + { + FT_ORIENTATION_TRUETYPE = 0, + FT_ORIENTATION_POSTSCRIPT = 1, + FT_ORIENTATION_FILL_RIGHT = FT_ORIENTATION_TRUETYPE, + FT_ORIENTATION_FILL_LEFT = FT_ORIENTATION_POSTSCRIPT, + FT_ORIENTATION_NONE + + } FT_Orientation; + + + /************************************************************************** + * + * @function: + * FT_Outline_Get_Orientation + * + * @description: + * This function analyzes a glyph outline and tries to compute its + * fill orientation (see @FT_Orientation). This is done by computing + * the direction of each global horizontal and/or vertical extrema + * within the outline. + * + * Note that this will return @FT_ORIENTATION_TRUETYPE for empty + * outlines. + * + * @input: + * outline :: + * A handle to the source outline. + * + * @return: + * The orientation. + * + */ + FT_EXPORT( FT_Orientation ) + FT_Outline_Get_Orientation( FT_Outline* outline ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTOUTLN_H__ */ + + +/* END */ + + +/* Local Variables: */ +/* coding: utf-8 */ +/* End: */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftpfr.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftpfr.h new file mode 100644 index 00000000..0b7b7d42 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftpfr.h @@ -0,0 +1,172 @@ +/***************************************************************************/ +/* */ +/* ftpfr.h */ +/* */ +/* FreeType API for accessing PFR-specific data (specification only). */ +/* */ +/* Copyright 2002, 2003, 2004, 2006, 2008, 2009 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTPFR_H__ +#define __FTPFR_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* pfr_fonts */ + /* */ + /* <Title> */ + /* PFR Fonts */ + /* */ + /* <Abstract> */ + /* PFR/TrueDoc specific API. */ + /* */ + /* <Description> */ + /* This section contains the declaration of PFR-specific functions. */ + /* */ + /*************************************************************************/ + + + /********************************************************************** + * + * @function: + * FT_Get_PFR_Metrics + * + * @description: + * Return the outline and metrics resolutions of a given PFR face. + * + * @input: + * face :: Handle to the input face. It can be a non-PFR face. + * + * @output: + * aoutline_resolution :: + * Outline resolution. This is equivalent to `face->units_per_EM' + * for non-PFR fonts. Optional (parameter can be NULL). + * + * ametrics_resolution :: + * Metrics resolution. This is equivalent to `outline_resolution' + * for non-PFR fonts. Optional (parameter can be NULL). + * + * ametrics_x_scale :: + * A 16.16 fixed-point number used to scale distance expressed + * in metrics units to device sub-pixels. This is equivalent to + * `face->size->x_scale', but for metrics only. Optional (parameter + * can be NULL). + * + * ametrics_y_scale :: + * Same as `ametrics_x_scale' but for the vertical direction. + * optional (parameter can be NULL). + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * If the input face is not a PFR, this function will return an error. + * However, in all cases, it will return valid values. + */ + FT_EXPORT( FT_Error ) + FT_Get_PFR_Metrics( FT_Face face, + FT_UInt *aoutline_resolution, + FT_UInt *ametrics_resolution, + FT_Fixed *ametrics_x_scale, + FT_Fixed *ametrics_y_scale ); + + + /********************************************************************** + * + * @function: + * FT_Get_PFR_Kerning + * + * @description: + * Return the kerning pair corresponding to two glyphs in a PFR face. + * The distance is expressed in metrics units, unlike the result of + * @FT_Get_Kerning. + * + * @input: + * face :: A handle to the input face. + * + * left :: Index of the left glyph. + * + * right :: Index of the right glyph. + * + * @output: + * avector :: A kerning vector. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * This function always return distances in original PFR metrics + * units. This is unlike @FT_Get_Kerning with the @FT_KERNING_UNSCALED + * mode, which always returns distances converted to outline units. + * + * You can use the value of the `x_scale' and `y_scale' parameters + * returned by @FT_Get_PFR_Metrics to scale these to device sub-pixels. + */ + FT_EXPORT( FT_Error ) + FT_Get_PFR_Kerning( FT_Face face, + FT_UInt left, + FT_UInt right, + FT_Vector *avector ); + + + /********************************************************************** + * + * @function: + * FT_Get_PFR_Advance + * + * @description: + * Return a given glyph advance, expressed in original metrics units, + * from a PFR font. + * + * @input: + * face :: A handle to the input face. + * + * gindex :: The glyph index. + * + * @output: + * aadvance :: The glyph advance in metrics units. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * You can use the `x_scale' or `y_scale' results of @FT_Get_PFR_Metrics + * to convert the advance to device sub-pixels (i.e., 1/64th of pixels). + */ + FT_EXPORT( FT_Error ) + FT_Get_PFR_Advance( FT_Face face, + FT_UInt gindex, + FT_Pos *aadvance ); + + /* */ + + +FT_END_HEADER + +#endif /* __FTPFR_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftrender.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftrender.h new file mode 100644 index 00000000..e06a8142 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftrender.h @@ -0,0 +1,230 @@ +/***************************************************************************/ +/* */ +/* ftrender.h */ +/* */ +/* FreeType renderer modules public interface (specification). */ +/* */ +/* Copyright 1996-2001, 2005, 2006, 2010 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTRENDER_H__ +#define __FTRENDER_H__ + + +#include <ft2build.h> +#include FT_MODULE_H +#include FT_GLYPH_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* module_management */ + /* */ + /*************************************************************************/ + + + /* create a new glyph object */ + typedef FT_Error + (*FT_Glyph_InitFunc)( FT_Glyph glyph, + FT_GlyphSlot slot ); + + /* destroys a given glyph object */ + typedef void + (*FT_Glyph_DoneFunc)( FT_Glyph glyph ); + + typedef void + (*FT_Glyph_TransformFunc)( FT_Glyph glyph, + const FT_Matrix* matrix, + const FT_Vector* delta ); + + typedef void + (*FT_Glyph_GetBBoxFunc)( FT_Glyph glyph, + FT_BBox* abbox ); + + typedef FT_Error + (*FT_Glyph_CopyFunc)( FT_Glyph source, + FT_Glyph target ); + + typedef FT_Error + (*FT_Glyph_PrepareFunc)( FT_Glyph glyph, + FT_GlyphSlot slot ); + +/* deprecated */ +#define FT_Glyph_Init_Func FT_Glyph_InitFunc +#define FT_Glyph_Done_Func FT_Glyph_DoneFunc +#define FT_Glyph_Transform_Func FT_Glyph_TransformFunc +#define FT_Glyph_BBox_Func FT_Glyph_GetBBoxFunc +#define FT_Glyph_Copy_Func FT_Glyph_CopyFunc +#define FT_Glyph_Prepare_Func FT_Glyph_PrepareFunc + + + struct FT_Glyph_Class_ + { + FT_Long glyph_size; + FT_Glyph_Format glyph_format; + FT_Glyph_InitFunc glyph_init; + FT_Glyph_DoneFunc glyph_done; + FT_Glyph_CopyFunc glyph_copy; + FT_Glyph_TransformFunc glyph_transform; + FT_Glyph_GetBBoxFunc glyph_bbox; + FT_Glyph_PrepareFunc glyph_prepare; + }; + + + typedef FT_Error + (*FT_Renderer_RenderFunc)( FT_Renderer renderer, + FT_GlyphSlot slot, + FT_UInt mode, + const FT_Vector* origin ); + + typedef FT_Error + (*FT_Renderer_TransformFunc)( FT_Renderer renderer, + FT_GlyphSlot slot, + const FT_Matrix* matrix, + const FT_Vector* delta ); + + + typedef void + (*FT_Renderer_GetCBoxFunc)( FT_Renderer renderer, + FT_GlyphSlot slot, + FT_BBox* cbox ); + + + typedef FT_Error + (*FT_Renderer_SetModeFunc)( FT_Renderer renderer, + FT_ULong mode_tag, + FT_Pointer mode_ptr ); + +/* deprecated identifiers */ +#define FTRenderer_render FT_Renderer_RenderFunc +#define FTRenderer_transform FT_Renderer_TransformFunc +#define FTRenderer_getCBox FT_Renderer_GetCBoxFunc +#define FTRenderer_setMode FT_Renderer_SetModeFunc + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Renderer_Class */ + /* */ + /* <Description> */ + /* The renderer module class descriptor. */ + /* */ + /* <Fields> */ + /* root :: The root @FT_Module_Class fields. */ + /* */ + /* glyph_format :: The glyph image format this renderer handles. */ + /* */ + /* render_glyph :: A method used to render the image that is in a */ + /* given glyph slot into a bitmap. */ + /* */ + /* transform_glyph :: A method used to transform the image that is in */ + /* a given glyph slot. */ + /* */ + /* get_glyph_cbox :: A method used to access the glyph's cbox. */ + /* */ + /* set_mode :: A method used to pass additional parameters. */ + /* */ + /* raster_class :: For @FT_GLYPH_FORMAT_OUTLINE renderers only. */ + /* This is a pointer to its raster's class. */ + /* */ + typedef struct FT_Renderer_Class_ + { + FT_Module_Class root; + + FT_Glyph_Format glyph_format; + + FT_Renderer_RenderFunc render_glyph; + FT_Renderer_TransformFunc transform_glyph; + FT_Renderer_GetCBoxFunc get_glyph_cbox; + FT_Renderer_SetModeFunc set_mode; + + FT_Raster_Funcs* raster_class; + + } FT_Renderer_Class; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Renderer */ + /* */ + /* <Description> */ + /* Retrieve the current renderer for a given glyph format. */ + /* */ + /* <Input> */ + /* library :: A handle to the library object. */ + /* */ + /* format :: The glyph format. */ + /* */ + /* <Return> */ + /* A renderer handle. 0~if none found. */ + /* */ + /* <Note> */ + /* An error will be returned if a module already exists by that name, */ + /* or if the module requires a version of FreeType that is too great. */ + /* */ + /* To add a new renderer, simply use @FT_Add_Module. To retrieve a */ + /* renderer by its name, use @FT_Get_Module. */ + /* */ + FT_EXPORT( FT_Renderer ) + FT_Get_Renderer( FT_Library library, + FT_Glyph_Format format ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Renderer */ + /* */ + /* <Description> */ + /* Set the current renderer to use, and set additional mode. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library object. */ + /* */ + /* <Input> */ + /* renderer :: A handle to the renderer object. */ + /* */ + /* num_params :: The number of additional parameters. */ + /* */ + /* parameters :: Additional parameters. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* In case of success, the renderer will be used to convert glyph */ + /* images in the renderer's known format into bitmaps. */ + /* */ + /* This doesn't change the current renderer for other formats. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_Renderer( FT_Library library, + FT_Renderer renderer, + FT_UInt num_params, + FT_Parameter* parameters ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTRENDER_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftsizes.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftsizes.h new file mode 100644 index 00000000..3e548cc3 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftsizes.h @@ -0,0 +1,159 @@ +/***************************************************************************/ +/* */ +/* ftsizes.h */ +/* */ +/* FreeType size objects management (specification). */ +/* */ +/* Copyright 1996-2001, 2003, 2004, 2006, 2009 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Typical application would normally not need to use these functions. */ + /* However, they have been placed in a public API for the rare cases */ + /* where they are needed. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTSIZES_H__ +#define __FTSIZES_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* sizes_management */ + /* */ + /* <Title> */ + /* Size Management */ + /* */ + /* <Abstract> */ + /* Managing multiple sizes per face. */ + /* */ + /* <Description> */ + /* When creating a new face object (e.g., with @FT_New_Face), an */ + /* @FT_Size object is automatically created and used to store all */ + /* pixel-size dependent information, available in the `face->size' */ + /* field. */ + /* */ + /* It is however possible to create more sizes for a given face, */ + /* mostly in order to manage several character pixel sizes of the */ + /* same font family and style. See @FT_New_Size and @FT_Done_Size. */ + /* */ + /* Note that @FT_Set_Pixel_Sizes and @FT_Set_Char_Size only */ + /* modify the contents of the current `active' size; you thus need */ + /* to use @FT_Activate_Size to change it. */ + /* */ + /* 99% of applications won't need the functions provided here, */ + /* especially if they use the caching sub-system, so be cautious */ + /* when using these. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Size */ + /* */ + /* <Description> */ + /* Create a new size object from a given face object. */ + /* */ + /* <Input> */ + /* face :: A handle to a parent face object. */ + /* */ + /* <Output> */ + /* asize :: A handle to a new size object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* You need to call @FT_Activate_Size in order to select the new size */ + /* for upcoming calls to @FT_Set_Pixel_Sizes, @FT_Set_Char_Size, */ + /* @FT_Load_Glyph, @FT_Load_Char, etc. */ + /* */ + FT_EXPORT( FT_Error ) + FT_New_Size( FT_Face face, + FT_Size* size ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Done_Size */ + /* */ + /* <Description> */ + /* Discard a given size object. Note that @FT_Done_Face */ + /* automatically discards all size objects allocated with */ + /* @FT_New_Size. */ + /* */ + /* <Input> */ + /* size :: A handle to a target size object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Done_Size( FT_Size size ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Activate_Size */ + /* */ + /* <Description> */ + /* Even though it is possible to create several size objects for a */ + /* given face (see @FT_New_Size for details), functions like */ + /* @FT_Load_Glyph or @FT_Load_Char only use the one which has been */ + /* activated last to determine the `current character pixel size'. */ + /* */ + /* This function can be used to `activate' a previously created size */ + /* object. */ + /* */ + /* <Input> */ + /* size :: A handle to a target size object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* If `face' is the size's parent face object, this function changes */ + /* the value of `face->size' to the input size handle. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Activate_Size( FT_Size size ); + + /* */ + + +FT_END_HEADER + +#endif /* __FTSIZES_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftsnames.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftsnames.h new file mode 100644 index 00000000..485e4e16 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftsnames.h @@ -0,0 +1,200 @@ +/***************************************************************************/ +/* */ +/* ftsnames.h */ +/* */ +/* Simple interface to access SFNT name tables (which are used */ +/* to hold font names, copyright info, notices, etc.) (specification). */ +/* */ +/* This is _not_ used to retrieve glyph names! */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2006, 2009, 2010 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FT_SFNT_NAMES_H__ +#define __FT_SFNT_NAMES_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* sfnt_names */ + /* */ + /* <Title> */ + /* SFNT Names */ + /* */ + /* <Abstract> */ + /* Access the names embedded in TrueType and OpenType files. */ + /* */ + /* <Description> */ + /* The TrueType and OpenType specifications allow the inclusion of */ + /* a special `names table' in font files. This table contains */ + /* textual (and internationalized) information regarding the font, */ + /* like family name, copyright, version, etc. */ + /* */ + /* The definitions below are used to access them if available. */ + /* */ + /* Note that this has nothing to do with glyph names! */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_SfntName */ + /* */ + /* <Description> */ + /* A structure used to model an SFNT `name' table entry. */ + /* */ + /* <Fields> */ + /* platform_id :: The platform ID for `string'. */ + /* */ + /* encoding_id :: The encoding ID for `string'. */ + /* */ + /* language_id :: The language ID for `string'. */ + /* */ + /* name_id :: An identifier for `string'. */ + /* */ + /* string :: The `name' string. Note that its format differs */ + /* depending on the (platform,encoding) pair. It can */ + /* be a Pascal String, a UTF-16 one, etc. */ + /* */ + /* Generally speaking, the string is not */ + /* zero-terminated. Please refer to the TrueType */ + /* specification for details. */ + /* */ + /* string_len :: The length of `string' in bytes. */ + /* */ + /* <Note> */ + /* Possible values for `platform_id', `encoding_id', `language_id', */ + /* and `name_id' are given in the file `ttnameid.h'. For details */ + /* please refer to the TrueType or OpenType specification. */ + /* */ + /* See also @TT_PLATFORM_XXX, @TT_APPLE_ID_XXX, @TT_MAC_ID_XXX, */ + /* @TT_ISO_ID_XXX, and @TT_MS_ID_XXX. */ + /* */ + typedef struct FT_SfntName_ + { + FT_UShort platform_id; + FT_UShort encoding_id; + FT_UShort language_id; + FT_UShort name_id; + + FT_Byte* string; /* this string is *not* null-terminated! */ + FT_UInt string_len; /* in bytes */ + + } FT_SfntName; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Sfnt_Name_Count */ + /* */ + /* <Description> */ + /* Retrieve the number of name strings in the SFNT `name' table. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face. */ + /* */ + /* <Return> */ + /* The number of strings in the `name' table. */ + /* */ + FT_EXPORT( FT_UInt ) + FT_Get_Sfnt_Name_Count( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Sfnt_Name */ + /* */ + /* <Description> */ + /* Retrieve a string of the SFNT `name' table for a given index. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face. */ + /* */ + /* idx :: The index of the `name' string. */ + /* */ + /* <Output> */ + /* aname :: The indexed @FT_SfntName structure. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + /* <Note> */ + /* The `string' array returned in the `aname' structure is not */ + /* null-terminated. The application should deallocate it if it is no */ + /* longer in use. */ + /* */ + /* Use @FT_Get_Sfnt_Name_Count to get the total number of available */ + /* `name' table entries, then do a loop until you get the right */ + /* platform, encoding, and name ID. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Sfnt_Name( FT_Face face, + FT_UInt idx, + FT_SfntName *aname ); + + + /*************************************************************************** + * + * @constant: + * FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY + * + * @description: + * A constant used as the tag of @FT_Parameter structures to make + * FT_Open_Face() ignore preferred family subfamily names in `name' + * table since OpenType version 1.4. For backwards compatibility with + * legacy systems which has 4-face-per-family restriction. + * + */ +#define FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY FT_MAKE_TAG( 'i', 'g', 'p', 'f' ) + + + /*************************************************************************** + * + * @constant: + * FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY + * + * @description: + * A constant used as the tag of @FT_Parameter structures to make + * FT_Open_Face() ignore preferred subfamily names in `name' table since + * OpenType version 1.4. For backwards compatibility with legacy + * systems which has 4-face-per-family restriction. + * + */ +#define FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY FT_MAKE_TAG( 'i', 'g', 'p', 's' ) + + /* */ + + +FT_END_HEADER + +#endif /* __FT_SFNT_NAMES_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftstroke.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftstroke.h new file mode 100644 index 00000000..3afb87df --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftstroke.h @@ -0,0 +1,716 @@ +/***************************************************************************/ +/* */ +/* ftstroke.h */ +/* */ +/* FreeType path stroker (specification). */ +/* */ +/* Copyright 2002, 2003, 2004, 2005, 2006, 2008, 2009 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FT_STROKE_H__ +#define __FT_STROKE_H__ + +#include <ft2build.h> +#include FT_OUTLINE_H +#include FT_GLYPH_H + + +FT_BEGIN_HEADER + + + /************************************************************************ + * + * @section: + * glyph_stroker + * + * @title: + * Glyph Stroker + * + * @abstract: + * Generating bordered and stroked glyphs. + * + * @description: + * This component generates stroked outlines of a given vectorial + * glyph. It also allows you to retrieve the `outside' and/or the + * `inside' borders of the stroke. + * + * This can be useful to generate `bordered' glyph, i.e., glyphs + * displayed with a coloured (and anti-aliased) border around their + * shape. + */ + + + /************************************************************** + * + * @type: + * FT_Stroker + * + * @description: + * Opaque handler to a path stroker object. + */ + typedef struct FT_StrokerRec_* FT_Stroker; + + + /************************************************************** + * + * @enum: + * FT_Stroker_LineJoin + * + * @description: + * These values determine how two joining lines are rendered + * in a stroker. + * + * @values: + * FT_STROKER_LINEJOIN_ROUND :: + * Used to render rounded line joins. Circular arcs are used + * to join two lines smoothly. + * + * FT_STROKER_LINEJOIN_BEVEL :: + * Used to render beveled line joins; i.e., the two joining lines + * are extended until they intersect. + * + * FT_STROKER_LINEJOIN_MITER :: + * Same as beveled rendering, except that an additional line + * break is added if the angle between the two joining lines + * is too closed (this is useful to avoid unpleasant spikes + * in beveled rendering). + */ + typedef enum FT_Stroker_LineJoin_ + { + FT_STROKER_LINEJOIN_ROUND = 0, + FT_STROKER_LINEJOIN_BEVEL, + FT_STROKER_LINEJOIN_MITER + + } FT_Stroker_LineJoin; + + + /************************************************************** + * + * @enum: + * FT_Stroker_LineCap + * + * @description: + * These values determine how the end of opened sub-paths are + * rendered in a stroke. + * + * @values: + * FT_STROKER_LINECAP_BUTT :: + * The end of lines is rendered as a full stop on the last + * point itself. + * + * FT_STROKER_LINECAP_ROUND :: + * The end of lines is rendered as a half-circle around the + * last point. + * + * FT_STROKER_LINECAP_SQUARE :: + * The end of lines is rendered as a square around the + * last point. + */ + typedef enum FT_Stroker_LineCap_ + { + FT_STROKER_LINECAP_BUTT = 0, + FT_STROKER_LINECAP_ROUND, + FT_STROKER_LINECAP_SQUARE + + } FT_Stroker_LineCap; + + + /************************************************************** + * + * @enum: + * FT_StrokerBorder + * + * @description: + * These values are used to select a given stroke border + * in @FT_Stroker_GetBorderCounts and @FT_Stroker_ExportBorder. + * + * @values: + * FT_STROKER_BORDER_LEFT :: + * Select the left border, relative to the drawing direction. + * + * FT_STROKER_BORDER_RIGHT :: + * Select the right border, relative to the drawing direction. + * + * @note: + * Applications are generally interested in the `inside' and `outside' + * borders. However, there is no direct mapping between these and the + * `left' and `right' ones, since this really depends on the glyph's + * drawing orientation, which varies between font formats. + * + * You can however use @FT_Outline_GetInsideBorder and + * @FT_Outline_GetOutsideBorder to get these. + */ + typedef enum FT_StrokerBorder_ + { + FT_STROKER_BORDER_LEFT = 0, + FT_STROKER_BORDER_RIGHT + + } FT_StrokerBorder; + + + /************************************************************** + * + * @function: + * FT_Outline_GetInsideBorder + * + * @description: + * Retrieve the @FT_StrokerBorder value corresponding to the + * `inside' borders of a given outline. + * + * @input: + * outline :: + * The source outline handle. + * + * @return: + * The border index. @FT_STROKER_BORDER_RIGHT for empty or invalid + * outlines. + */ + FT_EXPORT( FT_StrokerBorder ) + FT_Outline_GetInsideBorder( FT_Outline* outline ); + + + /************************************************************** + * + * @function: + * FT_Outline_GetOutsideBorder + * + * @description: + * Retrieve the @FT_StrokerBorder value corresponding to the + * `outside' borders of a given outline. + * + * @input: + * outline :: + * The source outline handle. + * + * @return: + * The border index. @FT_STROKER_BORDER_LEFT for empty or invalid + * outlines. + */ + FT_EXPORT( FT_StrokerBorder ) + FT_Outline_GetOutsideBorder( FT_Outline* outline ); + + + /************************************************************** + * + * @function: + * FT_Stroker_New + * + * @description: + * Create a new stroker object. + * + * @input: + * library :: + * FreeType library handle. + * + * @output: + * astroker :: + * A new stroker object handle. NULL in case of error. + * + * @return: + * FreeType error code. 0~means success. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_New( FT_Library library, + FT_Stroker *astroker ); + + + /************************************************************** + * + * @function: + * FT_Stroker_Set + * + * @description: + * Reset a stroker object's attributes. + * + * @input: + * stroker :: + * The target stroker handle. + * + * radius :: + * The border radius. + * + * line_cap :: + * The line cap style. + * + * line_join :: + * The line join style. + * + * miter_limit :: + * The miter limit for the FT_STROKER_LINEJOIN_MITER style, + * expressed as 16.16 fixed point value. + * + * @note: + * The radius is expressed in the same units as the outline + * coordinates. + */ + FT_EXPORT( void ) + FT_Stroker_Set( FT_Stroker stroker, + FT_Fixed radius, + FT_Stroker_LineCap line_cap, + FT_Stroker_LineJoin line_join, + FT_Fixed miter_limit ); + + + /************************************************************** + * + * @function: + * FT_Stroker_Rewind + * + * @description: + * Reset a stroker object without changing its attributes. + * You should call this function before beginning a new + * series of calls to @FT_Stroker_BeginSubPath or + * @FT_Stroker_EndSubPath. + * + * @input: + * stroker :: + * The target stroker handle. + */ + FT_EXPORT( void ) + FT_Stroker_Rewind( FT_Stroker stroker ); + + + /************************************************************** + * + * @function: + * FT_Stroker_ParseOutline + * + * @description: + * A convenience function used to parse a whole outline with + * the stroker. The resulting outline(s) can be retrieved + * later by functions like @FT_Stroker_GetCounts and @FT_Stroker_Export. + * + * @input: + * stroker :: + * The target stroker handle. + * + * outline :: + * The source outline. + * + * opened :: + * A boolean. If~1, the outline is treated as an open path instead + * of a closed one. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * If `opened' is~0 (the default), the outline is treated as a closed + * path, and the stroker generates two distinct `border' outlines. + * + * If `opened' is~1, the outline is processed as an open path, and the + * stroker generates a single `stroke' outline. + * + * This function calls @FT_Stroker_Rewind automatically. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_ParseOutline( FT_Stroker stroker, + FT_Outline* outline, + FT_Bool opened ); + + + /************************************************************** + * + * @function: + * FT_Stroker_BeginSubPath + * + * @description: + * Start a new sub-path in the stroker. + * + * @input: + * stroker :: + * The target stroker handle. + * + * to :: + * A pointer to the start vector. + * + * open :: + * A boolean. If~1, the sub-path is treated as an open one. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * This function is useful when you need to stroke a path that is + * not stored as an @FT_Outline object. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_BeginSubPath( FT_Stroker stroker, + FT_Vector* to, + FT_Bool open ); + + + /************************************************************** + * + * @function: + * FT_Stroker_EndSubPath + * + * @description: + * Close the current sub-path in the stroker. + * + * @input: + * stroker :: + * The target stroker handle. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * You should call this function after @FT_Stroker_BeginSubPath. + * If the subpath was not `opened', this function `draws' a + * single line segment to the start position when needed. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_EndSubPath( FT_Stroker stroker ); + + + /************************************************************** + * + * @function: + * FT_Stroker_LineTo + * + * @description: + * `Draw' a single line segment in the stroker's current sub-path, + * from the last position. + * + * @input: + * stroker :: + * The target stroker handle. + * + * to :: + * A pointer to the destination point. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * You should call this function between @FT_Stroker_BeginSubPath and + * @FT_Stroker_EndSubPath. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_LineTo( FT_Stroker stroker, + FT_Vector* to ); + + + /************************************************************** + * + * @function: + * FT_Stroker_ConicTo + * + * @description: + * `Draw' a single quadratic Bézier in the stroker's current sub-path, + * from the last position. + * + * @input: + * stroker :: + * The target stroker handle. + * + * control :: + * A pointer to a Bézier control point. + * + * to :: + * A pointer to the destination point. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * You should call this function between @FT_Stroker_BeginSubPath and + * @FT_Stroker_EndSubPath. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_ConicTo( FT_Stroker stroker, + FT_Vector* control, + FT_Vector* to ); + + + /************************************************************** + * + * @function: + * FT_Stroker_CubicTo + * + * @description: + * `Draw' a single cubic Bézier in the stroker's current sub-path, + * from the last position. + * + * @input: + * stroker :: + * The target stroker handle. + * + * control1 :: + * A pointer to the first Bézier control point. + * + * control2 :: + * A pointer to second Bézier control point. + * + * to :: + * A pointer to the destination point. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * You should call this function between @FT_Stroker_BeginSubPath and + * @FT_Stroker_EndSubPath. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_CubicTo( FT_Stroker stroker, + FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to ); + + + /************************************************************** + * + * @function: + * FT_Stroker_GetBorderCounts + * + * @description: + * Call this function once you have finished parsing your paths + * with the stroker. It returns the number of points and + * contours necessary to export one of the `border' or `stroke' + * outlines generated by the stroker. + * + * @input: + * stroker :: + * The target stroker handle. + * + * border :: + * The border index. + * + * @output: + * anum_points :: + * The number of points. + * + * anum_contours :: + * The number of contours. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * When an outline, or a sub-path, is `closed', the stroker generates + * two independent `border' outlines, named `left' and `right'. + * + * When the outline, or a sub-path, is `opened', the stroker merges + * the `border' outlines with caps. The `left' border receives all + * points, while the `right' border becomes empty. + * + * Use the function @FT_Stroker_GetCounts instead if you want to + * retrieve the counts associated to both borders. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_GetBorderCounts( FT_Stroker stroker, + FT_StrokerBorder border, + FT_UInt *anum_points, + FT_UInt *anum_contours ); + + + /************************************************************** + * + * @function: + * FT_Stroker_ExportBorder + * + * @description: + * Call this function after @FT_Stroker_GetBorderCounts to + * export the corresponding border to your own @FT_Outline + * structure. + * + * Note that this function appends the border points and + * contours to your outline, but does not try to resize its + * arrays. + * + * @input: + * stroker :: + * The target stroker handle. + * + * border :: + * The border index. + * + * outline :: + * The target outline handle. + * + * @note: + * Always call this function after @FT_Stroker_GetBorderCounts to + * get sure that there is enough room in your @FT_Outline object to + * receive all new data. + * + * When an outline, or a sub-path, is `closed', the stroker generates + * two independent `border' outlines, named `left' and `right' + * + * When the outline, or a sub-path, is `opened', the stroker merges + * the `border' outlines with caps. The `left' border receives all + * points, while the `right' border becomes empty. + * + * Use the function @FT_Stroker_Export instead if you want to + * retrieve all borders at once. + */ + FT_EXPORT( void ) + FT_Stroker_ExportBorder( FT_Stroker stroker, + FT_StrokerBorder border, + FT_Outline* outline ); + + + /************************************************************** + * + * @function: + * FT_Stroker_GetCounts + * + * @description: + * Call this function once you have finished parsing your paths + * with the stroker. It returns the number of points and + * contours necessary to export all points/borders from the stroked + * outline/path. + * + * @input: + * stroker :: + * The target stroker handle. + * + * @output: + * anum_points :: + * The number of points. + * + * anum_contours :: + * The number of contours. + * + * @return: + * FreeType error code. 0~means success. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_GetCounts( FT_Stroker stroker, + FT_UInt *anum_points, + FT_UInt *anum_contours ); + + + /************************************************************** + * + * @function: + * FT_Stroker_Export + * + * @description: + * Call this function after @FT_Stroker_GetBorderCounts to + * export all borders to your own @FT_Outline structure. + * + * Note that this function appends the border points and + * contours to your outline, but does not try to resize its + * arrays. + * + * @input: + * stroker :: + * The target stroker handle. + * + * outline :: + * The target outline handle. + */ + FT_EXPORT( void ) + FT_Stroker_Export( FT_Stroker stroker, + FT_Outline* outline ); + + + /************************************************************** + * + * @function: + * FT_Stroker_Done + * + * @description: + * Destroy a stroker object. + * + * @input: + * stroker :: + * A stroker handle. Can be NULL. + */ + FT_EXPORT( void ) + FT_Stroker_Done( FT_Stroker stroker ); + + + /************************************************************** + * + * @function: + * FT_Glyph_Stroke + * + * @description: + * Stroke a given outline glyph object with a given stroker. + * + * @inout: + * pglyph :: + * Source glyph handle on input, new glyph handle on output. + * + * @input: + * stroker :: + * A stroker handle. + * + * destroy :: + * A Boolean. If~1, the source glyph object is destroyed + * on success. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * The source glyph is untouched in case of error. + */ + FT_EXPORT( FT_Error ) + FT_Glyph_Stroke( FT_Glyph *pglyph, + FT_Stroker stroker, + FT_Bool destroy ); + + + /************************************************************** + * + * @function: + * FT_Glyph_StrokeBorder + * + * @description: + * Stroke a given outline glyph object with a given stroker, but + * only return either its inside or outside border. + * + * @inout: + * pglyph :: + * Source glyph handle on input, new glyph handle on output. + * + * @input: + * stroker :: + * A stroker handle. + * + * inside :: + * A Boolean. If~1, return the inside border, otherwise + * the outside border. + * + * destroy :: + * A Boolean. If~1, the source glyph object is destroyed + * on success. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * The source glyph is untouched in case of error. + */ + FT_EXPORT( FT_Error ) + FT_Glyph_StrokeBorder( FT_Glyph *pglyph, + FT_Stroker stroker, + FT_Bool inside, + FT_Bool destroy ); + + /* */ + +FT_END_HEADER + +#endif /* __FT_STROKE_H__ */ + + +/* END */ + + +/* Local Variables: */ +/* coding: utf-8 */ +/* End: */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftsynth.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftsynth.h new file mode 100644 index 00000000..a068b792 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftsynth.h @@ -0,0 +1,80 @@ +/***************************************************************************/ +/* */ +/* ftsynth.h */ +/* */ +/* FreeType synthesizing code for emboldening and slanting */ +/* (specification). */ +/* */ +/* Copyright 2000-2001, 2003, 2006, 2008 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********* *********/ + /********* WARNING, THIS IS ALPHA CODE! THIS API *********/ + /********* IS DUE TO CHANGE UNTIL STRICTLY NOTIFIED BY THE *********/ + /********* FREETYPE DEVELOPMENT TEAM *********/ + /********* *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* Main reason for not lifting the functions in this module to a */ + /* `standard' API is that the used parameters for emboldening and */ + /* slanting are not configurable. Consider the functions as a */ + /* code resource which should be copied into the application and */ + /* adapted to the particular needs. */ + + +#ifndef __FTSYNTH_H__ +#define __FTSYNTH_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + /* Embolden a glyph by a `reasonable' value (which is highly a matter of */ + /* taste). This function is actually a convenience function, providing */ + /* a wrapper for @FT_Outline_Embolden and @FT_Bitmap_Embolden. */ + /* */ + /* For emboldened outlines the metrics are estimates only; if you need */ + /* precise values you should call @FT_Outline_Get_CBox. */ + FT_EXPORT( void ) + FT_GlyphSlot_Embolden( FT_GlyphSlot slot ); + + /* Slant an outline glyph to the right by about 12 degrees. */ + FT_EXPORT( void ) + FT_GlyphSlot_Oblique( FT_GlyphSlot slot ); + + /* */ + +FT_END_HEADER + +#endif /* __FTSYNTH_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftsystem.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftsystem.h new file mode 100644 index 00000000..e07460c5 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftsystem.h @@ -0,0 +1,347 @@ +/***************************************************************************/ +/* */ +/* ftsystem.h */ +/* */ +/* FreeType low-level system interface definition (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2005, 2010 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTSYSTEM_H__ +#define __FTSYSTEM_H__ + + +#include <ft2build.h> + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* system_interface */ + /* */ + /* <Title> */ + /* System Interface */ + /* */ + /* <Abstract> */ + /* How FreeType manages memory and i/o. */ + /* */ + /* <Description> */ + /* This section contains various definitions related to memory */ + /* management and i/o access. You need to understand this */ + /* information if you want to use a custom memory manager or you own */ + /* i/o streams. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* M E M O R Y M A N A G E M E N T */ + /* */ + /*************************************************************************/ + + + /************************************************************************* + * + * @type: + * FT_Memory + * + * @description: + * A handle to a given memory manager object, defined with an + * @FT_MemoryRec structure. + * + */ + typedef struct FT_MemoryRec_* FT_Memory; + + + /************************************************************************* + * + * @functype: + * FT_Alloc_Func + * + * @description: + * A function used to allocate `size' bytes from `memory'. + * + * @input: + * memory :: + * A handle to the source memory manager. + * + * size :: + * The size in bytes to allocate. + * + * @return: + * Address of new memory block. 0~in case of failure. + * + */ + typedef void* + (*FT_Alloc_Func)( FT_Memory memory, + long size ); + + + /************************************************************************* + * + * @functype: + * FT_Free_Func + * + * @description: + * A function used to release a given block of memory. + * + * @input: + * memory :: + * A handle to the source memory manager. + * + * block :: + * The address of the target memory block. + * + */ + typedef void + (*FT_Free_Func)( FT_Memory memory, + void* block ); + + + /************************************************************************* + * + * @functype: + * FT_Realloc_Func + * + * @description: + * A function used to re-allocate a given block of memory. + * + * @input: + * memory :: + * A handle to the source memory manager. + * + * cur_size :: + * The block's current size in bytes. + * + * new_size :: + * The block's requested new size. + * + * block :: + * The block's current address. + * + * @return: + * New block address. 0~in case of memory shortage. + * + * @note: + * In case of error, the old block must still be available. + * + */ + typedef void* + (*FT_Realloc_Func)( FT_Memory memory, + long cur_size, + long new_size, + void* block ); + + + /************************************************************************* + * + * @struct: + * FT_MemoryRec + * + * @description: + * A structure used to describe a given memory manager to FreeType~2. + * + * @fields: + * user :: + * A generic typeless pointer for user data. + * + * alloc :: + * A pointer type to an allocation function. + * + * free :: + * A pointer type to an memory freeing function. + * + * realloc :: + * A pointer type to a reallocation function. + * + */ + struct FT_MemoryRec_ + { + void* user; + FT_Alloc_Func alloc; + FT_Free_Func free; + FT_Realloc_Func realloc; + }; + + + /*************************************************************************/ + /* */ + /* I / O M A N A G E M E N T */ + /* */ + /*************************************************************************/ + + + /************************************************************************* + * + * @type: + * FT_Stream + * + * @description: + * A handle to an input stream. + * + */ + typedef struct FT_StreamRec_* FT_Stream; + + + /************************************************************************* + * + * @struct: + * FT_StreamDesc + * + * @description: + * A union type used to store either a long or a pointer. This is used + * to store a file descriptor or a `FILE*' in an input stream. + * + */ + typedef union FT_StreamDesc_ + { + long value; + void* pointer; + + } FT_StreamDesc; + + + /************************************************************************* + * + * @functype: + * FT_Stream_IoFunc + * + * @description: + * A function used to seek and read data from a given input stream. + * + * @input: + * stream :: + * A handle to the source stream. + * + * offset :: + * The offset of read in stream (always from start). + * + * buffer :: + * The address of the read buffer. + * + * count :: + * The number of bytes to read from the stream. + * + * @return: + * The number of bytes effectively read by the stream. + * + * @note: + * This function might be called to perform a seek or skip operation + * with a `count' of~0. A non-zero return value then indicates an + * error. + * + */ + typedef unsigned long + (*FT_Stream_IoFunc)( FT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count ); + + + /************************************************************************* + * + * @functype: + * FT_Stream_CloseFunc + * + * @description: + * A function used to close a given input stream. + * + * @input: + * stream :: + * A handle to the target stream. + * + */ + typedef void + (*FT_Stream_CloseFunc)( FT_Stream stream ); + + + /************************************************************************* + * + * @struct: + * FT_StreamRec + * + * @description: + * A structure used to describe an input stream. + * + * @input: + * base :: + * For memory-based streams, this is the address of the first stream + * byte in memory. This field should always be set to NULL for + * disk-based streams. + * + * size :: + * The stream size in bytes. + * + * pos :: + * The current position within the stream. + * + * descriptor :: + * This field is a union that can hold an integer or a pointer. It is + * used by stream implementations to store file descriptors or `FILE*' + * pointers. + * + * pathname :: + * This field is completely ignored by FreeType. However, it is often + * useful during debugging to use it to store the stream's filename + * (where available). + * + * read :: + * The stream's input function. + * + * close :: + * The stream's close function. + * + * memory :: + * The memory manager to use to preload frames. This is set + * internally by FreeType and shouldn't be touched by stream + * implementations. + * + * cursor :: + * This field is set and used internally by FreeType when parsing + * frames. + * + * limit :: + * This field is set and used internally by FreeType when parsing + * frames. + * + */ + typedef struct FT_StreamRec_ + { + unsigned char* base; + unsigned long size; + unsigned long pos; + + FT_StreamDesc descriptor; + FT_StreamDesc pathname; + FT_Stream_IoFunc read; + FT_Stream_CloseFunc close; + + FT_Memory memory; + unsigned char* cursor; + unsigned char* limit; + + } FT_StreamRec; + + + /* */ + + +FT_END_HEADER + +#endif /* __FTSYSTEM_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/fttrigon.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/fttrigon.h new file mode 100644 index 00000000..6b77d2ee --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/fttrigon.h @@ -0,0 +1,350 @@ +/***************************************************************************/ +/* */ +/* fttrigon.h */ +/* */ +/* FreeType trigonometric functions (specification). */ +/* */ +/* Copyright 2001, 2003, 2005, 2007 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTTRIGON_H__ +#define __FTTRIGON_H__ + +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* computations */ + /* */ + /*************************************************************************/ + + + /************************************************************************* + * + * @type: + * FT_Angle + * + * @description: + * This type is used to model angle values in FreeType. Note that the + * angle is a 16.16 fixed float value expressed in degrees. + * + */ + typedef FT_Fixed FT_Angle; + + + /************************************************************************* + * + * @macro: + * FT_ANGLE_PI + * + * @description: + * The angle pi expressed in @FT_Angle units. + * + */ +#define FT_ANGLE_PI ( 180L << 16 ) + + + /************************************************************************* + * + * @macro: + * FT_ANGLE_2PI + * + * @description: + * The angle 2*pi expressed in @FT_Angle units. + * + */ +#define FT_ANGLE_2PI ( FT_ANGLE_PI * 2 ) + + + /************************************************************************* + * + * @macro: + * FT_ANGLE_PI2 + * + * @description: + * The angle pi/2 expressed in @FT_Angle units. + * + */ +#define FT_ANGLE_PI2 ( FT_ANGLE_PI / 2 ) + + + /************************************************************************* + * + * @macro: + * FT_ANGLE_PI4 + * + * @description: + * The angle pi/4 expressed in @FT_Angle units. + * + */ +#define FT_ANGLE_PI4 ( FT_ANGLE_PI / 4 ) + + + /************************************************************************* + * + * @function: + * FT_Sin + * + * @description: + * Return the sinus of a given angle in fixed point format. + * + * @input: + * angle :: + * The input angle. + * + * @return: + * The sinus value. + * + * @note: + * If you need both the sinus and cosinus for a given angle, use the + * function @FT_Vector_Unit. + * + */ + FT_EXPORT( FT_Fixed ) + FT_Sin( FT_Angle angle ); + + + /************************************************************************* + * + * @function: + * FT_Cos + * + * @description: + * Return the cosinus of a given angle in fixed point format. + * + * @input: + * angle :: + * The input angle. + * + * @return: + * The cosinus value. + * + * @note: + * If you need both the sinus and cosinus for a given angle, use the + * function @FT_Vector_Unit. + * + */ + FT_EXPORT( FT_Fixed ) + FT_Cos( FT_Angle angle ); + + + /************************************************************************* + * + * @function: + * FT_Tan + * + * @description: + * Return the tangent of a given angle in fixed point format. + * + * @input: + * angle :: + * The input angle. + * + * @return: + * The tangent value. + * + */ + FT_EXPORT( FT_Fixed ) + FT_Tan( FT_Angle angle ); + + + /************************************************************************* + * + * @function: + * FT_Atan2 + * + * @description: + * Return the arc-tangent corresponding to a given vector (x,y) in + * the 2d plane. + * + * @input: + * x :: + * The horizontal vector coordinate. + * + * y :: + * The vertical vector coordinate. + * + * @return: + * The arc-tangent value (i.e. angle). + * + */ + FT_EXPORT( FT_Angle ) + FT_Atan2( FT_Fixed x, + FT_Fixed y ); + + + /************************************************************************* + * + * @function: + * FT_Angle_Diff + * + * @description: + * Return the difference between two angles. The result is always + * constrained to the ]-PI..PI] interval. + * + * @input: + * angle1 :: + * First angle. + * + * angle2 :: + * Second angle. + * + * @return: + * Constrained value of `value2-value1'. + * + */ + FT_EXPORT( FT_Angle ) + FT_Angle_Diff( FT_Angle angle1, + FT_Angle angle2 ); + + + /************************************************************************* + * + * @function: + * FT_Vector_Unit + * + * @description: + * Return the unit vector corresponding to a given angle. After the + * call, the value of `vec.x' will be `sin(angle)', and the value of + * `vec.y' will be `cos(angle)'. + * + * This function is useful to retrieve both the sinus and cosinus of a + * given angle quickly. + * + * @output: + * vec :: + * The address of target vector. + * + * @input: + * angle :: + * The address of angle. + * + */ + FT_EXPORT( void ) + FT_Vector_Unit( FT_Vector* vec, + FT_Angle angle ); + + + /************************************************************************* + * + * @function: + * FT_Vector_Rotate + * + * @description: + * Rotate a vector by a given angle. + * + * @inout: + * vec :: + * The address of target vector. + * + * @input: + * angle :: + * The address of angle. + * + */ + FT_EXPORT( void ) + FT_Vector_Rotate( FT_Vector* vec, + FT_Angle angle ); + + + /************************************************************************* + * + * @function: + * FT_Vector_Length + * + * @description: + * Return the length of a given vector. + * + * @input: + * vec :: + * The address of target vector. + * + * @return: + * The vector length, expressed in the same units that the original + * vector coordinates. + * + */ + FT_EXPORT( FT_Fixed ) + FT_Vector_Length( FT_Vector* vec ); + + + /************************************************************************* + * + * @function: + * FT_Vector_Polarize + * + * @description: + * Compute both the length and angle of a given vector. + * + * @input: + * vec :: + * The address of source vector. + * + * @output: + * length :: + * The vector length. + * + * angle :: + * The vector angle. + * + */ + FT_EXPORT( void ) + FT_Vector_Polarize( FT_Vector* vec, + FT_Fixed *length, + FT_Angle *angle ); + + + /************************************************************************* + * + * @function: + * FT_Vector_From_Polar + * + * @description: + * Compute vector coordinates from a length and angle. + * + * @output: + * vec :: + * The address of source vector. + * + * @input: + * length :: + * The vector length. + * + * angle :: + * The vector angle. + * + */ + FT_EXPORT( void ) + FT_Vector_From_Polar( FT_Vector* vec, + FT_Fixed length, + FT_Angle angle ); + + /* */ + + +FT_END_HEADER + +#endif /* __FTTRIGON_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/fttypes.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/fttypes.h new file mode 100644 index 00000000..a57ffa69 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/fttypes.h @@ -0,0 +1,588 @@ +/***************************************************************************/ +/* */ +/* fttypes.h */ +/* */ +/* FreeType simple types definitions (specification only). */ +/* */ +/* Copyright 1996-2001, 2002, 2004, 2006, 2007, 2008 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTTYPES_H__ +#define __FTTYPES_H__ + + +#include <ft2build.h> +#include FT_CONFIG_CONFIG_H +#include FT_SYSTEM_H +#include FT_IMAGE_H + +#include <stddef.h> + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* basic_types */ + /* */ + /* <Title> */ + /* Basic Data Types */ + /* */ + /* <Abstract> */ + /* The basic data types defined by the library. */ + /* */ + /* <Description> */ + /* This section contains the basic data types defined by FreeType~2, */ + /* ranging from simple scalar types to bitmap descriptors. More */ + /* font-specific structures are defined in a different section. */ + /* */ + /* <Order> */ + /* FT_Byte */ + /* FT_Bytes */ + /* FT_Char */ + /* FT_Int */ + /* FT_UInt */ + /* FT_Int16 */ + /* FT_UInt16 */ + /* FT_Int32 */ + /* FT_UInt32 */ + /* FT_Short */ + /* FT_UShort */ + /* FT_Long */ + /* FT_ULong */ + /* FT_Bool */ + /* FT_Offset */ + /* FT_PtrDist */ + /* FT_String */ + /* FT_Tag */ + /* FT_Error */ + /* FT_Fixed */ + /* FT_Pointer */ + /* FT_Pos */ + /* FT_Vector */ + /* FT_BBox */ + /* FT_Matrix */ + /* FT_FWord */ + /* FT_UFWord */ + /* FT_F2Dot14 */ + /* FT_UnitVector */ + /* FT_F26Dot6 */ + /* */ + /* */ + /* FT_Generic */ + /* FT_Generic_Finalizer */ + /* */ + /* FT_Bitmap */ + /* FT_Pixel_Mode */ + /* FT_Palette_Mode */ + /* FT_Glyph_Format */ + /* FT_IMAGE_TAG */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Bool */ + /* */ + /* <Description> */ + /* A typedef of unsigned char, used for simple booleans. As usual, */ + /* values 1 and~0 represent true and false, respectively. */ + /* */ + typedef unsigned char FT_Bool; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_FWord */ + /* */ + /* <Description> */ + /* A signed 16-bit integer used to store a distance in original font */ + /* units. */ + /* */ + typedef signed short FT_FWord; /* distance in FUnits */ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_UFWord */ + /* */ + /* <Description> */ + /* An unsigned 16-bit integer used to store a distance in original */ + /* font units. */ + /* */ + typedef unsigned short FT_UFWord; /* unsigned distance */ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Char */ + /* */ + /* <Description> */ + /* A simple typedef for the _signed_ char type. */ + /* */ + typedef signed char FT_Char; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Byte */ + /* */ + /* <Description> */ + /* A simple typedef for the _unsigned_ char type. */ + /* */ + typedef unsigned char FT_Byte; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Bytes */ + /* */ + /* <Description> */ + /* A typedef for constant memory areas. */ + /* */ + typedef const FT_Byte* FT_Bytes; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Tag */ + /* */ + /* <Description> */ + /* A typedef for 32-bit tags (as used in the SFNT format). */ + /* */ + typedef FT_UInt32 FT_Tag; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_String */ + /* */ + /* <Description> */ + /* A simple typedef for the char type, usually used for strings. */ + /* */ + typedef char FT_String; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Short */ + /* */ + /* <Description> */ + /* A typedef for signed short. */ + /* */ + typedef signed short FT_Short; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_UShort */ + /* */ + /* <Description> */ + /* A typedef for unsigned short. */ + /* */ + typedef unsigned short FT_UShort; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Int */ + /* */ + /* <Description> */ + /* A typedef for the int type. */ + /* */ + typedef signed int FT_Int; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_UInt */ + /* */ + /* <Description> */ + /* A typedef for the unsigned int type. */ + /* */ + typedef unsigned int FT_UInt; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Long */ + /* */ + /* <Description> */ + /* A typedef for signed long. */ + /* */ + typedef signed long FT_Long; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_ULong */ + /* */ + /* <Description> */ + /* A typedef for unsigned long. */ + /* */ + typedef unsigned long FT_ULong; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_F2Dot14 */ + /* */ + /* <Description> */ + /* A signed 2.14 fixed float type used for unit vectors. */ + /* */ + typedef signed short FT_F2Dot14; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_F26Dot6 */ + /* */ + /* <Description> */ + /* A signed 26.6 fixed float type used for vectorial pixel */ + /* coordinates. */ + /* */ + typedef signed long FT_F26Dot6; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Fixed */ + /* */ + /* <Description> */ + /* This type is used to store 16.16 fixed float values, like scaling */ + /* values or matrix coefficients. */ + /* */ + typedef signed long FT_Fixed; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Error */ + /* */ + /* <Description> */ + /* The FreeType error code type. A value of~0 is always interpreted */ + /* as a successful operation. */ + /* */ + typedef int FT_Error; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Pointer */ + /* */ + /* <Description> */ + /* A simple typedef for a typeless pointer. */ + /* */ + typedef void* FT_Pointer; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Offset */ + /* */ + /* <Description> */ + /* This is equivalent to the ANSI~C `size_t' type, i.e., the largest */ + /* _unsigned_ integer type used to express a file size or position, */ + /* or a memory block size. */ + /* */ + typedef size_t FT_Offset; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_PtrDist */ + /* */ + /* <Description> */ + /* This is equivalent to the ANSI~C `ptrdiff_t' type, i.e., the */ + /* largest _signed_ integer type used to express the distance */ + /* between two pointers. */ + /* */ + typedef ft_ptrdiff_t FT_PtrDist; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_UnitVector */ + /* */ + /* <Description> */ + /* A simple structure used to store a 2D vector unit vector. Uses */ + /* FT_F2Dot14 types. */ + /* */ + /* <Fields> */ + /* x :: Horizontal coordinate. */ + /* */ + /* y :: Vertical coordinate. */ + /* */ + typedef struct FT_UnitVector_ + { + FT_F2Dot14 x; + FT_F2Dot14 y; + + } FT_UnitVector; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Matrix */ + /* */ + /* <Description> */ + /* A simple structure used to store a 2x2 matrix. Coefficients are */ + /* in 16.16 fixed float format. The computation performed is: */ + /* */ + /* { */ + /* x' = x*xx + y*xy */ + /* y' = x*yx + y*yy */ + /* } */ + /* */ + /* <Fields> */ + /* xx :: Matrix coefficient. */ + /* */ + /* xy :: Matrix coefficient. */ + /* */ + /* yx :: Matrix coefficient. */ + /* */ + /* yy :: Matrix coefficient. */ + /* */ + typedef struct FT_Matrix_ + { + FT_Fixed xx, xy; + FT_Fixed yx, yy; + + } FT_Matrix; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Data */ + /* */ + /* <Description> */ + /* Read-only binary data represented as a pointer and a length. */ + /* */ + /* <Fields> */ + /* pointer :: The data. */ + /* */ + /* length :: The length of the data in bytes. */ + /* */ + typedef struct FT_Data_ + { + const FT_Byte* pointer; + FT_Int length; + + } FT_Data; + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Generic_Finalizer */ + /* */ + /* <Description> */ + /* Describe a function used to destroy the `client' data of any */ + /* FreeType object. See the description of the @FT_Generic type for */ + /* details of usage. */ + /* */ + /* <Input> */ + /* The address of the FreeType object which is under finalization. */ + /* Its client data is accessed through its `generic' field. */ + /* */ + typedef void (*FT_Generic_Finalizer)(void* object); + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Generic */ + /* */ + /* <Description> */ + /* Client applications often need to associate their own data to a */ + /* variety of FreeType core objects. For example, a text layout API */ + /* might want to associate a glyph cache to a given size object. */ + /* */ + /* Most FreeType object contains a `generic' field, of type */ + /* FT_Generic, which usage is left to client applications and font */ + /* servers. */ + /* */ + /* It can be used to store a pointer to client-specific data, as well */ + /* as the address of a `finalizer' function, which will be called by */ + /* FreeType when the object is destroyed (for example, the previous */ + /* client example would put the address of the glyph cache destructor */ + /* in the `finalizer' field). */ + /* */ + /* <Fields> */ + /* data :: A typeless pointer to any client-specified data. This */ + /* field is completely ignored by the FreeType library. */ + /* */ + /* finalizer :: A pointer to a `generic finalizer' function, which */ + /* will be called when the object is destroyed. If this */ + /* field is set to NULL, no code will be called. */ + /* */ + typedef struct FT_Generic_ + { + void* data; + FT_Generic_Finalizer finalizer; + + } FT_Generic; + + + /*************************************************************************/ + /* */ + /* <Macro> */ + /* FT_MAKE_TAG */ + /* */ + /* <Description> */ + /* This macro converts four-letter tags which are used to label */ + /* TrueType tables into an unsigned long to be used within FreeType. */ + /* */ + /* <Note> */ + /* The produced values *must* be 32-bit integers. Don't redefine */ + /* this macro. */ + /* */ +#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ + (FT_Tag) \ + ( ( (FT_ULong)_x1 << 24 ) | \ + ( (FT_ULong)_x2 << 16 ) | \ + ( (FT_ULong)_x3 << 8 ) | \ + (FT_ULong)_x4 ) + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* L I S T M A N A G E M E N T */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* list_processing */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_ListNode */ + /* */ + /* <Description> */ + /* Many elements and objects in FreeType are listed through an */ + /* @FT_List record (see @FT_ListRec). As its name suggests, an */ + /* FT_ListNode is a handle to a single list element. */ + /* */ + typedef struct FT_ListNodeRec_* FT_ListNode; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_List */ + /* */ + /* <Description> */ + /* A handle to a list record (see @FT_ListRec). */ + /* */ + typedef struct FT_ListRec_* FT_List; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_ListNodeRec */ + /* */ + /* <Description> */ + /* A structure used to hold a single list element. */ + /* */ + /* <Fields> */ + /* prev :: The previous element in the list. NULL if first. */ + /* */ + /* next :: The next element in the list. NULL if last. */ + /* */ + /* data :: A typeless pointer to the listed object. */ + /* */ + typedef struct FT_ListNodeRec_ + { + FT_ListNode prev; + FT_ListNode next; + void* data; + + } FT_ListNodeRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_ListRec */ + /* */ + /* <Description> */ + /* A structure used to hold a simple doubly-linked list. These are */ + /* used in many parts of FreeType. */ + /* */ + /* <Fields> */ + /* head :: The head (first element) of doubly-linked list. */ + /* */ + /* tail :: The tail (last element) of doubly-linked list. */ + /* */ + typedef struct FT_ListRec_ + { + FT_ListNode head; + FT_ListNode tail; + + } FT_ListRec; + + + /* */ + +#define FT_IS_EMPTY( list ) ( (list).head == 0 ) + + /* return base error code (without module-specific prefix) */ +#define FT_ERROR_BASE( x ) ( (x) & 0xFF ) + + /* return module error code */ +#define FT_ERROR_MODULE( x ) ( (x) & 0xFF00U ) + +#define FT_BOOL( x ) ( (FT_Bool)( x ) ) + +FT_END_HEADER + +#endif /* __FTTYPES_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftwinfnt.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftwinfnt.h new file mode 100644 index 00000000..ea333535 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftwinfnt.h @@ -0,0 +1,274 @@ +/***************************************************************************/ +/* */ +/* ftwinfnt.h */ +/* */ +/* FreeType API for accessing Windows fnt-specific data. */ +/* */ +/* Copyright 2003, 2004, 2008 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTWINFNT_H__ +#define __FTWINFNT_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* winfnt_fonts */ + /* */ + /* <Title> */ + /* Window FNT Files */ + /* */ + /* <Abstract> */ + /* Windows FNT specific API. */ + /* */ + /* <Description> */ + /* This section contains the declaration of Windows FNT specific */ + /* functions. */ + /* */ + /*************************************************************************/ + + + /************************************************************************* + * + * @enum: + * FT_WinFNT_ID_XXX + * + * @description: + * A list of valid values for the `charset' byte in + * @FT_WinFNT_HeaderRec. Exact mapping tables for the various cpXXXX + * encodings (except for cp1361) can be found at ftp://ftp.unicode.org + * in the MAPPINGS/VENDORS/MICSFT/WINDOWS subdirectory. cp1361 is + * roughly a superset of MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT. + * + * @values: + * FT_WinFNT_ID_DEFAULT :: + * This is used for font enumeration and font creation as a + * `don't care' value. Valid font files don't contain this value. + * When querying for information about the character set of the font + * that is currently selected into a specified device context, this + * return value (of the related Windows API) simply denotes failure. + * + * FT_WinFNT_ID_SYMBOL :: + * There is no known mapping table available. + * + * FT_WinFNT_ID_MAC :: + * Mac Roman encoding. + * + * FT_WinFNT_ID_OEM :: + * From Michael Pöttgen <michael@poettgen.de>: + * + * The `Windows Font Mapping' article says that FT_WinFNT_ID_OEM + * is used for the charset of vector fonts, like `modern.fon', + * `roman.fon', and `script.fon' on Windows. + * + * The `CreateFont' documentation says: The FT_WinFNT_ID_OEM value + * specifies a character set that is operating-system dependent. + * + * The `IFIMETRICS' documentation from the `Windows Driver + * Development Kit' says: This font supports an OEM-specific + * character set. The OEM character set is system dependent. + * + * In general OEM, as opposed to ANSI (i.e., cp1252), denotes the + * second default codepage that most international versions of + * Windows have. It is one of the OEM codepages from + * + * http://www.microsoft.com/globaldev/reference/cphome.mspx, + * + * and is used for the `DOS boxes', to support legacy applications. + * A German Windows version for example usually uses ANSI codepage + * 1252 and OEM codepage 850. + * + * FT_WinFNT_ID_CP874 :: + * A superset of Thai TIS 620 and ISO 8859-11. + * + * FT_WinFNT_ID_CP932 :: + * A superset of Japanese Shift-JIS (with minor deviations). + * + * FT_WinFNT_ID_CP936 :: + * A superset of simplified Chinese GB 2312-1980 (with different + * ordering and minor deviations). + * + * FT_WinFNT_ID_CP949 :: + * A superset of Korean Hangul KS~C 5601-1987 (with different + * ordering and minor deviations). + * + * FT_WinFNT_ID_CP950 :: + * A superset of traditional Chinese Big~5 ETen (with different + * ordering and minor deviations). + * + * FT_WinFNT_ID_CP1250 :: + * A superset of East European ISO 8859-2 (with slightly different + * ordering). + * + * FT_WinFNT_ID_CP1251 :: + * A superset of Russian ISO 8859-5 (with different ordering). + * + * FT_WinFNT_ID_CP1252 :: + * ANSI encoding. A superset of ISO 8859-1. + * + * FT_WinFNT_ID_CP1253 :: + * A superset of Greek ISO 8859-7 (with minor modifications). + * + * FT_WinFNT_ID_CP1254 :: + * A superset of Turkish ISO 8859-9. + * + * FT_WinFNT_ID_CP1255 :: + * A superset of Hebrew ISO 8859-8 (with some modifications). + * + * FT_WinFNT_ID_CP1256 :: + * A superset of Arabic ISO 8859-6 (with different ordering). + * + * FT_WinFNT_ID_CP1257 :: + * A superset of Baltic ISO 8859-13 (with some deviations). + * + * FT_WinFNT_ID_CP1258 :: + * For Vietnamese. This encoding doesn't cover all necessary + * characters. + * + * FT_WinFNT_ID_CP1361 :: + * Korean (Johab). + */ + +#define FT_WinFNT_ID_CP1252 0 +#define FT_WinFNT_ID_DEFAULT 1 +#define FT_WinFNT_ID_SYMBOL 2 +#define FT_WinFNT_ID_MAC 77 +#define FT_WinFNT_ID_CP932 128 +#define FT_WinFNT_ID_CP949 129 +#define FT_WinFNT_ID_CP1361 130 +#define FT_WinFNT_ID_CP936 134 +#define FT_WinFNT_ID_CP950 136 +#define FT_WinFNT_ID_CP1253 161 +#define FT_WinFNT_ID_CP1254 162 +#define FT_WinFNT_ID_CP1258 163 +#define FT_WinFNT_ID_CP1255 177 +#define FT_WinFNT_ID_CP1256 178 +#define FT_WinFNT_ID_CP1257 186 +#define FT_WinFNT_ID_CP1251 204 +#define FT_WinFNT_ID_CP874 222 +#define FT_WinFNT_ID_CP1250 238 +#define FT_WinFNT_ID_OEM 255 + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_WinFNT_HeaderRec */ + /* */ + /* <Description> */ + /* Windows FNT Header info. */ + /* */ + typedef struct FT_WinFNT_HeaderRec_ + { + FT_UShort version; + FT_ULong file_size; + FT_Byte copyright[60]; + FT_UShort file_type; + FT_UShort nominal_point_size; + FT_UShort vertical_resolution; + FT_UShort horizontal_resolution; + FT_UShort ascent; + FT_UShort internal_leading; + FT_UShort external_leading; + FT_Byte italic; + FT_Byte underline; + FT_Byte strike_out; + FT_UShort weight; + FT_Byte charset; + FT_UShort pixel_width; + FT_UShort pixel_height; + FT_Byte pitch_and_family; + FT_UShort avg_width; + FT_UShort max_width; + FT_Byte first_char; + FT_Byte last_char; + FT_Byte default_char; + FT_Byte break_char; + FT_UShort bytes_per_row; + FT_ULong device_offset; + FT_ULong face_name_offset; + FT_ULong bits_pointer; + FT_ULong bits_offset; + FT_Byte reserved; + FT_ULong flags; + FT_UShort A_space; + FT_UShort B_space; + FT_UShort C_space; + FT_UShort color_table_offset; + FT_ULong reserved1[4]; + + } FT_WinFNT_HeaderRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_WinFNT_Header */ + /* */ + /* <Description> */ + /* A handle to an @FT_WinFNT_HeaderRec structure. */ + /* */ + typedef struct FT_WinFNT_HeaderRec_* FT_WinFNT_Header; + + + /********************************************************************** + * + * @function: + * FT_Get_WinFNT_Header + * + * @description: + * Retrieve a Windows FNT font info header. + * + * @input: + * face :: A handle to the input face. + * + * @output: + * aheader :: The WinFNT header. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * This function only works with Windows FNT faces, returning an error + * otherwise. + */ + FT_EXPORT( FT_Error ) + FT_Get_WinFNT_Header( FT_Face face, + FT_WinFNT_HeaderRec *aheader ); + + + /* */ + +FT_END_HEADER + +#endif /* __FTWINFNT_H__ */ + + +/* END */ + + +/* Local Variables: */ +/* coding: utf-8 */ +/* End: */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftxf86.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftxf86.h new file mode 100644 index 00000000..8c68afdc --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ftxf86.h @@ -0,0 +1,83 @@ +/***************************************************************************/ +/* */ +/* ftxf86.h */ +/* */ +/* Support functions for X11. */ +/* */ +/* Copyright 2002, 2003, 2004, 2006, 2007 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTXF86_H__ +#define __FTXF86_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* font_formats */ + /* */ + /* <Title> */ + /* Font Formats */ + /* */ + /* <Abstract> */ + /* Getting the font format. */ + /* */ + /* <Description> */ + /* The single function in this section can be used to get the font */ + /* format. Note that this information is not needed normally; */ + /* however, there are special cases (like in PDF devices) where it is */ + /* important to differentiate, in spite of FreeType's uniform API. */ + /* */ + /* This function is in the X11/xf86 namespace for historical reasons */ + /* and in no way depends on that windowing system. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_X11_Font_Format */ + /* */ + /* <Description> */ + /* Return a string describing the format of a given face, using values */ + /* which can be used as an X11 FONT_PROPERTY. Possible values are */ + /* `TrueType', `Type~1', `BDF', `PCF', `Type~42', `CID~Type~1', `CFF', */ + /* `PFR', and `Windows~FNT'. */ + /* */ + /* <Input> */ + /* face :: */ + /* Input face handle. */ + /* */ + /* <Return> */ + /* Font format string. NULL in case of error. */ + /* */ + FT_EXPORT( const char* ) + FT_Get_X11_Font_Format( FT_Face face ); + + /* */ + +FT_END_HEADER + +#endif /* __FTXF86_H__ */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/t1tables.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/t1tables.h new file mode 100644 index 00000000..5e2a3934 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/t1tables.h @@ -0,0 +1,504 @@ +/***************************************************************************/ +/* */ +/* t1tables.h */ +/* */ +/* Basic Type 1/Type 2 tables definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2008, 2009 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __T1TABLES_H__ +#define __T1TABLES_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* type1_tables */ + /* */ + /* <Title> */ + /* Type 1 Tables */ + /* */ + /* <Abstract> */ + /* Type~1 (PostScript) specific font tables. */ + /* */ + /* <Description> */ + /* This section contains the definition of Type 1-specific tables, */ + /* including structures related to other PostScript font formats. */ + /* */ + /*************************************************************************/ + + + /* Note that we separate font data in PS_FontInfoRec and PS_PrivateRec */ + /* structures in order to support Multiple Master fonts. */ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* PS_FontInfoRec */ + /* */ + /* <Description> */ + /* A structure used to model a Type~1 or Type~2 FontInfo dictionary. */ + /* Note that for Multiple Master fonts, each instance has its own */ + /* FontInfo dictionary. */ + /* */ + typedef struct PS_FontInfoRec_ + { + FT_String* version; + FT_String* notice; + FT_String* full_name; + FT_String* family_name; + FT_String* weight; + FT_Long italic_angle; + FT_Bool is_fixed_pitch; + FT_Short underline_position; + FT_UShort underline_thickness; + + } PS_FontInfoRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* PS_FontInfo */ + /* */ + /* <Description> */ + /* A handle to a @PS_FontInfoRec structure. */ + /* */ + typedef struct PS_FontInfoRec_* PS_FontInfo; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* T1_FontInfo */ + /* */ + /* <Description> */ + /* This type is equivalent to @PS_FontInfoRec. It is deprecated but */ + /* kept to maintain source compatibility between various versions of */ + /* FreeType. */ + /* */ + typedef PS_FontInfoRec T1_FontInfo; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* PS_PrivateRec */ + /* */ + /* <Description> */ + /* A structure used to model a Type~1 or Type~2 private dictionary. */ + /* Note that for Multiple Master fonts, each instance has its own */ + /* Private dictionary. */ + /* */ + typedef struct PS_PrivateRec_ + { + FT_Int unique_id; + FT_Int lenIV; + + FT_Byte num_blue_values; + FT_Byte num_other_blues; + FT_Byte num_family_blues; + FT_Byte num_family_other_blues; + + FT_Short blue_values[14]; + FT_Short other_blues[10]; + + FT_Short family_blues [14]; + FT_Short family_other_blues[10]; + + FT_Fixed blue_scale; + FT_Int blue_shift; + FT_Int blue_fuzz; + + FT_UShort standard_width[1]; + FT_UShort standard_height[1]; + + FT_Byte num_snap_widths; + FT_Byte num_snap_heights; + FT_Bool force_bold; + FT_Bool round_stem_up; + + FT_Short snap_widths [13]; /* including std width */ + FT_Short snap_heights[13]; /* including std height */ + + FT_Fixed expansion_factor; + + FT_Long language_group; + FT_Long password; + + FT_Short min_feature[2]; + + } PS_PrivateRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* PS_Private */ + /* */ + /* <Description> */ + /* A handle to a @PS_PrivateRec structure. */ + /* */ + typedef struct PS_PrivateRec_* PS_Private; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* T1_Private */ + /* */ + /* <Description> */ + /* This type is equivalent to @PS_PrivateRec. It is deprecated but */ + /* kept to maintain source compatibility between various versions of */ + /* FreeType. */ + /* */ + typedef PS_PrivateRec T1_Private; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* T1_Blend_Flags */ + /* */ + /* <Description> */ + /* A set of flags used to indicate which fields are present in a */ + /* given blend dictionary (font info or private). Used to support */ + /* Multiple Masters fonts. */ + /* */ + typedef enum T1_Blend_Flags_ + { + /*# required fields in a FontInfo blend dictionary */ + T1_BLEND_UNDERLINE_POSITION = 0, + T1_BLEND_UNDERLINE_THICKNESS, + T1_BLEND_ITALIC_ANGLE, + + /*# required fields in a Private blend dictionary */ + T1_BLEND_BLUE_VALUES, + T1_BLEND_OTHER_BLUES, + T1_BLEND_STANDARD_WIDTH, + T1_BLEND_STANDARD_HEIGHT, + T1_BLEND_STEM_SNAP_WIDTHS, + T1_BLEND_STEM_SNAP_HEIGHTS, + T1_BLEND_BLUE_SCALE, + T1_BLEND_BLUE_SHIFT, + T1_BLEND_FAMILY_BLUES, + T1_BLEND_FAMILY_OTHER_BLUES, + T1_BLEND_FORCE_BOLD, + + /*# never remove */ + T1_BLEND_MAX + + } T1_Blend_Flags; + + /* */ + + + /*# backwards compatible definitions */ +#define t1_blend_underline_position T1_BLEND_UNDERLINE_POSITION +#define t1_blend_underline_thickness T1_BLEND_UNDERLINE_THICKNESS +#define t1_blend_italic_angle T1_BLEND_ITALIC_ANGLE +#define t1_blend_blue_values T1_BLEND_BLUE_VALUES +#define t1_blend_other_blues T1_BLEND_OTHER_BLUES +#define t1_blend_standard_widths T1_BLEND_STANDARD_WIDTH +#define t1_blend_standard_height T1_BLEND_STANDARD_HEIGHT +#define t1_blend_stem_snap_widths T1_BLEND_STEM_SNAP_WIDTHS +#define t1_blend_stem_snap_heights T1_BLEND_STEM_SNAP_HEIGHTS +#define t1_blend_blue_scale T1_BLEND_BLUE_SCALE +#define t1_blend_blue_shift T1_BLEND_BLUE_SHIFT +#define t1_blend_family_blues T1_BLEND_FAMILY_BLUES +#define t1_blend_family_other_blues T1_BLEND_FAMILY_OTHER_BLUES +#define t1_blend_force_bold T1_BLEND_FORCE_BOLD +#define t1_blend_max T1_BLEND_MAX + + + /* maximum number of Multiple Masters designs, as defined in the spec */ +#define T1_MAX_MM_DESIGNS 16 + + /* maximum number of Multiple Masters axes, as defined in the spec */ +#define T1_MAX_MM_AXIS 4 + + /* maximum number of elements in a design map */ +#define T1_MAX_MM_MAP_POINTS 20 + + + /* this structure is used to store the BlendDesignMap entry for an axis */ + typedef struct PS_DesignMap_ + { + FT_Byte num_points; + FT_Long* design_points; + FT_Fixed* blend_points; + + } PS_DesignMapRec, *PS_DesignMap; + + /* backwards-compatible definition */ + typedef PS_DesignMapRec T1_DesignMap; + + + typedef struct PS_BlendRec_ + { + FT_UInt num_designs; + FT_UInt num_axis; + + FT_String* axis_names[T1_MAX_MM_AXIS]; + FT_Fixed* design_pos[T1_MAX_MM_DESIGNS]; + PS_DesignMapRec design_map[T1_MAX_MM_AXIS]; + + FT_Fixed* weight_vector; + FT_Fixed* default_weight_vector; + + PS_FontInfo font_infos[T1_MAX_MM_DESIGNS + 1]; + PS_Private privates [T1_MAX_MM_DESIGNS + 1]; + + FT_ULong blend_bitflags; + + FT_BBox* bboxes [T1_MAX_MM_DESIGNS + 1]; + + /* since 2.3.0 */ + + /* undocumented, optional: the default design instance; */ + /* corresponds to default_weight_vector -- */ + /* num_default_design_vector == 0 means it is not present */ + /* in the font and associated metrics files */ + FT_UInt default_design_vector[T1_MAX_MM_DESIGNS]; + FT_UInt num_default_design_vector; + + } PS_BlendRec, *PS_Blend; + + + /* backwards-compatible definition */ + typedef PS_BlendRec T1_Blend; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* CID_FaceDictRec */ + /* */ + /* <Description> */ + /* A structure used to represent data in a CID top-level dictionary. */ + /* */ + typedef struct CID_FaceDictRec_ + { + PS_PrivateRec private_dict; + + FT_UInt len_buildchar; + FT_Fixed forcebold_threshold; + FT_Pos stroke_width; + FT_Fixed expansion_factor; + + FT_Byte paint_type; + FT_Byte font_type; + FT_Matrix font_matrix; + FT_Vector font_offset; + + FT_UInt num_subrs; + FT_ULong subrmap_offset; + FT_Int sd_bytes; + + } CID_FaceDictRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* CID_FaceDict */ + /* */ + /* <Description> */ + /* A handle to a @CID_FaceDictRec structure. */ + /* */ + typedef struct CID_FaceDictRec_* CID_FaceDict; + + /* */ + + + /* backwards-compatible definition */ + typedef CID_FaceDictRec CID_FontDict; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* CID_FaceInfoRec */ + /* */ + /* <Description> */ + /* A structure used to represent CID Face information. */ + /* */ + typedef struct CID_FaceInfoRec_ + { + FT_String* cid_font_name; + FT_Fixed cid_version; + FT_Int cid_font_type; + + FT_String* registry; + FT_String* ordering; + FT_Int supplement; + + PS_FontInfoRec font_info; + FT_BBox font_bbox; + FT_ULong uid_base; + + FT_Int num_xuid; + FT_ULong xuid[16]; + + FT_ULong cidmap_offset; + FT_Int fd_bytes; + FT_Int gd_bytes; + FT_ULong cid_count; + + FT_Int num_dicts; + CID_FaceDict font_dicts; + + FT_ULong data_offset; + + } CID_FaceInfoRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* CID_FaceInfo */ + /* */ + /* <Description> */ + /* A handle to a @CID_FaceInfoRec structure. */ + /* */ + typedef struct CID_FaceInfoRec_* CID_FaceInfo; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* CID_Info */ + /* */ + /* <Description> */ + /* This type is equivalent to @CID_FaceInfoRec. It is deprecated but */ + /* kept to maintain source compatibility between various versions of */ + /* FreeType. */ + /* */ + typedef CID_FaceInfoRec CID_Info; + + + /************************************************************************ + * + * @function: + * FT_Has_PS_Glyph_Names + * + * @description: + * Return true if a given face provides reliable PostScript glyph + * names. This is similar to using the @FT_HAS_GLYPH_NAMES macro, + * except that certain fonts (mostly TrueType) contain incorrect + * glyph name tables. + * + * When this function returns true, the caller is sure that the glyph + * names returned by @FT_Get_Glyph_Name are reliable. + * + * @input: + * face :: + * face handle + * + * @return: + * Boolean. True if glyph names are reliable. + * + */ + FT_EXPORT( FT_Int ) + FT_Has_PS_Glyph_Names( FT_Face face ); + + + /************************************************************************ + * + * @function: + * FT_Get_PS_Font_Info + * + * @description: + * Retrieve the @PS_FontInfoRec structure corresponding to a given + * PostScript font. + * + * @input: + * face :: + * PostScript face handle. + * + * @output: + * afont_info :: + * Output font info structure pointer. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * The string pointers within the font info structure are owned by + * the face and don't need to be freed by the caller. + * + * If the font's format is not PostScript-based, this function will + * return the `FT_Err_Invalid_Argument' error code. + * + */ + FT_EXPORT( FT_Error ) + FT_Get_PS_Font_Info( FT_Face face, + PS_FontInfo afont_info ); + + + /************************************************************************ + * + * @function: + * FT_Get_PS_Font_Private + * + * @description: + * Retrieve the @PS_PrivateRec structure corresponding to a given + * PostScript font. + * + * @input: + * face :: + * PostScript face handle. + * + * @output: + * afont_private :: + * Output private dictionary structure pointer. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * The string pointers within the @PS_PrivateRec structure are owned by + * the face and don't need to be freed by the caller. + * + * If the font's format is not PostScript-based, this function returns + * the `FT_Err_Invalid_Argument' error code. + * + */ + FT_EXPORT( FT_Error ) + FT_Get_PS_Font_Private( FT_Face face, + PS_Private afont_private ); + + /* */ + + +FT_END_HEADER + +#endif /* __T1TABLES_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ttnameid.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ttnameid.h new file mode 100644 index 00000000..66aef043 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ttnameid.h @@ -0,0 +1,1247 @@ +/***************************************************************************/ +/* */ +/* ttnameid.h */ +/* */ +/* TrueType name ID definitions (specification only). */ +/* */ +/* Copyright 1996-2002, 2003, 2004, 2006, 2007, 2008 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTNAMEID_H__ +#define __TTNAMEID_H__ + + +#include <ft2build.h> + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* truetype_tables */ + /* */ + + + /*************************************************************************/ + /* */ + /* Possible values for the `platform' identifier code in the name */ + /* records of the TTF `name' table. */ + /* */ + /*************************************************************************/ + + + /*********************************************************************** + * + * @enum: + * TT_PLATFORM_XXX + * + * @description: + * A list of valid values for the `platform_id' identifier code in + * @FT_CharMapRec and @FT_SfntName structures. + * + * @values: + * TT_PLATFORM_APPLE_UNICODE :: + * Used by Apple to indicate a Unicode character map and/or name entry. + * See @TT_APPLE_ID_XXX for corresponding `encoding_id' values. Note + * that name entries in this format are coded as big-endian UCS-2 + * character codes _only_. + * + * TT_PLATFORM_MACINTOSH :: + * Used by Apple to indicate a MacOS-specific charmap and/or name entry. + * See @TT_MAC_ID_XXX for corresponding `encoding_id' values. Note that + * most TrueType fonts contain an Apple roman charmap to be usable on + * MacOS systems (even if they contain a Microsoft charmap as well). + * + * TT_PLATFORM_ISO :: + * This value was used to specify ISO/IEC 10646 charmaps. It is however + * now deprecated. See @TT_ISO_ID_XXX for a list of corresponding + * `encoding_id' values. + * + * TT_PLATFORM_MICROSOFT :: + * Used by Microsoft to indicate Windows-specific charmaps. See + * @TT_MS_ID_XXX for a list of corresponding `encoding_id' values. + * Note that most fonts contain a Unicode charmap using + * (TT_PLATFORM_MICROSOFT, @TT_MS_ID_UNICODE_CS). + * + * TT_PLATFORM_CUSTOM :: + * Used to indicate application-specific charmaps. + * + * TT_PLATFORM_ADOBE :: + * This value isn't part of any font format specification, but is used + * by FreeType to report Adobe-specific charmaps in an @FT_CharMapRec + * structure. See @TT_ADOBE_ID_XXX. + */ + +#define TT_PLATFORM_APPLE_UNICODE 0 +#define TT_PLATFORM_MACINTOSH 1 +#define TT_PLATFORM_ISO 2 /* deprecated */ +#define TT_PLATFORM_MICROSOFT 3 +#define TT_PLATFORM_CUSTOM 4 +#define TT_PLATFORM_ADOBE 7 /* artificial */ + + + /*********************************************************************** + * + * @enum: + * TT_APPLE_ID_XXX + * + * @description: + * A list of valid values for the `encoding_id' for + * @TT_PLATFORM_APPLE_UNICODE charmaps and name entries. + * + * @values: + * TT_APPLE_ID_DEFAULT :: + * Unicode version 1.0. + * + * TT_APPLE_ID_UNICODE_1_1 :: + * Unicode 1.1; specifies Hangul characters starting at U+34xx. + * + * TT_APPLE_ID_ISO_10646 :: + * Deprecated (identical to preceding). + * + * TT_APPLE_ID_UNICODE_2_0 :: + * Unicode 2.0 and beyond (UTF-16 BMP only). + * + * TT_APPLE_ID_UNICODE_32 :: + * Unicode 3.1 and beyond, using UTF-32. + * + * TT_APPLE_ID_VARIANT_SELECTOR :: + * From Adobe, not Apple. Not a normal cmap. Specifies variations + * on a real cmap. + */ + +#define TT_APPLE_ID_DEFAULT 0 /* Unicode 1.0 */ +#define TT_APPLE_ID_UNICODE_1_1 1 /* specify Hangul at U+34xx */ +#define TT_APPLE_ID_ISO_10646 2 /* deprecated */ +#define TT_APPLE_ID_UNICODE_2_0 3 /* or later */ +#define TT_APPLE_ID_UNICODE_32 4 /* 2.0 or later, full repertoire */ +#define TT_APPLE_ID_VARIANT_SELECTOR 5 /* variation selector data */ + + + /*********************************************************************** + * + * @enum: + * TT_MAC_ID_XXX + * + * @description: + * A list of valid values for the `encoding_id' for + * @TT_PLATFORM_MACINTOSH charmaps and name entries. + * + * @values: + * TT_MAC_ID_ROMAN :: + * TT_MAC_ID_JAPANESE :: + * TT_MAC_ID_TRADITIONAL_CHINESE :: + * TT_MAC_ID_KOREAN :: + * TT_MAC_ID_ARABIC :: + * TT_MAC_ID_HEBREW :: + * TT_MAC_ID_GREEK :: + * TT_MAC_ID_RUSSIAN :: + * TT_MAC_ID_RSYMBOL :: + * TT_MAC_ID_DEVANAGARI :: + * TT_MAC_ID_GURMUKHI :: + * TT_MAC_ID_GUJARATI :: + * TT_MAC_ID_ORIYA :: + * TT_MAC_ID_BENGALI :: + * TT_MAC_ID_TAMIL :: + * TT_MAC_ID_TELUGU :: + * TT_MAC_ID_KANNADA :: + * TT_MAC_ID_MALAYALAM :: + * TT_MAC_ID_SINHALESE :: + * TT_MAC_ID_BURMESE :: + * TT_MAC_ID_KHMER :: + * TT_MAC_ID_THAI :: + * TT_MAC_ID_LAOTIAN :: + * TT_MAC_ID_GEORGIAN :: + * TT_MAC_ID_ARMENIAN :: + * TT_MAC_ID_MALDIVIAN :: + * TT_MAC_ID_SIMPLIFIED_CHINESE :: + * TT_MAC_ID_TIBETAN :: + * TT_MAC_ID_MONGOLIAN :: + * TT_MAC_ID_GEEZ :: + * TT_MAC_ID_SLAVIC :: + * TT_MAC_ID_VIETNAMESE :: + * TT_MAC_ID_SINDHI :: + * TT_MAC_ID_UNINTERP :: + */ + +#define TT_MAC_ID_ROMAN 0 +#define TT_MAC_ID_JAPANESE 1 +#define TT_MAC_ID_TRADITIONAL_CHINESE 2 +#define TT_MAC_ID_KOREAN 3 +#define TT_MAC_ID_ARABIC 4 +#define TT_MAC_ID_HEBREW 5 +#define TT_MAC_ID_GREEK 6 +#define TT_MAC_ID_RUSSIAN 7 +#define TT_MAC_ID_RSYMBOL 8 +#define TT_MAC_ID_DEVANAGARI 9 +#define TT_MAC_ID_GURMUKHI 10 +#define TT_MAC_ID_GUJARATI 11 +#define TT_MAC_ID_ORIYA 12 +#define TT_MAC_ID_BENGALI 13 +#define TT_MAC_ID_TAMIL 14 +#define TT_MAC_ID_TELUGU 15 +#define TT_MAC_ID_KANNADA 16 +#define TT_MAC_ID_MALAYALAM 17 +#define TT_MAC_ID_SINHALESE 18 +#define TT_MAC_ID_BURMESE 19 +#define TT_MAC_ID_KHMER 20 +#define TT_MAC_ID_THAI 21 +#define TT_MAC_ID_LAOTIAN 22 +#define TT_MAC_ID_GEORGIAN 23 +#define TT_MAC_ID_ARMENIAN 24 +#define TT_MAC_ID_MALDIVIAN 25 +#define TT_MAC_ID_SIMPLIFIED_CHINESE 25 +#define TT_MAC_ID_TIBETAN 26 +#define TT_MAC_ID_MONGOLIAN 27 +#define TT_MAC_ID_GEEZ 28 +#define TT_MAC_ID_SLAVIC 29 +#define TT_MAC_ID_VIETNAMESE 30 +#define TT_MAC_ID_SINDHI 31 +#define TT_MAC_ID_UNINTERP 32 + + + /*********************************************************************** + * + * @enum: + * TT_ISO_ID_XXX + * + * @description: + * A list of valid values for the `encoding_id' for + * @TT_PLATFORM_ISO charmaps and name entries. + * + * Their use is now deprecated. + * + * @values: + * TT_ISO_ID_7BIT_ASCII :: + * ASCII. + * TT_ISO_ID_10646 :: + * ISO/10646. + * TT_ISO_ID_8859_1 :: + * Also known as Latin-1. + */ + +#define TT_ISO_ID_7BIT_ASCII 0 +#define TT_ISO_ID_10646 1 +#define TT_ISO_ID_8859_1 2 + + + /*********************************************************************** + * + * @enum: + * TT_MS_ID_XXX + * + * @description: + * A list of valid values for the `encoding_id' for + * @TT_PLATFORM_MICROSOFT charmaps and name entries. + * + * @values: + * TT_MS_ID_SYMBOL_CS :: + * Corresponds to Microsoft symbol encoding. See + * @FT_ENCODING_MS_SYMBOL. + * + * TT_MS_ID_UNICODE_CS :: + * Corresponds to a Microsoft WGL4 charmap, matching Unicode. See + * @FT_ENCODING_UNICODE. + * + * TT_MS_ID_SJIS :: + * Corresponds to SJIS Japanese encoding. See @FT_ENCODING_SJIS. + * + * TT_MS_ID_GB2312 :: + * Corresponds to Simplified Chinese as used in Mainland China. See + * @FT_ENCODING_GB2312. + * + * TT_MS_ID_BIG_5 :: + * Corresponds to Traditional Chinese as used in Taiwan and Hong Kong. + * See @FT_ENCODING_BIG5. + * + * TT_MS_ID_WANSUNG :: + * Corresponds to Korean Wansung encoding. See @FT_ENCODING_WANSUNG. + * + * TT_MS_ID_JOHAB :: + * Corresponds to Johab encoding. See @FT_ENCODING_JOHAB. + * + * TT_MS_ID_UCS_4 :: + * Corresponds to UCS-4 or UTF-32 charmaps. This has been added to + * the OpenType specification version 1.4 (mid-2001.) + */ + +#define TT_MS_ID_SYMBOL_CS 0 +#define TT_MS_ID_UNICODE_CS 1 +#define TT_MS_ID_SJIS 2 +#define TT_MS_ID_GB2312 3 +#define TT_MS_ID_BIG_5 4 +#define TT_MS_ID_WANSUNG 5 +#define TT_MS_ID_JOHAB 6 +#define TT_MS_ID_UCS_4 10 + + + /*********************************************************************** + * + * @enum: + * TT_ADOBE_ID_XXX + * + * @description: + * A list of valid values for the `encoding_id' for + * @TT_PLATFORM_ADOBE charmaps. This is a FreeType-specific extension! + * + * @values: + * TT_ADOBE_ID_STANDARD :: + * Adobe standard encoding. + * TT_ADOBE_ID_EXPERT :: + * Adobe expert encoding. + * TT_ADOBE_ID_CUSTOM :: + * Adobe custom encoding. + * TT_ADOBE_ID_LATIN_1 :: + * Adobe Latin~1 encoding. + */ + +#define TT_ADOBE_ID_STANDARD 0 +#define TT_ADOBE_ID_EXPERT 1 +#define TT_ADOBE_ID_CUSTOM 2 +#define TT_ADOBE_ID_LATIN_1 3 + + + /*************************************************************************/ + /* */ + /* Possible values of the language identifier field in the name records */ + /* of the TTF `name' table if the `platform' identifier code is */ + /* TT_PLATFORM_MACINTOSH. */ + /* */ + /* The canonical source for the Apple assigned Language ID's is at */ + /* */ + /* http://fonts.apple.com/TTRefMan/RM06/Chap6name.html */ + /* */ +#define TT_MAC_LANGID_ENGLISH 0 +#define TT_MAC_LANGID_FRENCH 1 +#define TT_MAC_LANGID_GERMAN 2 +#define TT_MAC_LANGID_ITALIAN 3 +#define TT_MAC_LANGID_DUTCH 4 +#define TT_MAC_LANGID_SWEDISH 5 +#define TT_MAC_LANGID_SPANISH 6 +#define TT_MAC_LANGID_DANISH 7 +#define TT_MAC_LANGID_PORTUGUESE 8 +#define TT_MAC_LANGID_NORWEGIAN 9 +#define TT_MAC_LANGID_HEBREW 10 +#define TT_MAC_LANGID_JAPANESE 11 +#define TT_MAC_LANGID_ARABIC 12 +#define TT_MAC_LANGID_FINNISH 13 +#define TT_MAC_LANGID_GREEK 14 +#define TT_MAC_LANGID_ICELANDIC 15 +#define TT_MAC_LANGID_MALTESE 16 +#define TT_MAC_LANGID_TURKISH 17 +#define TT_MAC_LANGID_CROATIAN 18 +#define TT_MAC_LANGID_CHINESE_TRADITIONAL 19 +#define TT_MAC_LANGID_URDU 20 +#define TT_MAC_LANGID_HINDI 21 +#define TT_MAC_LANGID_THAI 22 +#define TT_MAC_LANGID_KOREAN 23 +#define TT_MAC_LANGID_LITHUANIAN 24 +#define TT_MAC_LANGID_POLISH 25 +#define TT_MAC_LANGID_HUNGARIAN 26 +#define TT_MAC_LANGID_ESTONIAN 27 +#define TT_MAC_LANGID_LETTISH 28 +#define TT_MAC_LANGID_SAAMISK 29 +#define TT_MAC_LANGID_FAEROESE 30 +#define TT_MAC_LANGID_FARSI 31 +#define TT_MAC_LANGID_RUSSIAN 32 +#define TT_MAC_LANGID_CHINESE_SIMPLIFIED 33 +#define TT_MAC_LANGID_FLEMISH 34 +#define TT_MAC_LANGID_IRISH 35 +#define TT_MAC_LANGID_ALBANIAN 36 +#define TT_MAC_LANGID_ROMANIAN 37 +#define TT_MAC_LANGID_CZECH 38 +#define TT_MAC_LANGID_SLOVAK 39 +#define TT_MAC_LANGID_SLOVENIAN 40 +#define TT_MAC_LANGID_YIDDISH 41 +#define TT_MAC_LANGID_SERBIAN 42 +#define TT_MAC_LANGID_MACEDONIAN 43 +#define TT_MAC_LANGID_BULGARIAN 44 +#define TT_MAC_LANGID_UKRAINIAN 45 +#define TT_MAC_LANGID_BYELORUSSIAN 46 +#define TT_MAC_LANGID_UZBEK 47 +#define TT_MAC_LANGID_KAZAKH 48 +#define TT_MAC_LANGID_AZERBAIJANI 49 +#define TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT 49 +#define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT 50 +#define TT_MAC_LANGID_ARMENIAN 51 +#define TT_MAC_LANGID_GEORGIAN 52 +#define TT_MAC_LANGID_MOLDAVIAN 53 +#define TT_MAC_LANGID_KIRGHIZ 54 +#define TT_MAC_LANGID_TAJIKI 55 +#define TT_MAC_LANGID_TURKMEN 56 +#define TT_MAC_LANGID_MONGOLIAN 57 +#define TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT 57 +#define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT 58 +#define TT_MAC_LANGID_PASHTO 59 +#define TT_MAC_LANGID_KURDISH 60 +#define TT_MAC_LANGID_KASHMIRI 61 +#define TT_MAC_LANGID_SINDHI 62 +#define TT_MAC_LANGID_TIBETAN 63 +#define TT_MAC_LANGID_NEPALI 64 +#define TT_MAC_LANGID_SANSKRIT 65 +#define TT_MAC_LANGID_MARATHI 66 +#define TT_MAC_LANGID_BENGALI 67 +#define TT_MAC_LANGID_ASSAMESE 68 +#define TT_MAC_LANGID_GUJARATI 69 +#define TT_MAC_LANGID_PUNJABI 70 +#define TT_MAC_LANGID_ORIYA 71 +#define TT_MAC_LANGID_MALAYALAM 72 +#define TT_MAC_LANGID_KANNADA 73 +#define TT_MAC_LANGID_TAMIL 74 +#define TT_MAC_LANGID_TELUGU 75 +#define TT_MAC_LANGID_SINHALESE 76 +#define TT_MAC_LANGID_BURMESE 77 +#define TT_MAC_LANGID_KHMER 78 +#define TT_MAC_LANGID_LAO 79 +#define TT_MAC_LANGID_VIETNAMESE 80 +#define TT_MAC_LANGID_INDONESIAN 81 +#define TT_MAC_LANGID_TAGALOG 82 +#define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT 83 +#define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT 84 +#define TT_MAC_LANGID_AMHARIC 85 +#define TT_MAC_LANGID_TIGRINYA 86 +#define TT_MAC_LANGID_GALLA 87 +#define TT_MAC_LANGID_SOMALI 88 +#define TT_MAC_LANGID_SWAHILI 89 +#define TT_MAC_LANGID_RUANDA 90 +#define TT_MAC_LANGID_RUNDI 91 +#define TT_MAC_LANGID_CHEWA 92 +#define TT_MAC_LANGID_MALAGASY 93 +#define TT_MAC_LANGID_ESPERANTO 94 +#define TT_MAC_LANGID_WELSH 128 +#define TT_MAC_LANGID_BASQUE 129 +#define TT_MAC_LANGID_CATALAN 130 +#define TT_MAC_LANGID_LATIN 131 +#define TT_MAC_LANGID_QUECHUA 132 +#define TT_MAC_LANGID_GUARANI 133 +#define TT_MAC_LANGID_AYMARA 134 +#define TT_MAC_LANGID_TATAR 135 +#define TT_MAC_LANGID_UIGHUR 136 +#define TT_MAC_LANGID_DZONGKHA 137 +#define TT_MAC_LANGID_JAVANESE 138 +#define TT_MAC_LANGID_SUNDANESE 139 + + +#if 0 /* these seem to be errors that have been dropped */ + +#define TT_MAC_LANGID_SCOTTISH_GAELIC 140 +#define TT_MAC_LANGID_IRISH_GAELIC 141 + +#endif + + + /* The following codes are new as of 2000-03-10 */ +#define TT_MAC_LANGID_GALICIAN 140 +#define TT_MAC_LANGID_AFRIKAANS 141 +#define TT_MAC_LANGID_BRETON 142 +#define TT_MAC_LANGID_INUKTITUT 143 +#define TT_MAC_LANGID_SCOTTISH_GAELIC 144 +#define TT_MAC_LANGID_MANX_GAELIC 145 +#define TT_MAC_LANGID_IRISH_GAELIC 146 +#define TT_MAC_LANGID_TONGAN 147 +#define TT_MAC_LANGID_GREEK_POLYTONIC 148 +#define TT_MAC_LANGID_GREELANDIC 149 +#define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT 150 + + + /*************************************************************************/ + /* */ + /* Possible values of the language identifier field in the name records */ + /* of the TTF `name' table if the `platform' identifier code is */ + /* TT_PLATFORM_MICROSOFT. */ + /* */ + /* The canonical source for the MS assigned LCID's (seems to) be at */ + /* */ + /* http://www.microsoft.com/globaldev/reference/lcid-all.mspx */ + /* */ + /* It used to be at various places, among them */ + /* */ + /* http://www.microsoft.com/typography/OTSPEC/lcid-cp.txt */ + /* http://www.microsoft.com/globaldev/reference/loclanghome.asp */ + /* http://support.microsoft.com/support/kb/articles/Q224/8/04.ASP */ + /* http://msdn.microsoft.com/library/en-us/passport25/ */ + /* NET_Passport_VBScript_Documentation/Single_Sign_In/ */ + /* Advanced_Single_Sign_In/Localization_and_LCIDs.asp */ + /* */ + /* Hopefully, it seems now that the Globaldev site prevails... */ + /* (updated by Antoine, 2004-02-17) */ + +#define TT_MS_LANGID_ARABIC_GENERAL 0x0001 +#define TT_MS_LANGID_ARABIC_SAUDI_ARABIA 0x0401 +#define TT_MS_LANGID_ARABIC_IRAQ 0x0801 +#define TT_MS_LANGID_ARABIC_EGYPT 0x0c01 +#define TT_MS_LANGID_ARABIC_LIBYA 0x1001 +#define TT_MS_LANGID_ARABIC_ALGERIA 0x1401 +#define TT_MS_LANGID_ARABIC_MOROCCO 0x1801 +#define TT_MS_LANGID_ARABIC_TUNISIA 0x1c01 +#define TT_MS_LANGID_ARABIC_OMAN 0x2001 +#define TT_MS_LANGID_ARABIC_YEMEN 0x2401 +#define TT_MS_LANGID_ARABIC_SYRIA 0x2801 +#define TT_MS_LANGID_ARABIC_JORDAN 0x2c01 +#define TT_MS_LANGID_ARABIC_LEBANON 0x3001 +#define TT_MS_LANGID_ARABIC_KUWAIT 0x3401 +#define TT_MS_LANGID_ARABIC_UAE 0x3801 +#define TT_MS_LANGID_ARABIC_BAHRAIN 0x3c01 +#define TT_MS_LANGID_ARABIC_QATAR 0x4001 +#define TT_MS_LANGID_BULGARIAN_BULGARIA 0x0402 +#define TT_MS_LANGID_CATALAN_SPAIN 0x0403 +#define TT_MS_LANGID_CHINESE_GENERAL 0x0004 +#define TT_MS_LANGID_CHINESE_TAIWAN 0x0404 +#define TT_MS_LANGID_CHINESE_PRC 0x0804 +#define TT_MS_LANGID_CHINESE_HONG_KONG 0x0c04 +#define TT_MS_LANGID_CHINESE_SINGAPORE 0x1004 + +#if 1 /* this looks like the correct value */ +#define TT_MS_LANGID_CHINESE_MACAU 0x1404 +#else /* but beware, Microsoft may change its mind... + the most recent Word reference has the following: */ +#define TT_MS_LANGID_CHINESE_MACAU TT_MS_LANGID_CHINESE_HONG_KONG +#endif + +#if 0 /* used only with .NET `cultures'; commented out */ +#define TT_MS_LANGID_CHINESE_TRADITIONAL 0x7C04 +#endif + +#define TT_MS_LANGID_CZECH_CZECH_REPUBLIC 0x0405 +#define TT_MS_LANGID_DANISH_DENMARK 0x0406 +#define TT_MS_LANGID_GERMAN_GERMANY 0x0407 +#define TT_MS_LANGID_GERMAN_SWITZERLAND 0x0807 +#define TT_MS_LANGID_GERMAN_AUSTRIA 0x0c07 +#define TT_MS_LANGID_GERMAN_LUXEMBOURG 0x1007 +#define TT_MS_LANGID_GERMAN_LIECHTENSTEI 0x1407 +#define TT_MS_LANGID_GREEK_GREECE 0x0408 + + /* don't ask what this one means... It is commented out currently. */ +#if 0 +#define TT_MS_LANGID_GREEK_GREECE2 0x2008 +#endif + +#define TT_MS_LANGID_ENGLISH_GENERAL 0x0009 +#define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409 +#define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM 0x0809 +#define TT_MS_LANGID_ENGLISH_AUSTRALIA 0x0c09 +#define TT_MS_LANGID_ENGLISH_CANADA 0x1009 +#define TT_MS_LANGID_ENGLISH_NEW_ZEALAND 0x1409 +#define TT_MS_LANGID_ENGLISH_IRELAND 0x1809 +#define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA 0x1c09 +#define TT_MS_LANGID_ENGLISH_JAMAICA 0x2009 +#define TT_MS_LANGID_ENGLISH_CARIBBEAN 0x2409 +#define TT_MS_LANGID_ENGLISH_BELIZE 0x2809 +#define TT_MS_LANGID_ENGLISH_TRINIDAD 0x2c09 +#define TT_MS_LANGID_ENGLISH_ZIMBABWE 0x3009 +#define TT_MS_LANGID_ENGLISH_PHILIPPINES 0x3409 +#define TT_MS_LANGID_ENGLISH_INDONESIA 0x3809 +#define TT_MS_LANGID_ENGLISH_HONG_KONG 0x3c09 +#define TT_MS_LANGID_ENGLISH_INDIA 0x4009 +#define TT_MS_LANGID_ENGLISH_MALAYSIA 0x4409 +#define TT_MS_LANGID_ENGLISH_SINGAPORE 0x4809 +#define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT 0x040a +#define TT_MS_LANGID_SPANISH_MEXICO 0x080a +#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT 0x0c0a +#define TT_MS_LANGID_SPANISH_GUATEMALA 0x100a +#define TT_MS_LANGID_SPANISH_COSTA_RICA 0x140a +#define TT_MS_LANGID_SPANISH_PANAMA 0x180a +#define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC 0x1c0a +#define TT_MS_LANGID_SPANISH_VENEZUELA 0x200a +#define TT_MS_LANGID_SPANISH_COLOMBIA 0x240a +#define TT_MS_LANGID_SPANISH_PERU 0x280a +#define TT_MS_LANGID_SPANISH_ARGENTINA 0x2c0a +#define TT_MS_LANGID_SPANISH_ECUADOR 0x300a +#define TT_MS_LANGID_SPANISH_CHILE 0x340a +#define TT_MS_LANGID_SPANISH_URUGUAY 0x380a +#define TT_MS_LANGID_SPANISH_PARAGUAY 0x3c0a +#define TT_MS_LANGID_SPANISH_BOLIVIA 0x400a +#define TT_MS_LANGID_SPANISH_EL_SALVADOR 0x440a +#define TT_MS_LANGID_SPANISH_HONDURAS 0x480a +#define TT_MS_LANGID_SPANISH_NICARAGUA 0x4c0a +#define TT_MS_LANGID_SPANISH_PUERTO_RICO 0x500a +#define TT_MS_LANGID_SPANISH_UNITED_STATES 0x540a + /* The following ID blatantly violate MS specs by using a */ + /* sublanguage > 0x1F. */ +#define TT_MS_LANGID_SPANISH_LATIN_AMERICA 0xE40aU +#define TT_MS_LANGID_FINNISH_FINLAND 0x040b +#define TT_MS_LANGID_FRENCH_FRANCE 0x040c +#define TT_MS_LANGID_FRENCH_BELGIUM 0x080c +#define TT_MS_LANGID_FRENCH_CANADA 0x0c0c +#define TT_MS_LANGID_FRENCH_SWITZERLAND 0x100c +#define TT_MS_LANGID_FRENCH_LUXEMBOURG 0x140c +#define TT_MS_LANGID_FRENCH_MONACO 0x180c +#define TT_MS_LANGID_FRENCH_WEST_INDIES 0x1c0c +#define TT_MS_LANGID_FRENCH_REUNION 0x200c +#define TT_MS_LANGID_FRENCH_CONGO 0x240c + /* which was formerly: */ +#define TT_MS_LANGID_FRENCH_ZAIRE TT_MS_LANGID_FRENCH_CONGO +#define TT_MS_LANGID_FRENCH_SENEGAL 0x280c +#define TT_MS_LANGID_FRENCH_CAMEROON 0x2c0c +#define TT_MS_LANGID_FRENCH_COTE_D_IVOIRE 0x300c +#define TT_MS_LANGID_FRENCH_MALI 0x340c +#define TT_MS_LANGID_FRENCH_MOROCCO 0x380c +#define TT_MS_LANGID_FRENCH_HAITI 0x3c0c + /* and another violation of the spec (see 0xE40aU) */ +#define TT_MS_LANGID_FRENCH_NORTH_AFRICA 0xE40cU +#define TT_MS_LANGID_HEBREW_ISRAEL 0x040d +#define TT_MS_LANGID_HUNGARIAN_HUNGARY 0x040e +#define TT_MS_LANGID_ICELANDIC_ICELAND 0x040f +#define TT_MS_LANGID_ITALIAN_ITALY 0x0410 +#define TT_MS_LANGID_ITALIAN_SWITZERLAND 0x0810 +#define TT_MS_LANGID_JAPANESE_JAPAN 0x0411 +#define TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA 0x0412 +#define TT_MS_LANGID_KOREAN_JOHAB_KOREA 0x0812 +#define TT_MS_LANGID_DUTCH_NETHERLANDS 0x0413 +#define TT_MS_LANGID_DUTCH_BELGIUM 0x0813 +#define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL 0x0414 +#define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK 0x0814 +#define TT_MS_LANGID_POLISH_POLAND 0x0415 +#define TT_MS_LANGID_PORTUGUESE_BRAZIL 0x0416 +#define TT_MS_LANGID_PORTUGUESE_PORTUGAL 0x0816 +#define TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND 0x0417 +#define TT_MS_LANGID_ROMANIAN_ROMANIA 0x0418 +#define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA 0x0818 +#define TT_MS_LANGID_RUSSIAN_RUSSIA 0x0419 +#define TT_MS_LANGID_RUSSIAN_MOLDAVIA 0x0819 +#define TT_MS_LANGID_CROATIAN_CROATIA 0x041a +#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN 0x081a +#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 0x0c1a + +#if 0 /* this used to be this value, but it looks like we were wrong */ +#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x101a +#else /* current sources say */ +#define TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA 0x101a +#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x141a + /* and XPsp2 Platform SDK added (2004-07-26) */ + /* Names are shortened to be significant within 40 chars. */ +#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN 0x181a +#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC 0x181a +#endif + +#define TT_MS_LANGID_SLOVAK_SLOVAKIA 0x041b +#define TT_MS_LANGID_ALBANIAN_ALBANIA 0x041c +#define TT_MS_LANGID_SWEDISH_SWEDEN 0x041d +#define TT_MS_LANGID_SWEDISH_FINLAND 0x081d +#define TT_MS_LANGID_THAI_THAILAND 0x041e +#define TT_MS_LANGID_TURKISH_TURKEY 0x041f +#define TT_MS_LANGID_URDU_PAKISTAN 0x0420 +#define TT_MS_LANGID_URDU_INDIA 0x0820 +#define TT_MS_LANGID_INDONESIAN_INDONESIA 0x0421 +#define TT_MS_LANGID_UKRAINIAN_UKRAINE 0x0422 +#define TT_MS_LANGID_BELARUSIAN_BELARUS 0x0423 +#define TT_MS_LANGID_SLOVENE_SLOVENIA 0x0424 +#define TT_MS_LANGID_ESTONIAN_ESTONIA 0x0425 +#define TT_MS_LANGID_LATVIAN_LATVIA 0x0426 +#define TT_MS_LANGID_LITHUANIAN_LITHUANIA 0x0427 +#define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA 0x0827 +#define TT_MS_LANGID_TAJIK_TAJIKISTAN 0x0428 +#define TT_MS_LANGID_FARSI_IRAN 0x0429 +#define TT_MS_LANGID_VIETNAMESE_VIET_NAM 0x042a +#define TT_MS_LANGID_ARMENIAN_ARMENIA 0x042b +#define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN 0x042c +#define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC 0x082c +#define TT_MS_LANGID_BASQUE_SPAIN 0x042d +#define TT_MS_LANGID_SORBIAN_GERMANY 0x042e +#define TT_MS_LANGID_MACEDONIAN_MACEDONIA 0x042f +#define TT_MS_LANGID_SUTU_SOUTH_AFRICA 0x0430 +#define TT_MS_LANGID_TSONGA_SOUTH_AFRICA 0x0431 +#define TT_MS_LANGID_TSWANA_SOUTH_AFRICA 0x0432 +#define TT_MS_LANGID_VENDA_SOUTH_AFRICA 0x0433 +#define TT_MS_LANGID_XHOSA_SOUTH_AFRICA 0x0434 +#define TT_MS_LANGID_ZULU_SOUTH_AFRICA 0x0435 +#define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA 0x0436 +#define TT_MS_LANGID_GEORGIAN_GEORGIA 0x0437 +#define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 0x0438 +#define TT_MS_LANGID_HINDI_INDIA 0x0439 +#define TT_MS_LANGID_MALTESE_MALTA 0x043a + /* Added by XPsp2 Platform SDK (2004-07-26) */ +#define TT_MS_LANGID_SAMI_NORTHERN_NORWAY 0x043b +#define TT_MS_LANGID_SAMI_NORTHERN_SWEDEN 0x083b +#define TT_MS_LANGID_SAMI_NORTHERN_FINLAND 0x0C3b +#define TT_MS_LANGID_SAMI_LULE_NORWAY 0x103b +#define TT_MS_LANGID_SAMI_LULE_SWEDEN 0x143b +#define TT_MS_LANGID_SAMI_SOUTHERN_NORWAY 0x183b +#define TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN 0x1C3b +#define TT_MS_LANGID_SAMI_SKOLT_FINLAND 0x203b +#define TT_MS_LANGID_SAMI_INARI_FINLAND 0x243b + /* ... and we also keep our old identifier... */ +#define TT_MS_LANGID_SAAMI_LAPONIA 0x043b + +#if 0 /* this seems to be a previous inversion */ +#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c +#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c +#else +#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c +#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c +#endif + +#define TT_MS_LANGID_YIDDISH_GERMANY 0x043d +#define TT_MS_LANGID_MALAY_MALAYSIA 0x043e +#define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 0x083e +#define TT_MS_LANGID_KAZAK_KAZAKSTAN 0x043f +#define TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN /* Cyrillic*/ 0x0440 + /* alias declared in Windows 2000 */ +#define TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC \ + TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN + +#define TT_MS_LANGID_SWAHILI_KENYA 0x0441 +#define TT_MS_LANGID_TURKMEN_TURKMENISTAN 0x0442 +#define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 0x0443 +#define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC 0x0843 +#define TT_MS_LANGID_TATAR_TATARSTAN 0x0444 +#define TT_MS_LANGID_BENGALI_INDIA 0x0445 +#define TT_MS_LANGID_BENGALI_BANGLADESH 0x0845 +#define TT_MS_LANGID_PUNJABI_INDIA 0x0446 +#define TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN 0x0846 +#define TT_MS_LANGID_GUJARATI_INDIA 0x0447 +#define TT_MS_LANGID_ORIYA_INDIA 0x0448 +#define TT_MS_LANGID_TAMIL_INDIA 0x0449 +#define TT_MS_LANGID_TELUGU_INDIA 0x044a +#define TT_MS_LANGID_KANNADA_INDIA 0x044b +#define TT_MS_LANGID_MALAYALAM_INDIA 0x044c +#define TT_MS_LANGID_ASSAMESE_INDIA 0x044d +#define TT_MS_LANGID_MARATHI_INDIA 0x044e +#define TT_MS_LANGID_SANSKRIT_INDIA 0x044f +#define TT_MS_LANGID_MONGOLIAN_MONGOLIA /* Cyrillic */ 0x0450 +#define TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN 0x0850 +#define TT_MS_LANGID_TIBETAN_CHINA 0x0451 + /* Don't use the next constant! It has */ + /* (1) the wrong spelling (Dzonghka) */ + /* (2) Microsoft doesn't officially define it -- */ + /* at least it is not in the List of Local */ + /* ID Values. */ + /* (3) Dzongkha is not the same language as */ + /* Tibetan, so merging it is wrong anyway. */ + /* */ + /* TT_MS_LANGID_TIBETAN_BHUTAN is correct, BTW. */ +#define TT_MS_LANGID_DZONGHKA_BHUTAN 0x0851 + +#if 0 + /* the following used to be defined */ +#define TT_MS_LANGID_TIBETAN_BHUTAN 0x0451 + /* ... but it was changed; */ +#else + /* So we will continue to #define it, but with the correct value */ +#define TT_MS_LANGID_TIBETAN_BHUTAN TT_MS_LANGID_DZONGHKA_BHUTAN +#endif + +#define TT_MS_LANGID_WELSH_WALES 0x0452 +#define TT_MS_LANGID_KHMER_CAMBODIA 0x0453 +#define TT_MS_LANGID_LAO_LAOS 0x0454 +#define TT_MS_LANGID_BURMESE_MYANMAR 0x0455 +#define TT_MS_LANGID_GALICIAN_SPAIN 0x0456 +#define TT_MS_LANGID_KONKANI_INDIA 0x0457 +#define TT_MS_LANGID_MANIPURI_INDIA /* Bengali */ 0x0458 +#define TT_MS_LANGID_SINDHI_INDIA /* Arabic */ 0x0459 +#define TT_MS_LANGID_SINDHI_PAKISTAN 0x0859 + /* Missing a LCID for Sindhi in Devanagari script */ +#define TT_MS_LANGID_SYRIAC_SYRIA 0x045a +#define TT_MS_LANGID_SINHALESE_SRI_LANKA 0x045b +#define TT_MS_LANGID_CHEROKEE_UNITED_STATES 0x045c +#define TT_MS_LANGID_INUKTITUT_CANADA 0x045d +#define TT_MS_LANGID_AMHARIC_ETHIOPIA 0x045e +#define TT_MS_LANGID_TAMAZIGHT_MOROCCO /* Arabic */ 0x045f +#define TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN 0x085f + /* Missing a LCID for Tifinagh script */ +#define TT_MS_LANGID_KASHMIRI_PAKISTAN /* Arabic */ 0x0460 + /* Spelled this way by XPsp2 Platform SDK (2004-07-26) */ + /* script is yet unclear... might be Arabic, Nagari or Sharada */ +#define TT_MS_LANGID_KASHMIRI_SASIA 0x0860 + /* ... and aliased (by MS) for compatibility reasons. */ +#define TT_MS_LANGID_KASHMIRI_INDIA TT_MS_LANGID_KASHMIRI_SASIA +#define TT_MS_LANGID_NEPALI_NEPAL 0x0461 +#define TT_MS_LANGID_NEPALI_INDIA 0x0861 +#define TT_MS_LANGID_FRISIAN_NETHERLANDS 0x0462 +#define TT_MS_LANGID_PASHTO_AFGHANISTAN 0x0463 +#define TT_MS_LANGID_FILIPINO_PHILIPPINES 0x0464 +#define TT_MS_LANGID_DHIVEHI_MALDIVES 0x0465 + /* alias declared in Windows 2000 */ +#define TT_MS_LANGID_DIVEHI_MALDIVES TT_MS_LANGID_DHIVEHI_MALDIVES +#define TT_MS_LANGID_EDO_NIGERIA 0x0466 +#define TT_MS_LANGID_FULFULDE_NIGERIA 0x0467 +#define TT_MS_LANGID_HAUSA_NIGERIA 0x0468 +#define TT_MS_LANGID_IBIBIO_NIGERIA 0x0469 +#define TT_MS_LANGID_YORUBA_NIGERIA 0x046a +#define TT_MS_LANGID_QUECHUA_BOLIVIA 0x046b +#define TT_MS_LANGID_QUECHUA_ECUADOR 0x086b +#define TT_MS_LANGID_QUECHUA_PERU 0x0c6b +#define TT_MS_LANGID_SEPEDI_SOUTH_AFRICA 0x046c + /* Also spelled by XPsp2 Platform SDK (2004-07-26) */ +#define TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA \ + TT_MS_LANGID_SEPEDI_SOUTH_AFRICA + /* language codes 0x046d, 0x046e and 0x046f are (still) unknown. */ +#define TT_MS_LANGID_IGBO_NIGERIA 0x0470 +#define TT_MS_LANGID_KANURI_NIGERIA 0x0471 +#define TT_MS_LANGID_OROMO_ETHIOPIA 0x0472 +#define TT_MS_LANGID_TIGRIGNA_ETHIOPIA 0x0473 +#define TT_MS_LANGID_TIGRIGNA_ERYTHREA 0x0873 + /* also spelled in the `Passport SDK' list as: */ +#define TT_MS_LANGID_TIGRIGNA_ERYTREA TT_MS_LANGID_TIGRIGNA_ERYTHREA +#define TT_MS_LANGID_GUARANI_PARAGUAY 0x0474 +#define TT_MS_LANGID_HAWAIIAN_UNITED_STATES 0x0475 +#define TT_MS_LANGID_LATIN 0x0476 +#define TT_MS_LANGID_SOMALI_SOMALIA 0x0477 + /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */ + /* not written (but OTOH the peculiar writing system is worth */ + /* studying). */ +#define TT_MS_LANGID_YI_CHINA 0x0478 +#define TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES 0x0479 + /* language codes from 0x047a to 0x047f are (still) unknown. */ +#define TT_MS_LANGID_UIGHUR_CHINA 0x0480 +#define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0481 + +#if 0 /* not deemed useful for fonts */ +#define TT_MS_LANGID_HUMAN_INTERFACE_DEVICE 0x04ff +#endif + + + /*************************************************************************/ + /* */ + /* Possible values of the `name' identifier field in the name records of */ + /* the TTF `name' table. These values are platform independent. */ + /* */ +#define TT_NAME_ID_COPYRIGHT 0 +#define TT_NAME_ID_FONT_FAMILY 1 +#define TT_NAME_ID_FONT_SUBFAMILY 2 +#define TT_NAME_ID_UNIQUE_ID 3 +#define TT_NAME_ID_FULL_NAME 4 +#define TT_NAME_ID_VERSION_STRING 5 +#define TT_NAME_ID_PS_NAME 6 +#define TT_NAME_ID_TRADEMARK 7 + + /* the following values are from the OpenType spec */ +#define TT_NAME_ID_MANUFACTURER 8 +#define TT_NAME_ID_DESIGNER 9 +#define TT_NAME_ID_DESCRIPTION 10 +#define TT_NAME_ID_VENDOR_URL 11 +#define TT_NAME_ID_DESIGNER_URL 12 +#define TT_NAME_ID_LICENSE 13 +#define TT_NAME_ID_LICENSE_URL 14 + /* number 15 is reserved */ +#define TT_NAME_ID_PREFERRED_FAMILY 16 +#define TT_NAME_ID_PREFERRED_SUBFAMILY 17 +#define TT_NAME_ID_MAC_FULL_NAME 18 + + /* The following code is new as of 2000-01-21 */ +#define TT_NAME_ID_SAMPLE_TEXT 19 + + /* This is new in OpenType 1.3 */ +#define TT_NAME_ID_CID_FINDFONT_NAME 20 + + /* This is new in OpenType 1.5 */ +#define TT_NAME_ID_WWS_FAMILY 21 +#define TT_NAME_ID_WWS_SUBFAMILY 22 + + + /*************************************************************************/ + /* */ + /* Bit mask values for the Unicode Ranges from the TTF `OS2 ' table. */ + /* */ + /* Updated 08-Nov-2008. */ + /* */ + + /* Bit 0 Basic Latin */ +#define TT_UCR_BASIC_LATIN (1L << 0) /* U+0020-U+007E */ + /* Bit 1 C1 Controls and Latin-1 Supplement */ +#define TT_UCR_LATIN1_SUPPLEMENT (1L << 1) /* U+0080-U+00FF */ + /* Bit 2 Latin Extended-A */ +#define TT_UCR_LATIN_EXTENDED_A (1L << 2) /* U+0100-U+017F */ + /* Bit 3 Latin Extended-B */ +#define TT_UCR_LATIN_EXTENDED_B (1L << 3) /* U+0180-U+024F */ + /* Bit 4 IPA Extensions */ + /* Phonetic Extensions */ + /* Phonetic Extensions Supplement */ +#define TT_UCR_IPA_EXTENSIONS (1L << 4) /* U+0250-U+02AF */ + /* U+1D00-U+1D7F */ + /* U+1D80-U+1DBF */ + /* Bit 5 Spacing Modifier Letters */ + /* Modifier Tone Letters */ +#define TT_UCR_SPACING_MODIFIER (1L << 5) /* U+02B0-U+02FF */ + /* U+A700-U+A71F */ + /* Bit 6 Combining Diacritical Marks */ + /* Combining Diacritical Marks Supplement */ +#define TT_UCR_COMBINING_DIACRITICS (1L << 6) /* U+0300-U+036F */ + /* U+1DC0-U+1DFF */ + /* Bit 7 Greek and Coptic */ +#define TT_UCR_GREEK (1L << 7) /* U+0370-U+03FF */ + /* Bit 8 Coptic */ +#define TT_UCR_COPTIC (1L << 8) /* U+2C80-U+2CFF */ + /* Bit 9 Cyrillic */ + /* Cyrillic Supplement */ + /* Cyrillic Extended-A */ + /* Cyrillic Extended-B */ +#define TT_UCR_CYRILLIC (1L << 9) /* U+0400-U+04FF */ + /* U+0500-U+052F */ + /* U+2DE0-U+2DFF */ + /* U+A640-U+A69F */ + /* Bit 10 Armenian */ +#define TT_UCR_ARMENIAN (1L << 10) /* U+0530-U+058F */ + /* Bit 11 Hebrew */ +#define TT_UCR_HEBREW (1L << 11) /* U+0590-U+05FF */ + /* Bit 12 Vai */ +#define TT_UCR_VAI (1L << 12) /* U+A500-U+A63F */ + /* Bit 13 Arabic */ + /* Arabic Supplement */ +#define TT_UCR_ARABIC (1L << 13) /* U+0600-U+06FF */ + /* U+0750-U+077F */ + /* Bit 14 NKo */ +#define TT_UCR_NKO (1L << 14) /* U+07C0-U+07FF */ + /* Bit 15 Devanagari */ +#define TT_UCR_DEVANAGARI (1L << 15) /* U+0900-U+097F */ + /* Bit 16 Bengali */ +#define TT_UCR_BENGALI (1L << 16) /* U+0980-U+09FF */ + /* Bit 17 Gurmukhi */ +#define TT_UCR_GURMUKHI (1L << 17) /* U+0A00-U+0A7F */ + /* Bit 18 Gujarati */ +#define TT_UCR_GUJARATI (1L << 18) /* U+0A80-U+0AFF */ + /* Bit 19 Oriya */ +#define TT_UCR_ORIYA (1L << 19) /* U+0B00-U+0B7F */ + /* Bit 20 Tamil */ +#define TT_UCR_TAMIL (1L << 20) /* U+0B80-U+0BFF */ + /* Bit 21 Telugu */ +#define TT_UCR_TELUGU (1L << 21) /* U+0C00-U+0C7F */ + /* Bit 22 Kannada */ +#define TT_UCR_KANNADA (1L << 22) /* U+0C80-U+0CFF */ + /* Bit 23 Malayalam */ +#define TT_UCR_MALAYALAM (1L << 23) /* U+0D00-U+0D7F */ + /* Bit 24 Thai */ +#define TT_UCR_THAI (1L << 24) /* U+0E00-U+0E7F */ + /* Bit 25 Lao */ +#define TT_UCR_LAO (1L << 25) /* U+0E80-U+0EFF */ + /* Bit 26 Georgian */ + /* Georgian Supplement */ +#define TT_UCR_GEORGIAN (1L << 26) /* U+10A0-U+10FF */ + /* U+2D00-U+2D2F */ + /* Bit 27 Balinese */ +#define TT_UCR_BALINESE (1L << 27) /* U+1B00-U+1B7F */ + /* Bit 28 Hangul Jamo */ +#define TT_UCR_HANGUL_JAMO (1L << 28) /* U+1100-U+11FF */ + /* Bit 29 Latin Extended Additional */ + /* Latin Extended-C */ + /* Latin Extended-D */ +#define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1L << 29) /* U+1E00-U+1EFF */ + /* U+2C60-U+2C7F */ + /* U+A720-U+A7FF */ + /* Bit 30 Greek Extended */ +#define TT_UCR_GREEK_EXTENDED (1L << 30) /* U+1F00-U+1FFF */ + /* Bit 31 General Punctuation */ + /* Supplemental Punctuation */ +#define TT_UCR_GENERAL_PUNCTUATION (1L << 31) /* U+2000-U+206F */ + /* U+2E00-U+2E7F */ + /* Bit 32 Superscripts And Subscripts */ +#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1L << 0) /* U+2070-U+209F */ + /* Bit 33 Currency Symbols */ +#define TT_UCR_CURRENCY_SYMBOLS (1L << 1) /* U+20A0-U+20CF */ + /* Bit 34 Combining Diacritical Marks For Symbols */ +#define TT_UCR_COMBINING_DIACRITICS_SYMB (1L << 2) /* U+20D0-U+20FF */ + /* Bit 35 Letterlike Symbols */ +#define TT_UCR_LETTERLIKE_SYMBOLS (1L << 3) /* U+2100-U+214F */ + /* Bit 36 Number Forms */ +#define TT_UCR_NUMBER_FORMS (1L << 4) /* U+2150-U+218F */ + /* Bit 37 Arrows */ + /* Supplemental Arrows-A */ + /* Supplemental Arrows-B */ + /* Miscellaneous Symbols and Arrows */ +#define TT_UCR_ARROWS (1L << 5) /* U+2190-U+21FF */ + /* U+27F0-U+27FF */ + /* U+2900-U+297F */ + /* U+2B00-U+2BFF */ + /* Bit 38 Mathematical Operators */ + /* Supplemental Mathematical Operators */ + /* Miscellaneous Mathematical Symbols-A */ + /* Miscellaneous Mathematical Symbols-B */ +#define TT_UCR_MATHEMATICAL_OPERATORS (1L << 6) /* U+2200-U+22FF */ + /* U+2A00-U+2AFF */ + /* U+27C0-U+27EF */ + /* U+2980-U+29FF */ + /* Bit 39 Miscellaneous Technical */ +#define TT_UCR_MISCELLANEOUS_TECHNICAL (1L << 7) /* U+2300-U+23FF */ + /* Bit 40 Control Pictures */ +#define TT_UCR_CONTROL_PICTURES (1L << 8) /* U+2400-U+243F */ + /* Bit 41 Optical Character Recognition */ +#define TT_UCR_OCR (1L << 9) /* U+2440-U+245F */ + /* Bit 42 Enclosed Alphanumerics */ +#define TT_UCR_ENCLOSED_ALPHANUMERICS (1L << 10) /* U+2460-U+24FF */ + /* Bit 43 Box Drawing */ +#define TT_UCR_BOX_DRAWING (1L << 11) /* U+2500-U+257F */ + /* Bit 44 Block Elements */ +#define TT_UCR_BLOCK_ELEMENTS (1L << 12) /* U+2580-U+259F */ + /* Bit 45 Geometric Shapes */ +#define TT_UCR_GEOMETRIC_SHAPES (1L << 13) /* U+25A0-U+25FF */ + /* Bit 46 Miscellaneous Symbols */ +#define TT_UCR_MISCELLANEOUS_SYMBOLS (1L << 14) /* U+2600-U+26FF */ + /* Bit 47 Dingbats */ +#define TT_UCR_DINGBATS (1L << 15) /* U+2700-U+27BF */ + /* Bit 48 CJK Symbols and Punctuation */ +#define TT_UCR_CJK_SYMBOLS (1L << 16) /* U+3000-U+303F */ + /* Bit 49 Hiragana */ +#define TT_UCR_HIRAGANA (1L << 17) /* U+3040-U+309F */ + /* Bit 50 Katakana */ + /* Katakana Phonetic Extensions */ +#define TT_UCR_KATAKANA (1L << 18) /* U+30A0-U+30FF */ + /* U+31F0-U+31FF */ + /* Bit 51 Bopomofo */ + /* Bopomofo Extended */ +#define TT_UCR_BOPOMOFO (1L << 19) /* U+3100-U+312F */ + /* U+31A0-U+31BF */ + /* Bit 52 Hangul Compatibility Jamo */ +#define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1L << 20) /* U+3130-U+318F */ + /* Bit 53 Phags-Pa */ +#define TT_UCR_CJK_MISC (1L << 21) /* U+A840-U+A87F */ +#define TT_UCR_KANBUN TT_UCR_CJK_MISC /* deprecated */ +#define TT_UCR_PHAGSPA + /* Bit 54 Enclosed CJK Letters and Months */ +#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1L << 22) /* U+3200-U+32FF */ + /* Bit 55 CJK Compatibility */ +#define TT_UCR_CJK_COMPATIBILITY (1L << 23) /* U+3300-U+33FF */ + /* Bit 56 Hangul Syllables */ +#define TT_UCR_HANGUL (1L << 24) /* U+AC00-U+D7A3 */ + /* Bit 57 High Surrogates */ + /* High Private Use Surrogates */ + /* Low Surrogates */ + /* */ + /* According to OpenType specs v.1.3+, */ + /* setting bit 57 implies that there is */ + /* at least one codepoint beyond the */ + /* Basic Multilingual Plane that is */ + /* supported by this font. So it really */ + /* means >= U+10000 */ +#define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DB7F */ + /* U+DB80-U+DBFF */ + /* U+DC00-U+DFFF */ +#define TT_UCR_NON_PLANE_0 TT_UCR_SURROGATES + /* Bit 58 Phoenician */ +#define TT_UCR_PHOENICIAN (1L << 26) /*U+10900-U+1091F*/ + /* Bit 59 CJK Unified Ideographs */ + /* CJK Radicals Supplement */ + /* Kangxi Radicals */ + /* Ideographic Description Characters */ + /* CJK Unified Ideographs Extension A */ + /* CJK Unified Ideographs Extension B */ + /* Kanbun */ +#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1L << 27) /* U+4E00-U+9FFF */ + /* U+2E80-U+2EFF */ + /* U+2F00-U+2FDF */ + /* U+2FF0-U+2FFF */ + /* U+3400-U+4DB5 */ + /*U+20000-U+2A6DF*/ + /* U+3190-U+319F */ + /* Bit 60 Private Use */ +#define TT_UCR_PRIVATE_USE (1L << 28) /* U+E000-U+F8FF */ + /* Bit 61 CJK Strokes */ + /* CJK Compatibility Ideographs */ + /* CJK Compatibility Ideographs Supplement */ +#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1L << 29) /* U+31C0-U+31EF */ + /* U+F900-U+FAFF */ + /*U+2F800-U+2FA1F*/ + /* Bit 62 Alphabetic Presentation Forms */ +#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1L << 30) /* U+FB00-U+FB4F */ + /* Bit 63 Arabic Presentation Forms-A */ +#define TT_UCR_ARABIC_PRESENTATIONS_A (1L << 31) /* U+FB50-U+FDFF */ + /* Bit 64 Combining Half Marks */ +#define TT_UCR_COMBINING_HALF_MARKS (1L << 0) /* U+FE20-U+FE2F */ + /* Bit 65 Vertical forms */ + /* CJK Compatibility Forms */ +#define TT_UCR_CJK_COMPATIBILITY_FORMS (1L << 1) /* U+FE10-U+FE1F */ + /* U+FE30-U+FE4F */ + /* Bit 66 Small Form Variants */ +#define TT_UCR_SMALL_FORM_VARIANTS (1L << 2) /* U+FE50-U+FE6F */ + /* Bit 67 Arabic Presentation Forms-B */ +#define TT_UCR_ARABIC_PRESENTATIONS_B (1L << 3) /* U+FE70-U+FEFE */ + /* Bit 68 Halfwidth and Fullwidth Forms */ +#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1L << 4) /* U+FF00-U+FFEF */ + /* Bit 69 Specials */ +#define TT_UCR_SPECIALS (1L << 5) /* U+FFF0-U+FFFD */ + /* Bit 70 Tibetan */ +#define TT_UCR_TIBETAN (1L << 6) /* U+0F00-U+0FFF */ + /* Bit 71 Syriac */ +#define TT_UCR_SYRIAC (1L << 7) /* U+0700-U+074F */ + /* Bit 72 Thaana */ +#define TT_UCR_THAANA (1L << 8) /* U+0780-U+07BF */ + /* Bit 73 Sinhala */ +#define TT_UCR_SINHALA (1L << 9) /* U+0D80-U+0DFF */ + /* Bit 74 Myanmar */ +#define TT_UCR_MYANMAR (1L << 10) /* U+1000-U+109F */ + /* Bit 75 Ethiopic */ + /* Ethiopic Supplement */ + /* Ethiopic Extended */ +#define TT_UCR_ETHIOPIC (1L << 11) /* U+1200-U+137F */ + /* U+1380-U+139F */ + /* U+2D80-U+2DDF */ + /* Bit 76 Cherokee */ +#define TT_UCR_CHEROKEE (1L << 12) /* U+13A0-U+13FF */ + /* Bit 77 Unified Canadian Aboriginal Syllabics */ +#define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS (1L << 13) /* U+1400-U+167F */ + /* Bit 78 Ogham */ +#define TT_UCR_OGHAM (1L << 14) /* U+1680-U+169F */ + /* Bit 79 Runic */ +#define TT_UCR_RUNIC (1L << 15) /* U+16A0-U+16FF */ + /* Bit 80 Khmer */ + /* Khmer Symbols */ +#define TT_UCR_KHMER (1L << 16) /* U+1780-U+17FF */ + /* U+19E0-U+19FF */ + /* Bit 81 Mongolian */ +#define TT_UCR_MONGOLIAN (1L << 17) /* U+1800-U+18AF */ + /* Bit 82 Braille Patterns */ +#define TT_UCR_BRAILLE (1L << 18) /* U+2800-U+28FF */ + /* Bit 83 Yi Syllables */ + /* Yi Radicals */ +#define TT_UCR_YI (1L << 19) /* U+A000-U+A48F */ + /* U+A490-U+A4CF */ + /* Bit 84 Tagalog */ + /* Hanunoo */ + /* Buhid */ + /* Tagbanwa */ +#define TT_UCR_PHILIPPINE (1L << 20) /* U+1700-U+171F */ + /* U+1720-U+173F */ + /* U+1740-U+175F */ + /* U+1760-U+177F */ + /* Bit 85 Old Italic */ +#define TT_UCR_OLD_ITALIC (1L << 21) /*U+10300-U+1032F*/ + /* Bit 86 Gothic */ +#define TT_UCR_GOTHIC (1L << 22) /*U+10330-U+1034F*/ + /* Bit 87 Deseret */ +#define TT_UCR_DESERET (1L << 23) /*U+10400-U+1044F*/ + /* Bit 88 Byzantine Musical Symbols */ + /* Musical Symbols */ + /* Ancient Greek Musical Notation */ +#define TT_UCR_MUSICAL_SYMBOLS (1L << 24) /*U+1D000-U+1D0FF*/ + /*U+1D100-U+1D1FF*/ + /*U+1D200-U+1D24F*/ + /* Bit 89 Mathematical Alphanumeric Symbols */ +#define TT_UCR_MATH_ALPHANUMERIC_SYMBOLS (1L << 25) /*U+1D400-U+1D7FF*/ + /* Bit 90 Private Use (plane 15) */ + /* Private Use (plane 16) */ +#define TT_UCR_PRIVATE_USE_SUPPLEMENTARY (1L << 26) /*U+F0000-U+FFFFD*/ + /*U+100000-U+10FFFD*/ + /* Bit 91 Variation Selectors */ + /* Variation Selectors Supplement */ +#define TT_UCR_VARIATION_SELECTORS (1L << 27) /* U+FE00-U+FE0F */ + /*U+E0100-U+E01EF*/ + /* Bit 92 Tags */ +#define TT_UCR_TAGS (1L << 28) /*U+E0000-U+E007F*/ + /* Bit 93 Limbu */ +#define TT_UCR_LIMBU (1L << 29) /* U+1900-U+194F */ + /* Bit 94 Tai Le */ +#define TT_UCR_TAI_LE (1L << 30) /* U+1950-U+197F */ + /* Bit 95 New Tai Lue */ +#define TT_UCR_NEW_TAI_LUE (1L << 31) /* U+1980-U+19DF */ + /* Bit 96 Buginese */ +#define TT_UCR_BUGINESE (1L << 0) /* U+1A00-U+1A1F */ + /* Bit 97 Glagolitic */ +#define TT_UCR_GLAGOLITIC (1L << 1) /* U+2C00-U+2C5F */ + /* Bit 98 Tifinagh */ +#define TT_UCR_TIFINAGH (1L << 2) /* U+2D30-U+2D7F */ + /* Bit 99 Yijing Hexagram Symbols */ +#define TT_UCR_YIJING (1L << 3) /* U+4DC0-U+4DFF */ + /* Bit 100 Syloti Nagri */ +#define TT_UCR_SYLOTI_NAGRI (1L << 4) /* U+A800-U+A82F */ + /* Bit 101 Linear B Syllabary */ + /* Linear B Ideograms */ + /* Aegean Numbers */ +#define TT_UCR_LINEAR_B (1L << 5) /*U+10000-U+1007F*/ + /*U+10080-U+100FF*/ + /*U+10100-U+1013F*/ + /* Bit 102 Ancient Greek Numbers */ +#define TT_UCR_ANCIENT_GREEK_NUMBERS (1L << 6) /*U+10140-U+1018F*/ + /* Bit 103 Ugaritic */ +#define TT_UCR_UGARITIC (1L << 7) /*U+10380-U+1039F*/ + /* Bit 104 Old Persian */ +#define TT_UCR_OLD_PERSIAN (1L << 8) /*U+103A0-U+103DF*/ + /* Bit 105 Shavian */ +#define TT_UCR_SHAVIAN (1L << 9) /*U+10450-U+1047F*/ + /* Bit 106 Osmanya */ +#define TT_UCR_OSMANYA (1L << 10) /*U+10480-U+104AF*/ + /* Bit 107 Cypriot Syllabary */ +#define TT_UCR_CYPRIOT_SYLLABARY (1L << 11) /*U+10800-U+1083F*/ + /* Bit 108 Kharoshthi */ +#define TT_UCR_KHAROSHTHI (1L << 12) /*U+10A00-U+10A5F*/ + /* Bit 109 Tai Xuan Jing Symbols */ +#define TT_UCR_TAI_XUAN_JING (1L << 13) /*U+1D300-U+1D35F*/ + /* Bit 110 Cuneiform */ + /* Cuneiform Numbers and Punctuation */ +#define TT_UCR_CUNEIFORM (1L << 14) /*U+12000-U+123FF*/ + /*U+12400-U+1247F*/ + /* Bit 111 Counting Rod Numerals */ +#define TT_UCR_COUNTING_ROD_NUMERALS (1L << 15) /*U+1D360-U+1D37F*/ + /* Bit 112 Sundanese */ +#define TT_UCR_SUNDANESE (1L << 16) /* U+1B80-U+1BBF */ + /* Bit 113 Lepcha */ +#define TT_UCR_LEPCHA (1L << 17) /* U+1C00-U+1C4F */ + /* Bit 114 Ol Chiki */ +#define TT_UCR_OL_CHIKI (1L << 18) /* U+1C50-U+1C7F */ + /* Bit 115 Saurashtra */ +#define TT_UCR_SAURASHTRA (1L << 19) /* U+A880-U+A8DF */ + /* Bit 116 Kayah Li */ +#define TT_UCR_KAYAH_LI (1L << 20) /* U+A900-U+A92F */ + /* Bit 117 Rejang */ +#define TT_UCR_REJANG (1L << 21) /* U+A930-U+A95F */ + /* Bit 118 Cham */ +#define TT_UCR_CHAM (1L << 22) /* U+AA00-U+AA5F */ + /* Bit 119 Ancient Symbols */ +#define TT_UCR_ANCIENT_SYMBOLS (1L << 23) /*U+10190-U+101CF*/ + /* Bit 120 Phaistos Disc */ +#define TT_UCR_PHAISTOS_DISC (1L << 24) /*U+101D0-U+101FF*/ + /* Bit 121 Carian */ + /* Lycian */ + /* Lydian */ +#define TT_UCR_OLD_ANATOLIAN (1L << 25) /*U+102A0-U+102DF*/ + /*U+10280-U+1029F*/ + /*U+10920-U+1093F*/ + /* Bit 122 Domino Tiles */ + /* Mahjong Tiles */ +#define TT_UCR_GAME_TILES (1L << 26) /*U+1F030-U+1F09F*/ + /*U+1F000-U+1F02F*/ + /* Bit 123-127 Reserved for process-internal usage */ + + + /*************************************************************************/ + /* */ + /* Some compilers have a very limited length of identifiers. */ + /* */ +#if defined( __TURBOC__ ) && __TURBOC__ < 0x0410 || defined( __PACIFIC__ ) +#define HAVE_LIMIT_ON_IDENTS +#endif + + +#ifndef HAVE_LIMIT_ON_IDENTS + + + /*************************************************************************/ + /* */ + /* Here some alias #defines in order to be clearer. */ + /* */ + /* These are not always #defined to stay within the 31~character limit */ + /* which some compilers have. */ + /* */ + /* Credits go to Dave Hoo <dhoo@flash.net> for pointing out that modern */ + /* Borland compilers (read: from BC++ 3.1 on) can increase this limit. */ + /* If you get a warning with such a compiler, use the -i40 switch. */ + /* */ +#define TT_UCR_ARABIC_PRESENTATION_FORMS_A \ + TT_UCR_ARABIC_PRESENTATIONS_A +#define TT_UCR_ARABIC_PRESENTATION_FORMS_B \ + TT_UCR_ARABIC_PRESENTATIONS_B + +#define TT_UCR_COMBINING_DIACRITICAL_MARKS \ + TT_UCR_COMBINING_DIACRITICS +#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \ + TT_UCR_COMBINING_DIACRITICS_SYMB + + +#endif /* !HAVE_LIMIT_ON_IDENTS */ + + +FT_END_HEADER + +#endif /* __TTNAMEID_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/tttables.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/tttables.h new file mode 100644 index 00000000..4610e501 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/tttables.h @@ -0,0 +1,759 @@ +/***************************************************************************/ +/* */ +/* tttables.h */ +/* */ +/* Basic SFNT/TrueType tables definitions and interface */ +/* (specification only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTTABLES_H__ +#define __TTTABLES_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + /*************************************************************************/ + /* */ + /* <Section> */ + /* truetype_tables */ + /* */ + /* <Title> */ + /* TrueType Tables */ + /* */ + /* <Abstract> */ + /* TrueType specific table types and functions. */ + /* */ + /* <Description> */ + /* This section contains the definition of TrueType-specific tables */ + /* as well as some routines used to access and process them. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_Header */ + /* */ + /* <Description> */ + /* A structure used to model a TrueType font header table. All */ + /* fields follow the TrueType specification. */ + /* */ + typedef struct TT_Header_ + { + FT_Fixed Table_Version; + FT_Fixed Font_Revision; + + FT_Long CheckSum_Adjust; + FT_Long Magic_Number; + + FT_UShort Flags; + FT_UShort Units_Per_EM; + + FT_Long Created [2]; + FT_Long Modified[2]; + + FT_Short xMin; + FT_Short yMin; + FT_Short xMax; + FT_Short yMax; + + FT_UShort Mac_Style; + FT_UShort Lowest_Rec_PPEM; + + FT_Short Font_Direction; + FT_Short Index_To_Loc_Format; + FT_Short Glyph_Data_Format; + + } TT_Header; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_HoriHeader */ + /* */ + /* <Description> */ + /* A structure used to model a TrueType horizontal header, the `hhea' */ + /* table, as well as the corresponding horizontal metrics table, */ + /* i.e., the `hmtx' table. */ + /* */ + /* <Fields> */ + /* Version :: The table version. */ + /* */ + /* Ascender :: The font's ascender, i.e., the distance */ + /* from the baseline to the top-most of all */ + /* glyph points found in the font. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of the */ + /* glyphs found in the font (maybe ASCII). */ + /* */ + /* You should use the `sTypoAscender' field */ + /* of the OS/2 table instead if you want */ + /* the correct one. */ + /* */ + /* Descender :: The font's descender, i.e., the distance */ + /* from the baseline to the bottom-most of */ + /* all glyph points found in the font. It */ + /* is negative. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of the */ + /* glyphs found in the font (maybe ASCII). */ + /* */ + /* You should use the `sTypoDescender' */ + /* field of the OS/2 table instead if you */ + /* want the correct one. */ + /* */ + /* Line_Gap :: The font's line gap, i.e., the distance */ + /* to add to the ascender and descender to */ + /* get the BTB, i.e., the */ + /* baseline-to-baseline distance for the */ + /* font. */ + /* */ + /* advance_Width_Max :: This field is the maximum of all advance */ + /* widths found in the font. It can be */ + /* used to compute the maximum width of an */ + /* arbitrary string of text. */ + /* */ + /* min_Left_Side_Bearing :: The minimum left side bearing of all */ + /* glyphs within the font. */ + /* */ + /* min_Right_Side_Bearing :: The minimum right side bearing of all */ + /* glyphs within the font. */ + /* */ + /* xMax_Extent :: The maximum horizontal extent (i.e., the */ + /* `width' of a glyph's bounding box) for */ + /* all glyphs in the font. */ + /* */ + /* caret_Slope_Rise :: The rise coefficient of the cursor's */ + /* slope of the cursor (slope=rise/run). */ + /* */ + /* caret_Slope_Run :: The run coefficient of the cursor's */ + /* slope. */ + /* */ + /* Reserved :: 8~reserved bytes. */ + /* */ + /* metric_Data_Format :: Always~0. */ + /* */ + /* number_Of_HMetrics :: Number of HMetrics entries in the `hmtx' */ + /* table -- this value can be smaller than */ + /* the total number of glyphs in the font. */ + /* */ + /* long_metrics :: A pointer into the `hmtx' table. */ + /* */ + /* short_metrics :: A pointer into the `hmtx' table. */ + /* */ + /* <Note> */ + /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ + /* be identical except for the names of their fields which */ + /* are different. */ + /* */ + /* This ensures that a single function in the `ttload' */ + /* module is able to read both the horizontal and vertical */ + /* headers. */ + /* */ + typedef struct TT_HoriHeader_ + { + FT_Fixed Version; + FT_Short Ascender; + FT_Short Descender; + FT_Short Line_Gap; + + FT_UShort advance_Width_Max; /* advance width maximum */ + + FT_Short min_Left_Side_Bearing; /* minimum left-sb */ + FT_Short min_Right_Side_Bearing; /* minimum right-sb */ + FT_Short xMax_Extent; /* xmax extents */ + FT_Short caret_Slope_Rise; + FT_Short caret_Slope_Run; + FT_Short caret_Offset; + + FT_Short Reserved[4]; + + FT_Short metric_Data_Format; + FT_UShort number_Of_HMetrics; + + /* The following fields are not defined by the TrueType specification */ + /* but they are used to connect the metrics header to the relevant */ + /* `HMTX' table. */ + + void* long_metrics; + void* short_metrics; + + } TT_HoriHeader; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_VertHeader */ + /* */ + /* <Description> */ + /* A structure used to model a TrueType vertical header, the `vhea' */ + /* table, as well as the corresponding vertical metrics table, i.e., */ + /* the `vmtx' table. */ + /* */ + /* <Fields> */ + /* Version :: The table version. */ + /* */ + /* Ascender :: The font's ascender, i.e., the distance */ + /* from the baseline to the top-most of */ + /* all glyph points found in the font. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of */ + /* the glyphs found in the font (maybe */ + /* ASCII). */ + /* */ + /* You should use the `sTypoAscender' */ + /* field of the OS/2 table instead if you */ + /* want the correct one. */ + /* */ + /* Descender :: The font's descender, i.e., the */ + /* distance from the baseline to the */ + /* bottom-most of all glyph points found */ + /* in the font. It is negative. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of */ + /* the glyphs found in the font (maybe */ + /* ASCII). */ + /* */ + /* You should use the `sTypoDescender' */ + /* field of the OS/2 table instead if you */ + /* want the correct one. */ + /* */ + /* Line_Gap :: The font's line gap, i.e., the distance */ + /* to add to the ascender and descender to */ + /* get the BTB, i.e., the */ + /* baseline-to-baseline distance for the */ + /* font. */ + /* */ + /* advance_Height_Max :: This field is the maximum of all */ + /* advance heights found in the font. It */ + /* can be used to compute the maximum */ + /* height of an arbitrary string of text. */ + /* */ + /* min_Top_Side_Bearing :: The minimum top side bearing of all */ + /* glyphs within the font. */ + /* */ + /* min_Bottom_Side_Bearing :: The minimum bottom side bearing of all */ + /* glyphs within the font. */ + /* */ + /* yMax_Extent :: The maximum vertical extent (i.e., the */ + /* `height' of a glyph's bounding box) for */ + /* all glyphs in the font. */ + /* */ + /* caret_Slope_Rise :: The rise coefficient of the cursor's */ + /* slope of the cursor (slope=rise/run). */ + /* */ + /* caret_Slope_Run :: The run coefficient of the cursor's */ + /* slope. */ + /* */ + /* caret_Offset :: The cursor's offset for slanted fonts. */ + /* This value is `reserved' in vmtx */ + /* version 1.0. */ + /* */ + /* Reserved :: 8~reserved bytes. */ + /* */ + /* metric_Data_Format :: Always~0. */ + /* */ + /* number_Of_HMetrics :: Number of VMetrics entries in the */ + /* `vmtx' table -- this value can be */ + /* smaller than the total number of glyphs */ + /* in the font. */ + /* */ + /* long_metrics :: A pointer into the `vmtx' table. */ + /* */ + /* short_metrics :: A pointer into the `vmtx' table. */ + /* */ + /* <Note> */ + /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ + /* be identical except for the names of their fields which */ + /* are different. */ + /* */ + /* This ensures that a single function in the `ttload' */ + /* module is able to read both the horizontal and vertical */ + /* headers. */ + /* */ + typedef struct TT_VertHeader_ + { + FT_Fixed Version; + FT_Short Ascender; + FT_Short Descender; + FT_Short Line_Gap; + + FT_UShort advance_Height_Max; /* advance height maximum */ + + FT_Short min_Top_Side_Bearing; /* minimum left-sb or top-sb */ + FT_Short min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb */ + FT_Short yMax_Extent; /* xmax or ymax extents */ + FT_Short caret_Slope_Rise; + FT_Short caret_Slope_Run; + FT_Short caret_Offset; + + FT_Short Reserved[4]; + + FT_Short metric_Data_Format; + FT_UShort number_Of_VMetrics; + + /* The following fields are not defined by the TrueType specification */ + /* but they're used to connect the metrics header to the relevant */ + /* `HMTX' or `VMTX' table. */ + + void* long_metrics; + void* short_metrics; + + } TT_VertHeader; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_OS2 */ + /* */ + /* <Description> */ + /* A structure used to model a TrueType OS/2 table. This is the long */ + /* table version. All fields comply to the TrueType specification. */ + /* */ + /* Note that we now support old Mac fonts which do not include an */ + /* OS/2 table. In this case, the `version' field is always set to */ + /* 0xFFFF. */ + /* */ + typedef struct TT_OS2_ + { + FT_UShort version; /* 0x0001 - more or 0xFFFF */ + FT_Short xAvgCharWidth; + FT_UShort usWeightClass; + FT_UShort usWidthClass; + FT_Short fsType; + FT_Short ySubscriptXSize; + FT_Short ySubscriptYSize; + FT_Short ySubscriptXOffset; + FT_Short ySubscriptYOffset; + FT_Short ySuperscriptXSize; + FT_Short ySuperscriptYSize; + FT_Short ySuperscriptXOffset; + FT_Short ySuperscriptYOffset; + FT_Short yStrikeoutSize; + FT_Short yStrikeoutPosition; + FT_Short sFamilyClass; + + FT_Byte panose[10]; + + FT_ULong ulUnicodeRange1; /* Bits 0-31 */ + FT_ULong ulUnicodeRange2; /* Bits 32-63 */ + FT_ULong ulUnicodeRange3; /* Bits 64-95 */ + FT_ULong ulUnicodeRange4; /* Bits 96-127 */ + + FT_Char achVendID[4]; + + FT_UShort fsSelection; + FT_UShort usFirstCharIndex; + FT_UShort usLastCharIndex; + FT_Short sTypoAscender; + FT_Short sTypoDescender; + FT_Short sTypoLineGap; + FT_UShort usWinAscent; + FT_UShort usWinDescent; + + /* only version 1 tables: */ + + FT_ULong ulCodePageRange1; /* Bits 0-31 */ + FT_ULong ulCodePageRange2; /* Bits 32-63 */ + + /* only version 2 tables: */ + + FT_Short sxHeight; + FT_Short sCapHeight; + FT_UShort usDefaultChar; + FT_UShort usBreakChar; + FT_UShort usMaxContext; + + } TT_OS2; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_Postscript */ + /* */ + /* <Description> */ + /* A structure used to model a TrueType PostScript table. All fields */ + /* comply to the TrueType specification. This structure does not */ + /* reference the PostScript glyph names, which can be nevertheless */ + /* accessed with the `ttpost' module. */ + /* */ + typedef struct TT_Postscript_ + { + FT_Fixed FormatType; + FT_Fixed italicAngle; + FT_Short underlinePosition; + FT_Short underlineThickness; + FT_ULong isFixedPitch; + FT_ULong minMemType42; + FT_ULong maxMemType42; + FT_ULong minMemType1; + FT_ULong maxMemType1; + + /* Glyph names follow in the file, but we don't */ + /* load them by default. See the ttpost.c file. */ + + } TT_Postscript; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_PCLT */ + /* */ + /* <Description> */ + /* A structure used to model a TrueType PCLT table. All fields */ + /* comply to the TrueType specification. */ + /* */ + typedef struct TT_PCLT_ + { + FT_Fixed Version; + FT_ULong FontNumber; + FT_UShort Pitch; + FT_UShort xHeight; + FT_UShort Style; + FT_UShort TypeFamily; + FT_UShort CapHeight; + FT_UShort SymbolSet; + FT_Char TypeFace[16]; + FT_Char CharacterComplement[8]; + FT_Char FileName[6]; + FT_Char StrokeWeight; + FT_Char WidthType; + FT_Byte SerifStyle; + FT_Byte Reserved; + + } TT_PCLT; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_MaxProfile */ + /* */ + /* <Description> */ + /* The maximum profile is a table containing many max values which */ + /* can be used to pre-allocate arrays. This ensures that no memory */ + /* allocation occurs during a glyph load. */ + /* */ + /* <Fields> */ + /* version :: The version number. */ + /* */ + /* numGlyphs :: The number of glyphs in this TrueType */ + /* font. */ + /* */ + /* maxPoints :: The maximum number of points in a */ + /* non-composite TrueType glyph. See also */ + /* the structure element */ + /* `maxCompositePoints'. */ + /* */ + /* maxContours :: The maximum number of contours in a */ + /* non-composite TrueType glyph. See also */ + /* the structure element */ + /* `maxCompositeContours'. */ + /* */ + /* maxCompositePoints :: The maximum number of points in a */ + /* composite TrueType glyph. See also the */ + /* structure element `maxPoints'. */ + /* */ + /* maxCompositeContours :: The maximum number of contours in a */ + /* composite TrueType glyph. See also the */ + /* structure element `maxContours'. */ + /* */ + /* maxZones :: The maximum number of zones used for */ + /* glyph hinting. */ + /* */ + /* maxTwilightPoints :: The maximum number of points in the */ + /* twilight zone used for glyph hinting. */ + /* */ + /* maxStorage :: The maximum number of elements in the */ + /* storage area used for glyph hinting. */ + /* */ + /* maxFunctionDefs :: The maximum number of function */ + /* definitions in the TrueType bytecode for */ + /* this font. */ + /* */ + /* maxInstructionDefs :: The maximum number of instruction */ + /* definitions in the TrueType bytecode for */ + /* this font. */ + /* */ + /* maxStackElements :: The maximum number of stack elements used */ + /* during bytecode interpretation. */ + /* */ + /* maxSizeOfInstructions :: The maximum number of TrueType opcodes */ + /* used for glyph hinting. */ + /* */ + /* maxComponentElements :: The maximum number of simple (i.e., non- */ + /* composite) glyphs in a composite glyph. */ + /* */ + /* maxComponentDepth :: The maximum nesting depth of composite */ + /* glyphs. */ + /* */ + /* <Note> */ + /* This structure is only used during font loading. */ + /* */ + typedef struct TT_MaxProfile_ + { + FT_Fixed version; + FT_UShort numGlyphs; + FT_UShort maxPoints; + FT_UShort maxContours; + FT_UShort maxCompositePoints; + FT_UShort maxCompositeContours; + FT_UShort maxZones; + FT_UShort maxTwilightPoints; + FT_UShort maxStorage; + FT_UShort maxFunctionDefs; + FT_UShort maxInstructionDefs; + FT_UShort maxStackElements; + FT_UShort maxSizeOfInstructions; + FT_UShort maxComponentElements; + FT_UShort maxComponentDepth; + + } TT_MaxProfile; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Sfnt_Tag */ + /* */ + /* <Description> */ + /* An enumeration used to specify the index of an SFNT table. */ + /* Used in the @FT_Get_Sfnt_Table API function. */ + /* */ + typedef enum FT_Sfnt_Tag_ + { + ft_sfnt_head = 0, /* TT_Header */ + ft_sfnt_maxp = 1, /* TT_MaxProfile */ + ft_sfnt_os2 = 2, /* TT_OS2 */ + ft_sfnt_hhea = 3, /* TT_HoriHeader */ + ft_sfnt_vhea = 4, /* TT_VertHeader */ + ft_sfnt_post = 5, /* TT_Postscript */ + ft_sfnt_pclt = 6, /* TT_PCLT */ + + sfnt_max /* internal end mark */ + + } FT_Sfnt_Tag; + + /* */ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Sfnt_Table */ + /* */ + /* <Description> */ + /* Return a pointer to a given SFNT table within a face. */ + /* */ + /* <Input> */ + /* face :: A handle to the source. */ + /* */ + /* tag :: The index of the SFNT table. */ + /* */ + /* <Return> */ + /* A type-less pointer to the table. This will be~0 in case of */ + /* error, or if the corresponding table was not found *OR* loaded */ + /* from the file. */ + /* */ + /* Use a typecast according to `tag' to access the structure */ + /* elements. */ + /* */ + /* <Note> */ + /* The table is owned by the face object and disappears with it. */ + /* */ + /* This function is only useful to access SFNT tables that are loaded */ + /* by the sfnt, truetype, and opentype drivers. See @FT_Sfnt_Tag for */ + /* a list. */ + /* */ + FT_EXPORT( void* ) + FT_Get_Sfnt_Table( FT_Face face, + FT_Sfnt_Tag tag ); + + + /************************************************************************** + * + * @function: + * FT_Load_Sfnt_Table + * + * @description: + * Load any font table into client memory. + * + * @input: + * face :: + * A handle to the source face. + * + * tag :: + * The four-byte tag of the table to load. Use the value~0 if you want + * to access the whole font file. Otherwise, you can use one of the + * definitions found in the @FT_TRUETYPE_TAGS_H file, or forge a new + * one with @FT_MAKE_TAG. + * + * offset :: + * The starting offset in the table (or file if tag == 0). + * + * @output: + * buffer :: + * The target buffer address. The client must ensure that the memory + * array is big enough to hold the data. + * + * @inout: + * length :: + * If the `length' parameter is NULL, then try to load the whole table. + * Return an error code if it fails. + * + * Else, if `*length' is~0, exit immediately while returning the + * table's (or file) full size in it. + * + * Else the number of bytes to read from the table or file, from the + * starting offset. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * If you need to determine the table's length you should first call this + * function with `*length' set to~0, as in the following example: + * + * { + * FT_ULong length = 0; + * + * + * error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length ); + * if ( error ) { ... table does not exist ... } + * + * buffer = malloc( length ); + * if ( buffer == NULL ) { ... not enough memory ... } + * + * error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length ); + * if ( error ) { ... could not load table ... } + * } + */ + FT_EXPORT( FT_Error ) + FT_Load_Sfnt_Table( FT_Face face, + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ); + + + /************************************************************************** + * + * @function: + * FT_Sfnt_Table_Info + * + * @description: + * Return information on an SFNT table. + * + * @input: + * face :: + * A handle to the source face. + * + * table_index :: + * The index of an SFNT table. The function returns + * FT_Err_Table_Missing for an invalid value. + * + * @output: + * tag :: + * The name tag of the SFNT table. + * + * length :: + * The length of the SFNT table. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * SFNT tables with length zero are treated as missing. + * + */ + FT_EXPORT( FT_Error ) + FT_Sfnt_Table_Info( FT_Face face, + FT_UInt table_index, + FT_ULong *tag, + FT_ULong *length ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_CMap_Language_ID */ + /* */ + /* <Description> */ + /* Return TrueType/sfnt specific cmap language ID. Definitions of */ + /* language ID values are in `freetype/ttnameid.h'. */ + /* */ + /* <Input> */ + /* charmap :: */ + /* The target charmap. */ + /* */ + /* <Return> */ + /* The language ID of `charmap'. If `charmap' doesn't belong to a */ + /* TrueType/sfnt face, just return~0 as the default value. */ + /* */ + FT_EXPORT( FT_ULong ) + FT_Get_CMap_Language_ID( FT_CharMap charmap ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_CMap_Format */ + /* */ + /* <Description> */ + /* Return TrueType/sfnt specific cmap format. */ + /* */ + /* <Input> */ + /* charmap :: */ + /* The target charmap. */ + /* */ + /* <Return> */ + /* The format of `charmap'. If `charmap' doesn't belong to a */ + /* TrueType/sfnt face, return -1. */ + /* */ + FT_EXPORT( FT_Long ) + FT_Get_CMap_Format( FT_CharMap charmap ); + + /* */ + + +FT_END_HEADER + +#endif /* __TTTABLES_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/tttags.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/tttags.h new file mode 100644 index 00000000..307ce4b6 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/tttags.h @@ -0,0 +1,107 @@ +/***************************************************************************/ +/* */ +/* tttags.h */ +/* */ +/* Tags for TrueType and OpenType tables (specification only). */ +/* */ +/* Copyright 1996-2001, 2004, 2005, 2007, 2008 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTAGS_H__ +#define __TTAGS_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + +#define TTAG_avar FT_MAKE_TAG( 'a', 'v', 'a', 'r' ) +#define TTAG_BASE FT_MAKE_TAG( 'B', 'A', 'S', 'E' ) +#define TTAG_bdat FT_MAKE_TAG( 'b', 'd', 'a', 't' ) +#define TTAG_BDF FT_MAKE_TAG( 'B', 'D', 'F', ' ' ) +#define TTAG_bhed FT_MAKE_TAG( 'b', 'h', 'e', 'd' ) +#define TTAG_bloc FT_MAKE_TAG( 'b', 'l', 'o', 'c' ) +#define TTAG_bsln FT_MAKE_TAG( 'b', 's', 'l', 'n' ) +#define TTAG_CFF FT_MAKE_TAG( 'C', 'F', 'F', ' ' ) +#define TTAG_CID FT_MAKE_TAG( 'C', 'I', 'D', ' ' ) +#define TTAG_cmap FT_MAKE_TAG( 'c', 'm', 'a', 'p' ) +#define TTAG_cvar FT_MAKE_TAG( 'c', 'v', 'a', 'r' ) +#define TTAG_cvt FT_MAKE_TAG( 'c', 'v', 't', ' ' ) +#define TTAG_DSIG FT_MAKE_TAG( 'D', 'S', 'I', 'G' ) +#define TTAG_EBDT FT_MAKE_TAG( 'E', 'B', 'D', 'T' ) +#define TTAG_EBLC FT_MAKE_TAG( 'E', 'B', 'L', 'C' ) +#define TTAG_EBSC FT_MAKE_TAG( 'E', 'B', 'S', 'C' ) +#define TTAG_feat FT_MAKE_TAG( 'f', 'e', 'a', 't' ) +#define TTAG_FOND FT_MAKE_TAG( 'F', 'O', 'N', 'D' ) +#define TTAG_fpgm FT_MAKE_TAG( 'f', 'p', 'g', 'm' ) +#define TTAG_fvar FT_MAKE_TAG( 'f', 'v', 'a', 'r' ) +#define TTAG_gasp FT_MAKE_TAG( 'g', 'a', 's', 'p' ) +#define TTAG_GDEF FT_MAKE_TAG( 'G', 'D', 'E', 'F' ) +#define TTAG_glyf FT_MAKE_TAG( 'g', 'l', 'y', 'f' ) +#define TTAG_GPOS FT_MAKE_TAG( 'G', 'P', 'O', 'S' ) +#define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' ) +#define TTAG_gvar FT_MAKE_TAG( 'g', 'v', 'a', 'r' ) +#define TTAG_hdmx FT_MAKE_TAG( 'h', 'd', 'm', 'x' ) +#define TTAG_head FT_MAKE_TAG( 'h', 'e', 'a', 'd' ) +#define TTAG_hhea FT_MAKE_TAG( 'h', 'h', 'e', 'a' ) +#define TTAG_hmtx FT_MAKE_TAG( 'h', 'm', 't', 'x' ) +#define TTAG_JSTF FT_MAKE_TAG( 'J', 'S', 'T', 'F' ) +#define TTAG_just FT_MAKE_TAG( 'j', 'u', 's', 't' ) +#define TTAG_kern FT_MAKE_TAG( 'k', 'e', 'r', 'n' ) +#define TTAG_lcar FT_MAKE_TAG( 'l', 'c', 'a', 'r' ) +#define TTAG_loca FT_MAKE_TAG( 'l', 'o', 'c', 'a' ) +#define TTAG_LTSH FT_MAKE_TAG( 'L', 'T', 'S', 'H' ) +#define TTAG_LWFN FT_MAKE_TAG( 'L', 'W', 'F', 'N' ) +#define TTAG_MATH FT_MAKE_TAG( 'M', 'A', 'T', 'H' ) +#define TTAG_maxp FT_MAKE_TAG( 'm', 'a', 'x', 'p' ) +#define TTAG_META FT_MAKE_TAG( 'M', 'E', 'T', 'A' ) +#define TTAG_MMFX FT_MAKE_TAG( 'M', 'M', 'F', 'X' ) +#define TTAG_MMSD FT_MAKE_TAG( 'M', 'M', 'S', 'D' ) +#define TTAG_mort FT_MAKE_TAG( 'm', 'o', 'r', 't' ) +#define TTAG_morx FT_MAKE_TAG( 'm', 'o', 'r', 'x' ) +#define TTAG_name FT_MAKE_TAG( 'n', 'a', 'm', 'e' ) +#define TTAG_opbd FT_MAKE_TAG( 'o', 'p', 'b', 'd' ) +#define TTAG_OS2 FT_MAKE_TAG( 'O', 'S', '/', '2' ) +#define TTAG_OTTO FT_MAKE_TAG( 'O', 'T', 'T', 'O' ) +#define TTAG_PCLT FT_MAKE_TAG( 'P', 'C', 'L', 'T' ) +#define TTAG_POST FT_MAKE_TAG( 'P', 'O', 'S', 'T' ) +#define TTAG_post FT_MAKE_TAG( 'p', 'o', 's', 't' ) +#define TTAG_prep FT_MAKE_TAG( 'p', 'r', 'e', 'p' ) +#define TTAG_prop FT_MAKE_TAG( 'p', 'r', 'o', 'p' ) +#define TTAG_sfnt FT_MAKE_TAG( 's', 'f', 'n', 't' ) +#define TTAG_SING FT_MAKE_TAG( 'S', 'I', 'N', 'G' ) +#define TTAG_trak FT_MAKE_TAG( 't', 'r', 'a', 'k' ) +#define TTAG_true FT_MAKE_TAG( 't', 'r', 'u', 'e' ) +#define TTAG_ttc FT_MAKE_TAG( 't', 't', 'c', ' ' ) +#define TTAG_ttcf FT_MAKE_TAG( 't', 't', 'c', 'f' ) +#define TTAG_TYP1 FT_MAKE_TAG( 'T', 'Y', 'P', '1' ) +#define TTAG_typ1 FT_MAKE_TAG( 't', 'y', 'p', '1' ) +#define TTAG_VDMX FT_MAKE_TAG( 'V', 'D', 'M', 'X' ) +#define TTAG_vhea FT_MAKE_TAG( 'v', 'h', 'e', 'a' ) +#define TTAG_vmtx FT_MAKE_TAG( 'v', 'm', 't', 'x' ) + + +FT_END_HEADER + +#endif /* __TTAGS_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ttunpat.h b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ttunpat.h new file mode 100644 index 00000000..a0162759 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/freetype2/freetype/ttunpat.h @@ -0,0 +1,59 @@ +/***************************************************************************/ +/* */ +/* ttunpat.h */ +/* */ +/* Definitions for the unpatented TrueType hinting system */ +/* */ +/* Copyright 2003, 2006 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* Written by Graham Asher <graham.asher@btinternet.com> */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTUNPAT_H__ +#define __TTUNPAT_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************** + * + * @constant: + * FT_PARAM_TAG_UNPATENTED_HINTING + * + * @description: + * A constant used as the tag of an @FT_Parameter structure to indicate + * that unpatented methods only should be used by the TrueType bytecode + * interpreter for a typeface opened by @FT_Open_Face. + * + */ +#define FT_PARAM_TAG_UNPATENTED_HINTING FT_MAKE_TAG( 'u', 'n', 'p', 'a' ) + + /* */ + +FT_END_HEADER + + +#endif /* __TTUNPAT_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/ft2build.h b/plugins/snes9x_gx/portlibs/include/ft2build.h new file mode 100644 index 00000000..6a3b8d90 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/ft2build.h @@ -0,0 +1,61 @@ +/***************************************************************************/ +/* */ +/* ft2build.h */ +/* */ +/* Build macros of the FreeType 2 library. */ +/* */ +/* Copyright 1996-2001, 2003, 2006 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This is a Unix-specific version of <ft2build.h> that should be used */ + /* exclusively *after* installation of the library. */ + /* */ + /* It assumes that `/usr/local/include/freetype2' (or whatever is */ + /* returned by the `freetype-config --cflags' or `pkg-config --cflags' */ + /* command) is in your compilation include path. */ + /* */ + /* We don't need to do anything special in this release. However, for */ + /* a future FreeType 2 release, the following installation changes will */ + /* be performed: */ + /* */ + /* - The contents of `freetype-2.x/include/freetype' will be installed */ + /* to `/usr/local/include/freetype2' instead of */ + /* `/usr/local/include/freetype2/freetype'. */ + /* */ + /* - This file will #include <freetype2/config/ftheader.h>, instead */ + /* of <freetype/config/ftheader.h>. */ + /* */ + /* - The contents of `ftheader.h' will be processed with `sed' to */ + /* replace all `<freetype/xxx>' with `<freetype2/xxx>'. */ + /* */ + /* - Adding `/usr/local/include/freetype2' to your compilation include */ + /* path will not be necessary anymore. */ + /* */ + /* These changes will be transparent to client applications which use */ + /* freetype-config (or pkg-config). No modifications will be necessary */ + /* to compile with the new scheme. */ + /* */ + /*************************************************************************/ + + +#ifndef __FT2_BUILD_UNIX_H__ +#define __FT2_BUILD_UNIX_H__ + + /* `<prefix>/include/freetype2' must be in your current inclusion path */ +#include <freetype/config/ftheader.h> + +#endif /* __FT2_BUILD_UNIX_H__ */ + + +/* END */ diff --git a/plugins/snes9x_gx/portlibs/include/gd.h b/plugins/snes9x_gx/portlibs/include/gd.h new file mode 100644 index 00000000..18d8f544 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/gd.h @@ -0,0 +1,889 @@ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef GD_H +#define GD_H 1 + +#define GD_MAJOR_VERSION 2 +#define GD_MINOR_VERSION 1 +#define GD_RELEASE_VERSION 0 +#define GD_EXTRA_VERSION "alpha" +#define GD_VERSION_STRING "2.1.0-alpha" + +/* Do the DLL dance: dllexport when building the DLL, + dllimport when importing from it, nothing when + not on Silly Silly Windows (tm Aardman Productions). */ + +/* 2.0.20: for headers */ + +/* 2.0.24: __stdcall also needed for Visual BASIC + and other languages. This breaks ABI compatibility + with previous DLL revs, but it's necessary. */ + +/* 2.0.29: WIN32 programmers can declare the NONDLL macro if they + wish to build gd as a static library or by directly including + the gd sources in a project. */ + +#if !defined(WIN32) && !defined(_WIN32_WCE) +#define NONDLL 1 +#endif /* WIN32 */ + +#ifdef NONDLL +#define BGD_DECLARE(rt) extern rt +#else +#ifdef BGDWIN32 + +#define BGD_DECLARE(rt) __declspec(dllexport) rt __stdcall +#else +#define BGD_DECLARE(rt) __declspec(dllimport) rt _stdcall +#endif /* BGDWIN32 */ +#endif /* NONDLL */ + +/* 2.0.20: for actual storage of exported data, functions don't need this, + currently needed only for font pointers */ +#ifdef NONDLL +/* 2.0.25: bring back extern */ +#define BGD_EXPORT_DATA_PROT extern +#define BGD_EXPORT_DATA_IMPL +#else +#ifdef BGDWIN32 +#define BGD_EXPORT_DATA_PROT __declspec(dllexport) extern +#define BGD_EXPORT_DATA_IMPL __declspec(dllexport) +#else +#define BGD_EXPORT_DATA_PROT __declspec(dllimport) extern +#define BGD_EXPORT_DATA_IMPL __declspec(dllimport) +#endif /* BGDWIN32 */ +#endif /* NONDLL */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* some might want to set DEFAULT_FONTPATH from configure in config.h */ +#ifdef NETWARE +/* default fontpath for netware systems, could probably be handled in configure for 2.1 */ +#define DEFAULT_FONTPATH "sys:/java/nwgfx/lib/x11/fonts/ttf;." +#define PATHSEPARATOR ";" +#endif + +/* 2.0.23: more Type 1 fonts */ +#ifndef DEFAULT_FONTPATH +/* default fontpath for unix systems - whatever happened to standards ! */ +#define DEFAULT_FONTPATH "/usr/X11R6/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/truetype:/usr/X11R6/lib/X11/fonts/TTF:/usr/share/fonts/TrueType:/usr/share/fonts/truetype:/usr/openwin/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/Type1:/usr/lib/X11/fonts/Type1:/usr/openwin/lib/X11/fonts/Type1" +#endif +#ifndef PATHSEPARATOR +#define PATHSEPARATOR ":" +#endif + +/* gd.h: declarations file for the graphic-draw module. + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. This software is provided "AS IS." Thomas Boutell and + * Boutell.Com, Inc. disclaim all warranties, either express or implied, + * including but not limited to implied warranties of merchantability and + * fitness for a particular purpose, with respect to this code and accompanying + * documentation. */ + +/* stdio is needed for file I/O. */ +#include <stdio.h> +#include "gd_io.h" + +/* The maximum number of palette entries in palette-based images. + In the wonderful new world of gd 2.0, you can of course have + many more colors when using truecolor mode. */ + +#define gdMaxColors 256 + +/* Image type. See functions below; you will not need to change + the elements directly. Use the provided macros to + access sx, sy, the color table, and colorsTotal for + read-only purposes. */ + +/* If 'truecolor' is set true, the image is truecolor; + pixels are represented by integers, which + must be 32 bits wide or more. + + True colors are repsented as follows: + + ARGB + + Where 'A' (alpha channel) occupies only the + LOWER 7 BITS of the MSB. This very small + loss of alpha channel resolution allows gd 2.x + to keep backwards compatibility by allowing + signed integers to be used to represent colors, + and negative numbers to represent special cases, + just as in gd 1.x. */ + +#define gdAlphaMax 127 +#define gdAlphaOpaque 0 +#define gdAlphaTransparent 127 +#define gdRedMax 255 +#define gdGreenMax 255 +#define gdBlueMax 255 +#define gdTrueColorGetAlpha(c) (((c) & 0x7F000000) >> 24) +#define gdTrueColorGetRed(c) (((c) & 0xFF0000) >> 16) +#define gdTrueColorGetGreen(c) (((c) & 0x00FF00) >> 8) +#define gdTrueColorGetBlue(c) ((c) & 0x0000FF) + +enum gdCropMode { + GD_CROP_DEFAULT = 0, + GD_CROP_TRANSPARENT, + GD_CROP_BLACK, + GD_CROP_WHITE, + GD_CROP_SIDES +}; + + +/* This function accepts truecolor pixel values only. The + source color is composited with the destination color + based on the alpha channel value of the source color. + The resulting color is opaque. */ + +BGD_DECLARE(int) gdAlphaBlend (int dest, int src); + + typedef struct gdImageStruct + { + /* Palette-based image pixels */ + unsigned char **pixels; + int sx; + int sy; + /* These are valid in palette images only. See also + 'alpha', which appears later in the structure to + preserve binary backwards compatibility */ + int colorsTotal; + int red[gdMaxColors]; + int green[gdMaxColors]; + int blue[gdMaxColors]; + int open[gdMaxColors]; + /* For backwards compatibility, this is set to the + first palette entry with 100% transparency, + and is also set and reset by the + gdImageColorTransparent function. Newer + applications can allocate palette entries + with any desired level of transparency; however, + bear in mind that many viewers, notably + many web browsers, fail to implement + full alpha channel for PNG and provide + support for full opacity or transparency only. */ + int transparent; + int *polyInts; + int polyAllocated; + struct gdImageStruct *brush; + struct gdImageStruct *tile; + int brushColorMap[gdMaxColors]; + int tileColorMap[gdMaxColors]; + int styleLength; + int stylePos; + int *style; + int interlace; + /* New in 2.0: thickness of line. Initialized to 1. */ + int thick; + /* New in 2.0: alpha channel for palettes. Note that only + Macintosh Internet Explorer and (possibly) Netscape 6 + really support multiple levels of transparency in + palettes, to my knowledge, as of 2/15/01. Most + common browsers will display 100% opaque and + 100% transparent correctly, and do something + unpredictable and/or undesirable for levels + in between. TBB */ + int alpha[gdMaxColors]; + /* Truecolor flag and pixels. New 2.0 fields appear here at the + end to minimize breakage of existing object code. */ + int trueColor; + int **tpixels; + /* Should alpha channel be copied, or applied, each time a + pixel is drawn? This applies to truecolor images only. + No attempt is made to alpha-blend in palette images, + even if semitransparent palette entries exist. + To do that, build your image as a truecolor image, + then quantize down to 8 bits. */ + int alphaBlendingFlag; + /* Should the alpha channel of the image be saved? This affects + PNG at the moment; other future formats may also + have that capability. JPEG doesn't. */ + int saveAlphaFlag; + + /* There should NEVER BE ACCESSOR MACROS FOR ITEMS BELOW HERE, so this + part of the structure can be safely changed in new releases. */ + + /* 2.0.12: anti-aliased globals. 2.0.26: just a few vestiges after + switching to the fast, memory-cheap implementation from PHP-gd. */ + int AA; + int AA_color; + int AA_dont_blend; + + /* 2.0.12: simple clipping rectangle. These values + must be checked for safety when set; please use + gdImageSetClip */ + int cx1; + int cy1; + int cx2; + int cy2; + + /* 2.1.0: allows to specify resolution in dpi */ + unsigned int res_x; + unsigned int res_y; + } + gdImage; + + typedef gdImage *gdImagePtr; + + typedef struct + { + /* # of characters in font */ + int nchars; + /* First character is numbered... (usually 32 = space) */ + int offset; + /* Character width and height */ + int w; + int h; + /* Font data; array of characters, one row after another. + Easily included in code, also easily loaded from + data files. */ + char *data; + } + gdFont; + +/* Text functions take these. */ + typedef gdFont *gdFontPtr; + +/* For backwards compatibility only. Use gdImageSetStyle() + for MUCH more flexible line drawing. Also see + gdImageSetBrush(). */ +#define gdDashSize 4 + +/* Special colors. */ + +#define gdStyled (-2) +#define gdBrushed (-3) +#define gdStyledBrushed (-4) +#define gdTiled (-5) + +/* NOT the same as the transparent color index. + This is used in line styles only. */ +#define gdTransparent (-6) + +#define gdAntiAliased (-7) + +/* Functions to manipulate images. */ + +/* Creates a palette-based image (up to 256 colors). */ +BGD_DECLARE(gdImagePtr) gdImageCreate (int sx, int sy); + +/* An alternate name for the above (2.0). */ +#define gdImageCreatePalette gdImageCreate + +/* Creates a truecolor image (millions of colors). */ +BGD_DECLARE(gdImagePtr) gdImageCreateTrueColor (int sx, int sy); + +/* Creates an image from various file types. These functions + return a palette or truecolor image based on the + nature of the file being loaded. Truecolor PNG + stays truecolor; palette PNG stays palette-based; + JPEG is always truecolor. */ +BGD_DECLARE(gdImagePtr) gdImageCreateFromPng (FILE * fd); +BGD_DECLARE(gdImagePtr) gdImageCreateFromPngCtx (gdIOCtxPtr in); +BGD_DECLARE(gdImagePtr) gdImageCreateFromPngPtr (int size, void *data); + +/* These read the first frame only */ +BGD_DECLARE(gdImagePtr) gdImageCreateFromGif (FILE * fd); +BGD_DECLARE(gdImagePtr) gdImageCreateFromGifCtx (gdIOCtxPtr in); +BGD_DECLARE(gdImagePtr) gdImageCreateFromGifPtr (int size, void *data); +BGD_DECLARE(gdImagePtr) gdImageCreateFromWBMP (FILE * inFile); +BGD_DECLARE(gdImagePtr) gdImageCreateFromWBMPCtx (gdIOCtx * infile); +BGD_DECLARE(gdImagePtr) gdImageCreateFromWBMPPtr (int size, void *data); +BGD_DECLARE(gdImagePtr) gdImageCreateFromJpeg (FILE * infile); +BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegCtx (gdIOCtx * infile); +BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegPtr (int size, void *data); + +BGD_DECLARE(gdImagePtr) gdImageCreateFromTiff(FILE *inFile); +BGD_DECLARE(gdImagePtr) gdImageCreateFromTiffCtx(gdIOCtx *infile); +BGD_DECLARE(gdImagePtr) gdImageCreateFromTiffPtr(int size, void *data); + +BGD_DECLARE(gdImagePtr) gdImageCreateFromTga( FILE * fp ); +BGD_DECLARE(gdImagePtr) gdImageCreateFromTgaCtx(gdIOCtx* ctx); +BGD_DECLARE(gdImagePtr) gdImageCreateFromTgaPtr(int size, void *data); + +BGD_DECLARE(gdImagePtr) gdImageCreateFromBmp (FILE * inFile); +BGD_DECLARE(gdImagePtr) gdImageCreateFromBmpPtr (int size, void *data); +BGD_DECLARE(gdImagePtr) gdImageCreateFromBmpCtx (gdIOCtxPtr infile); + +/* A custom data source. */ +/* The source function must return -1 on error, otherwise the number + of bytes fetched. 0 is EOF, not an error! */ +/* context will be passed to your source function. */ + + typedef struct + { + int (*source) (void *context, char *buffer, int len); + void *context; + } + gdSource, *gdSourcePtr; + + /* Deprecated in favor of gdImageCreateFromPngCtx */ +BGD_DECLARE(gdImagePtr) gdImageCreateFromPngSource (gdSourcePtr in); + +BGD_DECLARE(gdImagePtr) gdImageCreateFromGd (FILE * in); +BGD_DECLARE(gdImagePtr) gdImageCreateFromGdCtx (gdIOCtxPtr in); +BGD_DECLARE(gdImagePtr) gdImageCreateFromGdPtr (int size, void *data); + +BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2 (FILE * in); +BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2Ctx (gdIOCtxPtr in); +BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2Ptr (int size, void *data); + +BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2Part (FILE * in, int srcx, int srcy, int w, + int h); +BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2PartCtx (gdIOCtxPtr in, int srcx, int srcy, + int w, int h); +BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2PartPtr (int size, void *data, int srcx, int srcy, + int w, int h); + /* 2.0.10: prototype was missing */ +BGD_DECLARE(gdImagePtr) gdImageCreateFromXbm (FILE * in); + + /* NOTE: filename, not FILE */ +BGD_DECLARE(gdImagePtr) gdImageCreateFromXpm (char *filename); + +BGD_DECLARE(void) gdImageDestroy (gdImagePtr im); + +/* Replaces or blends with the background depending on the + most recent call to gdImageAlphaBlending and the + alpha channel value of 'color'; default is to overwrite. + Tiling and line styling are also implemented + here. All other gd drawing functions pass through this call, + allowing for many useful effects. */ + +BGD_DECLARE(void) gdImageSetPixel (gdImagePtr im, int x, int y, int color); +/* FreeType 2 text output with hook to extra flags */ + +BGD_DECLARE(int) gdImageGetPixel (gdImagePtr im, int x, int y); +BGD_DECLARE(int) gdImageGetTrueColorPixel (gdImagePtr im, int x, int y); + +BGD_DECLARE(void) gdImageAABlend (gdImagePtr im); + +BGD_DECLARE(void) gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color); + +/* For backwards compatibility only. Use gdImageSetStyle() + for much more flexible line drawing. */ +BGD_DECLARE(void) gdImageDashedLine (gdImagePtr im, int x1, int y1, int x2, int y2, + int color); +/* Corners specified (not width and height). Upper left first, lower right + second. */ +BGD_DECLARE(void) gdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, + int color); +/* Solid bar. Upper left corner first, lower right corner second. */ +BGD_DECLARE(void) gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, + int color); +BGD_DECLARE(void) gdImageSetClip(gdImagePtr im, int x1, int y1, int x2, int y2); +BGD_DECLARE(void) gdImageGetClip(gdImagePtr im, int *x1P, int *y1P, int *x2P, int *y2P); +BGD_DECLARE(void) gdImageSetResolution(gdImagePtr im, const unsigned int res_x, const unsigned int res_y); +BGD_DECLARE(int) gdImageBoundsSafe (gdImagePtr im, int x, int y); +BGD_DECLARE(void) gdImageChar (gdImagePtr im, gdFontPtr f, int x, int y, int c, + int color); +BGD_DECLARE(void) gdImageCharUp (gdImagePtr im, gdFontPtr f, int x, int y, int c, + int color); +BGD_DECLARE(void) gdImageString (gdImagePtr im, gdFontPtr f, int x, int y, + unsigned char *s, int color); +BGD_DECLARE(void) gdImageStringUp (gdImagePtr im, gdFontPtr f, int x, int y, + unsigned char *s, int color); +BGD_DECLARE(void) gdImageString16 (gdImagePtr im, gdFontPtr f, int x, int y, + unsigned short *s, int color); +BGD_DECLARE(void) gdImageStringUp16 (gdImagePtr im, gdFontPtr f, int x, int y, + unsigned short *s, int color); + +/* 2.0.16: for thread-safe use of gdImageStringFT and friends, + call this before allowing any thread to call gdImageStringFT. + Otherwise it is invoked by the first thread to invoke + gdImageStringFT, with a very small but real risk of a race condition. + Return 0 on success, nonzero on failure to initialize freetype. */ +BGD_DECLARE(int) gdFontCacheSetup (void); + +/* Optional: clean up after application is done using fonts in +BGD_DECLARE( ) + gdImageStringFT(). */ +BGD_DECLARE(void) gdFontCacheShutdown (void); +/* 2.0.20: for backwards compatibility. A few applications did start calling + this function when it first appeared although it was never documented. + Simply invokes gdFontCacheShutdown. */ +BGD_DECLARE(void) gdFreeFontCache (void); + +/* Calls gdImageStringFT. Provided for backwards compatibility only. */ +BGD_DECLARE(char *) gdImageStringTTF (gdImage * im, int *brect, int fg, char *fontlist, + double ptsize, double angle, int x, int y, + char *string); + +/* FreeType 2 text output */ +BGD_DECLARE(char *) gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist, + double ptsize, double angle, int x, int y, + char *string); + +/* 2.0.5: provides an extensible way to pass additional parameters. + Thanks to Wez Furlong, sorry for the delay. */ + + typedef struct + { + int flags; /* Logical OR of gdFTEX_ values */ + double linespacing; /* fine tune line spacing for '\n' */ + int charmap; /* TBB: 2.0.12: may be gdFTEX_Unicode, + gdFTEX_Shift_JIS, gdFTEX_Big5, + or gdFTEX_Adobe_Custom; + when not specified, maps are searched + for in the above order. */ + int hdpi; /* if (flags & gdFTEX_RESOLUTION) */ + int vdpi; /* if (flags & gdFTEX_RESOLUTION) */ + char *xshow; /* if (flags & gdFTEX_XSHOW) + then, on return, xshow is a malloc'ed + string containing xshow position data for + the last string. + + NB. The caller is responsible for gdFree'ing + the xshow string. + */ + char *fontpath; /* if (flags & gdFTEX_RETURNFONTPATHNAME) + then, on return, fontpath is a malloc'ed + string containing the actual font file path name + used, which can be interesting when fontconfig + is in use. + + The caller is responsible for gdFree'ing the + fontpath string. + */ + + } + gdFTStringExtra, *gdFTStringExtraPtr; + +#define gdFTEX_LINESPACE 1 +#define gdFTEX_CHARMAP 2 +#define gdFTEX_RESOLUTION 4 +#define gdFTEX_DISABLE_KERNING 8 +#define gdFTEX_XSHOW 16 +/* The default unless gdFTUseFontConfig(1); has been called: + fontlist is a full or partial font file pathname or list thereof + (i.e. just like before 2.0.29) */ +#define gdFTEX_FONTPATHNAME 32 +/* Necessary to use fontconfig patterns instead of font pathnames + as the fontlist argument, unless gdFTUseFontConfig(1); has + been called. New in 2.0.29 */ +#define gdFTEX_FONTCONFIG 64 +/* Sometimes interesting when fontconfig is used: the fontpath + element of the structure above will contain a gdMalloc'd string + copy of the actual font file pathname used, if this flag is set + when the call is made */ +#define gdFTEX_RETURNFONTPATHNAME 128 + +/* If flag is nonzero, the fontlist parameter to gdImageStringFT + and gdImageStringFTEx shall be assumed to be a fontconfig font pattern + if fontconfig was compiled into gd. This function returns zero + if fontconfig is not available, nonzero otherwise. */ +BGD_DECLARE(int) gdFTUseFontConfig(int flag); + +/* These are NOT flags; set one in 'charmap' if you set the + gdFTEX_CHARMAP bit in 'flags'. */ +#define gdFTEX_Unicode 0 +#define gdFTEX_Shift_JIS 1 +#define gdFTEX_Big5 2 +#define gdFTEX_Adobe_Custom 3 + +BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, + double ptsize, double angle, int x, int y, + char *string, gdFTStringExtraPtr strex); + +/* Point type for use in polygon drawing. */ +typedef struct +{ + int x, y; +} +gdPoint, *gdPointPtr; + +typedef struct +{ + int x, y; + int width, height; +} +gdRect, *gdRectPtr; + + +BGD_DECLARE(void) gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c); +BGD_DECLARE(void) gdImageOpenPolygon (gdImagePtr im, gdPointPtr p, int n, int c); +BGD_DECLARE(void) gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int c); + +/* These functions still work with truecolor images, + for which they never return error. */ +BGD_DECLARE(int) gdImageColorAllocate (gdImagePtr im, int r, int g, int b); +/* gd 2.0: palette entries with non-opaque transparency are permitted. */ +BGD_DECLARE(int) gdImageColorAllocateAlpha (gdImagePtr im, int r, int g, int b, int a); +/* Assumes opaque is the preferred alpha channel value */ +BGD_DECLARE(int) gdImageColorClosest (gdImagePtr im, int r, int g, int b); +/* Closest match taking all four parameters into account. + A slightly different color with the same transparency + beats the exact same color with radically different + transparency */ +BGD_DECLARE(int) gdImageColorClosestAlpha (gdImagePtr im, int r, int g, int b, int a); +/* An alternate method */ +BGD_DECLARE(int) gdImageColorClosestHWB (gdImagePtr im, int r, int g, int b); +/* Returns exact, 100% opaque matches only */ +BGD_DECLARE(int) gdImageColorExact (gdImagePtr im, int r, int g, int b); +/* Returns an exact match only, including alpha */ +BGD_DECLARE(int) gdImageColorExactAlpha (gdImagePtr im, int r, int g, int b, int a); +/* Opaque only */ +BGD_DECLARE(int) gdImageColorResolve (gdImagePtr im, int r, int g, int b); +/* Based on gdImageColorExactAlpha and gdImageColorClosestAlpha */ +BGD_DECLARE(int) gdImageColorResolveAlpha (gdImagePtr im, int r, int g, int b, int a); + +/* A simpler way to obtain an opaque truecolor value for drawing on a + truecolor image. Not for use with palette images! */ + +#define gdTrueColor(r, g, b) (((r) << 16) + \ + ((g) << 8) + \ + (b)) + +/* Returns a truecolor value with an alpha channel component. + gdAlphaMax (127, **NOT 255**) is transparent, 0 is completely + opaque. */ + +#define gdTrueColorAlpha(r, g, b, a) (((a) << 24) + \ + ((r) << 16) + \ + ((g) << 8) + \ + (b)) + +BGD_DECLARE(void) gdImageColorDeallocate (gdImagePtr im, int color); + +/* Converts a truecolor image to a palette-based image, + using a high-quality two-pass quantization routine + which attempts to preserve alpha channel information + as well as R/G/B color information when creating + a palette. If ditherFlag is set, the image will be + dithered to approximate colors better, at the expense + of some obvious "speckling." colorsWanted can be + anything up to 256. If the original source image + includes photographic information or anything that + came out of a JPEG, 256 is strongly recommended. + + Better yet, don't use these function -- write real + truecolor PNGs and JPEGs. The disk space gain of + conversion to palette is not great (for small images + it can be negative) and the quality loss is ugly. + + DIFFERENCES: gdImageCreatePaletteFromTrueColor creates and + returns a new image. gdImageTrueColorToPalette modifies + an existing image, and the truecolor pixels are discarded. */ + +BGD_DECLARE(gdImagePtr) gdImageCreatePaletteFromTrueColor (gdImagePtr im, int ditherFlag, + int colorsWanted); + +BGD_DECLARE(void) gdImageTrueColorToPalette (gdImagePtr im, int ditherFlag, + int colorsWanted); + +/* Specifies a color index (if a palette image) or an + RGB color (if a truecolor image) which should be + considered 100% transparent. FOR TRUECOLOR IMAGES, + THIS IS IGNORED IF AN ALPHA CHANNEL IS BEING + SAVED. Use gdImageSaveAlpha(im, 0); to + turn off the saving of a full alpha channel in + a truecolor image. Note that gdImageColorTransparent + is usually compatible with older browsers that + do not understand full alpha channels well. TBB */ +BGD_DECLARE(void) gdImageColorTransparent (gdImagePtr im, int color); + +BGD_DECLARE(void) gdImagePaletteCopy (gdImagePtr dst, gdImagePtr src); + +typedef int (*gdCallbackImageColor)(gdImagePtr im, int src); + +BGD_DECLARE(int) gdImageColorReplace(gdImagePtr im, int src, int dst); +BGD_DECLARE(int) gdImageColorReplaceThreshold(gdImagePtr im, int src, int dst, float threshold); +BGD_DECLARE(int) gdImageColorReplaceArray(gdImagePtr im, int len, int *src, int *dst); +BGD_DECLARE(int) gdImageColorReplaceCallback(gdImagePtr im, gdCallbackImageColor callback); + +BGD_DECLARE(void) gdImageGif (gdImagePtr im, FILE * out); +BGD_DECLARE(void) gdImagePng (gdImagePtr im, FILE * out); +BGD_DECLARE(void) gdImagePngCtx (gdImagePtr im, gdIOCtx * out); +BGD_DECLARE(void) gdImageGifCtx (gdImagePtr im, gdIOCtx * out); +BGD_DECLARE(void) gdImageTiff(gdImagePtr im, FILE *outFile); +BGD_DECLARE(void *) gdImageTiffPtr(gdImagePtr im, int *size); +BGD_DECLARE(void) gdImageTiffCtx(gdImagePtr image, gdIOCtx *out); + +BGD_DECLARE(void *) gdImageBmpPtr(gdImagePtr im, int *size, int compression); +BGD_DECLARE(void) gdImageBmp(gdImagePtr im, FILE *outFile, int compression); +BGD_DECLARE(void) gdImageBmpCtx(gdImagePtr im, gdIOCtxPtr out, int compression); + +/* 2.0.12: Compression level: 0-9 or -1, where 0 is NO COMPRESSION at all, + 1 is FASTEST but produces larger files, 9 provides the best + compression (smallest files) but takes a long time to compress, and + -1 selects the default compiled into the zlib library. */ +BGD_DECLARE(void) gdImagePngEx (gdImagePtr im, FILE * out, int level); +BGD_DECLARE(void) gdImagePngCtxEx (gdImagePtr im, gdIOCtx * out, int level); + +BGD_DECLARE(void) gdImageWBMP (gdImagePtr image, int fg, FILE * out); +BGD_DECLARE(void) gdImageWBMPCtx (gdImagePtr image, int fg, gdIOCtx * out); + +/* Guaranteed to correctly free memory returned + by the gdImage*Ptr functions */ +BGD_DECLARE(void) gdFree (void *m); + +/* Best to free this memory with gdFree(), not free() */ +BGD_DECLARE(void *) gdImageWBMPPtr (gdImagePtr im, int *size, int fg); + +/* 100 is highest quality (there is always a little loss with JPEG). + 0 is lowest. 10 is about the lowest useful setting. */ +BGD_DECLARE(void) gdImageJpeg (gdImagePtr im, FILE * out, int quality); +BGD_DECLARE(void) gdImageJpegCtx (gdImagePtr im, gdIOCtx * out, int quality); + +/* Best to free this memory with gdFree(), not free() */ +BGD_DECLARE(void *) gdImageJpegPtr (gdImagePtr im, int *size, int quality); + +/* Legal values for Disposal. gdDisposalNone is always used by + the built-in optimizer if previm is passed. */ + +enum { + gdDisposalUnknown, + gdDisposalNone, + gdDisposalRestoreBackground, + gdDisposalRestorePrevious +}; + +BGD_DECLARE(void) gdImageGifAnimBegin(gdImagePtr im, FILE *outFile, int GlobalCM, int Loops); +BGD_DECLARE(void) gdImageGifAnimAdd(gdImagePtr im, FILE *outFile, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm); +BGD_DECLARE(void) gdImageGifAnimEnd(FILE *outFile); +BGD_DECLARE(void) gdImageGifAnimBeginCtx(gdImagePtr im, gdIOCtx *out, int GlobalCM, int Loops); +BGD_DECLARE(void) gdImageGifAnimAddCtx(gdImagePtr im, gdIOCtx *out, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm); +BGD_DECLARE(void) gdImageGifAnimEndCtx(gdIOCtx *out); +BGD_DECLARE(void *) gdImageGifAnimBeginPtr(gdImagePtr im, int *size, int GlobalCM, int Loops); +BGD_DECLARE(void *) gdImageGifAnimAddPtr(gdImagePtr im, int *size, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm); +BGD_DECLARE(void *) gdImageGifAnimEndPtr(int *size); + +/* A custom data sink. For backwards compatibility. Use + gdIOCtx instead. */ +/* The sink function must return -1 on error, otherwise the number + of bytes written, which must be equal to len. */ +/* context will be passed to your sink function. */ + typedef struct + { + int (*sink) (void *context, const char *buffer, int len); + void *context; + } + gdSink, *gdSinkPtr; + +BGD_DECLARE(void) gdImagePngToSink (gdImagePtr im, gdSinkPtr out); + +BGD_DECLARE(void) gdImageGd (gdImagePtr im, FILE * out); +BGD_DECLARE(void) gdImageGd2 (gdImagePtr im, FILE * out, int cs, int fmt); + +/* Best to free this memory with gdFree(), not free() */ +BGD_DECLARE(void *) gdImageGifPtr (gdImagePtr im, int *size); + +/* Best to free this memory with gdFree(), not free() */ +BGD_DECLARE(void *) gdImagePngPtr (gdImagePtr im, int *size); +BGD_DECLARE(void *) gdImagePngPtrEx (gdImagePtr im, int *size, int level); + +/* Best to free this memory with gdFree(), not free() */ +BGD_DECLARE(void *) gdImageGdPtr (gdImagePtr im, int *size); + +/* Best to free this memory with gdFree(), not free() */ +BGD_DECLARE(void *) gdImageGd2Ptr (gdImagePtr im, int cs, int fmt, int *size); + +/* Style is a bitwise OR ( | operator ) of these. + gdArc and gdChord are mutually exclusive; + gdChord just connects the starting and ending + angles with a straight line, while gdArc produces + a rounded edge. gdPie is a synonym for gdArc. + gdNoFill indicates that the arc or chord should be + outlined, not filled. gdEdged, used together with + gdNoFill, indicates that the beginning and ending + angles should be connected to the center; this is + a good way to outline (rather than fill) a + 'pie slice'. */ +#define gdArc 0 +#define gdPie gdArc +#define gdChord 1 +#define gdNoFill 2 +#define gdEdged 4 + +BGD_DECLARE(void) gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, + int e, int color, int style); +BGD_DECLARE(void) gdImageArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e, + int color); +BGD_DECLARE(void) gdImageEllipse(gdImagePtr im, int cx, int cy, int w, int h, int color); +BGD_DECLARE(void) gdImageFilledEllipse (gdImagePtr im, int cx, int cy, int w, int h, + int color); +BGD_DECLARE(void) gdImageFillToBorder (gdImagePtr im, int x, int y, int border, + int color); +BGD_DECLARE(void) gdImageFill (gdImagePtr im, int x, int y, int color); +BGD_DECLARE(void) gdImageCopy (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, + int srcX, int srcY, int w, int h); +BGD_DECLARE(void) gdImageCopyMerge (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, + int srcX, int srcY, int w, int h, int pct); +BGD_DECLARE(void) gdImageCopyMergeGray (gdImagePtr dst, gdImagePtr src, int dstX, + int dstY, int srcX, int srcY, int w, int h, + int pct); + +/* Stretches or shrinks to fit, as needed. Does NOT attempt + to average the entire set of source pixels that scale down onto the + destination pixel. */ +BGD_DECLARE(void) gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, + int srcX, int srcY, int dstW, int dstH, int srcW, + int srcH); + +/* gd 2.0: stretches or shrinks to fit, as needed. When called with a + truecolor destination image, this function averages the + entire set of source pixels that scale down onto the + destination pixel, taking into account what portion of the + destination pixel each source pixel represents. This is a + floating point operation, but this is not a performance issue + on modern hardware, except for some embedded devices. If the + destination is a palette image, gdImageCopyResized is + substituted automatically. */ +BGD_DECLARE(void) gdImageCopyResampled (gdImagePtr dst, gdImagePtr src, int dstX, + int dstY, int srcX, int srcY, int dstW, int dstH, + int srcW, int srcH); + +/* gd 2.0.8: gdImageCopyRotated is added. Source + is a rectangle, with its upper left corner at + srcX and srcY. Destination is the *center* of + the rotated copy. Angle is in degrees, same as + gdImageArc. Floating point destination center + coordinates allow accurate rotation of + objects of odd-numbered width or height. */ +BGD_DECLARE(void) gdImageCopyRotated (gdImagePtr dst, + gdImagePtr src, + double dstX, double dstY, + int srcX, int srcY, + int srcWidth, int srcHeight, int angle); + +BGD_DECLARE(void) gdImageSetBrush (gdImagePtr im, gdImagePtr brush); +BGD_DECLARE(void) gdImageSetTile (gdImagePtr im, gdImagePtr tile); +BGD_DECLARE(void) gdImageSetAntiAliased (gdImagePtr im, int c); +BGD_DECLARE(void) gdImageSetAntiAliasedDontBlend (gdImagePtr im, int c, int dont_blend); +BGD_DECLARE(void) gdImageSetStyle (gdImagePtr im, int *style, int noOfPixels); +/* Line thickness (defaults to 1). Affects lines, ellipses, + rectangles, polygons and so forth. */ +BGD_DECLARE(void) gdImageSetThickness (gdImagePtr im, int thickness); +/* On or off (1 or 0) for all three of these. */ +BGD_DECLARE(void) gdImageInterlace (gdImagePtr im, int interlaceArg); +BGD_DECLARE(void) gdImageAlphaBlending (gdImagePtr im, int alphaBlendingArg); +BGD_DECLARE(void) gdImageSaveAlpha (gdImagePtr im, int saveAlphaArg); + + +BGD_DECLARE(gdImagePtr) gdImageCrop(gdImagePtr src, const gdRect *crop); +BGD_DECLARE(gdImagePtr) gdImageAutoCrop(gdImagePtr im, const unsigned int mode); +BGD_DECLARE(gdImagePtr) gdImageThresholdCrop(gdImagePtr im, const unsigned int color, const float threshold); + +BGD_DECLARE(void) gdImageFlipHorizontal(gdImagePtr im); +BGD_DECLARE(void) gdImageFlipVertical(gdImagePtr im); +BGD_DECLARE(void) gdImageFlipBoth(gdImagePtr im); + +BGD_DECLARE(gdImagePtr) gdImageNeuQuant(gdImagePtr im, const int max_color, int sample_factor); + +enum gdPixelateMode { + GD_PIXELATE_UPPERLEFT, + GD_PIXELATE_AVERAGE +}; + +BGD_DECLARE(int) gdImagePixelate(gdImagePtr im, int block_size, const unsigned int mode); + +typedef struct { + int sub; + int plus; + unsigned int num_colors; + int *colors; + unsigned int seed; +} gdScatter, *gdScatterPtr; + +BGD_DECLARE(int) gdImageScatter(gdImagePtr im, int sub, int plus); +BGD_DECLARE(int) gdImageScatterColor(gdImagePtr im, int sub, int plus, int colors[], unsigned int num_colors); +BGD_DECLARE(int) gdImageScatterEx(gdImagePtr im, gdScatterPtr s); + +/* Macros to access information about images. */ + +/* Returns nonzero if the image is a truecolor image, + zero for a palette image. */ + +#define gdImageTrueColor(im) ((im)->trueColor) + +#define gdImageSX(im) ((im)->sx) +#define gdImageSY(im) ((im)->sy) +#define gdImageColorsTotal(im) ((im)->colorsTotal) +#define gdImageRed(im, c) ((im)->trueColor ? (int) gdTrueColorGetRed(c) : \ + (im)->red[(c)]) +#define gdImageGreen(im, c) ((im)->trueColor ? (int) gdTrueColorGetGreen(c) : \ + (im)->green[(c)]) +#define gdImageBlue(im, c) ((im)->trueColor ? (int) gdTrueColorGetBlue(c) : \ + (im)->blue[(c)]) +#define gdImageAlpha(im, c) ((im)->trueColor ? (int) gdTrueColorGetAlpha(c) : \ + (im)->alpha[(c)]) +#define gdImageGetTransparent(im) ((im)->transparent) +#define gdImageGetInterlaced(im) ((im)->interlace) + +/* These macros provide direct access to pixels in + palette-based and truecolor images, respectively. + If you use these macros, you must perform your own + bounds checking. Use of the macro for the correct type + of image is also your responsibility. */ +#define gdImagePalettePixel(im, x, y) (im)->pixels[(y)][(x)] +#define gdImageTrueColorPixel(im, x, y) (im)->tpixels[(y)][(x)] + +#define gdImageResolutionX(im) (im)->res_x +#define gdImageResolutionY(im) (im)->res_y + +/* I/O Support routines. */ + +BGD_DECLARE(gdIOCtx *) gdNewFileCtx (FILE *); + /* If data is null, size is ignored and an initial data buffer is + allocated automatically. NOTE: this function assumes gd has the right + to free or reallocate "data" at will! Also note that gd will free + "data" when the IO context is freed. If data is not null, it must point + to memory allocated with gdMalloc, or by a call to gdImage[something]Ptr. + If not, see gdNewDynamicCtxEx for an alternative. */ +BGD_DECLARE(gdIOCtx *) gdNewDynamicCtx (int size, void *data); + /* 2.0.21: if freeFlag is nonzero, gd will free and/or reallocate "data" as + needed as described above. If freeFlag is zero, gd will never free + or reallocate "data", which means that the context should only be used + for *reading* an image from a memory buffer, or writing an image to a + memory buffer which is already large enough. If the memory buffer is + not large enough and an image write is attempted, the write operation + will fail. Those wishing to write an image to a buffer in memory have + a much simpler alternative in the gdImage[something]Ptr functions. */ +BGD_DECLARE(gdIOCtx *) gdNewDynamicCtxEx (int size, void *data, int freeFlag); +BGD_DECLARE(gdIOCtx *) gdNewSSCtx (gdSourcePtr in, gdSinkPtr out); +BGD_DECLARE(void *) gdDPExtractData (struct gdIOCtx *ctx, int *size); + +#define GD2_CHUNKSIZE 128 +#define GD2_CHUNKSIZE_MIN 64 +#define GD2_CHUNKSIZE_MAX 4096 + +#define GD2_VERS 2 +#define GD2_ID "gd2" + +#define GD2_FMT_RAW 1 +#define GD2_FMT_COMPRESSED 2 + +/* Image comparison definitions */ +BGD_DECLARE(int) gdImageCompare (gdImagePtr im1, gdImagePtr im2); + +#define GD_CMP_IMAGE 1 /* Actual image IS different */ +#define GD_CMP_NUM_COLORS 2 /* Number of Colours in pallette differ */ +#define GD_CMP_COLOR 4 /* Image colours differ */ +#define GD_CMP_SIZE_X 8 /* Image width differs */ +#define GD_CMP_SIZE_Y 16 /* Image heights differ */ +#define GD_CMP_TRANSPARENT 32 /* Transparent colour */ +#define GD_CMP_BACKGROUND 64 /* Background colour */ +#define GD_CMP_INTERLACE 128 /* Interlaced setting */ +#define GD_CMP_TRUECOLOR 256 /* Truecolor vs palette differs */ + +#define GD_RESOLUTION 96 /* dots per inch */ + +#ifdef __cplusplus +} +#endif + +/* newfangled special effects */ +#include "gdfx.h" + +#endif /* GD_H */ + +#ifdef __cplusplus +} +#endif diff --git a/plugins/snes9x_gx/portlibs/include/gd_io.h b/plugins/snes9x_gx/portlibs/include/gd_io.h new file mode 100644 index 00000000..0f4aefac --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/gd_io.h @@ -0,0 +1,52 @@ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef GD_IO_H +#define GD_IO_H 1 + +#include <stdio.h> + +#ifdef VMS +# define Putchar gdPutchar +#endif + +typedef struct gdIOCtx +{ + int (*getC)(struct gdIOCtx *); + int (*getBuf)(struct gdIOCtx *, void *, int); + void (*putC)(struct gdIOCtx *, int); + int (*putBuf)(struct gdIOCtx *, const void *, int); + /* seek must return 1 on SUCCESS, 0 on FAILURE. Unlike fseek! */ + int (*seek)(struct gdIOCtx *, const int); + long (*tell)(struct gdIOCtx *); + void (*gd_free)(struct gdIOCtx *); +} +gdIOCtx; + +typedef struct gdIOCtx *gdIOCtxPtr; + +void Putword(int w, gdIOCtx *ctx); +void Putchar(int c, gdIOCtx *ctx); + +void gdPutC(const unsigned char c, gdIOCtx *ctx); +int gdPutBuf(const void *, int, gdIOCtx *); +void gdPutWord(int w, gdIOCtx *ctx); +void gdPutInt(int w, gdIOCtx *ctx); + +int gdGetC(gdIOCtx *ctx); +int gdGetBuf(void *, int, gdIOCtx *); +int gdGetByte(int *result, gdIOCtx *ctx); +int gdGetWord(int *result, gdIOCtx *ctx); +int gdGetWordLSB(signed short int *result, gdIOCtx *ctx); +int gdGetInt(int *result, gdIOCtx *ctx); +int gdGetIntLSB(signed int *result, gdIOCtx *ctx); + +int gdSeek(gdIOCtx *ctx, const int offset); +long gdTell(gdIOCtx *ctx); + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/plugins/snes9x_gx/portlibs/include/gdfx.h b/plugins/snes9x_gx/portlibs/include/gdfx.h new file mode 100644 index 00000000..8b5aa273 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/gdfx.h @@ -0,0 +1,73 @@ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef GDFX_H +#define GDFX_H 1 + +#include "gd.h" + +/* im MUST be square, but can have any size. Returns a new image + of width and height radius * 2, in which the X axis of + the original has been remapped to theta (angle) and the Y axis + of the original has been remapped to rho (distance from center). + This is known as a "polar coordinate transform." */ + + BGD_DECLARE(gdImagePtr) gdImageSquareToCircle(gdImagePtr im, int radius); + +/* Draws the text 'top' and 'bottom' on 'im', curved along the + edge of a circle of radius 'radius', with its + center at 'cx' and 'cy'. 'top' is written clockwise + along the top; 'bottom' is written counterclockwise + along the bottom. 'textRadius' determines the 'height' + of each character; if 'textRadius' is 1/2 of 'radius', + characters extend halfway from the edge to the center. + 'fillPortion' varies from 0 to 1.0, with useful values + from about 0.4 to 0.9, and determines how much of the + 180 degrees of arc assigned to each section of text + is actually occupied by text; 0.9 looks better than + 1.0 which is rather crowded. 'font' is a freetype + font; see gdImageStringFT. 'points' is passed to the + freetype engine and has an effect on hinting; although + the size of the text is determined by radius, textRadius, + and fillPortion, you should pass a point size that + 'hints' appropriately -- if you know the text will be + large, pass a large point size such as 24.0 to get the + best results. 'fgcolor' can be any color, and may have + an alpha component, do blending, etc. + + Returns 0 on success, or an error string. */ + +BGD_DECLARE(char *) gdImageStringFTCircle( + gdImagePtr im, + int cx, + int cy, + double radius, + double textRadius, + double fillPortion, + char *font, + double points, + char *top, + char *bottom, + int fgcolor); + + /* 2.0.16: + * Sharpen function added on 2003-11-19 + * by Paul Troughton (paul<dot>troughton<at>ieee<dot>org) + * Simple 3x3 convolution kernel + * Makes use of seperability + * Faster, but less flexible, than full-blown unsharp masking + * pct is sharpening percentage, and can be greater than 100 + * Silently does nothing to non-truecolor images + * Silently does nothing for pct<0, as not a useful blurring function + * Leaves transparency/alpha-channel untouched + */ + + BGD_DECLARE(void) gdImageSharpen (gdImagePtr im, int pct); + +#endif /* GDFX_H */ + + +#ifdef __cplusplus +} +#endif diff --git a/plugins/snes9x_gx/portlibs/include/jconfig.h b/plugins/snes9x_gx/portlibs/include/jconfig.h new file mode 100644 index 00000000..ebb280c6 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/jconfig.h @@ -0,0 +1,44 @@ +/* jconfig.h. Generated automatically by configure. */ +/* jconfig.cfg --- source file edited by configure script */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +#undef void +#undef const +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#define NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS /* DJGPP uses flat 32-bit addressing */ +#undef NEED_SHORT_EXTERNAL_NAMES +/* Define this if you get warnings about undefined structures. */ +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED +#define INLINE __inline__ +/* These are for configuring the JPEG memory manager. */ +#undef DEFAULT_MAX_MEM +#undef NO_MKTEMP + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#undef TWO_FILE_COMMANDLINE /* optional */ +#undef USE_SETMODE /* Needed to make one-file style work in DJGPP */ +#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */ +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/plugins/snes9x_gx/portlibs/include/jerror.h b/plugins/snes9x_gx/portlibs/include/jerror.h new file mode 100644 index 00000000..1cfb2b19 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/jerror.h @@ -0,0 +1,304 @@ +/* + * jerror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported") +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT6(cinfo,code,p1,p2,p3,p4,p5,p6) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (cinfo)->err->msg_parm.i[4] = (p5), \ + (cinfo)->err->msg_parm.i[5] = (p6), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/plugins/snes9x_gx/portlibs/include/jmorecfg.h b/plugins/snes9x_gx/portlibs/include/jmorecfg.h new file mode 100644 index 00000000..6c085c36 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/jmorecfg.h @@ -0,0 +1,369 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2011 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ +#ifndef _BASETSD_H /* MinGW is slightly different */ +#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ +typedef long INT32; +#endif +#endif +#endif +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#ifndef FAR +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/plugins/snes9x_gx/portlibs/include/jpeglib.h b/plugins/snes9x_gx/portlibs/include/jpeglib.h new file mode 100644 index 00000000..1327cffa --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/jpeglib.h @@ -0,0 +1,1160 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2002-2011 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +extern "C" { +#endif +#endif + +/* Version IDs for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 80". + */ + +#define JPEG_LIB_VERSION 80 /* Compatibility version 8.0 */ +#define JPEG_LIB_VERSION_MAJOR 8 +#define JPEG_LIB_VERSION_MINOR 4 + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 coefficients */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples, + * reflecting any scaling we choose to apply during the DCT step. + * Values from 1 to 16 are supported. + * Note that different components may receive different DCT scalings. + */ + int DCT_h_scaled_size; + int DCT_v_scaled_size; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface); + * DCT scaling is included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_h_scaled_size/DCTSIZE) + * and similarly for height. + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples: MCU_width * DCT_h_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK /* Y/Cb/Cr/K */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + JDIMENSION jpeg_width; /* scaled JPEG image width */ + JDIMENSION jpeg_height; /* scaled JPEG image height */ + /* Dimensions of actual JPEG image that will be written to file, + * derived from input dimensions by scaling factors above. + * These fields are computed by jpeg_start_compress(). + * You can also use jpeg_calc_jpeg_dimensions() to determine these values + * in advance of calling jpeg_start_compress(). + */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + int q_scale_factor[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined, + * and corresponding scale factors (percentage, initialized 100). + */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_coef_controller * coef; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_v_scaled_size sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* These fields are derived from Se of first SOS marker. + */ + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array for entropy decode */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_coef_controller * coef; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(void, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_error jStdError +#define jpeg_CreateCompress jCreaCompress +#define jpeg_CreateDecompress jCreaDecompress +#define jpeg_destroy_compress jDestCompress +#define jpeg_destroy_decompress jDestDecompress +#define jpeg_stdio_dest jStdDest +#define jpeg_stdio_src jStdSrc +#define jpeg_mem_dest jMemDest +#define jpeg_mem_src jMemSrc +#define jpeg_set_defaults jSetDefaults +#define jpeg_set_colorspace jSetColorspace +#define jpeg_default_colorspace jDefColorspace +#define jpeg_set_quality jSetQuality +#define jpeg_set_linear_quality jSetLQuality +#define jpeg_default_qtables jDefQTables +#define jpeg_add_quant_table jAddQuantTable +#define jpeg_quality_scaling jQualityScaling +#define jpeg_simple_progression jSimProgress +#define jpeg_suppress_tables jSuppressTables +#define jpeg_alloc_quant_table jAlcQTable +#define jpeg_alloc_huff_table jAlcHTable +#define jpeg_start_compress jStrtCompress +#define jpeg_write_scanlines jWrtScanlines +#define jpeg_finish_compress jFinCompress +#define jpeg_calc_jpeg_dimensions jCjpegDimensions +#define jpeg_write_raw_data jWrtRawData +#define jpeg_write_marker jWrtMarker +#define jpeg_write_m_header jWrtMHeader +#define jpeg_write_m_byte jWrtMByte +#define jpeg_write_tables jWrtTables +#define jpeg_read_header jReadHeader +#define jpeg_start_decompress jStrtDecompress +#define jpeg_read_scanlines jReadScanlines +#define jpeg_finish_decompress jFinDecompress +#define jpeg_read_raw_data jReadRawData +#define jpeg_has_multiple_scans jHasMultScn +#define jpeg_start_output jStrtOutput +#define jpeg_finish_output jFinOutput +#define jpeg_input_complete jInComplete +#define jpeg_new_colormap jNewCMap +#define jpeg_consume_input jConsumeInput +#define jpeg_core_output_dimensions jCoreDimensions +#define jpeg_calc_output_dimensions jCalcDimensions +#define jpeg_save_markers jSaveMarkers +#define jpeg_set_marker_processor jSetMarker +#define jpeg_read_coefficients jReadCoefs +#define jpeg_write_coefficients jWrtCoefs +#define jpeg_copy_critical_parameters jCopyCrit +#define jpeg_abort_compress jAbrtCompress +#define jpeg_abort_decompress jAbrtDecompress +#define jpeg_abort jAbort +#define jpeg_destroy jDestroy +#define jpeg_resync_to_restart jResyncRestart +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Data source and destination managers: memory buffers. */ +EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, + unsigned char ** outbuffer, + unsigned long * outsize)); +EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, + unsigned char * inbuffer, + unsigned long insize)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Precalculate JPEG dimensions for current compression parameters. */ +EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.txt concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_core_output_dimensions JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +} +#endif +#endif + +#endif /* JPEGLIB_H */ diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/archive.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/archive.hpp new file mode 100644 index 00000000..fa1bf359 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/archive.hpp @@ -0,0 +1,126 @@ +#ifndef _RAR_ARCHIVE_ +#define _RAR_ARCHIVE_ + +class Pack; + +enum {EN_LOCK=1,EN_VOL=2,EN_FIRSTVOL=4}; + +class Archive:public File +{ + private: + bool IsSignature(byte *D); + void UpdateLatestTime(FileHeader *CurBlock); + void ConvertNameCase(char *Name); + void ConvertNameCase(wchar *Name); + void ConvertUnknownHeader(); + size_t ReadOldHeader(); + void UnexpEndArcMsg(); + +#if !defined(SHELL_EXT) && !defined(NOCRYPT) + CryptData HeadersCrypt; + byte HeadersSalt[SALT_SIZE]; +#endif +#ifndef SHELL_EXT + ComprDataIO SubDataIO; + byte SubDataSalt[SALT_SIZE]; +#endif + RAROptions *Cmd,DummyCmd; + + MarkHeader MarkHead; + OldMainHeader OldMhd; + + int RecoverySectors; + int64 RecoveryPos; + + RarTime LatestTime; + int LastReadBlock; + int CurHeaderType; + + bool SilentOpen; + public: + Archive(RAROptions *InitCmd=NULL); + bool IsArchive(bool EnableBroken); + size_t SearchBlock(int BlockType); + size_t SearchSubBlock(const char *Type); + int ReadBlock(int BlockType); + void WriteBlock(int BlockType,BaseBlock *wb=NULL); + int PrepareNamesToWrite(char *Name,wchar *NameW,char *DestName,byte *DestNameW); + void SetLhdSize(); + size_t ReadHeader(); + void CheckArc(bool EnableBroken); + void CheckOpen(char *Name,wchar *NameW=NULL); + bool WCheckOpen(char *Name,wchar *NameW=NULL); + bool TestLock(int Mode); + void MakeTemp(); + void CopyMainHeader(Archive &Src,bool CopySFX=true,char *NameToDisplay=NULL); + bool ProcessToFileHead(Archive &Src,bool LastBlockAdded, + Pack *Pack=NULL,const char *SkipName=NULL); + void TmpToArc(Archive &Src); + void CloseNew(int AdjustRecovery,bool CloseVolume); + void WriteEndBlock(bool CloseVolume); + void CopyFileRecord(Archive &Src); + void CopyArchiveData(Archive &Src); + bool GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW); + void ViewComment(); + void ViewFileComment(); + void SetLatestTime(RarTime *NewTime); + void SeekToNext(); + bool CheckAccess(); + bool IsArcDir(); + bool IsArcLabel(); + void ConvertAttributes(); + int GetRecoverySize(bool Required); + void VolSubtractHeaderSize(size_t SubSize); + void AddSubData(byte *SrcData,size_t DataSize,File *SrcFile,const char *Name,bool AllowSplit); + bool ReadSubData(Array<byte> *UnpData,File *DestFile); + int GetHeaderType() {return(CurHeaderType);}; + size_t ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW); + void WriteCommentData(byte *Data,size_t DataSize,bool FileComment); + RAROptions* GetRAROptions() {return(Cmd);} + void SetSilentOpen(bool Mode) {SilentOpen=Mode;} + + BaseBlock ShortBlock; + MainHeader NewMhd; + FileHeader NewLhd; + EndArcHeader EndArcHead; + SubBlockHeader SubBlockHead; + FileHeader SubHead; + CommentHeader CommHead; + ProtectHeader ProtectHead; + AVHeader AVHead; + SignHeader SignHead; + UnixOwnersHeader UOHead; + MacFInfoHeader MACHead; + EAHeader EAHead; + StreamHeader StreamHead; + + int64 CurBlockPos; + int64 NextBlockPos; + + bool OldFormat; + bool Solid; + bool Volume; + bool MainComment; + bool Locked; + bool Signed; + bool NotFirstVolume; + bool Protected; + bool Encrypted; + size_t SFXSize; + bool BrokenFileHeader; + + bool Splitting; + + ushort HeaderCRC; + + int64 VolWrite; + int64 AddingFilesSize; + size_t AddingHeadersSize; + + bool NewArchive; + + char FirstVolumeName[NM]; + wchar FirstVolumeNameW[NM]; +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/array.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/array.hpp new file mode 100644 index 00000000..c67817a3 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/array.hpp @@ -0,0 +1,122 @@ +#ifndef _RAR_ARRAY_ +#define _RAR_ARRAY_ + +extern ErrorHandler ErrHandler; + +template <class T> class Array +{ + private: + T *Buffer; + size_t BufSize; + size_t AllocSize; + public: + Array(); + Array(size_t Size); + ~Array(); + inline void CleanData(); + inline T& operator [](size_t Item); + inline size_t Size(); + void Add(size_t Items); + void Alloc(size_t Items); + void Reset(); + void operator = (Array<T> &Src); + void Push(T Item); + T* Addr() {return(Buffer);} +}; + +template <class T> void Array<T>::CleanData() +{ + Buffer=NULL; + BufSize=0; + AllocSize=0; +} + + +template <class T> Array<T>::Array() +{ + CleanData(); +} + + +template <class T> Array<T>::Array(size_t Size) +{ + Buffer=(T *)rarmalloc(sizeof(T)*Size); + if (Buffer==NULL && Size!=0) + ErrHandler.MemoryError(); + + AllocSize=BufSize=Size; +} + + +template <class T> Array<T>::~Array() +{ + if (Buffer!=NULL) + rarfree(Buffer); +} + + +template <class T> inline T& Array<T>::operator [](size_t Item) +{ + return(Buffer[Item]); +} + + +template <class T> inline size_t Array<T>::Size() +{ + return(BufSize); +} + + +template <class T> void Array<T>::Add(size_t Items) +{ + BufSize+=Items; + if (BufSize>AllocSize) + { + size_t Suggested=AllocSize+AllocSize/4+32; + size_t NewSize=Max(BufSize,Suggested); + + Buffer=(T *)rarrealloc(Buffer,NewSize*sizeof(T)); + if (Buffer==NULL) + ErrHandler.MemoryError(); + AllocSize=NewSize; + } +} + + +template <class T> void Array<T>::Alloc(size_t Items) +{ + if (Items>AllocSize) + Add(Items-BufSize); + else + BufSize=Items; +} + + +template <class T> void Array<T>::Reset() +{ + if (Buffer!=NULL) + { + rarfree(Buffer); + Buffer=NULL; + } + BufSize=0; + AllocSize=0; +} + + +template <class T> void Array<T>::operator =(Array<T> &Src) +{ + Reset(); + Alloc(Src.BufSize); + if (Src.BufSize!=0) + memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T)); +} + + +template <class T> void Array<T>::Push(T Item) +{ + Add(1); + (*this)[Size()-1]=Item; +} + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/cmddata.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/cmddata.hpp new file mode 100644 index 00000000..8219c52f --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/cmddata.hpp @@ -0,0 +1,57 @@ +#ifndef _RAR_CMDDATA_ +#define _RAR_CMDDATA_ + +#define DefaultStoreList "7z;ace;arj;bz2;cab;gz;jpeg;jpg;lha;lzh;mp3;rar;taz;tgz;z;zip" + +class CommandData:public RAROptions +{ + private: + void ProcessSwitchesString(char *Str); + void ProcessSwitch(char *Switch,wchar *SwitchW=NULL); + void BadSwitch(char *Switch); + bool ExclCheckArgs(StringList *Args,char *CheckName,bool CheckFullPath,int MatchMode); + uint GetExclAttr(char *Str); + + bool FileLists; + bool NoMoreSwitches; + bool BareOutput; + public: + CommandData(); + ~CommandData(); + void Init(); + void Close(); + void ParseArg(char *Arg,wchar *ArgW); + void ParseDone(); + void ParseEnvVar(); + void ReadConfig(int argc,char *argv[]); + bool IsConfigEnabled(int argc,char *argv[]); + void OutTitle(); + void OutHelp(); + bool IsSwitch(int Ch); + bool ExclCheck(char *CheckName,bool CheckFullPath,bool CheckInclList); + bool StoreCheck(char *CheckName); + bool TimeCheck(RarTime &ft); + bool SizeCheck(int64 Size); + bool AnyFiltersActive(); + int IsProcessFile(FileHeader &NewLhd,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH); + void ProcessCommand(); + void AddArcName(char *Name,wchar *NameW); + bool GetArcName(char *Name,wchar *NameW,int MaxSize); + bool CheckWinSize(); + + int GetRecoverySize(char *Str,int DefSize); + + char Command[NM+16]; + wchar CommandW[NM+16]; + + char ArcName[NM]; + wchar ArcNameW[NM]; + + StringList *FileArgs; + StringList *ExclArgs; + StringList *InclArgs; + StringList *ArcNames; + StringList *StoreArgs; +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/coder.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/coder.hpp new file mode 100644 index 00000000..f09f911c --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/coder.hpp @@ -0,0 +1,24 @@ +/**************************************************************************** + * Contents: 'Carryless rangecoder' by Dmitry Subbotin * + ****************************************************************************/ + +const uint TOP=1 << 24, BOT=1 << 15; + +class RangeCoder +{ + public: + void InitDecoder(Unpack *UnpackRead); + inline int GetCurrentCount(); + inline uint GetCurrentShiftCount(uint SHIFT); + inline void Decode(); + inline void PutChar(unsigned int c); + inline unsigned int GetChar(); + + uint low, code, range; + struct SUBRANGE + { + uint LowCount, HighCount, scale; + } SubRange; + + Unpack *UnpackRead; +}; diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/compress.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/compress.hpp new file mode 100644 index 00000000..3181e45d --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/compress.hpp @@ -0,0 +1,36 @@ +#ifndef _RAR_COMPRESS_ +#define _RAR_COMPRESS_ + +class ComprDataIO; +class PackingFileTable; + +#define CODEBUFSIZE 0x4000 +#define MAXWINSIZE 0x400000 +#define MAXWINMASK (MAXWINSIZE-1) + +#define LOW_DIST_REP_COUNT 16 + +#define NC 299 /* alphabet = {0, 1, 2, ..., NC - 1} */ +#define DC 60 +#define LDC 17 +#define RC 28 +#define HUFF_TABLE_SIZE (NC+DC+RC+LDC) +#define BC 20 + +#define NC20 298 /* alphabet = {0, 1, 2, ..., NC - 1} */ +#define DC20 48 +#define RC20 28 +#define BC20 19 +#define MC20 257 + +enum {CODE_HUFFMAN,CODE_LZ,CODE_LZ2,CODE_REPEATLZ,CODE_CACHELZ, + CODE_STARTFILE,CODE_ENDFILE,CODE_VM,CODE_VMDATA}; + + +enum FilterType { + FILTER_NONE, FILTER_PPM /*dummy*/, FILTER_E8, FILTER_E8E9, + FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA, + FILTER_ITANIUM, FILTER_E8E9V2 +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/consio.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/consio.hpp new file mode 100644 index 00000000..74433d0c --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/consio.hpp @@ -0,0 +1,46 @@ +#ifndef _RAR_CONSIO_ +#define _RAR_CONSIO_ + +#if !defined(SILENT) && !defined(SFX_MODULE) +enum {SOUND_OK,SOUND_ALARM,SOUND_ERROR,SOUND_QUESTION}; +#endif + +enum PASSWORD_TYPE {PASSWORD_GLOBAL,PASSWORD_FILE,PASSWORD_ARCHIVE}; + +void InitConsoleOptions(MESSAGE_TYPE MsgStream,bool Sound); + +#ifndef SILENT +void mprintf(const char *fmt,...); +void eprintf(const char *fmt,...); +void Alarm(); +void GetPasswordText(char *Str,int MaxLength); +bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength); +int Ask(const char *AskStr); +#endif + +void OutComment(char *Comment,size_t Size); + +#ifdef SILENT +#ifdef __GNUC__ + #define mprintf(args...) + #define eprintf(args...) +#else + #ifdef _MSC_VER + inline void mprintf(const char *fmt,...) {} + #else + inline void mprintf(const char *fmt,const char *a=NULL,const char *b=NULL) {} + #endif + inline void eprintf(const char *fmt,const char *a=NULL,const char *b=NULL) {} + inline void mprintf(const char *fmt,int b) {} + inline void eprintf(const char *fmt,int b) {} + inline void mprintf(const char *fmt,const char *a,int b) {} + inline void eprintf(const char *fmt,const char *a,int b) {} +#endif +inline void Alarm() {} +inline void GetPasswordText(char *Str,int MaxLength) {} +inline unsigned int GetKey() {return(0);} +inline bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength) {return(false);} +inline int Ask(const char *AskStr) {return(0);} +#endif + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/crc.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/crc.hpp new file mode 100644 index 00000000..a632a541 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/crc.hpp @@ -0,0 +1,10 @@ +#ifndef _RAR_CRC_ +#define _RAR_CRC_ + +extern uint CRCTab[256]; + +void InitCRC(); +uint CRC(uint StartCRC,const void *Addr,size_t Size); +ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/crypt.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/crypt.hpp new file mode 100644 index 00000000..b16e650c --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/crypt.hpp @@ -0,0 +1,62 @@ +#ifndef _RAR_CRYPT_ +#define _RAR_CRYPT_ + +enum { OLD_DECODE=0,OLD_ENCODE=1,NEW_CRYPT=2 }; + + +struct CryptKeyCacheItem +{ +#ifndef _SFX_RTL_ + CryptKeyCacheItem() + { + *Password=0; + } + + ~CryptKeyCacheItem() + { + memset(AESKey,0,sizeof(AESKey)); + memset(AESInit,0,sizeof(AESInit)); + memset(Password,0,sizeof(Password)); + } +#endif + byte AESKey[16],AESInit[16]; + char Password[MAXPASSWORD]; + bool SaltPresent; + byte Salt[SALT_SIZE]; + bool HandsOffHash; +}; + +class CryptData +{ + private: + void Encode13(byte *Data,uint Count); + void Decode13(byte *Data,uint Count); + void Crypt15(byte *Data,uint Count); + void UpdKeys(byte *Buf); + void Swap(byte *Ch1,byte *Ch2); + void SetOldKeys(const char *Password); + + Rijndael rin; + + byte SubstTable[256]; + uint Key[4]; + ushort OldKey[4]; + byte PN1,PN2,PN3; + + byte AESKey[16],AESInit[16]; + + static CryptKeyCacheItem Cache[4]; + static int CachePos; + public: + void SetCryptKeys(const char *Password,const byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash); + void SetAV15Encryption(); + void SetCmt13Encryption(); + void EncryptBlock20(byte *Buf); + void DecryptBlock20(byte *Buf); + void EncryptBlock(byte *Buf,size_t Size); + void DecryptBlock(byte *Buf,size_t Size); + void Crypt(byte *Data,uint Count,int Method); + static void SetSalt(byte *Salt,int SaltSize); +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/dll.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/dll.hpp new file mode 100644 index 00000000..4582f2c6 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/dll.hpp @@ -0,0 +1,140 @@ +#ifndef _UNRAR_DLL_ +#define _UNRAR_DLL_ + +#define ERAR_END_ARCHIVE 10 +#define ERAR_NO_MEMORY 11 +#define ERAR_BAD_DATA 12 +#define ERAR_BAD_ARCHIVE 13 +#define ERAR_UNKNOWN_FORMAT 14 +#define ERAR_EOPEN 15 +#define ERAR_ECREATE 16 +#define ERAR_ECLOSE 17 +#define ERAR_EREAD 18 +#define ERAR_EWRITE 19 +#define ERAR_SMALL_BUF 20 +#define ERAR_UNKNOWN 21 +#define ERAR_MISSING_PASSWORD 22 + +#define RAR_OM_LIST 0 +#define RAR_OM_EXTRACT 1 +#define RAR_OM_LIST_INCSPLIT 2 + +#define RAR_SKIP 0 +#define RAR_TEST 1 +#define RAR_EXTRACT 2 + +#define RAR_VOL_ASK 0 +#define RAR_VOL_NOTIFY 1 + +#define RAR_DLL_VERSION 4 + +#ifdef _UNIX +#define CALLBACK +#define PASCAL +#define LONG long +#define HANDLE void * +#define LPARAM long +#define UINT unsigned int +#endif + +struct RARHeaderData +{ + char ArcName[260]; + char FileName[260]; + unsigned int Flags; + unsigned int PackSize; + unsigned int UnpSize; + unsigned int HostOS; + unsigned int FileCRC; + unsigned int FileTime; + unsigned int UnpVer; + unsigned int Method; + unsigned int FileAttr; + char *CmtBuf; + unsigned int CmtBufSize; + unsigned int CmtSize; + unsigned int CmtState; +}; + + +struct RARHeaderDataEx +{ + char ArcName[1024]; + wchar_t ArcNameW[1024]; + char FileName[1024]; + wchar_t FileNameW[1024]; + unsigned int Flags; + unsigned int PackSize; + unsigned int PackSizeHigh; + unsigned int UnpSize; + unsigned int UnpSizeHigh; + unsigned int HostOS; + unsigned int FileCRC; + unsigned int FileTime; + unsigned int UnpVer; + unsigned int Method; + unsigned int FileAttr; + char *CmtBuf; + unsigned int CmtBufSize; + unsigned int CmtSize; + unsigned int CmtState; + unsigned int Reserved[1024]; +}; + + +struct RAROpenArchiveData +{ + char *ArcName; + unsigned int OpenMode; + unsigned int OpenResult; + char *CmtBuf; + unsigned int CmtBufSize; + unsigned int CmtSize; + unsigned int CmtState; +}; + +struct RAROpenArchiveDataEx +{ + char *ArcName; + wchar_t *ArcNameW; + unsigned int OpenMode; + unsigned int OpenResult; + char *CmtBuf; + unsigned int CmtBufSize; + unsigned int CmtSize; + unsigned int CmtState; + unsigned int Flags; + unsigned int Reserved[32]; +}; + +enum UNRARCALLBACK_MESSAGES { + UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD +}; + +typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2); + +typedef int (PASCAL *CHANGEVOLPROC)(char *ArcName,int Mode); +typedef int (PASCAL *PROCESSDATAPROC)(unsigned char *Addr,int Size); + +#ifdef __cplusplus +extern "C" { +#endif + +HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *ArchiveData); +HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *ArchiveData); +int PASCAL RARCloseArchive(HANDLE hArcData); +int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *HeaderData); +int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *HeaderData); +int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName); +int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar_t *DestPath,wchar_t *DestName); +void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData); +void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc); +void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc); +void PASCAL RARSetPassword(HANDLE hArcData,char *Password); +int PASCAL RARGetDllVersion(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/encname.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/encname.hpp new file mode 100644 index 00000000..3e7786f5 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/encname.hpp @@ -0,0 +1,20 @@ +#ifndef _RAR_ENCNAME_ +#define _RAR_ENCNAME_ + +class EncodeFileName +{ + private: + void AddFlags(int Value); + + byte *EncName; + byte Flags; + uint FlagBits; + size_t FlagsPos; + size_t DestSize; + public: + EncodeFileName(); + size_t Encode(char *Name,wchar *NameW,byte *EncName); + void Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW,size_t MaxDecSize); +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/errhnd.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/errhnd.hpp new file mode 100644 index 00000000..28e9843f --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/errhnd.hpp @@ -0,0 +1,63 @@ +#ifndef _RAR_ERRHANDLER_ +#define _RAR_ERRHANDLER_ + +#if (defined(GUI) || !defined(_WIN_32)) && !defined(SFX_MODULE) && !defined(_WIN_CE) || defined(RARDLL) +#define ALLOW_EXCEPTIONS +#endif + + + +#define rarmalloc malloc +#define rarcalloc calloc +#define rarrealloc realloc +#define rarfree free +#define rarstrdup strdup +#define rarstrdupw strdupw + + + +enum { SUCCESS,WARNING,FATAL_ERROR,CRC_ERROR,LOCK_ERROR,WRITE_ERROR, + OPEN_ERROR,USER_ERROR,MEMORY_ERROR,CREATE_ERROR,USER_BREAK=255}; + +class ErrorHandler +{ + private: + void ErrMsg(const char *ArcName,const char *fmt,...); + + int ExitCode; + int ErrCount; + bool EnableBreak; + bool Silent; + bool DoShutdown; + public: + ErrorHandler(); + void Clean(); + void MemoryError(); + void OpenError(const char *FileName); + void CloseError(const char *FileName); + void ReadError(const char *FileName); + bool AskRepeatRead(const char *FileName); + void WriteError(const char *ArcName,const char *FileName); + void WriteErrorFAT(const char *FileName); + bool AskRepeatWrite(const char *FileName,bool DiskFull); + void SeekError(const char *FileName); + void GeneralErrMsg(const char *Msg); + void MemoryErrorMsg(); + void OpenErrorMsg(const char *FileName); + void OpenErrorMsg(const char *ArcName,const char *FileName); + void CreateErrorMsg(const char *FileName); + void CreateErrorMsg(const char *ArcName,const char *FileName); + void ReadErrorMsg(const char *ArcName,const char *FileName); + void WriteErrorMsg(const char *ArcName,const char *FileName); + void Exit(int ExitCode); + void SetErrorCode(int Code); + int GetErrorCode() {return(ExitCode);} + int GetErrorCount() {return(ErrCount);} + void SetSignalHandlers(bool Enable); + void Throw(int Code); + void SetSilent(bool Mode) {Silent=Mode;}; + void SetShutdown(bool Mode) {DoShutdown=Mode;}; + void SysErrMsg(); +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/extinfo.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/extinfo.hpp new file mode 100644 index 00000000..db7cea53 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/extinfo.hpp @@ -0,0 +1,8 @@ +#ifndef _RAR_EXTINFO_ +#define _RAR_EXTINFO_ + + +void SetExtraInfo(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW); +void SetExtraInfoNew(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/extract.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/extract.hpp new file mode 100644 index 00000000..40f9cc0a --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/extract.hpp @@ -0,0 +1,43 @@ +#ifndef _RAR_EXTRACT_ +#define _RAR_EXTRACT_ + +enum EXTRACT_ARC_CODE {EXTRACT_ARC_NEXT,EXTRACT_ARC_REPEAT}; + +class CmdExtract +{ + private: + EXTRACT_ARC_CODE ExtractArchive(CommandData *Cmd); + RarTime StartTime; // time when extraction started + + ComprDataIO DataIO; + Unpack *Unp; + unsigned long TotalFileCount; + + unsigned long FileCount; + unsigned long MatchedArgs; + bool FirstFile; + bool AllMatchesExact; + bool ReconstructDone; + + char ArcName[NM]; + wchar ArcNameW[NM]; + + char Password[MAXPASSWORD]; + bool PasswordAll; + bool PrevExtracted; + char DestFileName[NM]; + wchar DestFileNameW[NM]; + bool PasswordCancelled; + public: + CmdExtract(); + ~CmdExtract(); + void DoExtract(CommandData *Cmd); + void ExtractArchiveInit(CommandData *Cmd,Archive &Arc); + bool ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderSize, + bool &Repeat); + static void UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize); + + bool SignatureFound; +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/filcreat.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/filcreat.hpp new file mode 100644 index 00000000..5c8e8f54 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/filcreat.hpp @@ -0,0 +1,13 @@ +#ifndef _RAR_FILECREATE_ +#define _RAR_FILECREATE_ + +bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW, + OVERWRITE_MODE Mode,bool *UserReject,int64 FileSize=INT64NDF, + uint FileTime=0); +bool GetAutoRenamedName(char *Name); + +#if defined(_WIN_32) && !defined(_WIN_CE) +bool UpdateExistingShortName(char *Name,wchar *NameW); +#endif + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/file.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/file.hpp new file mode 100644 index 00000000..3e17ae99 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/file.hpp @@ -0,0 +1,98 @@ +#ifndef _RAR_FILE_ +#define _RAR_FILE_ + +#ifdef _WIN_32 +typedef HANDLE FileHandle; +#define BAD_HANDLE INVALID_HANDLE_VALUE +#else +typedef FILE* FileHandle; +#define BAD_HANDLE NULL +#endif + +class RAROptions; + +enum FILE_HANDLETYPE {FILE_HANDLENORMAL,FILE_HANDLESTD,FILE_HANDLEERR}; + +enum FILE_ERRORTYPE {FILE_SUCCESS,FILE_NOTFOUND,FILE_READERROR}; + +struct FileStat +{ + uint FileAttr; + uint FileTime; + int64 FileSize; + bool IsDir; +}; + + +class File +{ + private: + void AddFileToList(FileHandle hFile); + + FileHandle hFile; + bool LastWrite; + FILE_HANDLETYPE HandleType; + bool SkipClose; + bool IgnoreReadErrors; + bool NewFile; + bool AllowDelete; + bool AllowExceptions; +#ifdef _WIN_32 + bool NoSequentialRead; +#endif + protected: + bool OpenShared; + public: + char FileName[NM]; + wchar FileNameW[NM]; + + FILE_ERRORTYPE ErrorType; + + uint CloseCount; + public: + File(); + virtual ~File(); + void operator = (File &SrcFile); + bool Open(const char *Name,const wchar *NameW=NULL,bool OpenShared=false,bool Update=false); + void TOpen(const char *Name,const wchar *NameW=NULL); + bool WOpen(const char *Name,const wchar *NameW=NULL); + bool Create(const char *Name,const wchar *NameW=NULL,bool ShareRead=true); + void TCreate(const char *Name,const wchar *NameW=NULL,bool ShareRead=true); + bool WCreate(const char *Name,const wchar *NameW=NULL,bool ShareRead=true); + bool Close(); + void Flush(); + bool Delete(); + bool Rename(const char *NewName,const wchar *NewNameW=NULL); + void Write(const void *Data,size_t Size); + int Read(void *Data,size_t Size); + int DirectRead(void *Data,size_t Size); + void Seek(int64 Offset,int Method); + bool RawSeek(int64 Offset,int Method); + int64 Tell(); + void Prealloc(int64 Size); + byte GetByte(); + void PutByte(byte Byte); + bool Truncate(); + void SetOpenFileTime(RarTime *ftm,RarTime *ftc=NULL,RarTime *fta=NULL); + void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL); + static void SetCloseFileTimeByName(const char *Name,RarTime *ftm,RarTime *fta); + void GetOpenFileTime(RarTime *ft); + bool IsOpened() {return(hFile!=BAD_HANDLE);}; + int64 FileLength(); + void SetHandleType(FILE_HANDLETYPE Type); + FILE_HANDLETYPE GetHandleType() {return(HandleType);}; + bool IsDevice(); + void fprintf(const char *fmt,...); + static bool RemoveCreated(); + FileHandle GetHandle() {return(hFile);}; + void SetIgnoreReadErrors(bool Mode) {IgnoreReadErrors=Mode;}; + char *GetName() {return(FileName);} + int64 Copy(File &Dest,int64 Length=INT64NDF); + void SetAllowDelete(bool Allow) {AllowDelete=Allow;} + void SetExceptions(bool Allow) {AllowExceptions=Allow;} +#ifdef _WIN_32 + void RemoveSequentialFlag() {NoSequentialRead=true;} +#endif +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/filefn.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/filefn.hpp new file mode 100644 index 00000000..77df8479 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/filefn.hpp @@ -0,0 +1,44 @@ +#ifndef _RAR_FILEFN_ +#define _RAR_FILEFN_ + +enum MKDIR_CODE {MKDIR_SUCCESS,MKDIR_ERROR,MKDIR_BADPATH}; + +MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,bool SetAttr,uint Attr); +bool CreatePath(const char *Path,const wchar *PathW,bool SkipLastName); +void SetDirTime(const char *Name,const wchar *NameW,RarTime *ftm,RarTime *ftc,RarTime *fta); +bool IsRemovable(const char *Name); +int64 GetFreeDisk(const char *Name); +bool FileExist(const char *Name,const wchar *NameW=NULL); +bool WildFileExist(const char *Name,const wchar *NameW=NULL); +bool IsDir(uint Attr); +bool IsUnreadable(uint Attr); +bool IsLabel(uint Attr); +bool IsLink(uint Attr); +void SetSFXMode(const char *FileName); +void EraseDiskContents(const char *FileName); +bool IsDeleteAllowed(uint FileAttr); +void PrepareToDelete(const char *Name,const wchar *NameW=NULL); +uint GetFileAttr(const char *Name,const wchar *NameW=NULL); +bool SetFileAttr(const char *Name,const wchar *NameW,uint Attr); +void ConvertNameToFull(const char *Src,char *Dest); +void ConvertNameToFull(const wchar *Src,wchar *Dest); +char* MkTemp(char *Name); + + +enum CALCCRC_SHOWMODE {CALCCRC_SHOWNONE,CALCCRC_SHOWTEXT,CALCCRC_SHOWALL}; +uint CalcFileCRC(File *SrcFile,int64 Size=INT64NDF,CALCCRC_SHOWMODE ShowMode=CALCCRC_SHOWNONE); + +bool RenameFile(const char *SrcName,const wchar *SrcNameW,const char *DestName,const wchar *DestNameW); +bool DelFile(const char *Name); +bool DelFile(const char *Name,const wchar *NameW); +bool DelDir(const char *Name); +bool DelDir(const char *Name,const wchar *NameW); + +#if defined(_WIN_32) && !defined(_WIN_CE) +bool SetFileCompression(char *Name,wchar *NameW,bool State); +#endif + + + + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/filestr.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/filestr.hpp new file mode 100644 index 00000000..5b2b15db --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/filestr.hpp @@ -0,0 +1,9 @@ +#ifndef _RAR_FILESTR_ +#define _RAR_FILESTR_ + +bool ReadTextFile(const char *Name,StringList *List,bool Config, + bool AbortOnError=false,RAR_CHARSET SrcCharset=RCH_DEFAULT, + bool Unquote=false,bool SkipComments=false, + bool ExpandEnvStr=false); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/find.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/find.hpp new file mode 100644 index 00000000..99e804a7 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/find.hpp @@ -0,0 +1,53 @@ +#ifndef _RAR_FINDDATA_ +#define _RAR_FINDDATA_ + +enum FINDDATA_FLAGS { + FDDF_SECONDDIR=1 // Second encounter of same directory in SCAN_GETDIRSTWICE ScanTree mode +}; + +struct FindData +{ + char Name[NM]; + wchar NameW[NM]; + int64 Size; + uint FileAttr; + uint FileTime; + bool IsDir; + RarTime mtime; + RarTime ctime; + RarTime atime; +#ifdef _WIN_32 + char ShortName[NM]; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; +#endif + uint Flags; + bool Error; +}; + +class FindFile +{ + private: +#ifdef _WIN_32 + static HANDLE Win32Find(HANDLE hFind,const char *Mask,const wchar *MaskW,struct FindData *fd); +#endif + + char FindMask[NM]; + wchar FindMaskW[NM]; + bool FirstCall; +#ifdef _WIN_32 + HANDLE hFind; +#else + DIR *dirp; +#endif + public: + FindFile(); + ~FindFile(); + void SetMask(const char *FindMask); + void SetMaskW(const wchar *FindMaskW); + bool Next(struct FindData *fd,bool GetSymLink=false); + static bool FastFind(const char *FindMask,const wchar *FindMaskW,struct FindData *fd,bool GetSymLink=false); +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/getbits.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/getbits.hpp new file mode 100644 index 00000000..d44fb9f0 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/getbits.hpp @@ -0,0 +1,51 @@ +#ifndef _RAR_GETBITS_ +#define _RAR_GETBITS_ + +class BitInput +{ + public: + enum BufferSize {MAX_SIZE=0x8000}; // Size of input buffer. + protected: + int InAddr; // Curent byte position in the buffer. + int InBit; // Current bit position in the current byte. + public: + BitInput(); + ~BitInput(); + + byte *InBuf; // Dynamically allocated input buffer. + + void InitBitInput() + { + InAddr=InBit=0; + } + + // Move forward by 'Bits' bits. + void addbits(uint Bits) + { + Bits+=InBit; + InAddr+=Bits>>3; + InBit=Bits&7; + } + + // Return 16 bits from current position in the buffer. + // Bit at (InAddr,InBit) has the highest position in returning data. + uint getbits() + { + uint BitField=(uint)InBuf[InAddr] << 16; + BitField|=(uint)InBuf[InAddr+1] << 8; + BitField|=(uint)InBuf[InAddr+2]; + BitField >>= (8-InBit); + return(BitField & 0xffff); + } + + void faddbits(uint Bits); + uint fgetbits(); + + // Check if buffer has enough space for IncPtr bytes. Returns 'true' + // if buffer will be overflown. + bool Overflow(uint IncPtr) + { + return(InAddr+IncPtr>=MAX_SIZE); + } +}; +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/global.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/global.hpp new file mode 100644 index 00000000..35c6cf91 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/global.hpp @@ -0,0 +1,14 @@ +#ifndef _RAR_GLOBAL_ +#define _RAR_GLOBAL_ + +#ifdef INCLUDEGLOBAL + #define EXTVAR +#else + #define EXTVAR extern +#endif + +EXTVAR ErrorHandler ErrHandler; + + + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/headers.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/headers.hpp new file mode 100644 index 00000000..9e632f4f --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/headers.hpp @@ -0,0 +1,308 @@ +#ifndef _RAR_HEADERS_ +#define _RAR_HEADERS_ + +#define SIZEOF_MARKHEAD 7 +#define SIZEOF_OLDMHD 7 +#define SIZEOF_NEWMHD 13 +#define SIZEOF_OLDLHD 21 +#define SIZEOF_NEWLHD 32 +#define SIZEOF_SHORTBLOCKHEAD 7 +#define SIZEOF_LONGBLOCKHEAD 11 +#define SIZEOF_SUBBLOCKHEAD 14 +#define SIZEOF_COMMHEAD 13 +#define SIZEOF_PROTECTHEAD 26 +#define SIZEOF_AVHEAD 14 +#define SIZEOF_SIGNHEAD 15 +#define SIZEOF_UOHEAD 18 +#define SIZEOF_MACHEAD 22 +#define SIZEOF_EAHEAD 24 +#define SIZEOF_BEEAHEAD 24 +#define SIZEOF_STREAMHEAD 26 + +#define PACK_VER 29 +#define PACK_CRYPT_VER 29 +#define UNP_VER 36 +#define CRYPT_VER 29 +#define AV_VER 20 +#define PROTECT_VER 20 + +#define MHD_VOLUME 0x0001U +#define MHD_COMMENT 0x0002U +#define MHD_LOCK 0x0004U +#define MHD_SOLID 0x0008U +#define MHD_PACK_COMMENT 0x0010U +#define MHD_NEWNUMBERING 0x0010U +#define MHD_AV 0x0020U +#define MHD_PROTECT 0x0040U +#define MHD_PASSWORD 0x0080U +#define MHD_FIRSTVOLUME 0x0100U +#define MHD_ENCRYPTVER 0x0200U + +#define LHD_SPLIT_BEFORE 0x0001U +#define LHD_SPLIT_AFTER 0x0002U +#define LHD_PASSWORD 0x0004U +#define LHD_COMMENT 0x0008U +#define LHD_SOLID 0x0010U + +#define LHD_WINDOWMASK 0x00e0U +#define LHD_WINDOW64 0x0000U +#define LHD_WINDOW128 0x0020U +#define LHD_WINDOW256 0x0040U +#define LHD_WINDOW512 0x0060U +#define LHD_WINDOW1024 0x0080U +#define LHD_WINDOW2048 0x00a0U +#define LHD_WINDOW4096 0x00c0U +#define LHD_DIRECTORY 0x00e0U + +#define LHD_LARGE 0x0100U +#define LHD_UNICODE 0x0200U +#define LHD_SALT 0x0400U +#define LHD_VERSION 0x0800U +#define LHD_EXTTIME 0x1000U +#define LHD_EXTFLAGS 0x2000U + +#define SKIP_IF_UNKNOWN 0x4000U +#define LONG_BLOCK 0x8000U + +#define EARC_NEXT_VOLUME 0x0001U // not last volume +#define EARC_DATACRC 0x0002U // store CRC32 of RAR archive (now used only in volumes) +#define EARC_REVSPACE 0x0004U // reserve space for end of REV file 7 byte record +#define EARC_VOLNUMBER 0x0008U // store a number of current volume + +enum HEADER_TYPE { + MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74,COMM_HEAD=0x75,AV_HEAD=0x76, + SUB_HEAD=0x77,PROTECT_HEAD=0x78,SIGN_HEAD=0x79,NEWSUB_HEAD=0x7a, + ENDARC_HEAD=0x7b +}; + +enum { EA_HEAD=0x100,UO_HEAD=0x101,MAC_HEAD=0x102,BEEA_HEAD=0x103, + NTACL_HEAD=0x104,STREAM_HEAD=0x105 }; + +enum HOST_SYSTEM { + HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4, + HOST_BEOS=5,HOST_MAX +}; + +#define SUBHEAD_TYPE_CMT "CMT" +#define SUBHEAD_TYPE_ACL "ACL" +#define SUBHEAD_TYPE_STREAM "STM" +#define SUBHEAD_TYPE_UOWNER "UOW" +#define SUBHEAD_TYPE_AV "AV" +#define SUBHEAD_TYPE_RR "RR" +#define SUBHEAD_TYPE_OS2EA "EA2" +#define SUBHEAD_TYPE_BEOSEA "EABE" + +/* new file inherits a subblock when updating a host file */ +#define SUBHEAD_FLAGS_INHERITED 0x80000000 + +#define SUBHEAD_FLAGS_CMT_UNICODE 0x00000001 + +struct OldMainHeader +{ + byte Mark[4]; + ushort HeadSize; + byte Flags; +}; + + +struct OldFileHeader +{ + uint PackSize; + uint UnpSize; + ushort FileCRC; + ushort HeadSize; + uint FileTime; + byte FileAttr; + byte Flags; + byte UnpVer; + byte NameSize; + byte Method; +}; + + +struct MarkHeader +{ + byte Mark[7]; +}; + + +struct BaseBlock +{ + ushort HeadCRC; + HEADER_TYPE HeadType;//byte + ushort Flags; + ushort HeadSize; + + bool IsSubBlock() + { + if (HeadType==SUB_HEAD) + return(true); + if (HeadType==NEWSUB_HEAD && (Flags & LHD_SOLID)!=0) + return(true); + return(false); + } +}; + +struct BlockHeader:BaseBlock +{ + union { + uint DataSize; + uint PackSize; + }; +}; + + +struct MainHeader:BaseBlock +{ + ushort HighPosAV; + uint PosAV; + byte EncryptVer; +}; + + +#define SALT_SIZE 8 + +struct FileHeader:BlockHeader +{ + uint UnpSize; + byte HostOS; + uint FileCRC; + uint FileTime; + byte UnpVer; + byte Method; + ushort NameSize; + union { + uint FileAttr; + uint SubFlags; + }; +/* optional */ + uint HighPackSize; + uint HighUnpSize; +/* names */ + char FileName[NM]; + wchar FileNameW[NM]; +/* optional */ + Array<byte> SubData; + byte Salt[SALT_SIZE]; + + RarTime mtime; + RarTime ctime; + RarTime atime; + RarTime arctime; +/* dummy */ + int64 FullPackSize; + int64 FullUnpSize; + + void Clear(size_t SubDataSize) + { + SubData.Alloc(SubDataSize); + Flags=LONG_BLOCK; + SubFlags=0; + } + + bool CmpName(const char *Name) + { + return(strcmp(FileName,Name)==0); + } + + FileHeader& operator = (FileHeader &hd) + { + SubData.Reset(); + memcpy(this,&hd,sizeof(*this)); + SubData.CleanData(); + SubData=hd.SubData; + return(*this); + } +}; + + +struct EndArcHeader:BaseBlock +{ + uint ArcDataCRC; // optional archive CRC32 + ushort VolNumber; // optional current volume number +}; + + +// SubBlockHeader and its successors were used in RAR 2.x format. +// RAR 3.x uses FileHeader with NEWSUB_HEAD HeadType for subblocks. +struct SubBlockHeader:BlockHeader +{ + ushort SubType; + byte Level; +}; + + +struct CommentHeader:BaseBlock +{ + ushort UnpSize; + byte UnpVer; + byte Method; + ushort CommCRC; +}; + + +struct ProtectHeader:BlockHeader +{ + byte Version; + ushort RecSectors; + uint TotalBlocks; + byte Mark[8]; +}; + + +struct AVHeader:BaseBlock +{ + byte UnpVer; + byte Method; + byte AVVer; + uint AVInfoCRC; +}; + + +struct SignHeader:BaseBlock +{ + uint CreationTime; + ushort ArcNameSize; + ushort UserNameSize; +}; + + +struct UnixOwnersHeader:SubBlockHeader +{ + ushort OwnerNameSize; + ushort GroupNameSize; +/* dummy */ + char OwnerName[NM]; + char GroupName[NM]; +}; + + +struct EAHeader:SubBlockHeader +{ + uint UnpSize; + byte UnpVer; + byte Method; + uint EACRC; +}; + + +struct StreamHeader:SubBlockHeader +{ + uint UnpSize; + byte UnpVer; + byte Method; + uint StreamCRC; + ushort StreamNameSize; +/* dummy */ + byte StreamName[NM]; +}; + + +struct MacFInfoHeader:SubBlockHeader +{ + uint fileType; + uint fileCreator; +}; + + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/isnt.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/isnt.hpp new file mode 100644 index 00000000..02652361 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/isnt.hpp @@ -0,0 +1,6 @@ +#ifndef _RAR_ISNT_ +#define _RAR_ISNT_ + +int WinNT(); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/list.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/list.hpp new file mode 100644 index 00000000..7721ae52 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/list.hpp @@ -0,0 +1,6 @@ +#ifndef _RAR_LIST_ +#define _RAR_LIST_ + +void ListArchive(CommandData *Cmd); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/loclang.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/loclang.hpp new file mode 100644 index 00000000..86352049 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/loclang.hpp @@ -0,0 +1,354 @@ +#define MYesNo "_Yes_No" +#define MYesNoAll "_Yes_No_All" +#define MYesNoAllQ "_Yes_No_All_nEver_Quit" +#define MYesNoAllRenQ "_Yes_No_All_nEver_Rename_Quit" +#define MContinueQuit "_Continue_Quit" +#define MRetryAbort "_Retry_Abort" +#define MCopyright "\nRAR %s Copyright (c) 1993-%d Alexander Roshal %d %s %d" +#define MRegTo "\nRegistered to %s\n" +#define MShare "\nShareware version Type RAR -? for help\n" +#define MUCopyright "\nUNRAR %s freeware Copyright (c) 1993-%d Alexander Roshal\n" +#define MBeta "beta" +#define MMonthJan "Jan" +#define MMonthFeb "Feb" +#define MMonthMar "Mar" +#define MMonthApr "Apr" +#define MMonthMay "May" +#define MMonthJun "Jun" +#define MMonthJul "Jul" +#define MMonthAug "Aug" +#define MMonthSep "Sep" +#define MMonthOct "Oct" +#define MMonthNov "Nov" +#define MMonthDec "Dec" +#define MRARTitle1 "\nUsage: rar <command> -<switch 1> -<switch N> <archive> <files...>" +#define MUNRARTitle1 "\nUsage: unrar <command> -<switch 1> -<switch N> <archive> <files...>" +#define MRARTitle2 "\n <@listfiles...> <path_to_extract\\>" +#define MCHelpCmd "\n\n<Commands>" +#define MCHelpCmdA "\n a Add files to archive" +#define MCHelpCmdC "\n c Add archive comment" +#define MCHelpCmdCF "\n cf Add files comment" +#define MCHelpCmdCH "\n ch Change archive parameters" +#define MCHelpCmdCW "\n cw Write archive comment to file" +#define MCHelpCmdD "\n d Delete files from archive" +#define MCHelpCmdE "\n e Extract files to current directory" +#define MCHelpCmdF "\n f Freshen files in archive" +#define MCHelpCmdI "\n i[par]=<str> Find string in archives" +#define MCHelpCmdK "\n k Lock archive" +#define MCHelpCmdL "\n l[t,b] List archive [technical, bare]" +#define MCHelpCmdM "\n m[f] Move to archive [files only]" +#define MCHelpCmdP "\n p Print file to stdout" +#define MCHelpCmdR "\n r Repair archive" +#define MCHelpCmdRC "\n rc Reconstruct missing volumes" +#define MCHelpCmdRN "\n rn Rename archived files" +#define MCHelpCmdRR "\n rr[N] Add data recovery record" +#define MCHelpCmdRV "\n rv[N] Create recovery volumes" +#define MCHelpCmdS "\n s[name|-] Convert archive to or from SFX" +#define MCHelpCmdT "\n t Test archive files" +#define MCHelpCmdU "\n u Update files in archive" +#define MCHelpCmdV "\n v[t,b] Verbosely list archive [technical,bare]" +#define MCHelpCmdX "\n x Extract files with full path" +#define MCHelpSw "\n\n<Switches>" +#define MCHelpSwm "\n - Stop switches scanning" +#define MCHelpSwAC "\n ac Clear Archive attribute after compression or extraction" +#define MCHelpSwAD "\n ad Append archive name to destination path" +#define MCHelpSwAG "\n ag[format] Generate archive name using the current date" +#define MCHelpSwAI "\n ai Ignore file attributes" +#define MCHelpSwAO "\n ao Add files with Archive attribute set" +#define MCHelpSwAP "\n ap<path> Set path inside archive" +#define MCHelpSwAS "\n as Synchronize archive contents" +#define MCHelpSwAV "\n av Put authenticity verification (registered versions only)" +#define MCHelpSwAVm "\n av- Disable authenticity verification check" +#define MCHelpSwCm "\n c- Disable comments show" +#define MCHelpSwCFGm "\n cfg- Disable read configuration" +#define MCHelpSwCL "\n cl Convert names to lower case" +#define MCHelpSwCU "\n cu Convert names to upper case" +#define MCHelpSwDF "\n df Delete files after archiving" +#define MCHelpSwDH "\n dh Open shared files" +#define MCHelpSwDR "\n dr Delete files to Recycle Bin" +#define MCHelpSwDS "\n ds Disable name sort for solid archive" +#define MCHelpSwDW "\n dw Wipe files after archiving" +#define MCHelpSwEa "\n e[+]<attr> Set file exclude and include attributes" +#define MCHelpSwED "\n ed Do not add empty directories" +#define MCHelpSwEE "\n ee Do not save and extract extended attributes" +#define MCHelpSwEN "\n en Do not put 'end of archive' block" +#define MCHelpSwEP "\n ep Exclude paths from names" +#define MCHelpSwEP1 "\n ep1 Exclude base directory from names" +#define MCHelpSwEP2 "\n ep2 Expand paths to full" +#define MCHelpSwEP3 "\n ep3 Expand paths to full including the drive letter" +#define MCHelpSwF "\n f Freshen files" +#define MCHelpSwHP "\n hp[password] Encrypt both file data and headers" +#define MCHelpSwIDP "\n id[c,d,p,q] Disable messages" +#define MCHelpSwIEML "\n ieml[addr] Send archive by email" +#define MCHelpSwIERR "\n ierr Send all messages to stderr" +#define MCHelpSwILOG "\n ilog[name] Log errors to file (registered versions only)" +#define MCHelpSwINUL "\n inul Disable all messages" +#define MCHelpSwIOFF "\n ioff Turn PC off after completing an operation" +#define MCHelpSwISND "\n isnd Enable sound" +#define MCHelpSwK "\n k Lock archive" +#define MCHelpSwKB "\n kb Keep broken extracted files" +#define MCHelpSwMn "\n m<0..5> Set compression level (0-store...3-default...5-maximal)" +#define MCHelpSwMC "\n mc<par> Set advanced compression parameters" +#define MCHelpSwMD "\n md<size> Dictionary size in KB (64,128,256,512,1024,2048,4096 or A-G)" +#define MCHelpSwMS "\n ms[ext;ext] Specify file types to store" +#define MCHelpSwMT "\n mt<threads> Set the number of threads" +#define MCHelpSwN "\n n<file> Include only specified file" +#define MCHelpSwNa "\n n@ Read file names to include from stdin" +#define MCHelpSwNal "\n n@<list> Include files listed in specified list file" +#define MCHelpSwO "\n o[+|-] Set the overwrite mode" +#define MCHelpSwOC "\n oc Set NTFS Compressed attribute" +#define MCHelpSwOL "\n ol Save symbolic links as the link instead of the file" +#define MCHelpSwOR "\n or Rename files automatically" +#define MCHelpSwOS "\n os Save NTFS streams" +#define MCHelpSwOW "\n ow Save or restore file owner and group" +#define MCHelpSwP "\n p[password] Set password" +#define MCHelpSwPm "\n p- Do not query password" +#define MCHelpSwR "\n r Recurse subdirectories" +#define MCHelpSwRm "\n r- Disable recursion" +#define MCHelpSwR0 "\n r0 Recurse subdirectories for wildcard names only" +#define MCHelpSwRI "\n ri<P>[:<S>] Set priority (0-default,1-min..15-max) and sleep time in ms" +#define MCHelpSwRR "\n rr[N] Add data recovery record" +#define MCHelpSwRV "\n rv[N] Create recovery volumes" +#define MCHelpSwS "\n s[<N>,v[-],e] Create solid archive" +#define MCHelpSwSm "\n s- Disable solid archiving" +#define MCHelpSwSC "\n sc<chr>[obj] Specify the character set" +#define MCHelpSwSFX "\n sfx[name] Create SFX archive" +#define MCHelpSwSI "\n si[name] Read data from standard input (stdin)" +#define MCHelpSwSL "\n sl<size> Process files with size less than specified" +#define MCHelpSwSM "\n sm<size> Process files with size more than specified" +#define MCHelpSwT "\n t Test files after archiving" +#define MCHelpSwTK "\n tk Keep original archive time" +#define MCHelpSwTL "\n tl Set archive time to latest file" +#define MCHelpSwTN "\n tn<time> Process files newer than <time>" +#define MCHelpSwTO "\n to<time> Process files older than <time>" +#define MCHelpSwTA "\n ta<date> Process files modified after <date> in YYYYMMDDHHMMSS format" +#define MCHelpSwTB "\n tb<date> Process files modified before <date> in YYYYMMDDHHMMSS format" +#define MCHelpSwTS "\n ts<m,c,a>[N] Save or restore file time (modification, creation, access)" +#define MCHelpSwU "\n u Update files" +#define MCHelpSwV "\n v Create volumes with size autodetection or list all volumes" +#define MCHelpSwVUnr "\n v List all volumes" +#define MCHelpSwVn "\n v<size>[k,b] Create volumes with size=<size>*1000 [*1024, *1]" +#define MCHelpSwVD "\n vd Erase disk contents before creating volume" +#define MCHelpSwVER "\n ver[n] File version control" +#define MCHelpSwVN "\n vn Use the old style volume naming scheme" +#define MCHelpSwVP "\n vp Pause before each volume" +#define MCHelpSwW "\n w<path> Assign work directory" +#define MCHelpSwX "\n x<file> Exclude specified file" +#define MCHelpSwXa "\n x@ Read file names to exclude from stdin" +#define MCHelpSwXal "\n x@<list> Exclude files listed in specified list file" +#define MCHelpSwY "\n y Assume Yes on all queries" +#define MCHelpSwZ "\n z[file] Read archive comment from file" +#define MBadArc "\nERROR: Bad archive %s\n" +#define MAskPsw "Enter password (will not be echoed)" +#define MAskPswEcho "Enter password" +#define MReAskPsw "\nReenter password: " +#define MFor " for " +#define MNotMatchPsw "\nERROR: Passwords do not match\n" +#define MErrWrite "Write error in the file %s" +#define MErrRead "Read error in the file %s" +#define MErrSeek "Seek error in the file %s" +#define MErrFClose "Cannot close the file %s" +#define MErrOutMem "Not enough memory" +#define MErrBrokenArc "Corrupt archive - use 'Repair' command" +#define MProgAborted "Program aborted" +#define MErrRename "\nCannot rename %s to %s" +#define MAbsNextVol "\nCannot find volume %s" +#define MBreak "\nUser break\n" +#define MAskCreatVol "\nCreate next volume ?" +#define MAskNextDisk "\nDisk full. Insert next" +#define MCreatVol "\n\nCreating %sarchive %s\n" +#define MAskNextVol "\nInsert disk with %s" +#define MTestVol "\n\nTesting archive %s\n" +#define MExtrVol "\n\nExtracting from %s\n" +#define MConverting "\nConverting %s" +#define MCvtToSFX "\nConvert archives to SFX" +#define MCvtFromSFX "\nRemoving SFX module" +#define MNotSFX "\n%s is not SFX archive" +#define MNotRAR "\n%s is not RAR archive" +#define MNotFirstVol "\n%s is not the first volume" +#define MCvtOldFormat "\n%s - cannot convert to SFX archive with old format" +#define MCannotCreate "\nCannot create %s" +#define MCannotOpen "\nCannot open %s" +#define MUnknownMeth "\nUnknown method in %s" +#define MVerRequired "\nYou need RAR %d.%d to unpack it" +#define MOk " OK" +#define MDone "\nDone" +#define MLockingArc "\nLocking archive" +#define MNotMdfOld "\n\nERROR: Cannot modify old format archive" +#define MNotMdfLock "\n\nERROR: Locked archive" +#define MNotMdfVol "\n\nERROR: Cannot modify volume" +#define MVerifyAV "\nVerifying authenticity information ... " +#define MFailedAV " Failed\n" +#define MStrAV1 "\n\nArchive %s" +#define MStrAV2 "\ncreated at %s" +#define MStrAV3 "\nby %s\n" +#define MLogFailedAV "Invalid authenticity information" +#define MAddingAV "\nAdding authenticity verification " +#define MAVOldStyle "\n\nOld style authenticity information" +#define MPackAskReg "\nEvaluation copy. Please register.\n" +#define MCreateArchive "\nCreating %sarchive %s\n" +#define MUpdateArchive "\nUpdating %sarchive %s\n" +#define MAddSolid "solid " +#define MAddFile "\nAdding %-58s " +#define MUpdFile "\nUpdating %-58s " +#define MAddPoints "\n... %-58s " +#define MCannotUpdPswSolid "\nERROR: Cannot update solid archives with password\n" +#define MMoveDelFiles "\n\nDeleting files %s..." +#define MMoveDelDirs "and directories" +#define MMoveDelFile "\nDeleting %-30s" +#define MMoveDeleted " deleted" +#define MMoveNotDeleted " NOT DELETED" +#define MClearAttrib "\n\nClearing attributes..." +#define MMoveDelDir "\nDeleting directory %-30s" +#define MWarErrFOpen "\nWARNING: Cannot open %d %s" +#define MErrOpenFiles "files" +#define MErrOpenFile "file" +#define MAddNoFiles "\nWARNING: No files" +#define MMdfEncrSol "\n%s: encrypted" +#define MCannotMdfEncrSol "\nCannot modify solid archive containing encrypted files" +#define MAddAnalyze "\nAnalyzing archived files: " +#define MRepacking "\nRepacking archived files: " +#define MCRCFailed "\n%-20s - CRC failed" +#define MExtrTest "\n\nTesting archive %s\n" +#define MExtracting "\n\nExtracting from %s\n" +#define MUseCurPsw "\n%s - use current password ?" +#define MCreatDir "\nCreating %-56s" +#define MExtrSkipFile "\nSkipping %-56s" +#define MExtrTestFile "\nTesting %-56s" +#define MExtrFile "\nExtracting %-56s" +#define MExtrPoints "\n... %-56s" +#define MExtrErrMkDir "\nCannot create directory %s" +#define MExtrPrinting "\n------ Printing %s\n\n" +#define MEncrBadCRC "\nEncrypted file: CRC failed in %s (password incorrect ?)" +#define MExtrNoFiles "\nNo files to extract" +#define MExtrAllOk "\nAll OK" +#define MExtrTotalErr "\nTotal errors: %ld" +#define MFileExists "\n\n%s already exists. Overwrite it ?" +#define MAskOverwrite "\nOverwrite %s ?" +#define MAskNewName "\nEnter new name: " +#define MLogMainHead "\nThe archive header is corrupt" +#define MLogFileHead "\n%s - the file header is corrupt" +#define MLogCommHead "\nThe comment header is corrupt\n" +#define MLogProtectHead "The data recovery header is corrupt" +#define MReadStdinCmt "\nReading comment from stdin\n" +#define MReadCommFrom "\nReading comment from %s" +#define MDelComment "\nDeleting comment from %s" +#define MAddComment "\nAdding comment to %s" +#define MFCommAdd "\nAdding file comments" +#define MAskFComm "\n\nReading comment for %s : %s from stdin\n" +#define MLogCommBrk "\nThe archive comment is corrupt" +#define MCommAskCont "\nPress 'Enter' to continue or 'Q' to quit:" +#define MLogBrokFCmt "\nThe file comment is corrupt" +#define MWriteCommTo "\nWrite comment to %s" +#define MCommNotPres "\nComment is not present" +#define MDelFrom "\nDeleting from %s" +#define MDeleting "\nDeleting %s" +#define MEraseArc "\nErasing empty archive %s" +#define MNoDelFiles "\nNo files to delete" +#define MLogTitle "\n\n-------- %2d %s %d, archive %s\n" +#define MPathTooLong "\nERROR: Path too long\n" +#define MListSolid "Solid " +#define MListSFX "SFX " +#define MListVol1 "volume" +#define MListVol2 "Volume" +#define MListArc1 "archive" +#define MListArc2 "Archive" +#define MListRecRec "\nRecovery record is present\n" +#define MListLock "\nLock is present\n" +#define MListPathComm "\nPathname/Comment\n " +#define MListName "\n Name " +#define MListTitle " Size Packed Ratio Date Time Attr CRC Meth Ver\n" +#define MListTechTitle " Host OS Solid Old\n" +#define MListEAHead "\n OS/2 extended attributes" +#define MListUOHead "\n Unix Owner/Group data: %-14s %-14s" +#define MListBeEAHead "\n BeOS extended attributes" +#define MListNTACLHead "\n NTFS security data" +#define MListStrmHead "\n NTFS stream: %s" +#define MListUnkHead "\n Unknown subheader type: 0x%04x" +#define MFileComment "\nComment: " +#define MYes "Yes" +#define MNo "No" +#define MListNoFiles " 0 files\n" +#define MRprReconstr "\nReconstructing %s" +#define MRprBuild "\nBuilding %s" +#define MRprOldFormat "\nCannot repair archive with old format" +#define MRprFind "\nFound %s" +#define MRprAskIsSol "\nThe archive header is corrupt. Mark archive as solid ?" +#define MRprNoFiles "\nNo files found" +#define MRprSuspEntry "\n\nSuspicious entry %s" +#define MRprDir "\nDirectory" +#define MRprSuspSize "\nSize %ld Packed %ld" +#define MRprSuspAdd "\nAdd it to archive ?" +#define MLogUnexpEOF "\nUnexpected end of archive" +#define MRepAskReconst "\nReconstruct archive structure ?" +#define MRecScanning "\nScanning..." +#define MRecRNotFound "\nData recovery record not found" +#define MRecRFound "\nData recovery record found" +#define MRecSecDamage "\nSector %ld (offsets %lX...%lX) damaged" +#define MRecCorrected " - data recovered" +#define MRecFailed " - cannot recover data" +#define MAddRecRec "\nAdding data recovery record" +#define MEraseForVolume "\n\nErasing contents of drive %c:\n" +#define MGetOwnersError "\nWARNING: Cannot get %s owner and group\n" +#define MErrGetOwnerID "\nWARNING: Cannot get owner %s ID\n" +#define MErrGetGroupID "\nWARNING: Cannot get group %s ID\n" +#define MOwnersBroken "\nERROR: %s group and owner data are corrupt\n" +#define MSetOwnersError "\nWARNING: Cannot set %s owner and group\n" +#define MErrLnkRead "\nWARNING: Cannot read symbolic link %s" +#define MErrCreateLnk "\nWARNING: Cannot create link %s" +#define MSymLinkExists "\nWARNING: Symbolic link %s already exists" +#define MAskRetryCreate "\nCannot create %s. Retry ?" +#define MListMACHead1 "\n MacOS file type: %c%c%c%c ; " +#define MListMACHead2 "file creator: %c%c%c%c\n" +#define MDataBadCRC "\n%-20s : packed data CRC failed in volume %s" +#define MFileRO "\n%s is read-only" +#define MACLGetError "\nWARNING: Cannot get %s security data\n" +#define MACLSetError "\nWARNING: Cannot set %s security data\n" +#define MACLBroken "\nERROR: %s security data are corrupt\n" +#define MACLUnknown "\nWARNING: Unknown format of %s security data\n" +#define MStreamBroken "\nERROR: %s stream data are corrupt\n" +#define MStreamUnknown "\nWARNING: Unknown format of %s stream data\n" +#define MInvalidName "\nERROR: Invalid file name %s" +#define MEABroken "\nERROR: %s extended attributes are corrupt\n" +#define MEAUnknHeader "\nWARNING: %s - unknown format of extended attributes\n" +#define MCannotSetEA "\nWARNING: cannot set extended attributes to %s\n" +#define MCannotGetEA "\nERROR: Cannot get extended attributes of %s\n" +#define MShowEA " (+EA)" +#define MSkipEA "\n...skipping extended attributes" +#define MProcessArc "\n\nProcessing archive %s" +#define MSyncScanError "\nFile search errors, cannot synchronize archive" +#define MCorrectingName "\nWARNING: Attempting to correct the invalid file name" +#define MUnpCannotMerge "\nWARNING: You need to start extraction from a previous volume to unpack %s" +#define MUnknownOption "\nERROR: Unknown option: %s" +#define MSubHeadCorrupt "\nERROR: Corrupt data header found, ignored" +#define MSubHeadUnknown "\nWARNING: Unknown data header format, ignored" +#define MSubHeadDataCRC "\nERROR: Corrupt %s data block" +#define MSubHeadType "\nData header type: %s" +#define MScanError "\nCannot read contents of %s" +#define MNotVolume "\n%s is not volume" +#define MRecVolDiffSets "\nERROR: %s and %s belong to different sets" +#define MRecVolMissing "\n%d volumes missing" +#define MRecVolFound "\n%d recovery volumes found" +#define MRecVolAllExist "\nNothing to reconstruct" +#define MRecVolCannotFix "\nReconstruction impossible" +#define MReconstructing "\nReconstructing..." +#define MCreating "\nCreating %s" +#define MRenaming "\nRenaming %s to %s" +#define MNTFSRequired "\nWrite error: only NTFS file system supports files larger than 4 GB" +#define MErrChangeAttr "\nWARNING: Cannot change attributes of %s" +#define MWrongSFXVer "\nERROR: default SFX module does not support RAR %d.%d archives" +#define MCannotEncName "\nCannot encrypt archive already contained encrypted files" +#define MCannotEmail "\nCannot email the file %s" +#define MCopyrightS "\nRAR SFX archive" +#define MSHelpCmd "\n\n<Commands>" +#define MSHelpCmdE "\n -x Extract from archive (default)" +#define MSHelpCmdT "\n -t Test archive files" +#define MSHelpCmdV "\n -v Verbosely list contents of archive" +#define MMaxPathLimit "\nTotal path and file name length must not exceed %d characters" +#define MRecVolLimit "\nTotal number of usual and recovery volumes must not exceed 255" +#define MVolumeNumber "volume %d" +#define MCannotDelete "\nCannot delete %s" +#define MCalcCRC "\nCalculating the control sum" +#define MTooLargeSFXArc "\nWARNING: Too large SFX archive. Windows cannot run the executable file exceeding 4 GB." +#define MCalcCRCAllVol "\nCalculating control sums of all volumes." +#define MNotEnoughDisk "\nERROR: Not enough disk space for %s." diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/log.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/log.hpp new file mode 100644 index 00000000..52d6b8d5 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/log.hpp @@ -0,0 +1,18 @@ +#ifndef _RAR_LOG_ +#define _RAR_LOG_ + +void InitLogOptions(char *LogName); + +#ifndef SILENT +void Log(const char *ArcName,const char *Format,...); +#endif + +#ifdef SILENT +#ifdef __GNUC__ +#define Log(args...) +#else +inline void Log(const char *a,const char *b,const char *c=NULL,const char *d=NULL) {} +#endif +#endif + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/match.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/match.hpp new file mode 100644 index 00000000..0e43514f --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/match.hpp @@ -0,0 +1,27 @@ +#ifndef _RAR_MATCH_ +#define _RAR_MATCH_ + +enum { + MATCH_NAMES, // Compare names only. + + MATCH_PATH, // Compares names and paths. Both must match exactly. + // Unlike MATCH_EXACTPATH, also matches names if + // mask contains path only and this path is a part + // of name path. + + MATCH_EXACTPATH, // Compares names and paths. Both must match exactly. + + MATCH_SUBPATH, // Names must be the same, but path in mask is allowed + // to be only a part of name path. + + MATCH_WILDSUBPATH // Works as MATCH_SUBPATH if mask contains wildcards + // and as MATCH_PATH otherwise. +}; + +#define MATCH_MODEMASK 0x0000ffff +#define MATCH_FORCECASESENSITIVE 0x80000000 + +bool CmpName(char *Wildcard,char *Name,int CmpPath); +bool CmpName(wchar *Wildcard,wchar *Name,int CmpPath); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/model.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/model.hpp new file mode 100644 index 00000000..5b4fa4f4 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/model.hpp @@ -0,0 +1,132 @@ +#ifndef _RAR_PPMMODEL_ +#define _RAR_PPMMODEL_ + +#include "coder.hpp" +#include "suballoc.hpp" + +const int MAX_O=64; /* maximum allowed model order */ + +const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS, + INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124; + +#ifndef STRICT_ALIGNMENT_REQUIRED +#pragma pack(1) +#endif + +struct SEE2_CONTEXT +{ // SEE-contexts for PPM-contexts with masked symbols + ushort Summ; + byte Shift, Count; + void init(int InitVal) + { + Summ=InitVal << (Shift=PERIOD_BITS-4); + Count=4; + } + uint getMean() + { + uint RetVal=SHORT16(Summ) >> Shift; + Summ -= RetVal; + return RetVal+(RetVal == 0); + } + void update() + { + if (Shift < PERIOD_BITS && --Count == 0) + { + Summ += Summ; + Count=3 << Shift++; + } + } +}; + + +class ModelPPM; +struct PPM_CONTEXT; + +struct STATE +{ + byte Symbol; + byte Freq; + PPM_CONTEXT* Successor; +}; + +struct FreqData +{ + ushort SummFreq; + STATE _PACK_ATTR * Stats; +}; + +struct PPM_CONTEXT +{ + ushort NumStats; + union + { + FreqData U; + STATE OneState; + }; + + PPM_CONTEXT* Suffix; + inline void encodeBinSymbol(ModelPPM *Model,int symbol); // MaxOrder: + inline void encodeSymbol1(ModelPPM *Model,int symbol); // ABCD context + inline void encodeSymbol2(ModelPPM *Model,int symbol); // BCD suffix + inline void decodeBinSymbol(ModelPPM *Model); // BCDE successor + inline bool decodeSymbol1(ModelPPM *Model); // other orders: + inline bool decodeSymbol2(ModelPPM *Model); // BCD context + inline void update1(ModelPPM *Model,STATE* p); // CD suffix + inline void update2(ModelPPM *Model,STATE* p); // BCDE successor + void rescale(ModelPPM *Model); + inline PPM_CONTEXT* createChild(ModelPPM *Model,STATE* pStats,STATE& FirstState); + inline SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff); +}; + +#ifndef STRICT_ALIGNMENT_REQUIRED +#ifdef _AIX +#pragma pack(pop) +#else +#pragma pack() +#endif +#endif + +const uint UNIT_SIZE=Max(sizeof(PPM_CONTEXT),sizeof(RAR_MEM_BLK)); +const uint FIXED_UNIT_SIZE=12; + +/* +inline PPM_CONTEXT::PPM_CONTEXT(STATE* pStats,PPM_CONTEXT* ShorterContext): + NumStats(1), Suffix(ShorterContext) { pStats->Successor=this; } +inline PPM_CONTEXT::PPM_CONTEXT(): NumStats(0) {} +*/ + +template <class T> +inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; } + + +class ModelPPM +{ + private: + friend struct PPM_CONTEXT; + + SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont; + + struct PPM_CONTEXT *MinContext, *MedContext, *MaxContext; + STATE* FoundState; // found next state transition + int NumMasked, InitEsc, OrderFall, MaxOrder, RunLength, InitRL; + byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256]; + byte EscCount, PrevSuccess, HiBitsFlag; + ushort BinSumm[128][64]; // binary SEE-contexts + + RangeCoder Coder; + SubAllocator SubAlloc; + + void RestartModelRare(); + void StartModelRare(int MaxOrder); + inline PPM_CONTEXT* CreateSuccessors(bool Skip,STATE* p1); + + inline void UpdateModel(); + inline void ClearMask(); + public: + ModelPPM(); + void CleanUp(); // reset PPM variables after data error + bool DecodeInit(Unpack *UnpackRead,int &EscChar); + int DecodeChar(); +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/options.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/options.hpp new file mode 100644 index 00000000..804dc9d5 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/options.hpp @@ -0,0 +1,162 @@ +#ifndef _RAR_OPTIONS_ +#define _RAR_OPTIONS_ + +#define DEFAULT_RECOVERY -1 + +#define DEFAULT_RECVOLUMES -10 + +enum PATH_EXCL_MODE { + EXCL_NONE,EXCL_BASEPATH,EXCL_SKIPWHOLEPATH,EXCL_SAVEFULLPATH, + EXCL_SKIPABSPATH,EXCL_ABSPATH +}; + +enum {SOLID_NONE=0,SOLID_NORMAL=1,SOLID_COUNT=2,SOLID_FILEEXT=4, + SOLID_VOLUME_DEPENDENT=8,SOLID_VOLUME_INDEPENDENT=16}; + +enum {ARCTIME_NONE,ARCTIME_KEEP,ARCTIME_LATEST}; + +enum EXTTIME_MODE { + EXTTIME_NONE,EXTTIME_1S,EXTTIME_HIGH1,EXTTIME_HIGH2,EXTTIME_HIGH3 +}; + +enum {NAMES_ORIGINALCASE,NAMES_UPPERCASE,NAMES_LOWERCASE}; + +enum MESSAGE_TYPE {MSG_STDOUT,MSG_STDERR,MSG_ERRONLY,MSG_NULL}; + +enum RECURSE_MODE +{ + RECURSE_NONE=0, // no recurse switches + RECURSE_DISABLE, // switch -r- + RECURSE_ALWAYS, // switch -r + RECURSE_WILDCARDS, // switch -r0 +}; + +enum OVERWRITE_MODE +{ + OVERWRITE_DEFAULT=0, // ask for extraction, silently overwrite for archiving + OVERWRITE_ALL, + OVERWRITE_NONE, + OVERWRITE_AUTORENAME, + OVERWRITE_FORCE_ASK +}; + +enum RAR_CHARSET { RCH_DEFAULT=0,RCH_ANSI,RCH_OEM,RCH_UNICODE }; + +#define MAX_FILTERS 16 +enum FilterState {FILTER_DEFAULT=0,FILTER_AUTO,FILTER_FORCE,FILTER_DISABLE}; + + +struct FilterMode +{ + FilterState State; + int Param1; + int Param2; +}; + + +class RAROptions +{ + public: + RAROptions(); + ~RAROptions(); + void Init(); + + uint ExclFileAttr; + uint InclFileAttr; + bool InclAttrSet; + uint WinSize; + char TempPath[NM]; + char SFXModule[NM]; + char ExtrPath[NM]; + wchar ExtrPathW[NM]; + char CommentFile[NM]; + RAR_CHARSET CommentCharset; + RAR_CHARSET FilelistCharset; + char ArcPath[NM]; + wchar ArcPathW[NM]; + char Password[MAXPASSWORD]; + bool EncryptHeaders; + char LogName[NM]; + MESSAGE_TYPE MsgStream; + bool Sound; + OVERWRITE_MODE Overwrite; + int Method; + int Recovery; + int RecVolNumber; + bool DisablePercentage; + bool DisableCopyright; + bool DisableDone; + int Solid; + int SolidCount; + bool ClearArc; + bool AddArcOnly; + bool AV; + bool DisableComment; + bool FreshFiles; + bool UpdateFiles; + PATH_EXCL_MODE ExclPath; + RECURSE_MODE Recurse; + int64 VolSize; + Array<int64> NextVolSizes; + uint CurVolNum; + bool AllYes; + bool DisableViewAV; + bool DisableSortSolid; + int ArcTime; + int ConvertNames; + bool ProcessOwners; + bool SaveLinks; + int Priority; + int SleepTime; + bool KeepBroken; + bool EraseDisk; + bool OpenShared; + bool DeleteFiles; + bool SyncFiles; + bool GenerateArcName; + char GenerateMask[80]; + bool ProcessEA; + bool SaveStreams; + bool SetCompressedAttr; + bool IgnoreGeneralAttr; + RarTime FileTimeBefore; + RarTime FileTimeAfter; + int64 FileSizeLess; + int64 FileSizeMore; + bool OldNumbering; + bool Lock; + bool Test; + bool VolumePause; + FilterMode FilterModes[MAX_FILTERS]; + char EmailTo[NM]; + uint VersionControl; + bool NoEndBlock; + bool AppendArcNameToPath; + bool Shutdown; + EXTTIME_MODE xmtime; + EXTTIME_MODE xctime; + EXTTIME_MODE xatime; + EXTTIME_MODE xarctime; + char CompressStdin[NM]; + +#ifdef PACK_SMP + uint Threads; +#endif + + + + + + +#ifdef RARDLL + char DllDestName[NM]; + wchar DllDestNameW[NM]; + int DllOpMode; + int DllError; + LPARAM UserData; + UNRARCALLBACK Callback; + CHANGEVOLPROC ChangeVolProc; + PROCESSDATAPROC ProcessDataProc; +#endif +}; +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/os.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/os.hpp new file mode 100644 index 00000000..4e15d11e --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/os.hpp @@ -0,0 +1,259 @@ +#ifndef _RAR_OS_ +#define _RAR_OS_ + +#define FALSE 0 +#define TRUE 1 + +#ifdef __EMX__ + #define INCL_BASE +#endif + +#if defined(RARDLL) && !defined(SILENT) +#define SILENT +#endif + +#if defined(_WIN_32) || defined(_EMX) +#define ENABLE_BAD_ALLOC +#endif + + +#if defined(_WIN_32) || defined(_EMX) + +#define LITTLE_ENDIAN +#define NM 1024 + +#ifdef _WIN_32 + + #define STRICT + #undef WINVER + #undef _WIN32_WINNT + #define WINVER 0x0400 + #define _WIN32_WINNT 0x0300 + + +#define WIN32_LEAN_AND_MEAN + +#include <windows.h> +#include <prsht.h> + +#ifndef _WIN_CE + #include <shellapi.h> + #include <shlobj.h> + #include <winioctl.h> + + +#endif // _WIN_CE + + +#endif // _WIN_32 + +#ifndef _WIN_CE + #include <sys/types.h> + #include <sys/stat.h> + #include <dos.h> +#endif // _WIN_CE + +#if !defined(_EMX) && !defined(_MSC_VER) && !defined(_WIN_CE) + #include <dir.h> +#endif +#ifdef _MSC_VER + #if _MSC_VER<1500 + #define for if (0) ; else for + #endif + #ifndef _WIN_CE + #include <direct.h> + #endif +#else + #include <dirent.h> +#endif // _MSC_VER + +#ifndef _WIN_CE + #include <share.h> +#endif // _WIN_CE + +#if defined(ENABLE_BAD_ALLOC) && !defined(_WIN_CE) + #include <new.h> +#endif + +#ifdef _EMX + #include <unistd.h> + #include <pwd.h> + #include <grp.h> + #include <errno.h> + #ifdef _DJGPP + #include <utime.h> + #else + #include <os2.h> + #include <sys/utime.h> + #include <emx/syscalls.h> + #endif +#else + #if defined(_MSC_VER) || defined(__MINGW32__) + #include <exception> + #else + #include <except.h> + #endif +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> +#ifndef _WIN_CE + #include <fcntl.h> + #include <dos.h> + #include <io.h> + #include <time.h> + #include <signal.h> +#endif + +/* +#ifdef _WIN_32 +#pragma hdrstop +#endif // _WIN_32 +*/ + +#define ENABLE_ACCESS + +#define DefConfigName "rar.ini" +#define DefLogName "rar.log" + + +#define PATHDIVIDER "\\" +#define PATHDIVIDERW L"\\" +#define CPATHDIVIDER '\\' +#define MASKALL "*" +#define MASKALLW L"*" + +#define READBINARY "rb" +#define READTEXT "rt" +#define UPDATEBINARY "r+b" +#define CREATEBINARY "w+b" +#define APPENDTEXT "at" + +#if defined(_WIN_32) + #ifdef _MSC_VER + #define _stdfunction __cdecl + #else + #define _stdfunction _USERENTRY + #endif +#else + #define _stdfunction +#endif + +#endif + +#ifdef _UNIX + +#define NM 1024 + +#ifdef _BEOS +#include <be/kernel/fs_info.h> +#include <be/kernel/fs_attr.h> +#endif + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#if defined(__QNXNTO__) + #include <sys/param.h> +#endif +#if defined(__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined(__APPLE__) + #include <sys/param.h> + #include <sys/mount.h> +#else +#endif +#include <pwd.h> +#include <grp.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> +#include <fcntl.h> +#include <errno.h> +#include <dirent.h> +#include <time.h> +#include <signal.h> +#include <utime.h> +#include <locale.h> + +#define ENABLE_ACCESS + +#define DefConfigName ".rarrc" +#define DefLogName ".rarlog" + + +#define PATHDIVIDER "/" +#define PATHDIVIDERW L"/" +#define CPATHDIVIDER '/' +#define MASKALL "*" +#define MASKALLW L"*" + +#define READBINARY "r" +#define READTEXT "r" +#define UPDATEBINARY "r+" +#define CREATEBINARY "w+" +#define APPENDTEXT "a" + +#define _stdfunction + +#ifdef _APPLE + #if defined(__BIG_ENDIAN__) && !defined(BIG_ENDIAN) + #define BIG_ENDIAN + #undef LITTLE_ENDIAN + #endif + #if defined(__i386__) && !defined(LITTLE_ENDIAN) + #define LITTLE_ENDIAN + #undef BIG_ENDIAN + #endif +#endif + +#if defined(__sparc) || defined(sparc) || defined(__hpux) + #ifndef BIG_ENDIAN + #define BIG_ENDIAN + #endif +#endif + +#endif + + typedef const char* MSGID; + +#define safebuf static + +#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) + #if defined(__i386) || defined(i386) || defined(__i386__) + #define LITTLE_ENDIAN + #elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN + #define LITTLE_ENDIAN + #elif defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN + #define BIG_ENDIAN + #else + #error "Neither LITTLE_ENDIAN nor BIG_ENDIAN are defined. Define one of them." + #endif +#endif + +#if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) + #if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN + #undef LITTLE_ENDIAN + #elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN + #undef BIG_ENDIAN + #else + #error "Both LITTLE_ENDIAN and BIG_ENDIAN are defined. Undef one of them." + #endif +#endif + +#if !defined(BIG_ENDIAN) && !defined(_WIN_CE) && defined(_WIN_32) +/* allow not aligned integer access, increases speed in some operations */ +#define ALLOW_NOT_ALIGNED_INT +#endif + +#if defined(__sparc) || defined(sparc) || defined(__sparcv9) +/* prohibit not aligned access to data structures in text comression + algorithm, increases memory requirements */ +#define STRICT_ALIGNMENT_REQUIRED +#endif + +#endif // _RAR_OS_ diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/pathfn.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/pathfn.hpp new file mode 100644 index 00000000..6b0ac31d --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/pathfn.hpp @@ -0,0 +1,49 @@ +#ifndef _RAR_PATHFN_ +#define _RAR_PATHFN_ + +char* PointToName(const char *Path); +wchar* PointToName(const wchar *Path); +char* PointToLastChar(const char *Path); +char* ConvertPath(const char *SrcPath,char *DestPath); +wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath); +void SetExt(char *Name,const char *NewExt); +void SetExt(wchar *Name,const wchar *NewExt); +void SetSFXExt(char *SFXName); +void SetSFXExt(wchar *SFXName); +char *GetExt(const char *Name); +wchar *GetExt(const wchar *Name); +bool CmpExt(const char *Name,const char *Ext); +bool IsWildcard(const char *Str,const wchar *StrW=NULL); +bool IsPathDiv(int Ch); +bool IsDriveDiv(int Ch); +int GetPathDisk(const char *Path); +void AddEndSlash(char *Path); +void AddEndSlash(wchar *Path); +void GetFilePath(const char *FullName,char *Path,int MaxLength); +void GetFilePath(const wchar *FullName,wchar *Path,int MaxLength); +void RemoveNameFromPath(char *Path); +void RemoveNameFromPath(wchar *Path); +void GetAppDataPath(char *Path); +void GetRarDataPath(char *Path); +bool EnumConfigPaths(char *Path,int Number); +void GetConfigName(const char *Name,char *FullName,bool CheckExist); +char* GetVolNumPart(char *ArcName); +void NextVolumeName(char *ArcName,wchar *ArcNameW,uint MaxLength,bool OldNumbering); +bool IsNameUsable(const char *Name); +void MakeNameUsable(char *Name,bool Extended); +char* UnixSlashToDos(char *SrcName,char *DestName=NULL,uint MaxLength=NM); +char* DosSlashToUnix(char *SrcName,char *DestName=NULL,uint MaxLength=NM); +wchar* UnixSlashToDos(wchar *SrcName,wchar *DestName=NULL,uint MaxLength=NM); +bool IsFullPath(const char *Path); +bool IsFullPath(const wchar *Path); +bool IsDiskLetter(const char *Path); +bool IsDiskLetter(const wchar *Path); +void GetPathRoot(const char *Path,char *Root); +int ParseVersionFileName(char *Name,wchar *NameW,bool Truncate); +char* VolNameToFirstName(const char *VolName,char *FirstName,bool NewNumbering); +wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW); + + +inline char* GetOutputName(const char *Name) {return((char *)Name);}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/rar.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/rar.hpp new file mode 100644 index 00000000..218830c2 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/rar.hpp @@ -0,0 +1,77 @@ +#ifndef _RAR_RARCOMMON_ +#define _RAR_RARCOMMON_ + +#include "raros.hpp" +#include "os.hpp" + +#ifdef RARDLL +#include "dll.hpp" +#endif + + +#ifndef _WIN_CE +#include "version.hpp" +#endif +#include "rartypes.hpp" +#include "rardefs.hpp" +#include "rarlang.hpp" +#include "unicode.hpp" +#include "errhnd.hpp" +#include "array.hpp" +#include "timefn.hpp" +#include "options.hpp" +#include "headers.hpp" +#include "pathfn.hpp" +#include "strfn.hpp" +#include "strlist.hpp" +#include "file.hpp" +#include "sha1.hpp" +#include "crc.hpp" +#include "rijndael.hpp" +#include "crypt.hpp" +#include "filefn.hpp" +#include "filestr.hpp" +#include "find.hpp" +#include "scantree.hpp" +#include "savepos.hpp" +#include "getbits.hpp" +#include "rdwrfn.hpp" +#include "archive.hpp" +#include "match.hpp" +#include "cmddata.hpp" +#include "filcreat.hpp" +#include "consio.hpp" +#include "system.hpp" +#include "isnt.hpp" +#include "log.hpp" +#include "rawread.hpp" +#include "encname.hpp" +#include "resource.hpp" +#include "compress.hpp" + + +#include "rarvm.hpp" +#include "model.hpp" + + +#include "unpack.hpp" + + +#include "extinfo.hpp" +#include "extract.hpp" + + + +#include "list.hpp" + + +#include "rs.hpp" +#include "recvol.hpp" +#include "volume.hpp" +#include "smallfn.hpp" +#include "ulinks.hpp" + +#include "global.hpp" + + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/rardefs.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/rardefs.hpp new file mode 100644 index 00000000..24f97b50 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/rardefs.hpp @@ -0,0 +1,24 @@ +#ifndef _RAR_DEFS_ +#define _RAR_DEFS_ + +#define Min(x,y) (((x)<(y)) ? (x):(y)) +#define Max(x,y) (((x)>(y)) ? (x):(y)) + +#define ASIZE(x) (sizeof(x)/sizeof(x[0])) + +#define MAXPASSWORD 128 +#define MAXSFXSIZE 0x80000 + +#define DefSFXName "default.sfx" +#define DefSortListName "rarfiles.lst" + +#ifndef FA_RDONLY + #define FA_RDONLY 0x01 + #define FA_HIDDEN 0x02 + #define FA_SYSTEM 0x04 + #define FA_LABEL 0x08 + #define FA_DIREC 0x10 + #define FA_ARCH 0x20 +#endif + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/rarlang.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/rarlang.hpp new file mode 100644 index 00000000..6151d15a --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/rarlang.hpp @@ -0,0 +1,10 @@ +#ifndef _RAR_LANG_ +#define _RAR_LANG_ + + #ifdef USE_RC + #include "rarres.hpp" + #else + #include "loclang.hpp" + #endif + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/raros.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/raros.hpp new file mode 100644 index 00000000..e6867981 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/raros.hpp @@ -0,0 +1,41 @@ +#ifndef _RAR_RAROS_ +#define _RAR_RAROS_ + +#ifdef __EMX__ + #define _EMX +#endif + +#ifdef __DJGPP__ + #define _DJGPP + #define _EMX +#endif + +#if defined(__WIN32__) || defined(_WIN32) + #define _WIN_32 +#endif + +#ifdef _WIN32_WCE + #define _WIN_32 + #define _WIN_CE + #ifdef WM_FILECHANGEINFO + #define PC2002 + #else + #undef PC2002 + #endif +#endif + +#ifdef __BEOS__ + #define _UNIX + #define _BEOS +#endif + +#ifdef __APPLE__ + #define _UNIX + #define _APPLE +#endif + +#if !defined(_EMX) && !defined(_WIN_32) && !defined(_BEOS) && !defined(_APPLE) + #define _UNIX +#endif + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/rartypes.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/rartypes.hpp new file mode 100644 index 00000000..595592e7 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/rartypes.hpp @@ -0,0 +1,47 @@ +#ifndef _RAR_TYPES_ +#define _RAR_TYPES_ + +typedef unsigned char byte; // unsigned 8 bits +typedef unsigned short ushort; // preferably 16 bits, but can be more +typedef unsigned int uint; // 32 bits or more + +#define PRESENT_INT32 // undefine if signed 32 bits is not available + +typedef unsigned int uint32; // 32 bits exactly +typedef signed int int32; // signed 32 bits exactly + +// If compiler does not support 64 bit variables, we can define +// uint64 and int64 as 32 bit, but it will limit the maximum processed +// file size to 2 GB. +#if defined(__BORLANDC__) || defined(_MSC_VER) +typedef unsigned __int64 uint64; // unsigned 64 bits +typedef signed __int64 int64; // signed 64 bits +#else +typedef unsigned long long uint64; // unsigned 64 bits +typedef signed long long int64; // signed 64 bits +#endif + + +#if defined(_WIN_32) || defined(__GNUC__) || defined(__sgi) || defined(_AIX) || defined(__sun) || defined(__hpux) || defined(_OSF_SOURCE) +typedef wchar_t wchar; +#else +typedef ushort wchar; +#endif + +// Get lowest 16 bits. +#define SHORT16(x) (sizeof(ushort)==2 ? (ushort)(x):((x)&0xffff)) + +// Get lowest 32 bits. +#define UINT32(x) (sizeof(uint32)==4 ? (uint32)(x):((x)&0xffffffff)) + +// Make 64 bit integer from two 32 bit. +#define INT32TO64(high,low) ((((uint64)(high))<<32)+((uint64)low)) + +// Special int64 value, large enough to be never found in real life. +// We use it in situations, when we need to indicate that parameter +// is not defined and probably should be calculated inside of function. +// Lower part is intentionally 0x7fffffff, not 0xffffffff, to make it +// compatible with 32 bit int64. +#define INT64NDF INT32TO64(0x7fffffff,0x7fffffff) + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/rarvm.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/rarvm.hpp new file mode 100644 index 00000000..96d42c23 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/rarvm.hpp @@ -0,0 +1,113 @@ +#ifndef _RAR_VM_ +#define _RAR_VM_ + +#define VM_STANDARDFILTERS + +#ifndef SFX_MODULE +#define VM_OPTIMIZE +#endif + + +#define VM_MEMSIZE 0x40000 +#define VM_MEMMASK (VM_MEMSIZE-1) +#define VM_GLOBALMEMADDR 0x3C000 +#define VM_GLOBALMEMSIZE 0x2000 +#define VM_FIXEDGLOBALSIZE 64 + +enum VM_Commands +{ + VM_MOV, VM_CMP, VM_ADD, VM_SUB, VM_JZ, VM_JNZ, VM_INC, VM_DEC, + VM_JMP, VM_XOR, VM_AND, VM_OR, VM_TEST, VM_JS, VM_JNS, VM_JB, + VM_JBE, VM_JA, VM_JAE, VM_PUSH, VM_POP, VM_CALL, VM_RET, VM_NOT, + VM_SHL, VM_SHR, VM_SAR, VM_NEG, VM_PUSHA,VM_POPA, VM_PUSHF,VM_POPF, + VM_MOVZX,VM_MOVSX,VM_XCHG, VM_MUL, VM_DIV, VM_ADC, VM_SBB, VM_PRINT, + +#ifdef VM_OPTIMIZE + VM_MOVB, VM_MOVD, VM_CMPB, VM_CMPD, + + VM_ADDB, VM_ADDD, VM_SUBB, VM_SUBD, VM_INCB, VM_INCD, VM_DECB, VM_DECD, + VM_NEGB, VM_NEGD, +#endif + + VM_STANDARD +}; + +enum VM_StandardFilters { + VMSF_NONE, VMSF_E8, VMSF_E8E9, VMSF_ITANIUM, VMSF_RGB, VMSF_AUDIO, + VMSF_DELTA, VMSF_UPCASE +}; + +enum VM_Flags {VM_FC=1,VM_FZ=2,VM_FS=0x80000000}; + +enum VM_OpType {VM_OPREG,VM_OPINT,VM_OPREGMEM,VM_OPNONE}; + +struct VM_PreparedOperand +{ + VM_OpType Type; + uint Data; + uint Base; + uint *Addr; +}; + +struct VM_PreparedCommand +{ + VM_Commands OpCode; + bool ByteMode; + VM_PreparedOperand Op1,Op2; +}; + + +struct VM_PreparedProgram +{ + VM_PreparedProgram() + { + AltCmd=NULL; + FilteredDataSize=0; + CmdCount=0; + } + + Array<VM_PreparedCommand> Cmd; + VM_PreparedCommand *AltCmd; + int CmdCount; + + Array<byte> GlobalData; + Array<byte> StaticData; // static data contained in DB operators + uint InitR[7]; + + byte *FilteredData; + uint FilteredDataSize; +}; + +class RarVM:private BitInput +{ + private: + inline uint GetValue(bool ByteMode,uint *Addr); + inline void SetValue(bool ByteMode,uint *Addr,uint Value); + inline uint* GetOperand(VM_PreparedOperand *CmdOp); + void DecodeArg(VM_PreparedOperand &Op,bool ByteMode); +#ifdef VM_OPTIMIZE + void Optimize(VM_PreparedProgram *Prg); +#endif + bool ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize); +#ifdef VM_STANDARDFILTERS + VM_StandardFilters IsStandardFilter(byte *Code,uint CodeSize); + void ExecuteStandardFilter(VM_StandardFilters FilterType); + uint FilterItanium_GetBits(byte *Data,int BitPos,int BitCount); + void FilterItanium_SetBits(byte *Data,uint BitField,int BitPos,int BitCount); +#endif + + byte *Mem; + uint R[8]; + uint Flags; + public: + RarVM(); + ~RarVM(); + void Init(); + void Prepare(byte *Code,uint CodeSize,VM_PreparedProgram *Prg); + void Execute(VM_PreparedProgram *Prg); + void SetLowEndianValue(uint *Addr,uint Value); + void SetMemory(uint Pos,byte *Data,uint DataSize); + static uint ReadData(BitInput &Inp); +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/rawread.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/rawread.hpp new file mode 100644 index 00000000..39fefe6f --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/rawread.hpp @@ -0,0 +1,32 @@ +#ifndef _RAR_RAWREAD_ +#define _RAR_RAWREAD_ + +class RawRead +{ + private: + Array<byte> Data; + File *SrcFile; + size_t DataSize; + size_t ReadPos; +#ifndef SHELL_EXT + CryptData *Crypt; +#endif + public: + RawRead(File *SrcFile); + void Read(size_t Size); + void Read(byte *SrcData,size_t Size); + void Get(byte &Field); + void Get(ushort &Field); + void Get(uint &Field); + void Get8(int64 &Field); + void Get(byte *Field,size_t Size); + void Get(wchar *Field,size_t Size); + uint GetCRC(bool ProcessedOnly); + size_t Size() {return DataSize;} + size_t PaddedSize() {return Data.Size()-DataSize;} +#ifndef SHELL_EXT + void SetCrypt(CryptData *Crypt) {RawRead::Crypt=Crypt;} +#endif +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/rdwrfn.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/rdwrfn.hpp new file mode 100644 index 00000000..10e026f3 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/rdwrfn.hpp @@ -0,0 +1,89 @@ +#ifndef _RAR_DATAIO_ +#define _RAR_DATAIO_ + +class CmdAdd; +class Unpack; + + +class ComprDataIO +{ + private: + void ShowUnpRead(int64 ArcPos,int64 ArcSize); + void ShowUnpWrite(); + + + bool UnpackFromMemory; + size_t UnpackFromMemorySize; + byte *UnpackFromMemoryAddr; + + bool UnpackToMemory; + size_t UnpackToMemorySize; + byte *UnpackToMemoryAddr; + + size_t UnpWrSize; + byte *UnpWrAddr; + + int64 UnpPackedSize; + + bool Progress; + bool TestMode; + bool SkipUnpCRC; + + File *SrcFile; + File *DestFile; + + CmdAdd *Command; + + FileHeader *SubHead; + int64 *SubHeadPos; + +#ifndef NOCRYPT + CryptData Crypt; + CryptData Decrypt; +#endif + + + int LastPercent; + + char CurrentCommand; + + public: + ComprDataIO(); + virtual ~ComprDataIO() {} + void Init(); + virtual int UnpRead(byte *Addr,size_t Count); + virtual void UnpWrite(byte *Addr,size_t Count); + void EnableShowProgress(bool Show) {Progress=Show;} + void GetUnpackedData(byte **Data,size_t *Size); + void SetPackedSizeToRead(int64 Size) {UnpPackedSize=Size;} + void SetTestMode(bool Mode) {TestMode=Mode;} + void SetSkipUnpCRC(bool Skip) {SkipUnpCRC=Skip;} + void SetFiles(File *SrcFile,File *DestFile); + void SetCommand(CmdAdd *Cmd) {Command=Cmd;} + void SetSubHeader(FileHeader *hd,int64 *Pos) {SubHead=hd;SubHeadPos=Pos;} + void SetEncryption(int Method,const char *Password,const byte *Salt,bool Encrypt,bool HandsOffHash); + void SetAV15Encryption(); + void SetCmt13Encryption(); + void SetUnpackToMemory(byte *Addr,uint Size); + void SetCurrentCommand(char Cmd) {CurrentCommand=Cmd;} + + bool PackVolume; + bool UnpVolume; + bool NextVolumeMissing; + int64 TotalPackRead; + int64 UnpArcSize; + int64 CurPackRead,CurPackWrite,CurUnpRead,CurUnpWrite; + + // Size of already processed archives. + // Used to calculate the total operation progress. + int64 ProcessedArcSize; + + int64 TotalArcSize; + + uint PackFileCRC,UnpFileCRC,PackedCRC; + + int Encryption; + int Decryption; +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/recvol.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/recvol.hpp new file mode 100644 index 00000000..5a0abe58 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/recvol.hpp @@ -0,0 +1,16 @@ +#ifndef _RAR_RECVOL_ +#define _RAR_RECVOL_ + +class RecVolumes +{ + private: + File *SrcFile[256]; + Array<byte> Buf; + public: + RecVolumes(); + ~RecVolumes(); + void Make(RAROptions *Cmd,char *ArcName,wchar *ArcNameW); + bool Restore(RAROptions *Cmd,const char *Name,const wchar *NameW,bool Silent); +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/resource.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/resource.hpp new file mode 100644 index 00000000..581b34b4 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/resource.hpp @@ -0,0 +1,14 @@ +#ifndef _RAR_RESOURCE_ +#define _RAR_RESOURCE_ + +#if defined(SILENT) && defined(RARDLL) +#define St(x) ("") +#else +const char *St(MSGID StringId); +#endif + + +inline const char *StT(MSGID StringId) {return(St(StringId));} + + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/rijndael.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/rijndael.hpp new file mode 100644 index 00000000..bb5bd881 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/rijndael.hpp @@ -0,0 +1,37 @@ +#ifndef _RIJNDAEL_H_ +#define _RIJNDAEL_H_ + +/************************************************************************** + * This code is based on Szymon Stefanek AES implementation: * + * http://www.esat.kuleuven.ac.be/~rijmen/rijndael/rijndael-cpplib.tar.gz * + * * + * Dynamic tables generation is based on the Brian Gladman's work: * + * http://fp.gladman.plus.com/cryptography_technology/rijndael * + **************************************************************************/ + +#define _MAX_KEY_COLUMNS (256/32) +#define _MAX_ROUNDS 14 +#define MAX_IV_SIZE 16 + +class Rijndael +{ + public: + enum Direction { Encrypt , Decrypt }; + private: + void keySched(byte key[_MAX_KEY_COLUMNS][4]); + void keyEncToDec(); + void encrypt(const byte a[16], byte b[16]); + void decrypt(const byte a[16], byte b[16]); + void GenerateTables(); + + Direction m_direction; + byte m_initVector[MAX_IV_SIZE]; + byte m_expandedKey[_MAX_ROUNDS+1][4][4]; + public: + Rijndael(); + void init(Direction dir,const byte *key,byte *initVector); + size_t blockEncrypt(const byte *input, size_t inputLen, byte *outBuffer); + size_t blockDecrypt(const byte *input, size_t inputLen, byte *outBuffer); +}; + +#endif // _RIJNDAEL_H_ diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/rs.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/rs.hpp new file mode 100644 index 00000000..2f099f00 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/rs.hpp @@ -0,0 +1,32 @@ +#ifndef _RAR_RS_ +#define _RAR_RS_ + +#define MAXPAR 255 +#define MAXPOL 512 + +class RSCoder +{ + private: + void gfInit(); + int gfMult(int a,int b); + void pnInit(); + void pnMult(int *p1,int *p2,int *r); + + int gfExp[MAXPOL]; + int gfLog[MAXPAR+1]; + + int GXPol[MAXPOL*2]; + + int ErrorLocs[MAXPAR+1],ErrCount; + int Dn[MAXPAR+1]; + + int ParSize; + int PolB[MAXPOL]; + bool FirstBlockDone; + public: + RSCoder(int ParSize); + void Encode(byte *Data,int DataSize,byte *DestData); + bool Decode(byte *Data,int DataSize,int *EraLoc,int EraSize); +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/savepos.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/savepos.hpp new file mode 100644 index 00000000..b3b23733 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/savepos.hpp @@ -0,0 +1,15 @@ +#ifndef _RAR_SAVEPOS_ +#define _RAR_SAVEPOS_ + +class SaveFilePos +{ + private: + File *SaveFile; + int64 SavePos; + uint CloseCount; + public: + SaveFilePos(File &SaveFile); + ~SaveFilePos(); +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/scantree.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/scantree.hpp new file mode 100644 index 00000000..cf960bf2 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/scantree.hpp @@ -0,0 +1,60 @@ +#ifndef _RAR_SCANTREE_ +#define _RAR_SCANTREE_ + +enum SCAN_DIRS +{ + SCAN_SKIPDIRS, // Skip directories, but recurse for files if recursion mode is enabled. + SCAN_GETDIRS, // Get subdirectories in recurse mode. + SCAN_GETDIRSTWICE, // Get the directory name both before and after the list of files it contains. + SCAN_GETCURDIRS // Get subdirectories in current directory even in RECURSE_NONE mode. +}; + +enum SCAN_CODE { SCAN_SUCCESS,SCAN_DONE,SCAN_ERROR,SCAN_NEXT }; + +#define MAXSCANDEPTH (NM/2) + +class CommandData; + +class ScanTree +{ + private: + bool GetNextMask(); + SCAN_CODE FindProc(FindData *FindData); + + FindFile *FindStack[MAXSCANDEPTH]; + int Depth; + + int SetAllMaskDepth; + + StringList *FileMasks; + RECURSE_MODE Recurse; + bool GetLinks; + SCAN_DIRS GetDirs; + int Errors; + + // set when processing paths like c:\ (root directory without wildcards) + bool ScanEntireDisk; + + char CurMask[NM]; + wchar CurMaskW[NM]; + char OrigCurMask[NM]; + wchar OrigCurMaskW[NM]; + bool SearchAllInRoot; + size_t SpecPathLength; + size_t SpecPathLengthW; + + char ErrArcName[NM]; + + CommandData *Cmd; + public: + ScanTree(StringList *FileMasks,RECURSE_MODE Recurse,bool GetLinks,SCAN_DIRS GetDirs); + ~ScanTree(); + SCAN_CODE GetNext(FindData *FindData); + size_t GetSpecPathLength() {return(SpecPathLength);}; + size_t GetSpecPathLengthW() {return(SpecPathLengthW);}; + int GetErrors() {return(Errors);}; + void SetErrArcName(const char *Name) {strcpy(ErrArcName,Name);} + void SetCommandData(CommandData *Cmd) {ScanTree::Cmd=Cmd;} +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/sha1.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/sha1.hpp new file mode 100644 index 00000000..27e15e7b --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/sha1.hpp @@ -0,0 +1,17 @@ +#ifndef _RAR_SHA1_ +#define _RAR_SHA1_ + +#define HW 5 + +typedef struct { + uint32 state[5]; + uint32 count[2]; + unsigned char buffer[64]; +} hash_context; + +void hash_initial( hash_context * c ); +void hash_process( hash_context * c, unsigned char * data, size_t len, + bool handsoff); +void hash_final( hash_context * c, uint32[HW], bool handsoff); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/smallfn.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/smallfn.hpp new file mode 100644 index 00000000..f53daa8b --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/smallfn.hpp @@ -0,0 +1,8 @@ +#ifndef _RAR_SMALLFN_ +#define _RAR_SMALLFN_ + +int ToPercent(int64 N1,int64 N2); +int ToPercentUnlim(int64 N1,int64 N2); +void RARInitData(); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/strfn.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/strfn.hpp new file mode 100644 index 00000000..0940bb29 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/strfn.hpp @@ -0,0 +1,41 @@ +#ifndef _RAR_STRFN_ +#define _RAR_STRFN_ + +const char *NullToEmpty(const char *Str); +const wchar *NullToEmpty(const wchar *Str); +char *IntNameToExt(const char *Name); +void ExtToInt(const char *Src,char *Dest); +void IntToExt(const char *Src,char *Dest); +char* strlower(char *Str); +char* strupper(char *Str); +int stricomp(const char *Str1,const char *Str2); +int strnicomp(const char *Str1,const char *Str2,size_t N); +char* RemoveEOL(char *Str); +char* RemoveLF(char *Str); +unsigned char loctolower(unsigned char ch); +unsigned char loctoupper(unsigned char ch); + +char* strncpyz(char *dest, const char *src, size_t maxlen); +wchar* strncpyzw(wchar *dest, const wchar *src, size_t maxlen); + +unsigned char etoupper(unsigned char ch); +wchar etoupperw(wchar ch); + +bool IsDigit(int ch); +bool IsSpace(int ch); + + + +bool LowAscii(const char *Str); +bool LowAscii(const wchar *Str); + + +int stricompc(const char *Str1,const char *Str2); +#ifndef SFX_MODULE +int stricompcw(const wchar *Str1,const wchar *Str2); +#endif + +void itoa(int64 n,char *Str); +int64 atoil(char *Str); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/strlist.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/strlist.hpp new file mode 100644 index 00000000..1e4e7ca7 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/strlist.hpp @@ -0,0 +1,39 @@ +#ifndef _RAR_STRLIST_ +#define _RAR_STRLIST_ + +class StringList +{ + private: + Array<char> StringData; + size_t CurPos; + + Array<wchar> StringDataW; + size_t CurPosW; + + Array<size_t> PosDataW; + size_t PosDataItem; + + uint StringsCount; + + size_t SaveCurPos[16],SaveCurPosW[16],SavePosDataItem[16],SavePosNumber; + public: + StringList(); + ~StringList(); + void Reset(); + size_t AddString(const char *Str); + size_t AddString(const char *Str,const wchar *StrW); + bool GetString(char *Str,size_t MaxLength); + bool GetString(char *Str,wchar *StrW,size_t MaxLength); + bool GetString(char *Str,wchar *StrW,size_t MaxLength,int StringNum); + char* GetString(); + bool GetString(char **Str,wchar **StrW); + char* GetString(uint StringPos); + void Rewind(); + uint ItemsCount() {return(StringsCount);}; + size_t GetBufferSize(); + bool Search(char *Str,wchar *StrW,bool CaseSensitive); + void SavePosition(); + void RestorePosition(); +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/suballoc.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/suballoc.hpp new file mode 100644 index 00000000..474ee592 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/suballoc.hpp @@ -0,0 +1,87 @@ +/**************************************************************************** + * This file is part of PPMd project * + * Written and distributed to public domain by Dmitry Shkarin 1997, * + * 1999-2000 * + * Contents: interface to memory allocation routines * + ****************************************************************************/ +#if !defined(_SUBALLOC_H_) +#define _SUBALLOC_H_ + +const int N1=4, N2=4, N3=4, N4=(128+3-1*N1-2*N2-3*N3)/4; +const int N_INDEXES=N1+N2+N3+N4; + +#if defined(__GNUC__) && !defined(STRICT_ALIGNMENT_REQUIRED) +#define _PACK_ATTR __attribute__ ((packed)) +#else +#define _PACK_ATTR +#endif /* defined(__GNUC__) */ + +#ifndef STRICT_ALIGNMENT_REQUIRED +#pragma pack(1) +#endif + +struct RAR_MEM_BLK +{ + ushort Stamp, NU; + RAR_MEM_BLK* next, * prev; + void insertAt(RAR_MEM_BLK* p) + { + next=(prev=p)->next; + p->next=next->prev=this; + } + void remove() + { + prev->next=next; + next->prev=prev; + } +} _PACK_ATTR; + +#ifndef STRICT_ALIGNMENT_REQUIRED +#ifdef _AIX +#pragma pack(pop) +#else +#pragma pack() +#endif +#endif + + +struct RAR_NODE +{ + RAR_NODE* next; +}; + +class SubAllocator +{ + private: + inline void InsertNode(void* p,int indx); + inline void* RemoveNode(int indx); + inline uint U2B(int NU); + inline void SplitBlock(void* pv,int OldIndx,int NewIndx); + uint GetUsedMemory(); + inline void GlueFreeBlocks(); + void* AllocUnitsRare(int indx); + inline RAR_MEM_BLK* MBPtr(RAR_MEM_BLK *BasePtr,int Items); + + long SubAllocatorSize; + byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount; + byte *HeapStart,*LoUnit, *HiUnit; + struct RAR_NODE FreeList[N_INDEXES]; + public: + SubAllocator(); + ~SubAllocator() {StopSubAllocator();} + void Clean(); + bool StartSubAllocator(int SASize); + void StopSubAllocator(); + void InitSubAllocator(); + inline void* AllocContext(); + inline void* AllocUnits(int NU); + inline void* ExpandUnits(void* ptr,int OldNU); + inline void* ShrinkUnits(void* ptr,int OldNU,int NewNU); + inline void FreeUnits(void* ptr,int OldNU); + long GetAllocatedMemory() {return(SubAllocatorSize);}; + + byte *pText, *UnitsStart,*HeapEnd,*FakeUnitsStart; +}; + + +#endif /* !defined(_SUBALLOC_H_) */ diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/system.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/system.hpp new file mode 100644 index 00000000..d98e5a22 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/system.hpp @@ -0,0 +1,26 @@ +#ifndef _RAR_SYSTEM_ +#define _RAR_SYSTEM_ + +#ifdef _WIN_32 +#ifndef BELOW_NORMAL_PRIORITY_CLASS +#define BELOW_NORMAL_PRIORITY_CLASS 0x00004000 +#define ABOVE_NORMAL_PRIORITY_CLASS 0x00008000 +#endif +#ifndef PROCESS_MODE_BACKGROUND_BEGIN +#define PROCESS_MODE_BACKGROUND_BEGIN 0x00100000 +#define PROCESS_MODE_BACKGROUND_END 0x00200000 +#endif +#ifndef SHTDN_REASON_MAJOR_APPLICATION +#define SHTDN_REASON_MAJOR_APPLICATION 0x00040000 +#define SHTDN_REASON_FLAG_PLANNED 0x80000000 +#define SHTDN_REASON_MINOR_MAINTENANCE 0x00000001 +#endif +#endif + +void InitSystemOptions(int SleepTime); +void SetPriority(int Priority); +void Wait(); +bool EmailFile(char *FileName,char *MailTo); +void Shutdown(); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/timefn.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/timefn.hpp new file mode 100644 index 00000000..176b86b0 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/timefn.hpp @@ -0,0 +1,54 @@ +#ifndef _RAR_TIMEFN_ +#define _RAR_TIMEFN_ + +struct RarLocalTime +{ + uint Year; + uint Month; + uint Day; + uint Hour; + uint Minute; + uint Second; + uint Reminder; + uint wDay; + uint yDay; +}; + + +class RarTime +{ + private: + RarLocalTime rlt; + public: + RarTime(); +#ifdef _WIN_32 + RarTime& operator =(FILETIME &ft); + void GetWin32(FILETIME *ft); +#endif +#if defined(_UNIX) || defined(_EMX) + RarTime& operator =(time_t ut); + time_t GetUnix(); +#endif + bool operator == (RarTime &rt); + bool operator < (RarTime &rt); + bool operator <= (RarTime &rt); + bool operator > (RarTime &rt); + bool operator >= (RarTime &rt); + void GetLocal(RarLocalTime *lt) {*lt=rlt;} + void SetLocal(RarLocalTime *lt) {rlt=*lt;} + int64 GetRaw(); + void SetRaw(int64 RawTime); + uint GetDos(); + void SetDos(uint DosTime); + void GetText(char *DateStr,bool FullYear); + void SetIsoText(char *TimeText); + void SetAgeText(char *TimeText); + void SetCurrentTime(); + void Reset() {rlt.Year=0;} + bool IsSet() {return(rlt.Year!=0);} +}; + +const char *GetMonthName(int Month); +bool IsLeapYear(int Year); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/ulinks.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/ulinks.hpp new file mode 100644 index 00000000..69b0e9f8 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/ulinks.hpp @@ -0,0 +1,9 @@ +#ifndef _RAR_ULINKS_ +#define _RAR_ULINKS_ + +void SaveLinkData(ComprDataIO &DataIO,Archive &TempArc,FileHeader &hd, + char *Name); +int ExtractLink(ComprDataIO &DataIO,Archive &Arc,char *DestName, + uint &LinkCRC,bool Create); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/unicode.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/unicode.hpp new file mode 100644 index 00000000..9c087e8f --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/unicode.hpp @@ -0,0 +1,83 @@ +#ifndef _RAR_UNICODE_ +#define _RAR_UNICODE_ + +#ifndef _EMX +#define MBFUNCTIONS +#endif + +#if defined(MBFUNCTIONS) || defined(_WIN_32) || defined(_EMX) && !defined(_DJGPP) +#define UNICODE_SUPPORTED +#endif + +#ifdef _WIN_32 +#define DBCS_SUPPORTED +#endif + +#ifdef _EMX +int uni_init(int codepage); +int uni_done(); +#endif + +bool WideToChar(const wchar *Src,char *Dest,size_t DestSize=0x1000000); +bool CharToWide(const char *Src,wchar *Dest,size_t DestSize=0x1000000); +byte* WideToRaw(const wchar *Src,byte *Dest,size_t DestSize=0x1000000); +wchar* RawToWide(const byte *Src,wchar *Dest,size_t DestSize=0x1000000); +void WideToUtf(const wchar *Src,char *Dest,size_t DestSize); +void UtfToWide(const char *Src,wchar *Dest,size_t DestSize); +bool UnicodeEnabled(); + +size_t strlenw(const wchar *str); +wchar* strcpyw(wchar *dest,const wchar *src); +wchar* strncpyw(wchar *dest,const wchar *src,size_t n); +wchar* strcatw(wchar *dest,const wchar *src); +wchar* strncatw(wchar *dest,const wchar *src,size_t n); +int strcmpw(const wchar *s1,const wchar *s2); +int strncmpw(const wchar *s1,const wchar *s2,size_t n); +int stricmpw(const wchar *s1,const wchar *s2); +int strnicmpw(const wchar *s1,const wchar *s2,size_t n); +wchar *strchrw(const wchar *s,int c); +wchar* strrchrw(const wchar *s,int c); +wchar* strpbrkw(const wchar *s1,const wchar *s2); +wchar* strlowerw(wchar *Str); +wchar* strupperw(wchar *Str); +wchar* strdupw(const wchar *Str); +int toupperw(int ch); +int atoiw(const wchar *s); + +#ifdef DBCS_SUPPORTED +class SupportDBCS +{ + public: + SupportDBCS(); + void Init(); + + char* charnext(const char *s); + size_t strlend(const char *s); + char *strchrd(const char *s, int c); + char *strrchrd(const char *s, int c); + void copychrd(char *dest,const char *src); + + bool IsLeadByte[256]; + bool DBCSMode; +}; + +extern SupportDBCS gdbcs; + +inline char* charnext(const char *s) {return (char *)(gdbcs.DBCSMode ? gdbcs.charnext(s):s+1);} +inline size_t strlend(const char *s) {return (uint)(gdbcs.DBCSMode ? gdbcs.strlend(s):strlen(s));} +inline char* strchrd(const char *s, int c) {return (char *)(gdbcs.DBCSMode ? gdbcs.strchrd(s,c):strchr(s,c));} +inline char* strrchrd(const char *s, int c) {return (char *)(gdbcs.DBCSMode ? gdbcs.strrchrd(s,c):strrchr(s,c));} +inline void copychrd(char *dest,const char *src) {if (gdbcs.DBCSMode) gdbcs.copychrd(dest,src); else *dest=*src;} +inline bool IsDBCSMode() {return(gdbcs.DBCSMode);} +inline void InitDBCS() {gdbcs.Init();} + +#else +#define charnext(s) ((s)+1) +#define strlend strlen +#define strchrd strchr +#define strrchrd strrchr +#define IsDBCSMode() (true) +inline void copychrd(char *dest,const char *src) {*dest=*src;} +#endif + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/unpack.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/unpack.hpp new file mode 100644 index 00000000..329b5cff --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/unpack.hpp @@ -0,0 +1,221 @@ +#ifndef _RAR_UNPACK_ +#define _RAR_UNPACK_ + +enum BLOCK_TYPES {BLOCK_LZ,BLOCK_PPM}; + +struct Decode +{ + unsigned int MaxNum; + unsigned int DecodeLen[16]; + unsigned int DecodePos[16]; + unsigned int DecodeNum[2]; +}; + +struct LitDecode +{ + unsigned int MaxNum; + unsigned int DecodeLen[16]; + unsigned int DecodePos[16]; + unsigned int DecodeNum[NC]; +}; + +struct DistDecode +{ + unsigned int MaxNum; + unsigned int DecodeLen[16]; + unsigned int DecodePos[16]; + unsigned int DecodeNum[DC]; +}; + +struct LowDistDecode +{ + unsigned int MaxNum; + unsigned int DecodeLen[16]; + unsigned int DecodePos[16]; + unsigned int DecodeNum[LDC]; +}; + +struct RepDecode +{ + unsigned int MaxNum; + unsigned int DecodeLen[16]; + unsigned int DecodePos[16]; + unsigned int DecodeNum[RC]; +}; + +struct BitDecode +{ + unsigned int MaxNum; + unsigned int DecodeLen[16]; + unsigned int DecodePos[16]; + unsigned int DecodeNum[BC]; +}; + +struct UnpackFilter +{ + unsigned int BlockStart; + unsigned int BlockLength; + unsigned int ExecCount; + bool NextWindow; + + // position of parent filter in Filters array used as prototype for filter + // in PrgStack array. Not defined for filters in Filters array. + unsigned int ParentFilter; + + VM_PreparedProgram Prg; +}; + +/***************************** Unpack v 2.0 *********************************/ +struct MultDecode +{ + unsigned int MaxNum; + unsigned int DecodeLen[16]; + unsigned int DecodePos[16]; + unsigned int DecodeNum[MC20]; +}; + +struct AudioVariables +{ + int K1,K2,K3,K4,K5; + int D1,D2,D3,D4; + int LastDelta; + unsigned int Dif[11]; + unsigned int ByteCount; + int LastChar; +}; +/***************************** Unpack v 2.0 *********************************/ + + +class Unpack:private BitInput +{ + private: + friend class Pack; + + void Unpack29(bool Solid); + bool UnpReadBuf(); + void UnpWriteBuf(); + void ExecuteCode(VM_PreparedProgram *Prg); + void UnpWriteArea(unsigned int StartPtr,unsigned int EndPtr); + void UnpWriteData(byte *Data,size_t Size); + bool ReadTables(); + void MakeDecodeTables(unsigned char *LenTab,struct Decode *Dec,int Size); + int DecodeNumber(struct Decode *Dec); + void CopyString(); + inline void InsertOldDist(unsigned int Distance); + inline void InsertLastMatch(unsigned int Length,unsigned int Distance); + void UnpInitData(int Solid); + void CopyString(unsigned int Length,unsigned int Distance); + bool ReadEndOfBlock(); + bool ReadVMCode(); + bool ReadVMCodePPM(); + bool AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize); + void InitFilters(); + + ComprDataIO *UnpIO; + ModelPPM PPM; + int PPMEscChar; + + RarVM VM; + + /* Filters code, one entry per filter */ + Array<UnpackFilter*> Filters; + + /* Filters stack, several entrances of same filter are possible */ + Array<UnpackFilter*> PrgStack; + + /* lengths of preceding blocks, one length per filter. Used to reduce + size required to write block length if lengths are repeating */ + Array<int> OldFilterLengths; + + int LastFilter; + + bool TablesRead; + struct LitDecode LD; + struct DistDecode DD; + struct LowDistDecode LDD; + struct RepDecode RD; + struct BitDecode BD; + + unsigned int OldDist[4],OldDistPtr; + unsigned int LastDist,LastLength; + + unsigned int UnpPtr,WrPtr; + + // Top border of read packed data. + int ReadTop; + + // Border to call UnpReadBuf. We use it instead of (ReadTop-C) + // for optimization reasons. Ensures that we have C bytes in buffer + // unless we are at the end of file. + int ReadBorder; + + unsigned char UnpOldTable[HUFF_TABLE_SIZE]; + + int UnpBlockType; + + byte *Window; + bool ExternalWindow; + + + int64 DestUnpSize; + + bool Suspended; + bool UnpAllBuf; + bool UnpSomeRead; + int64 WrittenFileSize; + bool FileExtracted; + + int PrevLowDist,LowDistRepCount; + +/***************************** Unpack v 1.5 *********************************/ + void Unpack15(bool Solid); + void ShortLZ(); + void LongLZ(); + void HuffDecode(); + void GetFlagsBuf(); + void OldUnpInitData(int Solid); + void InitHuff(); + void CorrHuff(unsigned int *CharSet,unsigned int *NumToPlace); + void OldCopyString(unsigned int Distance,unsigned int Length); + uint DecodeNum(uint Num,uint StartPos,uint *DecTab,uint *PosTab); + void OldUnpWriteBuf(); + + unsigned int ChSet[256],ChSetA[256],ChSetB[256],ChSetC[256]; + unsigned int Place[256],PlaceA[256],PlaceB[256],PlaceC[256]; + unsigned int NToPl[256],NToPlB[256],NToPlC[256]; + unsigned int FlagBuf,AvrPlc,AvrPlcB,AvrLn1,AvrLn2,AvrLn3; + int Buf60,NumHuf,StMode,LCount,FlagsCnt; + unsigned int Nhfb,Nlzb,MaxDist3; +/***************************** Unpack v 1.5 *********************************/ + +/***************************** Unpack v 2.0 *********************************/ + void Unpack20(bool Solid); + struct MultDecode MD[4]; + unsigned char UnpOldTable20[MC20*4]; + int UnpAudioBlock,UnpChannels,UnpCurChannel,UnpChannelDelta; + void CopyString20(unsigned int Length,unsigned int Distance); + bool ReadTables20(); + void UnpInitData20(int Solid); + void ReadLastTables(); + byte DecodeAudio(int Delta); + struct AudioVariables AudV[4]; +/***************************** Unpack v 2.0 *********************************/ + + public: + Unpack(ComprDataIO *DataIO); + ~Unpack(); + void Init(byte *Window=NULL); + void DoUnpack(int Method,bool Solid); + bool IsFileExtracted() {return(FileExtracted);} + void SetDestSize(int64 DestSize) {DestUnpSize=DestSize;FileExtracted=false;} + void SetSuspended(bool Suspended) {Unpack::Suspended=Suspended;} + + unsigned int GetChar() + { + if (InAddr>BitInput::MAX_SIZE-30) + UnpReadBuf(); + return(InBuf[InAddr++]); + } +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/version.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/version.hpp new file mode 100644 index 00000000..bb96a923 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/version.hpp @@ -0,0 +1,6 @@ +#define RARVER_MAJOR 3 +#define RARVER_MINOR 91 +#define RARVER_BETA 0 +#define RARVER_DAY 12 +#define RARVER_MONTH 12 +#define RARVER_YEAR 2009 diff --git a/plugins/snes9x_gx/portlibs/include/libunrar/volume.hpp b/plugins/snes9x_gx/portlibs/include/libunrar/volume.hpp new file mode 100644 index 00000000..6bf4c9e7 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/libunrar/volume.hpp @@ -0,0 +1,11 @@ +#ifndef _RAR_VOLUME_ +#define _RAR_VOLUME_ + +void SplitArchive(Archive &Arc,FileHeader *fh,int64 *HeaderPos, + ComprDataIO *DataIO); +bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName, + char Command); +void SetVolWrite(Archive &Dest,int64 VolSize); +bool AskNextVol(char *ArcName); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/mupdf/fitz.h b/plugins/snes9x_gx/portlibs/include/mupdf/fitz.h new file mode 100644 index 00000000..caba61e4 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/mupdf/fitz.h @@ -0,0 +1,10 @@ +#ifndef _FITZ_H_ +#define _FITZ_H_ + +#include "fitz_base.h" +#include "fitz_stream.h" +#include "fitz_res.h" +#include "fitz_draw.h" + +#endif + diff --git a/plugins/snes9x_gx/portlibs/include/mupdf/fitz_base.h b/plugins/snes9x_gx/portlibs/include/mupdf/fitz_base.h new file mode 100644 index 00000000..9ef1cf46 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/mupdf/fitz_base.h @@ -0,0 +1,249 @@ +/* + * Include the basic standard libc headers. + */ + +#ifndef _FITZ_BASE_H_ +#define _FITZ_BASE_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <assert.h> +#include <stdarg.h> + +#include <limits.h> /* INT_MIN, MAX ... */ +#include <float.h> /* DBL_EPSILON */ +#include <math.h> + +#include <errno.h> +#include <fcntl.h> /* O_RDONLY & co */ + +/* Stupid macros that don't exist everywhere */ + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 +#endif + +#ifdef _MSC_VER /* stupid stone-age compiler */ + +#include <io.h> + +extern int gettimeofday(struct timeval *tv, struct timezone *tz); + +#define restrict + +#define inline __inline + +#define __func__ __FUNCTION__ + +#define snprintf _snprintf + +#if _MSC_VER < 1500 +#define vsnprintf _vsnprintf +#endif + +#else /* C99 or close enough */ + +#include <unistd.h> + +#endif + +/* + * CPU detection and flags + */ + +#if defined(ARCH_X86) || defined(ARCH_X86_64) +# define HAVE_CPUDEP +# define HAVE_MMX (1<<0) +# define HAVE_MMXEXT (1<<1) +# define HAVE_SSE (1<<2) +# define HAVE_SSE2 (1<<3) +# define HAVE_SSE3 (1<<4) +# define HAVE_3DNOW (1<<5) +# define HAVE_AMD64 (1<<6) +#endif + +/* call this before using fitz */ +extern void fz_cpudetect(void); + +/* treat as constant! */ +extern unsigned fz_cpuflags; + +/* + * Base Fitz runtime. + */ + +#ifndef __printflike +#if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7 +#define __printflike(fmtarg, firstvararg) \ + __attribute__((__format__ (__printf__, fmtarg, firstvararg))) +#else +#define __printflike(fmtarg, firstvararg) +#endif +#endif + +#ifndef nil +#define nil ((void*)0) +#endif + +#ifndef offsetof +#define offsetof(s, m) (unsigned long)(&(((s*)0)->m)) +#endif + +#ifndef nelem +#define nelem(x) (sizeof(x)/sizeof((x)[0])) +#endif + +#ifndef ABS +#define ABS(x) ( (x) < 0 ? -(x) : (x) ) +#endif + +#ifndef MAX +#define MAX(a,b) ( (a) > (b) ? (a) : (b) ) +#endif + +#ifndef MIN +#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) +#endif + +#ifndef CLAMP +#define CLAMP(x,a,b) ( (x) > (b) ? (b) : ( (x) < (a) ? (a) : (x) ) ) +#endif + +/* utf-8 encoding and decoding */ +int chartorune(int *rune, char *str); +int runetochar(char *str, int *rune); +int runelen(int c); + +/* useful string functions */ +extern char *fz_strsep(char **stringp, const char *delim); +extern int fz_strlcpy(char *dst, const char *src, int n); +extern int fz_strlcat(char *dst, const char *src, int n); + +/* getopt */ +extern int fz_getopt(int nargc, char * const * nargv, const char *ostr); +extern int fz_opterr, fz_optind, fz_optopt; +extern char *fz_optarg; + +/* memory allocation */ +void *fz_malloc(int n); +void *fz_realloc(void *p, int n); +void fz_free(void *p); +char *fz_strdup(char *s); + +/* + * Error handling. + */ + +typedef int fz_error; + +extern char fz_errorbuf[]; + +void fz_warn(char *fmt, ...) __printflike(1,2); +fz_error fz_throwimp(const char *file, int line, const char *func, char *fmt, ...) __printflike(4, 5); +fz_error fz_rethrowimp(fz_error cause, const char *file, int line, const char *func, char *fmt, ...) __printflike(5, 6); +fz_error fz_catchimp(fz_error cause, const char *file, int line, const char *func, char *fmt, ...) __printflike(5, 6); + +#define fz_throw(...) fz_throwimp(__FILE__, __LINE__, __func__, __VA_ARGS__) +#define fz_rethrow(cause, ...) fz_rethrowimp(cause, __FILE__, __LINE__, __func__, __VA_ARGS__) +#define fz_catch(cause, ...) fz_catchimp(cause, __FILE__, __LINE__, __func__, __VA_ARGS__) +#define fz_okay ((fz_error)0) + +/* + * Generic hash-table with fixed-length keys. + */ + +typedef struct fz_hashtable_s fz_hashtable; + +fz_hashtable * fz_newhash(int initialsize, int keylen); +void fz_debughash(fz_hashtable *table); +void fz_emptyhash(fz_hashtable *table); +void fz_drophash(fz_hashtable *table); + +void *fz_hashfind(fz_hashtable *table, void *key); +void fz_hashinsert(fz_hashtable *table, void *key, void *val); +void fz_hashremove(fz_hashtable *table, void *key); + +int fz_hashlen(fz_hashtable *table); +void *fz_hashgetkey(fz_hashtable *table, int idx); +void *fz_hashgetval(fz_hashtable *table, int idx); + +/* + * Math and geometry + */ + +/* multiply 8-bit fixpoint (0..1) so that 0*0==0 and 255*255==255 */ +#define fz_mul255(a,b) (((a) * ((b) + ((b) >> 7))) >> 8) + +typedef struct fz_matrix_s fz_matrix; +typedef struct fz_point_s fz_point; +typedef struct fz_rect_s fz_rect; +typedef struct fz_bbox_s fz_bbox; + +extern const fz_rect fz_unitrect; +extern const fz_rect fz_emptyrect; +extern const fz_rect fz_infiniterect; + +extern const fz_bbox fz_unitbbox; +extern const fz_bbox fz_emptybbox; +extern const fz_bbox fz_infinitebbox; + +#define fz_isemptyrect(r) ((r).x0 == (r).x1) +#define fz_isinfiniterect(r) ((r).x0 > (r).x1) + +/* + / a b 0 \ + | c d 0 | + \ e f 1 / +*/ +struct fz_matrix_s +{ + float a, b, c, d, e, f; +}; + +struct fz_point_s +{ + float x, y; +}; + +struct fz_rect_s +{ + float x0, y0; + float x1, y1; +}; + +struct fz_bbox_s +{ + int x0, y0; + int x1, y1; +}; + +void fz_invert3x3(float *dst, float *m); + +fz_matrix fz_concat(fz_matrix one, fz_matrix two); +fz_matrix fz_identity(void); +fz_matrix fz_scale(float sx, float sy); +fz_matrix fz_rotate(float theta); +fz_matrix fz_translate(float tx, float ty); +fz_matrix fz_invertmatrix(fz_matrix m); +int fz_isrectilinear(fz_matrix m); +float fz_matrixexpansion(fz_matrix m); + +fz_bbox fz_roundrect(fz_rect r); +fz_bbox fz_intersectbbox(fz_bbox a, fz_bbox b); +fz_bbox fz_unionbbox(fz_bbox a, fz_bbox b); + +fz_point fz_transformpoint(fz_matrix m, fz_point p); +fz_rect fz_transformrect(fz_matrix m, fz_rect r); + +#endif + diff --git a/plugins/snes9x_gx/portlibs/include/mupdf/fitz_draw.h b/plugins/snes9x_gx/portlibs/include/mupdf/fitz_draw.h new file mode 100644 index 00000000..673a9633 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/mupdf/fitz_draw.h @@ -0,0 +1,121 @@ +/* + * Draw device and the graphics library. + */ + +typedef struct fz_glyphcache_s fz_glyphcache; + +fz_glyphcache * fz_newglyphcache(void); +fz_pixmap * fz_renderftglyph(fz_font *font, int cid, fz_matrix trm); +fz_pixmap * fz_rendert3glyph(fz_font *font, int cid, fz_matrix trm); +fz_pixmap * fz_renderglyph(fz_glyphcache*, fz_font*, int, fz_matrix); +void fz_evictglyphcache(fz_glyphcache *); +void fz_freeglyphcache(fz_glyphcache *); + +fz_device *fz_newdrawdevice(fz_glyphcache *cache, fz_pixmap *dest); + +/* + * Scan converter + */ + +typedef struct fz_edge_s fz_edge; +typedef struct fz_gel_s fz_gel; +typedef struct fz_ael_s fz_ael; + +struct fz_edge_s +{ + int x, e, h, y; + int adjup, adjdown; + int xmove; + int xdir, ydir; /* -1 or +1 */ +}; + +struct fz_gel_s +{ + fz_bbox clip; + fz_bbox bbox; + int cap; + int len; + fz_edge *edges; +}; + +struct fz_ael_s +{ + int cap; + int len; + fz_edge **edges; +}; + +fz_gel * fz_newgel(void); +void fz_insertgel(fz_gel *gel, float x0, float y0, float x1, float y1); +fz_bbox fz_boundgel(fz_gel *gel); +void fz_resetgel(fz_gel *gel, fz_bbox clip); +void fz_sortgel(fz_gel *gel); +void fz_freegel(fz_gel *gel); + +fz_ael * fz_newael(void); +void fz_freeael(fz_ael *ael); + +fz_error fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill, + fz_bbox clip, fz_pixmap *pix, unsigned char *argb, int over); + +void fz_fillpath(fz_gel *gel, fz_path *path, fz_matrix ctm, float flatness); +void fz_strokepath(fz_gel *gel, fz_path *path, fz_strokestate *stroke, fz_matrix ctm, float flatness, float linewidth); +void fz_dashpath(fz_gel *gel, fz_path *path, fz_strokestate *stroke, fz_matrix ctm, float flatness, float linewidth); + +/* + * Function pointers -- they can be replaced by cpu-optimized versions + */ + +#define FZ_PSRC \ + unsigned char *src, int srcw, int srch +#define FZ_PDST \ + unsigned char *dst0, int dstw +#define FZ_PCTM \ + int u0, int v0, int fa, int fb, int fc, int fd, int w0, int h + +extern void fz_accelerate(void); + +extern void (*fz_duff_non)(unsigned char*,int,int,unsigned char*,int,int,int); +extern void (*fz_duff_nimcn)(unsigned char*,int,int,unsigned char*,int,int,unsigned char*,int,int,int); +extern void (*fz_duff_nimon)(unsigned char*,int,int,unsigned char*,int,int,unsigned char*,int,int,int); +extern void (*fz_duff_1o1)(unsigned char*,int,unsigned char*,int,int,int); +extern void (*fz_duff_4o4)(unsigned char*,int,unsigned char*,int,int,int); +extern void (*fz_duff_1i1c1)(unsigned char*,int,unsigned char*,int,unsigned char*,int,int,int); +extern void (*fz_duff_4i1c4)(unsigned char*,int,unsigned char*,int,unsigned char*,int,int,int); +extern void (*fz_duff_1i1o1)(unsigned char*,int,unsigned char*,int,unsigned char*,int,int,int); +extern void (*fz_duff_4i1o4)(unsigned char*,int,unsigned char*,int,unsigned char*,int,int,int); + +extern void (*fz_path_1c1)(unsigned char*,unsigned char,int,unsigned char*); +extern void (*fz_path_1o1)(unsigned char*,unsigned char,int,unsigned char*); +extern void (*fz_path_w4i1o4)(unsigned char*,unsigned char*,unsigned char,int,unsigned char*); + +extern void (*fz_text_1c1)(unsigned char*,int,unsigned char*,int,int,int); +extern void (*fz_text_1o1)(unsigned char*,int,unsigned char*,int,int,int); +extern void (*fz_text_w4i1o4)(unsigned char*,unsigned char*,int,unsigned char*,int,int,int); + +extern void (*fz_img_ncn)(FZ_PSRC, int sn, FZ_PDST, FZ_PCTM); +extern void (*fz_img_1c1)(FZ_PSRC, FZ_PDST, FZ_PCTM); +extern void (*fz_img_4c4)(FZ_PSRC, FZ_PDST, FZ_PCTM); +extern void (*fz_img_1o1)(FZ_PSRC, FZ_PDST, FZ_PCTM); +extern void (*fz_img_4o4)(FZ_PSRC, FZ_PDST, FZ_PCTM); +extern void (*fz_img_w4i1o4)(unsigned char*,FZ_PSRC,FZ_PDST,FZ_PCTM); + +extern void (*fz_decodetile)(fz_pixmap *pix, int skip, float *decode); +extern void (*fz_loadtile1)(unsigned char*, int sw, unsigned char*, int dw, int w, int h, int pad); +extern void (*fz_loadtile2)(unsigned char*, int sw, unsigned char*, int dw, int w, int h, int pad); +extern void (*fz_loadtile4)(unsigned char*, int sw, unsigned char*, int dw, int w, int h, int pad); +extern void (*fz_loadtile8)(unsigned char*, int sw, unsigned char*, int dw, int w, int h, int pad); +extern void (*fz_loadtile16)(unsigned char*, int sw, unsigned char*, int dw, int w, int h, int pad); + +extern void (*fz_srown)(unsigned char *src, unsigned char *dst, int w, int denom, int n); +extern void (*fz_srow1)(unsigned char *src, unsigned char *dst, int w, int denom); +extern void (*fz_srow2)(unsigned char *src, unsigned char *dst, int w, int denom); +extern void (*fz_srow4)(unsigned char *src, unsigned char *dst, int w, int denom); +extern void (*fz_srow5)(unsigned char *src, unsigned char *dst, int w, int denom); + +extern void (*fz_scoln)(unsigned char *src, unsigned char *dst, int w, int denom, int n); +extern void (*fz_scol1)(unsigned char *src, unsigned char *dst, int w, int denom); +extern void (*fz_scol2)(unsigned char *src, unsigned char *dst, int w, int denom); +extern void (*fz_scol4)(unsigned char *src, unsigned char *dst, int w, int denom); +extern void (*fz_scol5)(unsigned char *src, unsigned char *dst, int w, int denom); + diff --git a/plugins/snes9x_gx/portlibs/include/mupdf/fitz_res.h b/plugins/snes9x_gx/portlibs/include/mupdf/fitz_res.h new file mode 100644 index 00000000..6b16b8a4 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/mupdf/fitz_res.h @@ -0,0 +1,385 @@ +/* + * Resources and other graphics related objects. + */ + +typedef struct fz_pixmap_s fz_pixmap; +typedef struct fz_colorspace_s fz_colorspace; +typedef struct fz_path_s fz_path; +typedef struct fz_text_s fz_text; +typedef struct fz_font_s fz_font; +typedef struct fz_shade_s fz_shade; + +typedef struct fz_strokestate_s fz_strokestate; + +enum { FZ_MAXCOLORS = 32 }; + +typedef enum fz_blendkind_e +{ + /* PDF 1.4 -- standard separable */ + FZ_BNORMAL, + FZ_BMULTIPLY, + FZ_BSCREEN, + FZ_BOVERLAY, + FZ_BDARKEN, + FZ_BLIGHTEN, + FZ_BCOLORDODGE, + FZ_BCOLORBURN, + FZ_BHARDLIGHT, + FZ_BSOFTLIGHT, + FZ_BDIFFERENCE, + FZ_BEXCLUSION, + + /* PDF 1.4 -- standard non-separable */ + FZ_BHUE, + FZ_BSATURATION, + FZ_BCOLOR, + FZ_BLUMINOSITY +} fz_blendkind; + +/* +pixmaps have n components per pixel. the first is always alpha. +premultiplied alpha when rendering, but non-premultiplied for colorspace +conversions and rescaling. +*/ + +extern fz_colorspace *pdf_devicegray; +extern fz_colorspace *pdf_devicergb; +extern fz_colorspace *pdf_devicecmyk; +extern fz_colorspace *pdf_devicelab; +extern fz_colorspace *pdf_devicepattern; + +struct fz_pixmap_s +{ + int refs; + int x, y, w, h, n; + fz_colorspace *colorspace; + unsigned char *samples; +}; + +fz_pixmap * fz_newpixmapwithrect(fz_colorspace *, fz_bbox bbox); +fz_pixmap * fz_newpixmap(fz_colorspace *, int x, int y, int w, int h); +fz_pixmap *fz_keeppixmap(fz_pixmap *map); +void fz_droppixmap(fz_pixmap *map); + +void fz_debugpixmap(fz_pixmap *map, char *prefix); +void fz_clearpixmap(fz_pixmap *map, unsigned char value); + +fz_pixmap * fz_scalepixmap(fz_pixmap *src, int xdenom, int ydenom); + +/* + * The device interface. + */ + +typedef struct fz_device_s fz_device; + +struct fz_device_s +{ + void *user; + void (*freeuser)(void *); + + void (*fillpath)(void *, fz_path *, int evenodd, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*strokepath)(void *, fz_path *, fz_strokestate *, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*clippath)(void *, fz_path *, int evenodd, fz_matrix); + void (*clipstrokepath)(void *, fz_path *, fz_strokestate *, fz_matrix); + + void (*filltext)(void *, fz_text *, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*stroketext)(void *, fz_text *, fz_strokestate *, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*cliptext)(void *, fz_text *, fz_matrix, int accumulate); + void (*clipstroketext)(void *, fz_text *, fz_strokestate *, fz_matrix); + void (*ignoretext)(void *, fz_text *, fz_matrix); + + void (*fillshade)(void *, fz_shade *shd, fz_matrix ctm); + void (*fillimage)(void *, fz_pixmap *img, fz_matrix ctm); + void (*fillimagemask)(void *, fz_pixmap *img, fz_matrix ctm, fz_colorspace *, float *color, float alpha); + void (*clipimagemask)(void *, fz_pixmap *img, fz_matrix ctm); + + void (*popclip)(void *); +}; + +fz_device *fz_newdevice(void *user); +void fz_freedevice(fz_device *dev); + +fz_device *fz_newtracedevice(void); + +fz_device *fz_newbboxdevice(fz_bbox *bboxp); + +/* Text extraction device */ + +typedef struct fz_textspan_s fz_textspan; +typedef struct fz_textchar_s fz_textchar; + +struct fz_textchar_s +{ + int c; + fz_bbox bbox; +}; + +struct fz_textspan_s +{ + fz_font *font; + float size; + int len, cap; + fz_textchar *text; + fz_textspan *next; + int eol; +}; + +fz_textspan * fz_newtextspan(void); +void fz_freetextspan(fz_textspan *line); +void fz_debugtextspan(fz_textspan *line); +void fz_debugtextspanxml(fz_textspan *span); + +fz_device *fz_newtextdevice(fz_textspan *text); + +/* Display list device -- record and play back device commands. */ + +typedef struct fz_displaylist_s fz_displaylist; +typedef struct fz_displaynode_s fz_displaynode; + +typedef enum fz_displaycommand_e +{ + FZ_CMDFILLPATH, + FZ_CMDSTROKEPATH, + FZ_CMDCLIPPATH, + FZ_CMDCLIPSTROKEPATH, + FZ_CMDFILLTEXT, + FZ_CMDSTROKETEXT, + FZ_CMDCLIPTEXT, + FZ_CMDCLIPSTROKETEXT, + FZ_CMDIGNORETEXT, + FZ_CMDFILLSHADE, + FZ_CMDFILLIMAGE, + FZ_CMDFILLIMAGEMASK, + FZ_CMDCLIPIMAGEMASK, + FZ_CMDPOPCLIP, +} fz_displaycommand; + +struct fz_displaylist_s +{ + fz_displaynode *first; + fz_displaynode *last; +}; + +struct fz_displaynode_s +{ + fz_displaycommand cmd; + fz_displaynode *next; + union { + fz_path *path; + fz_text *text; + fz_shade *shade; + fz_pixmap *image; + } item; + fz_strokestate *stroke; + int flag; /* evenodd, accumulate, ... */ + fz_matrix ctm; + fz_colorspace *colorspace; + float alpha; + float color[FZ_MAXCOLORS]; +}; + +fz_displaylist *fz_newdisplaylist(void); +void fz_freedisplaylist(fz_displaylist *list); +fz_device *fz_newlistdevice(fz_displaylist *list); +void fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix ctm); + +/* + * Vector path buffer. + * It can be stroked and dashed, or be filled. + * It has a fill rule (nonzero or evenodd). + * + * When rendering, they are flattened, stroked and dashed straight + * into the Global Edge List. + */ + +typedef union fz_pathel_s fz_pathel; + +typedef enum fz_pathelkind_e +{ + FZ_MOVETO, + FZ_LINETO, + FZ_CURVETO, + FZ_CLOSEPATH +} fz_pathelkind; + +union fz_pathel_s +{ + fz_pathelkind k; + float v; +}; + +struct fz_strokestate_s +{ + int linecap; + int linejoin; + float linewidth; + float miterlimit; + float dashphase; + int dashlen; + float dashlist[32]; +}; + +struct fz_path_s +{ + int len, cap; + fz_pathel *els; +}; + +fz_path *fz_newpath(void); +void fz_moveto(fz_path*, float x, float y); +void fz_lineto(fz_path*, float x, float y); +void fz_curveto(fz_path*, float, float, float, float, float, float); +void fz_curvetov(fz_path*, float, float, float, float); +void fz_curvetoy(fz_path*, float, float, float, float); +void fz_closepath(fz_path*); +void fz_freepath(fz_path *path); + +fz_path *fz_clonepath(fz_path *old); + +fz_rect fz_boundpath(fz_path *path, fz_strokestate *stroke, fz_matrix ctm); +void fz_debugpath(fz_path *, int indent); + +/* + * Text buffer. + * + * The trm field contains the a, b, c and d coefficients. + * The e and f coefficients come from the individual elements, + * together they form the transform matrix for the glyph. + * + * Glyphs are referenced by glyph ID. + * The Unicode text equivalent is kept in a separate array + * with indexes into the glyph array. + */ + +typedef struct fz_textel_s fz_textel; + +struct fz_textel_s +{ + float x, y; + int gid; + int ucs; +}; + +struct fz_text_s +{ + fz_font *font; + fz_matrix trm; + int len, cap; + fz_textel *els; +}; + +fz_text * fz_newtext(fz_font *face); +void fz_addtext(fz_text *text, int gid, int ucs, float x, float y); +void fz_endtext(fz_text *text); +void fz_freetext(fz_text *text); +void fz_debugtext(fz_text*, int indent); +fz_rect fz_boundtext(fz_text *text, fz_matrix ctm); +fz_text *fz_clonetext(fz_text *old); + +/* + * Colorspace resources. + * + * TODO: use lcms + */ + +struct fz_colorspace_s +{ + int refs; + char name[16]; + int n; + void (*convpixmap)(fz_colorspace *ss, fz_pixmap *sp, fz_colorspace *ds, fz_pixmap *dp); + void (*convcolor)(fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv); + void (*toxyz)(fz_colorspace *, float *src, float *xyz); + void (*fromxyz)(fz_colorspace *, float *xyz, float *dst); + void (*freefunc)(fz_colorspace *); +}; + +fz_colorspace *fz_keepcolorspace(fz_colorspace *cs); +void fz_dropcolorspace(fz_colorspace *cs); + +void fz_convertcolor(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv); +void fz_convertpixmap(fz_colorspace *srcs, fz_pixmap *srcv, fz_colorspace *dsts, fz_pixmap *dstv); + +void fz_stdconvcolor(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv); +void fz_stdconvpixmap(fz_colorspace *srcs, fz_pixmap *srcv, fz_colorspace *dsts, fz_pixmap *dstv); + +/* + * Fonts. + * + * Fonts come in three variants: + * Regular fonts are handled by FreeType. + * Type 3 fonts have callbacks to the interpreter. + * Substitute fonts are a thin wrapper over a regular font that adjusts metrics. + */ + +char *ft_errorstring(int err); + +struct fz_font_s +{ + int refs; + char name[32]; + + void *ftface; /* has an FT_Face if used */ + int ftsubstitute; /* ... substitute metrics */ + int fthint; /* ... force hinting for DynaLab fonts */ + + fz_matrix t3matrix; + fz_obj *t3resources; + fz_buffer **t3procs; /* has 256 entries if used */ + float *t3widths; /* has 256 entries if used */ + void *t3xref; /* a pdf_xref for the callback */ + fz_error (*t3runcontentstream)(fz_device *dev, fz_matrix ctm, + struct pdf_xref_s *xref, fz_obj *resources, fz_buffer *contents); + + fz_rect bbox; + + /* substitute metrics */ + int widthcount; + int *widthtable; +}; + +fz_error fz_newfreetypefont(fz_font **fontp, char *name, int substitute); +fz_error fz_loadfreetypefontfile(fz_font *font, char *path, int index); +fz_error fz_loadfreetypefontbuffer(fz_font *font, unsigned char *data, int len, int index); +fz_font * fz_newtype3font(char *name, fz_matrix matrix); + +fz_error fz_newfontfrombuffer(fz_font **fontp, unsigned char *data, int len, int index); +fz_error fz_newfontfromfile(fz_font **fontp, char *path, int index); + +fz_font * fz_keepfont(fz_font *font); +void fz_dropfont(fz_font *font); + +void fz_debugfont(fz_font *font); +void fz_setfontbbox(fz_font *font, float xmin, float ymin, float xmax, float ymax); + +/* + * The shading code is in rough shape but the general architecture is sound. + */ + +struct fz_shade_s +{ + int refs; + + fz_rect bbox; /* can be fz_infiniterect */ + fz_colorspace *cs; + + fz_matrix matrix; /* matrix from pattern dict */ + int usebackground; /* background color for fills but not 'sh' */ + float background[FZ_MAXCOLORS]; + + int usefunction; + float function[256][FZ_MAXCOLORS]; + + int meshlen; + int meshcap; + float *mesh; /* [x y t] or [x y c1 ... cn] * 3 * meshlen */ +}; + + +fz_shade *fz_keepshade(fz_shade *shade); +void fz_dropshade(fz_shade *shade); +void fz_debugshade(fz_shade *shade); + +fz_rect fz_boundshade(fz_shade *shade, fz_matrix ctm); +void fz_rendershade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dst); + diff --git a/plugins/snes9x_gx/portlibs/include/mupdf/fitz_stream.h b/plugins/snes9x_gx/portlibs/include/mupdf/fitz_stream.h new file mode 100644 index 00000000..8689677e --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/mupdf/fitz_stream.h @@ -0,0 +1,401 @@ +/* + * Dynamic objects. + * The same type of objects as found in PDF and PostScript. + * Used by the filter library and the mupdf parser. + */ + +#ifndef _FITZ_STREAM_H_ +#define _FITZ_STREAM_H_ + +typedef struct fz_obj_s fz_obj; +typedef struct fz_keyval_s fz_keyval; + +typedef enum fz_objkind_e +{ + FZ_NULL, + FZ_BOOL, + FZ_INT, + FZ_REAL, + FZ_STRING, + FZ_NAME, + FZ_ARRAY, + FZ_DICT, + FZ_INDIRECT +} fz_objkind; + +struct fz_keyval_s +{ + fz_obj *k; + fz_obj *v; +}; + +struct fz_obj_s +{ + int refs; + fz_objkind kind; + union + { + int b; + int i; + float f; + struct { + unsigned short len; + char buf[1]; + } s; + char n[1]; + struct { + int len; + int cap; + fz_obj **items; + } a; + struct { + char sorted; + int len; + int cap; + fz_keyval *items; + } d; + struct { + int num; + int gen; + struct pdf_xref_s *xref; + fz_obj *obj; + } r; + } u; +}; + +fz_obj * fz_newnull(void); +fz_obj * fz_newbool(int b); +fz_obj * fz_newint(int i); +fz_obj * fz_newreal(float f); +fz_obj * fz_newname(char *str); +fz_obj * fz_newstring(char *str, int len); +fz_obj * fz_newindirect(int num, int gen, struct pdf_xref_s *xref); + +fz_obj * fz_newarray(int initialcap); +fz_obj * fz_newdict(int initialcap); +fz_obj * fz_copyarray(fz_obj *array); +fz_obj * fz_copydict(fz_obj *dict); + +fz_obj *fz_keepobj(fz_obj *obj); +void fz_dropobj(fz_obj *obj); + +/* type queries */ +int fz_isnull(fz_obj *obj); +int fz_isbool(fz_obj *obj); +int fz_isint(fz_obj *obj); +int fz_isreal(fz_obj *obj); +int fz_isname(fz_obj *obj); +int fz_isstring(fz_obj *obj); +int fz_isarray(fz_obj *obj); +int fz_isdict(fz_obj *obj); +int fz_isindirect(fz_obj *obj); + +int fz_objcmp(fz_obj *a, fz_obj *b); + +fz_obj *fz_resolveindirect(fz_obj *obj); + +/* silent failure, no error reporting */ +int fz_tobool(fz_obj *obj); +int fz_toint(fz_obj *obj); +float fz_toreal(fz_obj *obj); +char *fz_toname(fz_obj *obj); +char *fz_tostrbuf(fz_obj *obj); +int fz_tostrlen(fz_obj *obj); +int fz_tonum(fz_obj *obj); +int fz_togen(fz_obj *obj); + +int fz_arraylen(fz_obj *array); +fz_obj *fz_arrayget(fz_obj *array, int i); +void fz_arrayput(fz_obj *array, int i, fz_obj *obj); +void fz_arraypush(fz_obj *array, fz_obj *obj); + +int fz_dictlen(fz_obj *dict); +fz_obj *fz_dictgetkey(fz_obj *dict, int idx); +fz_obj *fz_dictgetval(fz_obj *dict, int idx); +fz_obj *fz_dictget(fz_obj *dict, fz_obj *key); +fz_obj *fz_dictgets(fz_obj *dict, char *key); +fz_obj *fz_dictgetsa(fz_obj *dict, char *key, char *abbrev); +void fz_dictput(fz_obj *dict, fz_obj *key, fz_obj *val); +void fz_dictputs(fz_obj *dict, char *key, fz_obj *val); +void fz_dictdel(fz_obj *dict, fz_obj *key); +void fz_dictdels(fz_obj *dict, char *key); +void fz_sortdict(fz_obj *dict); + +int fz_sprintobj(char *s, int n, fz_obj *obj, int tight); +int fz_fprintobj(FILE *fp, fz_obj *obj, int tight); +void fz_debugobj(fz_obj *obj); + +char *fz_objkindstr(fz_obj *obj); + +/* + * Data buffers for streams and filters. + * + * bp is the pointer to the allocated memory + * rp is read-position (*in->rp++ to read data) + * wp is write-position (*out->wp++ to write data) + * ep is the sentinel + * + * Only the data between rp and wp is valid data. + * + * Writers set eof to true at the end. + * Readers look at eof. + * + * A buffer owns the memory it has allocated, unless ownsdata is false, + * in which case the creator of the buffer owns it. + */ + +typedef struct fz_buffer_s fz_buffer; + +#define FZ_BUFSIZE (8 * 1024) + +struct fz_buffer_s +{ + int refs; + int ownsdata; + unsigned char *bp; + unsigned char *rp; + unsigned char *wp; + unsigned char *ep; + int eof; +}; + +fz_buffer * fz_newbuffer(int size); +fz_buffer * fz_newbufferwithmemory(unsigned char *data, int size); + +void fz_rewindbuffer(fz_buffer *buf); +void fz_growbuffer(fz_buffer *buf); + +fz_buffer *fz_keepbuffer(fz_buffer *buf); +void fz_dropbuffer(fz_buffer *buf); + +/* + * Data filters for encryption, compression and decompression. + * + * A filter has one method, process, that takes an input and an output buffer. + * + * It returns one of three statuses: + * ioneedin -- input buffer exhausted, please give me more data (wp-rp) + * ioneedout -- output buffer exhausted, please provide more space (ep-wp) + * iodone -- finished, please never call me again. ever! + * or... + * any other error code -- oops, something blew up. + * + * To make using the filter easier, three variables are updated: + * produced -- if we actually produced any new data + * consumed -- like above + * count -- number of bytes produced in total since the beginning + * done -- remember if we've ever returned fz_iodone + * + * Most filters take fz_obj as a way to specify parameters. + * In most cases, this is a dictionary that contains the same keys + * that the corresponding PDF filter would expect. + * + * The pipeline filter is special, and needs some care when chaining + * and unchaining new filters. + */ + +typedef struct fz_filter_s fz_filter; + +#define fz_ioneedin ((fz_error)1) +#define fz_ioneedout ((fz_error)2) +#define fz_iodone ((fz_error)3) + +/* + * Evil looking macro to create an initialize a filter struct. + */ + +#define FZ_NEWFILTER(TYPE,VAR,NAME) \ + fz_error fz_process ## NAME (fz_filter*,fz_buffer*,fz_buffer*); \ + void fz_drop ## NAME (fz_filter*); \ + TYPE *VAR; \ + VAR = fz_malloc(sizeof(TYPE)); \ + ((fz_filter*)VAR)->refs = 1; \ + ((fz_filter*)VAR)->process = fz_process ## NAME ; \ + ((fz_filter*)VAR)->drop = fz_drop ## NAME ; \ + ((fz_filter*)VAR)->consumed = 0; \ + ((fz_filter*)VAR)->produced = 0; \ + ((fz_filter*)VAR)->count = 0; \ + ((fz_filter*)VAR)->done = 0; + +struct fz_filter_s +{ + int refs; + fz_error (*process)(fz_filter *filter, fz_buffer *in, fz_buffer *out); + void (*drop)(fz_filter *filter); + int consumed; + int produced; + int count; + int done; +}; + +fz_error fz_process(fz_filter *f, fz_buffer *in, fz_buffer *out); +fz_filter *fz_keepfilter(fz_filter *f); +void fz_dropfilter(fz_filter *f); + +fz_filter * fz_newpipeline(fz_filter *head, fz_filter *tail); +fz_filter * fz_chainpipeline(fz_filter *head, fz_filter *tail, fz_buffer *buf); +void fz_unchainpipeline(fz_filter *pipe, fz_filter **oldfp, fz_buffer **oldbp); + +/* stop and reverse! special case needed for postscript only */ +void fz_pushbackahxd(fz_filter *filter, fz_buffer *in, fz_buffer *out, int n); + +fz_filter * fz_newnullfilter(int len); +fz_filter * fz_newcopyfilter(); +fz_filter * fz_newarc4filter(unsigned char *key, unsigned keylen); +fz_filter * fz_newaesdfilter(unsigned char *key, unsigned keylen); +fz_filter * fz_newa85d(fz_obj *param); +fz_filter * fz_newahxd(fz_obj *param); +fz_filter * fz_newrld(fz_obj *param); +fz_filter * fz_newdctd(fz_obj *param); +fz_filter * fz_newfaxd(fz_obj *param); +fz_filter * fz_newflated(fz_obj *param); +fz_filter * fz_newlzwd(fz_obj *param); +fz_filter * fz_newpredictd(fz_obj *param); +fz_filter * fz_newjbig2d(fz_obj *param); +fz_filter * fz_newjpxd(fz_obj *param); + +fz_error fz_setjbig2dglobalstream(fz_filter *filter, unsigned char *buf, int len); + +/* + * Basic crypto functions. + * Independent of the rest of fitz. + * For further encapsulation in filters, or not. + */ + +/* md5 digests */ + +typedef struct fz_md5_s fz_md5; + +struct fz_md5_s +{ + unsigned int state[4]; + unsigned int count[2]; + unsigned char buffer[64]; +}; + +void fz_md5init(fz_md5 *state); +void fz_md5update(fz_md5 *state, const unsigned char *input, const unsigned inlen); +void fz_md5final(fz_md5 *state, unsigned char digest[16]); + +/* arc4 crypto */ + +typedef struct fz_arc4_s fz_arc4; + +struct fz_arc4_s +{ + unsigned x; + unsigned y; + unsigned char state[256]; +}; + +void fz_arc4init(fz_arc4 *state, const unsigned char *key, const unsigned len); +unsigned char fz_arc4next(fz_arc4 *state); +void fz_arc4encrypt(fz_arc4 *state, unsigned char *dest, const unsigned char *src, const unsigned len); + +/* AES block cipher implementation from XYSSL */ + +#define AES_DECRYPT 0 +#define AES_ENCRYPT 1 + +struct fz_aes_s +{ + int nr; /* number of rounds */ + unsigned long *rk; /* AES round keys */ + unsigned long buf[68]; /* unaligned data */ +}; + +typedef struct fz_aes_s fz_aes; + +void aes_setkey_enc( fz_aes *ctx, const unsigned char *key, int keysize ); +void aes_setkey_dec( fz_aes *ctx, const unsigned char *key, int keysize ); +void aes_crypt_cbc( fz_aes *ctx, int mode, int length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/* + * Stream API for Fitz. + * Read and write data to and from files, memory buffers and filters. + */ + +typedef struct fz_stream_s fz_stream; + +enum { FZ_SFILE, FZ_SBUFFER, FZ_SFILTER }; + +struct fz_stream_s +{ + int refs; + int kind; + int dead; + fz_buffer *buffer; + fz_filter *filter; + fz_stream *chain; + fz_error error; /* delayed error from readbyte and peekbyte */ + int file; +}; + +/* + * Various stream creation functions. + */ + +fz_stream * fz_openfile(int file); +fz_stream * fz_openmemory(unsigned char *mem, int len); +fz_stream * fz_openbuffer(fz_buffer *buf); +fz_stream * fz_openfilter(fz_filter *flt, fz_stream *chain); + +/* + * Functions that are common to both input and output streams. + */ + +fz_stream *fz_keepstream(fz_stream *stm); +void fz_dropstream(fz_stream *stm); + +int fz_tell(fz_stream *stm); +fz_error fz_seek(fz_stream *stm, int offset, int whence); + +/* + * Input stream functions. + */ + +fz_error fz_readimp(fz_stream *stm); +fz_error fz_read(int *np, fz_stream *stm, unsigned char *buf, int len); +fz_error fz_readline(fz_stream *stm, char *buf, int max); +fz_buffer * fz_readall(fz_stream *stm, int sizehint); + +/* + * Error handling when reading with readbyte/peekbyte is non-standard. + * The cause of an error is stuck into the stream struct, + * and EOF is returned. Not good, but any other way is too painful. + * So we have to be careful to check the error status eventually. + */ + +fz_error fz_readerror(fz_stream *stm); +int fz_readbytex(fz_stream *stm); +int fz_peekbytex(fz_stream *stm); + +#ifdef DEBUG + +#define fz_readbyte fz_readbytex +#define fz_peekbyte fz_peekbytex + +#else + +static inline int fz_readbyte(fz_stream *stm) +{ + fz_buffer *buf = stm->buffer; + if (buf->rp < buf->wp) + return *buf->rp++; + return fz_readbytex(stm); +} + +static inline int fz_peekbyte(fz_stream *stm) +{ + fz_buffer *buf = stm->buffer; + if (buf->rp < buf->wp) + return *buf->rp; + return fz_peekbytex(stm); +} + +#endif + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/mupdf/mupdf.h b/plugins/snes9x_gx/portlibs/include/mupdf/mupdf.h new file mode 100644 index 00000000..30c329f2 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/mupdf/mupdf.h @@ -0,0 +1,680 @@ +#ifndef _MUPDF_H_ +#define _MUPDF_H_ + +#ifndef _FITZ_H_ +#error "fitz.h must be included before mupdf.h" +#endif + +typedef struct pdf_xref_s pdf_xref; + +void pdf_logxref(char *fmt, ...); +void pdf_logrsrc(char *fmt, ...); +void pdf_logfont(char *fmt, ...); +void pdf_logimage(char *fmt, ...); +void pdf_logshade(char *fmt, ...); +void pdf_logpage(char *fmt, ...); + +/* + * tokenizer and low-level object parser + */ + +typedef enum pdf_token_e +{ + PDF_TERROR, PDF_TEOF, + PDF_TOARRAY, PDF_TCARRAY, + PDF_TODICT, PDF_TCDICT, + PDF_TOBRACE, PDF_TCBRACE, + PDF_TNAME, PDF_TINT, PDF_TREAL, PDF_TSTRING, PDF_TKEYWORD, + PDF_TR, PDF_TTRUE, PDF_TFALSE, PDF_TNULL, + PDF_TOBJ, PDF_TENDOBJ, + PDF_TSTREAM, PDF_TENDSTREAM, + PDF_TXREF, PDF_TTRAILER, PDF_TSTARTXREF, + PDF_NTOKENS +} pdf_token_e; + +/* lex.c */ +fz_error pdf_lex(pdf_token_e *tok, fz_stream *f, char *buf, int n, int *len); + +/* parse.c */ +fz_error pdf_parsearray(fz_obj **op, pdf_xref *xref, fz_stream *f, char *buf, int cap); +fz_error pdf_parsedict(fz_obj **op, pdf_xref *xref, fz_stream *f, char *buf, int cap); +fz_error pdf_parsestmobj(fz_obj **op, pdf_xref *xref, fz_stream *f, char *buf, int cap); +fz_error pdf_parseindobj(fz_obj **op, pdf_xref *xref, fz_stream *f, char *buf, int cap, int *oid, int *gen, int *stmofs); + +fz_rect pdf_torect(fz_obj *array); +fz_matrix pdf_tomatrix(fz_obj *array); +char * pdf_toutf8(fz_obj *src); +unsigned short * pdf_toucs2(fz_obj *src); + +/* + * Encryption + */ + +/* Permission flag bits */ +#define PDF_PERM_PRINT (1<<2) +#define PDF_PERM_CHANGE (1<<3) +#define PDF_PERM_COPY (1<<4) +#define PDF_PERM_NOTES (1<<5) +#define PDF_PERM_FILL_FORM (1<<8) +#define PDF_PERM_ACCESSIBILITY (1<<9) +#define PDF_PERM_ASSEMBLE (1<<10) +#define PDF_PERM_HIGH_RES_PRINT (1<<11) +#define PDF_DEFAULT_PERM_FLAGS 0xfffc + +enum pdf_cryptmethod_e +{ + PDF_CRYPT_NONE, + PDF_CRYPT_RC4, + PDF_CRYPT_AESV2, + PDF_CRYPT_UNKNOWN, +}; +typedef enum pdf_cryptmethod_e pdf_cryptmethod; + +struct pdf_cryptfilter_s +{ + pdf_cryptmethod method; + int length; + unsigned char key[16]; +}; +typedef struct pdf_cryptfilter_s pdf_cryptfilter; + +struct pdf_crypt_s +{ + unsigned char idstring[32]; + int idlength; + + int v; + int length; + fz_obj *cf; + pdf_cryptfilter stmf; + pdf_cryptfilter strf; + + int r; + unsigned char o[32]; + unsigned char u[32]; + int p; + int encryptmetadata; + + unsigned char key[32]; /* decryption key generated from password */ +}; +typedef struct pdf_crypt_s pdf_crypt; + +/* crypt.c */ +fz_error pdf_newcrypt(pdf_crypt **cp, fz_obj *enc, fz_obj *id); +void pdf_freecrypt(pdf_crypt *crypt); + +fz_error pdf_parsecryptfilter(pdf_cryptfilter *cf, fz_obj *dict, int defaultlength); +fz_filter * pdf_cryptstream(pdf_crypt *crypt, pdf_cryptfilter *cf, int num, int gen); +void pdf_cryptobj(pdf_crypt *crypt, fz_obj *obj, int num, int gen); + +int pdf_needspassword(pdf_xref *xref); +int pdf_authenticatepassword(pdf_xref *xref, char *pw); + +/* + * xref and object / stream api + */ + +typedef struct pdf_xrefentry_s pdf_xrefentry; + +struct pdf_xref_s +{ + fz_stream *file; + int version; + int startxref; + pdf_crypt *crypt; + fz_obj *trailer; + + int len; + int cap; + pdf_xrefentry *table; + + struct pdf_store_s *store; + struct pdf_outline_s *outlines; + + char scratch[65536]; +}; + +struct pdf_xrefentry_s +{ + int ofs; /* file offset / objstm object number */ + int gen; /* generation / objstm index */ + int stmofs; /* on-disk stream */ + fz_obj *obj; /* stored/cached object */ + int type; /* 0=unset (f)ree i(n)use (o)bjstm */ +}; + +pdf_xref * pdf_openxref(fz_stream *file); +void pdf_closexref(pdf_xref *); +void pdf_debugxref(pdf_xref *); +void pdf_flushxref(pdf_xref *, int force); + +fz_error pdf_cacheobject(pdf_xref *, int oid, int gen); +fz_error pdf_loadobject(fz_obj **objp, pdf_xref *, int oid, int gen); + +int pdf_isstream(pdf_xref *xref, int oid, int gen); +fz_filter * pdf_buildinlinefilter(pdf_xref *xref, fz_obj *stmobj); +fz_error pdf_loadrawstream(fz_buffer **bufp, pdf_xref *xref, int oid, int gen); +fz_error pdf_loadstream(fz_buffer **bufp, pdf_xref *xref, int oid, int gen); +fz_error pdf_openrawstream(fz_stream **stmp, pdf_xref *, int oid, int gen); +fz_error pdf_openstream(fz_stream **stmp, pdf_xref *, int oid, int gen); + +/* private */ +extern fz_error pdf_repairxref(pdf_xref *xref, char *buf, int bufsize); + +/* + * Resource store + */ + +typedef struct pdf_store_s pdf_store; + +typedef enum pdf_itemkind_e +{ + PDF_KCOLORSPACE, + PDF_KFUNCTION, + PDF_KXOBJECT, + PDF_KIMAGE, + PDF_KPATTERN, + PDF_KSHADE, + PDF_KCMAP, + PDF_KFONT +} pdf_itemkind; + +pdf_store * pdf_newstore(void); +void pdf_emptystore(pdf_store *store); +void pdf_dropstore(pdf_store *store); +void pdf_debugstore(pdf_store *store); + +void pdf_agestoreditems(pdf_store *store); +void pdf_evictageditems(pdf_store *store); + +void pdf_storeitem(pdf_store *store, pdf_itemkind tag, fz_obj *key, void *val); +void *pdf_finditem(pdf_store *store, pdf_itemkind tag, fz_obj *key); +void pdf_removeitem(pdf_store *store, pdf_itemkind tag, fz_obj *key); + +/* + * Functions + */ + +typedef struct pdf_function_s pdf_function; + +fz_error pdf_loadfunction(pdf_function **func, pdf_xref *xref, fz_obj *ref); +fz_error pdf_evalfunction(pdf_function *func, float *in, int inlen, float *out, int outlen); +pdf_function *pdf_keepfunction(pdf_function *func); +void pdf_dropfunction(pdf_function *func); + +/* + * ColorSpace + */ + +typedef struct pdf_indexed_s pdf_indexed; + +struct pdf_indexed_s +{ + fz_colorspace super; /* hmmm... */ + fz_colorspace *base; + int high; + unsigned char *lookup; +}; + +void pdf_convcolor(fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv); +void pdf_convpixmap(fz_colorspace *ss, fz_pixmap *sp, fz_colorspace *ds, fz_pixmap *dp); + +fz_error pdf_loadcolorspace(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj); + +/* + * Pattern + */ + +typedef struct pdf_pattern_s pdf_pattern; + +struct pdf_pattern_s +{ + int refs; + int ismask; + float xstep; + float ystep; + fz_matrix matrix; + fz_rect bbox; + fz_obj *resources; + fz_buffer *contents; +}; + +fz_error pdf_loadpattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *obj); +pdf_pattern *pdf_keeppattern(pdf_pattern *pat); +void pdf_droppattern(pdf_pattern *pat); + +/* + * Shading + */ + +fz_error pdf_loadshade(fz_shade **shadep, pdf_xref *xref, fz_obj *obj); + +/* + * XObject + */ + +typedef struct pdf_xobject_s pdf_xobject; + +struct pdf_xobject_s +{ + int refs; + fz_matrix matrix; + fz_rect bbox; + int isolated; + int knockout; + int transparency; + fz_obj *resources; + fz_buffer *contents; +}; + +fz_error pdf_loadxobject(pdf_xobject **xobjp, pdf_xref *xref, fz_obj *obj); +pdf_xobject *pdf_keepxobject(pdf_xobject *xobj); +void pdf_dropxobject(pdf_xobject *xobj); + +/* + * Image + */ + +typedef struct pdf_image_s pdf_image; + +struct pdf_image_s +{ + int refs; + int w, h, n, a; + fz_colorspace *cs; + pdf_image *mask; /* explicit mask with subimage */ + int usecolorkey; /* explicit color-keyed masking */ + int colorkey[FZ_MAXCOLORS * 2]; + pdf_indexed *indexed; + float decode[32]; + int bpc; + int stride; + fz_buffer *samples; +}; + +fz_error pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *file); +fz_error pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *obj); +fz_error pdf_loadtile(pdf_image *image, fz_pixmap *tile); +pdf_image *pdf_keepimage(pdf_image *img); +void pdf_dropimage(pdf_image *img); + +/* + * CMap + */ + +typedef struct pdf_cmap_s pdf_cmap; +typedef struct pdf_range_s pdf_range; + +enum { PDF_CMAP_SINGLE, PDF_CMAP_RANGE, PDF_CMAP_TABLE, PDF_CMAP_MULTI }; + +struct pdf_range_s +{ + unsigned short low; + unsigned short high; + unsigned short flag; /* single, range, table, multi */ + unsigned short offset; /* range-delta or table-index */ +}; + +struct pdf_cmap_s +{ + int refs; + char cmapname[32]; + + char usecmapname[32]; + pdf_cmap *usecmap; + + int wmode; + + int ncspace; + struct + { + unsigned short n; + unsigned short low; + unsigned short high; + } cspace[40]; + + int rlen, rcap; + pdf_range *ranges; + + int tlen, tcap; + unsigned short *table; +}; + +extern pdf_cmap *pdf_cmaptable[]; /* list of builtin system cmaps */ + +pdf_cmap *pdf_newcmap(void); +pdf_cmap *pdf_keepcmap(pdf_cmap *cmap); +void pdf_dropcmap(pdf_cmap *cmap); + +void pdf_debugcmap(pdf_cmap *cmap); +int pdf_getwmode(pdf_cmap *cmap); +pdf_cmap *pdf_getusecmap(pdf_cmap *cmap); +void pdf_setwmode(pdf_cmap *cmap, int wmode); +void pdf_setusecmap(pdf_cmap *cmap, pdf_cmap *usecmap); + +void pdf_addcodespace(pdf_cmap *cmap, int low, int high, int n); +void pdf_maprangetotable(pdf_cmap *cmap, int low, int *map, int len); +void pdf_maprangetorange(pdf_cmap *cmap, int srclo, int srchi, int dstlo); +void pdf_maponetomany(pdf_cmap *cmap, int one, int *many, int len); +void pdf_sortcmap(pdf_cmap *cmap); + +int pdf_lookupcmap(pdf_cmap *cmap, int cpt); +unsigned char *pdf_decodecmap(pdf_cmap *cmap, unsigned char *s, int *cpt); + +pdf_cmap * pdf_newidentitycmap(int wmode, int bytes); +fz_error pdf_parsecmap(pdf_cmap **cmapp, fz_stream *file); +fz_error pdf_loadembeddedcmap(pdf_cmap **cmapp, pdf_xref *xref, fz_obj *ref); +fz_error pdf_loadsystemcmap(pdf_cmap **cmapp, char *name); + +/* + * Font + */ + +void pdf_loadencoding(char **estrings, char *encoding); +int pdf_lookupagl(char *name); +char **pdf_lookupaglnames(int ucs); + +extern const unsigned short pdf_docencoding[256]; +extern const char * const pdf_macroman[256]; +extern const char * const pdf_macexpert[256]; +extern const char * const pdf_winansi[256]; +extern const char * const pdf_standard[256]; +extern const char * const pdf_expert[256]; +extern const char * const pdf_symbol[256]; +extern const char * const pdf_zapfdingbats[256]; + +typedef struct pdf_hmtx_s pdf_hmtx; +typedef struct pdf_vmtx_s pdf_vmtx; +typedef struct pdf_fontdesc_s pdf_fontdesc; + +struct pdf_hmtx_s +{ + unsigned short lo; + unsigned short hi; + int w; /* type3 fonts can be big! */ +}; + +struct pdf_vmtx_s +{ + unsigned short lo; + unsigned short hi; + short x; + short y; + short w; +}; + +struct pdf_fontdesc_s +{ + int refs; + + fz_font *font; + unsigned char *buffer; /* contains allocated memory that should be freed */ + + /* FontDescriptor */ + int flags; + float italicangle; + float ascent; + float descent; + float capheight; + float xheight; + float missingwidth; + + /* Encoding (CMap) */ + pdf_cmap *encoding; + pdf_cmap *tottfcmap; + int ncidtogid; + unsigned short *cidtogid; + + /* ToUnicode */ + pdf_cmap *tounicode; + int ncidtoucs; + unsigned short *cidtoucs; + + /* Metrics (given in the PDF file) */ + int wmode; + + int nhmtx, hmtxcap; + pdf_hmtx dhmtx; + pdf_hmtx *hmtx; + + int nvmtx, vmtxcap; + pdf_vmtx dvmtx; + pdf_vmtx *vmtx; + + int isembedded; +}; + +/* fontmtx.c */ +void pdf_setfontwmode(pdf_fontdesc *font, int wmode); +void pdf_setdefaulthmtx(pdf_fontdesc *font, int w); +void pdf_setdefaultvmtx(pdf_fontdesc *font, int y, int w); +void pdf_addhmtx(pdf_fontdesc *font, int lo, int hi, int w); +void pdf_addvmtx(pdf_fontdesc *font, int lo, int hi, int x, int y, int w); +void pdf_endhmtx(pdf_fontdesc *font); +void pdf_endvmtx(pdf_fontdesc *font); +pdf_hmtx pdf_gethmtx(pdf_fontdesc *font, int cid); +pdf_vmtx pdf_getvmtx(pdf_fontdesc *font, int cid); + +/* unicode.c */ +fz_error pdf_loadtounicode(pdf_fontdesc *font, pdf_xref *xref, char **strings, char *collection, fz_obj *cmapstm); + +/* fontfile.c */ +fz_error pdf_loadbuiltinfont(pdf_fontdesc *font, char *basefont); +fz_error pdf_loadembeddedfont(pdf_fontdesc *font, pdf_xref *xref, fz_obj *stmref); +fz_error pdf_loadsystemfont(pdf_fontdesc *font, char *basefont, char *collection); + +/* type3.c */ +fz_error pdf_loadtype3font(pdf_fontdesc **fontp, pdf_xref *xref, fz_obj *rdb, fz_obj *obj); + +/* font.c */ +int pdf_fontcidtogid(pdf_fontdesc *fontdesc, int cid); +fz_error pdf_loadfontdescriptor(pdf_fontdesc *font, pdf_xref *xref, fz_obj *desc, char *collection); +fz_error pdf_loadfont(pdf_fontdesc **fontp, pdf_xref *xref, fz_obj *rdb, fz_obj *obj); +pdf_fontdesc * pdf_newfontdesc(void); +pdf_fontdesc * pdf_keepfont(pdf_fontdesc *fontdesc); +void pdf_dropfont(pdf_fontdesc *font); +void pdf_debugfont(pdf_fontdesc *fontdesc); + +/* + * Interactive features + */ + +typedef struct pdf_link_s pdf_link; +typedef struct pdf_comment_s pdf_comment; +typedef struct pdf_widget_s pdf_widget; +typedef struct pdf_outline_s pdf_outline; + +typedef enum pdf_linkkind_e +{ + PDF_LGOTO = 0, + PDF_LURI, +} pdf_linkkind; + +struct pdf_link_s +{ + pdf_linkkind kind; + fz_rect rect; + fz_obj *dest; + pdf_link *next; +}; + +typedef enum pdf_commentkind_e +{ + PDF_CTEXT, + PDF_CFREETEXT, + PDF_CLINE, + PDF_CSQUARE, + PDF_CCIRCLE, + PDF_CPOLYGON, + PDF_CPOLYLINE, + PDF_CMARKUP, + PDF_CCARET, + PDF_CSTAMP, + PDF_CINK +} pdf_commentkind; + +struct pdf_comment_s +{ + pdf_commentkind kind; + fz_rect rect; + fz_rect popup; + fz_obj *contents; + pdf_comment *next; +}; + +struct pdf_outline_s +{ + char *title; + pdf_link *link; + int count; + pdf_outline *child; + pdf_outline *next; +}; + +fz_obj *pdf_lookupdest(pdf_xref *xref, fz_obj *nameddest); + +pdf_link *pdf_newlink(pdf_linkkind kind, fz_rect rect, fz_obj *dest); +pdf_link *pdf_loadlink(pdf_xref *xref, fz_obj *dict); +void pdf_droplink(pdf_link *link); + +pdf_outline *pdf_loadoutline(pdf_xref *xref); +void pdf_debugoutline(pdf_outline *outline, int level); +void pdf_dropoutline(pdf_outline *outline); + +void pdf_loadannots(pdf_comment **, pdf_link **, pdf_xref *, fz_obj *annots); + +/* + * Page tree, pages and related objects + */ + +typedef struct pdf_page_s pdf_page; + +struct pdf_page_s +{ + fz_rect mediabox; + int rotate; + fz_obj *resources; + fz_buffer *contents; + pdf_comment *comments; + pdf_link *links; +}; + +/* pagetree.c */ +int pdf_getpagecount(pdf_xref *xref); +fz_obj * pdf_getpageobject(pdf_xref *xref, int p); +int pdf_findpageobject(pdf_xref *xref, fz_obj *pageobj); + +/* page.c */ +fz_error pdf_loadpage(pdf_page **pagep, pdf_xref *xref, fz_obj *ref); +void pdf_droppage(pdf_page *page); + +/* + * content stream parsing + */ + +typedef struct pdf_material_s pdf_material; +typedef struct pdf_gstate_s pdf_gstate; +typedef struct pdf_csi_s pdf_csi; + +enum +{ + PDF_MFILL, + PDF_MSTROKE +}; + +enum +{ + PDF_MNONE, + PDF_MCOLOR, + PDF_MLAB, + PDF_MINDEXED, + PDF_MPATTERN, + PDF_MSHADE +}; + +struct pdf_material_s +{ + int kind; + fz_colorspace *cs; + pdf_indexed *indexed; + pdf_pattern *pattern; + fz_shade *shade; + float parentalpha; + float alpha; + float v[32]; +}; + +struct pdf_gstate_s +{ + fz_matrix ctm; + int clipdepth; + + /* path stroking */ + fz_strokestate strokestate; + + /* materials */ + pdf_material stroke; + pdf_material fill; + fz_blendkind blendmode; + + /* text state */ + float charspace; + float wordspace; + float scale; + float leading; + pdf_fontdesc *font; + float size; + int render; + float rise; +}; + +struct pdf_csi_s +{ + fz_device *dev; + pdf_xref *xref; + + fz_obj *stack[32]; + int top; + int xbalance; + fz_obj *array; + + /* path object state */ + fz_path *path; + int clip; + int clipevenodd; + + /* text object state */ + fz_text *text; + fz_matrix tlm; + fz_matrix tm; + int textmode; + int accumulate; + + /* graphics state */ + fz_matrix topctm; + pdf_gstate gstate[32]; + int gtop; +}; + +/* build.c */ +void pdf_initgstate(pdf_gstate *gs, fz_matrix ctm); +void pdf_setcolorspace(pdf_csi *csi, int what, fz_colorspace *cs); +void pdf_setcolor(pdf_csi *csi, int what, float *v); +void pdf_setpattern(pdf_csi *csi, int what, pdf_pattern *pat, float *v); +void pdf_setshade(pdf_csi *csi, int what, fz_shade *shade); +void pdf_showpath(pdf_csi*, int close, int fill, int stroke, int evenodd); +void pdf_showtext(pdf_csi*, fz_obj *text); +void pdf_flushtext(pdf_csi*); +void pdf_showimage(pdf_csi*, pdf_image *img); +void pdf_showshade(pdf_csi*, fz_shade *shd); + +/* interpret.c */ +void pdf_gsave(pdf_csi *csi); +void pdf_grestore(pdf_csi *csi); +fz_error pdf_runcsibuffer(pdf_csi *csi, fz_obj *rdb, fz_buffer *contents); +fz_error pdf_runcontentstream(fz_device *dev, fz_matrix ctm, pdf_xref *xref, fz_obj *resources, fz_buffer *contents); + +pdf_material * pdf_keepmaterial(pdf_material *mat); +pdf_material * pdf_dropmaterial(pdf_material *mat); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/mupdf/pdftool.h b/plugins/snes9x_gx/portlibs/include/mupdf/pdftool.h new file mode 100644 index 00000000..0c48aac7 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/mupdf/pdftool.h @@ -0,0 +1,27 @@ +#ifndef PDF_TOOL_H_ +#define PDF_TOOL_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "fitz.h" +#include "mupdf.h" + +extern char *basename; +extern pdf_xref *xref; +extern int pagecount; + +void die(fz_error error); +void setcleanup(void (*cleanup)(void)); + +void openxref(char *filename, char *password, int dieonbadpass); +void flushxref(void); +void closexref(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/mxml.h b/plugins/snes9x_gx/portlibs/include/mxml.h new file mode 100644 index 00000000..a5d7ee6e --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/mxml.h @@ -0,0 +1,308 @@ +/* + * "$Id: mxml.h 385 2009-03-19 05:38:52Z mike $" + * + * Header file for Mini-XML, a small XML-like file parsing library. + * + * Copyright 2003-2009 by Michael Sweet. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2, 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. + */ + +/* + * Prevent multiple inclusion... + */ + +#ifndef _mxml_h_ +# define _mxml_h_ + +/* + * Include necessary headers... + */ + +# include <stdio.h> +# include <stdlib.h> +# include <string.h> +# include <ctype.h> +# include <errno.h> + + +/* + * Constants... + */ + +# define MXML_TAB 8 /* Tabs every N columns */ + +# define MXML_NO_CALLBACK 0 /* Don't use a type callback */ +# define MXML_INTEGER_CALLBACK mxml_integer_cb + /* Treat all data as integers */ +# define MXML_OPAQUE_CALLBACK mxml_opaque_cb + /* Treat all data as opaque */ +# define MXML_REAL_CALLBACK mxml_real_cb + /* Treat all data as real numbers */ +# define MXML_TEXT_CALLBACK 0 /* Treat all data as text */ +# define MXML_IGNORE_CALLBACK mxml_ignore_cb + /* Ignore all non-element content */ + +# define MXML_NO_PARENT 0 /* No parent for the node */ + +# define MXML_DESCEND 1 /* Descend when finding/walking */ +# define MXML_NO_DESCEND 0 /* Don't descend when finding/walking */ +# define MXML_DESCEND_FIRST -1 /* Descend for first find */ + +# define MXML_WS_BEFORE_OPEN 0 /* Callback for before open tag */ +# define MXML_WS_AFTER_OPEN 1 /* Callback for after open tag */ +# define MXML_WS_BEFORE_CLOSE 2 /* Callback for before close tag */ +# define MXML_WS_AFTER_CLOSE 3 /* Callback for after close tag */ + +# define MXML_ADD_BEFORE 0 /* Add node before specified node */ +# define MXML_ADD_AFTER 1 /* Add node after specified node */ +# define MXML_ADD_TO_PARENT NULL /* Add node relative to parent */ + + +/* + * Data types... + */ + +typedef enum mxml_sax_event_e /**** SAX event type. ****/ +{ + MXML_SAX_CDATA, /* CDATA node */ + MXML_SAX_COMMENT, /* Comment node */ + MXML_SAX_DATA, /* Data node */ + MXML_SAX_DIRECTIVE, /* Processing directive node */ + MXML_SAX_ELEMENT_CLOSE, /* Element closed */ + MXML_SAX_ELEMENT_OPEN /* Element opened */ +} mxml_sax_event_t; + +typedef enum mxml_type_e /**** The XML node type. ****/ +{ + MXML_IGNORE = -1, /* Ignore/throw away node @since Mini-XML 2.3@ */ + MXML_ELEMENT, /* XML element with attributes */ + MXML_INTEGER, /* Integer value */ + MXML_OPAQUE, /* Opaque string */ + MXML_REAL, /* Real value */ + MXML_TEXT, /* Text fragment */ + MXML_CUSTOM /* Custom data @since Mini-XML 2.1@ */ +} mxml_type_t; + +typedef void (*mxml_custom_destroy_cb_t)(void *); + /**** Custom data destructor ****/ + +typedef void (*mxml_error_cb_t)(const char *); + /**** Error callback function ****/ + +typedef struct mxml_attr_s /**** An XML element attribute value. ****/ +{ + char *name; /* Attribute name */ + char *value; /* Attribute value */ +} mxml_attr_t; + +typedef struct mxml_element_s /**** An XML element value. ****/ +{ + char *name; /* Name of element */ + int num_attrs; /* Number of attributes */ + mxml_attr_t *attrs; /* Attributes */ +} mxml_element_t; + +typedef struct mxml_text_s /**** An XML text value. ****/ +{ + int whitespace; /* Leading whitespace? */ + char *string; /* Fragment string */ +} mxml_text_t; + +typedef struct mxml_custom_s /**** An XML custom value. @since Mini-XML 2.1@ ****/ +{ + void *data; /* Pointer to (allocated) custom data */ + mxml_custom_destroy_cb_t destroy; /* Pointer to destructor function */ +} mxml_custom_t; + +typedef union mxml_value_u /**** An XML node value. ****/ +{ + mxml_element_t element; /* Element */ + int integer; /* Integer number */ + char *opaque; /* Opaque string */ + double real; /* Real number */ + mxml_text_t text; /* Text fragment */ + mxml_custom_t custom; /* Custom data @since Mini-XML 2.1@ */ +} mxml_value_t; + +typedef struct mxml_node_s /**** An XML node. ****/ +{ + mxml_type_t type; /* Node type */ + struct mxml_node_s *next; /* Next node under same parent */ + struct mxml_node_s *prev; /* Previous node under same parent */ + struct mxml_node_s *parent; /* Parent node */ + struct mxml_node_s *child; /* First child node */ + struct mxml_node_s *last_child; /* Last child node */ + mxml_value_t value; /* Node value */ + int ref_count; /* Use count */ + void *user_data; /* User data */ +} mxml_node_t; + +typedef struct mxml_index_s /**** An XML node index. ****/ +{ + char *attr; /* Attribute used for indexing or NULL */ + int num_nodes; /* Number of nodes in index */ + int alloc_nodes; /* Allocated nodes in index */ + int cur_node; /* Current node */ + mxml_node_t **nodes; /* Node array */ +} mxml_index_t; + +typedef int (*mxml_custom_load_cb_t)(mxml_node_t *, const char *); + /**** Custom data load callback function ****/ + +typedef char *(*mxml_custom_save_cb_t)(mxml_node_t *); + /**** Custom data save callback function ****/ + +typedef int (*mxml_entity_cb_t)(const char *); + /**** Entity callback function */ + +typedef mxml_type_t (*mxml_load_cb_t)(mxml_node_t *); + /**** Load callback function ****/ + +typedef const char *(*mxml_save_cb_t)(mxml_node_t *, int); + /**** Save callback function ****/ + +typedef void (*mxml_sax_cb_t)(mxml_node_t *, mxml_sax_event_t, void *); + /**** SAX callback function ****/ + + +/* + * C++ support... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + +/* + * Prototypes... + */ + +extern void mxmlAdd(mxml_node_t *parent, int where, + mxml_node_t *child, mxml_node_t *node); +extern void mxmlDelete(mxml_node_t *node); +extern void mxmlElementDeleteAttr(mxml_node_t *node, + const char *name); +extern const char *mxmlElementGetAttr(mxml_node_t *node, const char *name); +extern void mxmlElementSetAttr(mxml_node_t *node, const char *name, + const char *value); +extern void mxmlElementSetAttrf(mxml_node_t *node, const char *name, + const char *format, ...) +# ifdef __GNUC__ +__attribute__ ((__format__ (__printf__, 3, 4))) +# endif /* __GNUC__ */ +; +extern int mxmlEntityAddCallback(mxml_entity_cb_t cb); +extern const char *mxmlEntityGetName(int val); +extern int mxmlEntityGetValue(const char *name); +extern void mxmlEntityRemoveCallback(mxml_entity_cb_t cb); +extern mxml_node_t *mxmlFindElement(mxml_node_t *node, mxml_node_t *top, + const char *name, const char *attr, + const char *value, int descend); +extern void mxmlIndexDelete(mxml_index_t *ind); +extern mxml_node_t *mxmlIndexEnum(mxml_index_t *ind); +extern mxml_node_t *mxmlIndexFind(mxml_index_t *ind, + const char *element, + const char *value); +extern mxml_index_t *mxmlIndexNew(mxml_node_t *node, const char *element, + const char *attr); +extern mxml_node_t *mxmlIndexReset(mxml_index_t *ind); +extern mxml_node_t *mxmlLoadFd(mxml_node_t *top, int fd, + mxml_type_t (*cb)(mxml_node_t *)); +extern mxml_node_t *mxmlLoadFile(mxml_node_t *top, FILE *fp, + mxml_type_t (*cb)(mxml_node_t *)); +extern mxml_node_t *mxmlLoadString(mxml_node_t *top, const char *s, + mxml_type_t (*cb)(mxml_node_t *)); +extern mxml_node_t *mxmlNewCDATA(mxml_node_t *parent, const char *string); +extern mxml_node_t *mxmlNewCustom(mxml_node_t *parent, void *data, + mxml_custom_destroy_cb_t destroy); +extern mxml_node_t *mxmlNewElement(mxml_node_t *parent, const char *name); +extern mxml_node_t *mxmlNewInteger(mxml_node_t *parent, int integer); +extern mxml_node_t *mxmlNewOpaque(mxml_node_t *parent, const char *opaque); +extern mxml_node_t *mxmlNewReal(mxml_node_t *parent, double real); +extern mxml_node_t *mxmlNewText(mxml_node_t *parent, int whitespace, + const char *string); +extern mxml_node_t *mxmlNewTextf(mxml_node_t *parent, int whitespace, + const char *format, ...) +# ifdef __GNUC__ +__attribute__ ((__format__ (__printf__, 3, 4))) +# endif /* __GNUC__ */ +; +extern mxml_node_t *mxmlNewXML(const char *version); +extern int mxmlRelease(mxml_node_t *node); +extern void mxmlRemove(mxml_node_t *node); +extern int mxmlRetain(mxml_node_t *node); +extern char *mxmlSaveAllocString(mxml_node_t *node, + mxml_save_cb_t cb); +extern int mxmlSaveFd(mxml_node_t *node, int fd, + mxml_save_cb_t cb); +extern int mxmlSaveFile(mxml_node_t *node, FILE *fp, + mxml_save_cb_t cb); +extern int mxmlSaveString(mxml_node_t *node, char *buffer, + int bufsize, mxml_save_cb_t cb); +extern mxml_node_t *mxmlSAXLoadFd(mxml_node_t *top, int fd, + mxml_type_t (*cb)(mxml_node_t *), + mxml_sax_cb_t sax, void *sax_data); +extern mxml_node_t *mxmlSAXLoadFile(mxml_node_t *top, FILE *fp, + mxml_type_t (*cb)(mxml_node_t *), + mxml_sax_cb_t sax, void *sax_data); +extern mxml_node_t *mxmlSAXLoadString(mxml_node_t *top, const char *s, + mxml_type_t (*cb)(mxml_node_t *), + mxml_sax_cb_t sax, void *sax_data); +extern int mxmlSetCDATA(mxml_node_t *node, const char *data); +extern int mxmlSetCustom(mxml_node_t *node, void *data, + mxml_custom_destroy_cb_t destroy); +extern void mxmlSetCustomHandlers(mxml_custom_load_cb_t load, + mxml_custom_save_cb_t save); +extern int mxmlSetElement(mxml_node_t *node, const char *name); +extern void mxmlSetErrorCallback(mxml_error_cb_t cb); +extern int mxmlSetInteger(mxml_node_t *node, int integer); +extern int mxmlSetOpaque(mxml_node_t *node, const char *opaque); +extern int mxmlSetReal(mxml_node_t *node, double real); +extern int mxmlSetText(mxml_node_t *node, int whitespace, + const char *string); +extern int mxmlSetTextf(mxml_node_t *node, int whitespace, + const char *format, ...) +# ifdef __GNUC__ +__attribute__ ((__format__ (__printf__, 3, 4))) +# endif /* __GNUC__ */ +; +extern void mxmlSetWrapMargin(int column); +extern mxml_node_t *mxmlWalkNext(mxml_node_t *node, mxml_node_t *top, + int descend); +extern mxml_node_t *mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top, + int descend); + + +/* + * Semi-private functions... + */ + +extern void mxml_error(const char *format, ...); +extern mxml_type_t mxml_ignore_cb(mxml_node_t *node); +extern mxml_type_t mxml_integer_cb(mxml_node_t *node); +extern mxml_type_t mxml_opaque_cb(mxml_node_t *node); +extern mxml_type_t mxml_real_cb(mxml_node_t *node); + + +/* + * C++ support... + */ + +# ifdef __cplusplus +} +# endif /* __cplusplus */ +#endif /* !_mxml_h_ */ + + +/* + * End of "$Id: mxml.h 385 2009-03-19 05:38:52Z mike $". + */ diff --git a/plugins/snes9x_gx/portlibs/include/nfs.h b/plugins/snes9x_gx/portlibs/include/nfs.h new file mode 100644 index 00000000..4ae0b37a --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/nfs.h @@ -0,0 +1,60 @@ +/* + nfs.h + Simple functionality for mounting and unmounting of NFS-based network storage. + + Copyright (c) 2012 r-win + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _LIBNFS_H +#define _LIBNFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define NFS_READWRITE 0 +#define NFS_READONLY 1 + +/* +Mount the network storage specified by the ipAddress of the server, and the mountdirectory +for the mountpoint. +You can then access the filesystem using "name:/". +This will also call net_init in order to initialize the network. If you want the network to +initiliaze async, make sure you've done so before calling nfsMount. +*/ +extern bool nfsMount(const char *name, const char *ipAddress, const char *mountdir); + +extern bool nfsMountEx(const char *name, const char *ipAddress, const char *mountdir, uint32_t uid, uint32_t gid, uint32_t readonly); + +/* +Unmount the remote mountpoint specified by name. +*/ +extern void nfsUnmount (const char* name); + +#ifdef __cplusplus +} +#endif + +#endif // _LIBNFS_H diff --git a/plugins/snes9x_gx/portlibs/include/ntfs.h b/plugins/snes9x_gx/portlibs/include/ntfs.h new file mode 100644 index 00000000..62f2f719 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/ntfs.h @@ -0,0 +1,148 @@ +/** + * ntfs.h - Simple functionality for startup, mounting and unmounting of NTFS-based devices. + * + * Copyright (c) 2010 Dimok + * Copyright (c) 2009 Rhys "Shareese" Koedijk + * Copyright (c) 2006 Michael "Chishm" Chisholm + * + * This program/include file 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/include file 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _LIBNTFS_H +#define _LIBNTFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <gctypes.h> +#include <gccore.h> +#include <ogc/disc_io.h> + +/* NTFS errno values */ +#define ENOPART 3000 /* No partition was found */ +#define EINVALPART 3001 /* Specified partition is invalid or not supported */ +#define EDIRTY 3002 /* Volume is dirty and NTFS_RECOVER was not specified during mount */ +#define EHIBERNATED 3003 /* Volume is hibernated and NTFS_IGNORE_HIBERFILE was not specified during mount */ + +/* NTFS cache options */ +#define CACHE_DEFAULT_PAGE_COUNT 8 /* The default number of pages in the cache */ +#define CACHE_DEFAULT_PAGE_SIZE 128 /* The default number of sectors per cache page */ + +/* NTFS mount flags */ +#define NTFS_DEFAULT 0x00000000 /* Standard mount, expects a clean, non-hibernated volume */ +#define NTFS_SHOW_HIDDEN_FILES 0x00000001 /* Display hidden files when enumerating directories */ +#define NTFS_SHOW_SYSTEM_FILES 0x00000002 /* Display system files when enumerating directories */ +#define NTFS_UPDATE_ACCESS_TIMES 0x00000004 /* Update file and directory access times */ +#define NTFS_RECOVER 0x00000008 /* Reset $LogFile if dirty (i.e. from unclean disconnect) */ +#define NTFS_IGNORE_HIBERFILE 0x00000010 /* Mount even if volume is hibernated */ +#define NTFS_READ_ONLY 0x00000020 /* Mount in read only mode */ +#define NTFS_IGNORE_CASE 0x00000040 /* Ignore case sensitivity. Everything must be and will be provided in lowercase. */ +#define NTFS_SU NTFS_SHOW_HIDDEN_FILES | NTFS_SHOW_SYSTEM_FILES +#define NTFS_FORCE NTFS_RECOVER | NTFS_IGNORE_HIBERFILE + +/** + * ntfs_md - NTFS mount descriptor + */ +typedef struct _ntfs_md { + char name[32]; /* Mount name (can be accessed as "name:/") */ + const DISC_INTERFACE *interface; /* Block device containing the mounted partition */ + sec_t startSector; /* Local block address to first sector of partition */ +} ntfs_md; + +/** + * Find all NTFS partitions on a block device. + * + * @param INTERFACE The block device to search + * @param PARTITIONS (out) A pointer to receive the array of partition start sectors + * + * @return The number of entries in PARTITIONS or -1 if an error occurred (see errno) + * @note The caller is responsible for freeing PARTITIONS when finished with it + */ +extern int ntfsFindPartitions (const DISC_INTERFACE *interface, sec_t **partitions); + +/** + * Mount all NTFS partitions on all inserted block devices. + * + * @param MOUNTS (out) A pointer to receive the array of mount descriptors + * @param FLAGS Additional mounting flags. (see above) + * + * @return The number of entries in MOUNTS or -1 if an error occurred (see errno) + * @note The caller is responsible for freeing MOUNTS when finished with it + * @note All device caches are setup using default values (see above) + */ +extern int ntfsMountAll (ntfs_md **mounts, u32 flags); + +/** + * Mount all NTFS partitions on a block devices. + * + * @param INTERFACE The block device to mount. + * @param MOUNTS (out) A pointer to receive the array of mount descriptors + * @param FLAGS Additional mounting flags. (see above) + * + * @return The number of entries in MOUNTS or -1 if an error occurred (see errno) + * @note The caller is responsible for freeing MOUNTS when finished with it + * @note The device cache is setup using default values (see above) + */ +extern int ntfsMountDevice (const DISC_INTERFACE* interface, ntfs_md **mounts, u32 flags); + +/** + * Mount a NTFS partition from a specific sector on a block device. + * + * @param NAME The name to mount the device under (can then be accessed as "NAME:/") + * @param INTERFACE The block device to mount + * @param STARTSECTOR The sector the partition begins at (see @ntfsFindPartitions) + * @param CACHEPAGECOUNT The total number of pages in the device cache + * @param CACHEPAGESIZE The number of sectors per cache page + * @param FLAGS Additional mounting flags (see above) + * + * @return True if mount was successful, false if no partition was found or an error occurred (see errno) + * @note ntfsFindPartitions should be used first to locate the partitions start sector + */ +extern bool ntfsMount (const char *name, const DISC_INTERFACE *interface, sec_t startSector, u32 cachePageCount, u32 cachePageSize, u32 flags); + +/** + * Unmount a NTFS partition. + * + * @param NAME The name of mount used in ntfsMountSimple() and ntfsMount() + * @param FORCE If true unmount even if the device is busy (may lead to data lose) + */ +extern void ntfsUnmount (const char *name, bool force); + +/** + * Get the volume name of a mounted NTFS partition. + * + * @param NAME The name of mount (see @ntfsMountAll, @ntfsMountDevice, and @ntfsMount) + * + * @return The volumes name if successful or NULL if an error occurred (see errno) + */ +extern const char *ntfsGetVolumeName (const char *name); + +/** + * Set the volume name of a mounted NTFS partition. + * + * @param NAME The name of mount (see @ntfsMountAll, @ntfsMountDevice, and @ntfsMount) + * @param VOLUMENAME The new volume name + * + * @return True if mount was successful, false if an error occurred (see errno) + * @note The mount must be write-enabled else this will fail + */ +extern bool ntfsSetVolumeName (const char *name, const char *volumeName); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBNTFS_H */ diff --git a/plugins/snes9x_gx/portlibs/include/png.h b/plugins/snes9x_gx/portlibs/include/png.h new file mode 100644 index 00000000..5617c972 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/png.h @@ -0,0 +1,2658 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.5.9 - February 18, 2012 + * Copyright (c) 1998-2012 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license (See LICENSE, below) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.5.9 - February 18, 2012: Glenn + * See also "Contributing Authors", below. + * + * Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + * 1.0.8rc1 1 10008 2.1.0.8rc1 + * 1.0.8 1 10008 2.1.0.8 + * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + * 1.0.9rc1 1 10009 2.1.0.9rc1 + * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + * 1.0.9rc2 1 10009 2.1.0.9rc2 + * 1.0.9 1 10009 2.1.0.9 + * 1.0.10beta1 1 10010 2.1.0.10beta1 + * 1.0.10rc1 1 10010 2.1.0.10rc1 + * 1.0.10 1 10010 2.1.0.10 + * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + * 1.0.11rc1 1 10011 2.1.0.11rc1 + * 1.0.11 1 10011 2.1.0.11 + * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + * 1.0.12rc1 2 10012 2.1.0.12rc1 + * 1.0.12 2 10012 2.1.0.12 + * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) + * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + * 1.2.0rc1 3 10200 3.1.2.0rc1 + * 1.2.0 3 10200 3.1.2.0 + * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 + * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + * 1.2.1 3 10201 3.1.2.1 + * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + * 1.0.13 10 10013 10.so.0.1.0.13 + * 1.2.2 12 10202 12.so.0.1.2.2 + * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + * 1.2.3 12 10203 12.so.0.1.2.3 + * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 + * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + * 1.0.14 10 10014 10.so.0.1.0.14 + * 1.2.4 13 10204 12.so.0.1.2.4 + * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 + * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 + * 1.0.15 10 10015 10.so.0.1.0.15 + * 1.2.5 13 10205 12.so.0.1.2.5 + * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + * 1.0.16 10 10016 10.so.0.1.0.16 + * 1.2.6 13 10206 12.so.0.1.2.6 + * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 + * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + * 1.0.17 10 10017 12.so.0.1.0.17 + * 1.2.7 13 10207 12.so.0.1.2.7 + * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 + * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 + * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + * 1.0.18 10 10018 12.so.0.1.0.18 + * 1.2.8 13 10208 12.so.0.1.2.8 + * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 + * 1.2.9beta4-11 13 10209 12.so.0.9[.0] + * 1.2.9rc1 13 10209 12.so.0.9[.0] + * 1.2.9 13 10209 12.so.0.9[.0] + * 1.2.10beta1-7 13 10210 12.so.0.10[.0] + * 1.2.10rc1-2 13 10210 12.so.0.10[.0] + * 1.2.10 13 10210 12.so.0.10[.0] + * 1.4.0beta1-5 14 10400 14.so.0.0[.0] + * 1.2.11beta1-4 13 10211 12.so.0.11[.0] + * 1.4.0beta7-8 14 10400 14.so.0.0[.0] + * 1.2.11 13 10211 12.so.0.11[.0] + * 1.2.12 13 10212 12.so.0.12[.0] + * 1.4.0beta9-14 14 10400 14.so.0.0[.0] + * 1.2.13 13 10213 12.so.0.13[.0] + * 1.4.0beta15-36 14 10400 14.so.0.0[.0] + * 1.4.0beta37-87 14 10400 14.so.14.0[.0] + * 1.4.0rc01 14 10400 14.so.14.0[.0] + * 1.4.0beta88-109 14 10400 14.so.14.0[.0] + * 1.4.0rc02-08 14 10400 14.so.14.0[.0] + * 1.4.0 14 10400 14.so.14.0[.0] + * 1.4.1beta01-03 14 10401 14.so.14.1[.0] + * 1.4.1rc01 14 10401 14.so.14.1[.0] + * 1.4.1beta04-12 14 10401 14.so.14.1[.0] + * 1.4.1 14 10401 14.so.14.1[.0] + * 1.4.2 14 10402 14.so.14.2[.0] + * 1.4.3 14 10403 14.so.14.3[.0] + * 1.4.4 14 10404 14.so.14.4[.0] + * 1.5.0beta01-58 15 10500 15.so.15.0[.0] + * 1.5.0rc01-07 15 10500 15.so.15.0[.0] + * 1.5.0 15 10500 15.so.15.0[.0] + * 1.5.1beta01-11 15 10501 15.so.15.1[.0] + * 1.5.1rc01-02 15 10501 15.so.15.1[.0] + * 1.5.1 15 10501 15.so.15.1[.0] + * 1.5.2beta01-03 15 10502 15.so.15.2[.0] + * 1.5.2rc01-03 15 10502 15.so.15.2[.0] + * 1.5.2 15 10502 15.so.15.2[.0] + * 1.5.3beta01-10 15 10503 15.so.15.3[.0] + * 1.5.3rc01-02 15 10503 15.so.15.3[.0] + * 1.5.3beta11 15 10503 15.so.15.3[.0] + * 1.5.3 [omitted] + * 1.5.4beta01-08 15 10504 15.so.15.4[.0] + * 1.5.4rc01 15 10504 15.so.15.4[.0] + * 1.5.4 15 10504 15.so.15.4[.0] + * 1.5.5beta01-08 15 10505 15.so.15.5[.0] + * 1.5.5rc01 15 10505 15.so.15.5[.0] + * 1.5.5 15 10505 15.so.15.5[.0] + * 1.5.6beta01-07 15 10506 15.so.15.6[.0] + * 1.5.6rc01-03 15 10506 15.so.15.6[.0] + * 1.5.6 15 10506 15.so.15.6[.0] + * 1.5.7beta01-05 15 10507 15.so.15.7[.0] + * 1.5.7rc01-03 15 10507 15.so.15.7[.0] + * 1.5.7 15 10507 15.so.15.7[.0] + * 1.5.8beta01 15 10508 15.so.15.8[.0] + * 1.5.8rc01 15 10508 15.so.15.8[.0] + * 1.5.8 15 10508 15.so.15.8[.0] + * 1.5.9beta01-02 15 10509 15.so.15.9[.0] + * 1.5.9rc01 15 10509 15.so.15.9[.0] + * 1.5.9 15 10509 15.so.15.9[.0] + * + * Henceforth the source version will match the shared-library major + * and minor numbers; the shared-library major version number will be + * used for changes in backward compatibility, as it is intended. The + * PNG_LIBPNG_VER macro, which is not used within libpng but is available + * for applications, is an unsigned integer of the form xyyzz corresponding + * to the source version x.y.z (leading zeros in y and z). Beta versions + * were given the previous public release number plus a letter, until + * version 1.0.6j; from then on they were given the upcoming public + * release number plus "betaNN" or "rcN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng-manual.txt or libpng.3 for more information. The PNG + * specification is available as a W3C Recommendation and as an ISO + * Specification, <http://www.w3.org/TR/2003/REC-PNG-20031110/ + */ + +/* + * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + * + * If you modify libpng you may insert additional notices immediately following + * this sentence. + * + * This code is released under the libpng license. + * + * libpng versions 1.2.6, August 15, 2004, through 1.5.9, February 18, 2012, are + * Copyright (c) 2004, 2006-2012 Glenn Randers-Pehrson, and are + * distributed according to the same disclaimer and license as libpng-1.2.5 + * with the following individual added to the list of Contributing Authors: + * + * Cosmin Truta + * + * libpng versions 1.0.7, July 1, 2000, through 1.2.5, October 3, 2002, are + * Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are + * distributed according to the same disclaimer and license as libpng-1.0.6 + * with the following individuals added to the list of Contributing Authors: + * + * Simon-Pierre Cadieux + * Eric S. Raymond + * Gilles Vollant + * + * and with the following additions to the disclaimer: + * + * There is no warranty against interference with your enjoyment of the + * library or against infringement. There is no warranty that our + * efforts or the library will fulfill any of your particular purposes + * or needs. This library is provided with all faults, and the entire + * risk of satisfactory quality, performance, accuracy, and effort is with + * the user. + * + * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are + * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson, and are + * distributed according to the same disclaimer and license as libpng-0.96, + * with the following individuals added to the list of Contributing Authors: + * + * Tom Lane + * Glenn Randers-Pehrson + * Willem van Schaik + * + * libpng versions 0.89, June 1996, through 0.96, May 1997, are + * Copyright (c) 1996, 1997 Andreas Dilger + * Distributed according to the same disclaimer and license as libpng-0.88, + * with the following individuals added to the list of Contributing Authors: + * + * John Bowler + * Kevin Bracey + * Sam Bushell + * Magnus Holmgren + * Greg Roelofs + * Tom Tanner + * + * libpng versions 0.5, May 1995, through 0.88, January 1996, are + * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + * + * For the purposes of this copyright and license, "Contributing Authors" + * is defined as the following set of individuals: + * + * Andreas Dilger + * Dave Martindale + * Guy Eric Schalnat + * Paul Schmidt + * Tim Wegner + * + * The PNG Reference Library is supplied "AS IS". The Contributing Authors + * and Group 42, Inc. disclaim all warranties, expressed or implied, + * including, without limitation, the warranties of merchantability and of + * fitness for any purpose. The Contributing Authors and Group 42, Inc. + * assume no liability for direct, indirect, incidental, special, exemplary, + * or consequential damages, which may result from the use of the PNG + * Reference Library, even if advised of the possibility of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * source code, or portions hereof, for any purpose, without fee, subject + * to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented. + * + * 2. Altered versions must be plainly marked as such and must not + * be misrepresented as being the original source. + * + * 3. This Copyright notice may not be removed or altered from + * any source or altered source distribution. + * + * The Contributing Authors and Group 42, Inc. specifically permit, without + * fee, and encourage the use of this source code as a component to + * supporting the PNG file format in commercial products. If you use this + * source code in a product, acknowledgment is not required but would be + * appreciated. + */ + +/* + * A "png_get_copyright" function is available, for convenient use in "about" + * boxes and the like: + * + * printf("%s", png_get_copyright(NULL)); + * + * Also, the PNG logo (in PNG format, of course) is supplied in the + * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + */ + +/* + * Libpng is OSI Certified Open Source Software. OSI Certified is a + * certification mark of the Open Source Initiative. + */ + +/* + * The contributing authors would like to thank all those who helped + * with testing, bug fixes, and patience. This wouldn't have been + * possible without all of you. + * + * Thanks to Frank J. T. Wojcik for helping with the documentation. + */ + +/* + * Y2K compliance in libpng: + * ========================= + * + * February 18, 2012 + * + * Since the PNG Development group is an ad-hoc body, we can't make + * an official declaration. + * + * This is your unofficial assurance that libpng from version 0.71 and + * upward through 1.5.9 are Y2K compliant. It is my belief that + * earlier versions were also Y2K compliant. + * + * Libpng only has two year fields. One is a 2-byte unsigned integer + * that will hold years up to 65535. The other holds the date in text + * format, and will hold years up to 9999. + * + * The integer is + * "png_uint_16 year" in png_time_struct. + * + * The string is + * "png_char time_buffer" in png_struct + * + * There are seven time-related functions: + * png.c: png_convert_to_rfc_1123() in png.c + * (formerly png_convert_to_rfc_1152() in error) + * png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c + * png_convert_from_time_t() in pngwrite.c + * png_get_tIME() in pngget.c + * png_handle_tIME() in pngrutil.c, called in pngread.c + * png_set_tIME() in pngset.c + * png_write_tIME() in pngwutil.c, called in pngwrite.c + * + * All handle dates properly in a Y2K environment. The + * png_convert_from_time_t() function calls gmtime() to convert from system + * clock time, which returns (year - 1900), which we properly convert to + * the full 4-digit year. There is a possibility that applications using + * libpng are not passing 4-digit years into the png_convert_to_rfc_1123() + * function, or that they are incorrectly passing only a 2-digit year + * instead of "year - 1900" into the png_convert_from_struct_tm() function, + * but this is not under our control. The libpng documentation has always + * stated that it works with 4-digit years, and the APIs have been + * documented as such. + * + * The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned + * integer to hold the year, and can hold years as large as 65535. + * + * zlib, upon which libpng depends, is also Y2K compliant. It contains + * no date-related code. + * + * Glenn Randers-Pehrson + * libpng maintainer + * PNG Development Group + */ + +#ifndef PNG_H +#define PNG_H + +/* This is not the place to learn how to use libpng. The file libpng-manual.txt + * describes how to use libpng, and the file example.c summarizes it + * with some code on which to build. This file is useful for looking + * at the actual function definitions and structure components. + * + * If you just need to read a PNG file and don't want to read the documentation + * skip to the end of this file and read the section entitled 'simplified API'. + */ + +/* Version information for png.h - this should match the version in png.c */ +#define PNG_LIBPNG_VER_STRING "1.5.9" +#define PNG_HEADER_VERSION_STRING \ + " libpng version 1.5.9 - February 18, 2012\n" + +#define PNG_LIBPNG_VER_SONUM 15 +#define PNG_LIBPNG_VER_DLLNUM 15 + +/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ +#define PNG_LIBPNG_VER_MAJOR 1 +#define PNG_LIBPNG_VER_MINOR 5 +#define PNG_LIBPNG_VER_RELEASE 9 + +/* This should match the numeric part of the final component of + * PNG_LIBPNG_VER_STRING, omitting any leading zero: + */ + +#define PNG_LIBPNG_VER_BUILD 0 + +/* Release Status */ +#define PNG_LIBPNG_BUILD_ALPHA 1 +#define PNG_LIBPNG_BUILD_BETA 2 +#define PNG_LIBPNG_BUILD_RC 3 +#define PNG_LIBPNG_BUILD_STABLE 4 +#define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 + +/* Release-Specific Flags */ +#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with + PNG_LIBPNG_BUILD_STABLE only */ +#define PNG_LIBPNG_BUILD_PRIVATE 16 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_SPECIAL */ +#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_PRIVATE */ + +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_BETA + +/* Careful here. At one time, Guy wanted to use 082, but that would be octal. + * We must not include leading zeros. + * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only + * version 1.0.0 was mis-numbered 100 instead of 10000). From + * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release + */ +#define PNG_LIBPNG_VER 10509 /* 1.5.9 */ + +/* Library configuration: these options cannot be changed after + * the library has been built. + */ +#ifndef PNGLCONF_H + /* If pnglibconf.h is missing, you can + * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h + */ +# include "pnglibconf.h" +#endif + +#ifndef PNG_VERSION_INFO_ONLY +# ifndef PNG_BUILDING_SYMBOL_TABLE + /* + * Standard header files (not needed for the version info or while + * building symbol table -- see scripts/pnglibconf.dfa) + */ +# ifdef PNG_SETJMP_SUPPORTED +# include <setjmp.h> +# endif + + /* Need the time information for converting tIME chunks, it + * defines struct tm: + */ +# ifdef PNG_CONVERT_tIME_SUPPORTED + /* "time.h" functions are not supported on all operating systems */ +# include <time.h> +# endif +# endif + +/* Machine specific configuration. */ +# include "pngconf.h" +#endif + +/* + * Added at libpng-1.2.8 + * + * Ref MSDN: Private as priority over Special + * VS_FF_PRIVATEBUILD File *was not* built using standard release + * procedures. If this value is given, the StringFileInfo block must + * contain a PrivateBuild string. + * + * VS_FF_SPECIALBUILD File *was* built by the original company using + * standard release procedures but is a variation of the standard + * file of the same version number. If this value is given, the + * StringFileInfo block must contain a SpecialBuild string. + */ + +#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) +#else +# ifdef PNG_LIBPNG_SPECIALBUILD +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) +# else +# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) +# endif +#endif + +#ifndef PNG_VERSION_INFO_ONLY + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#define png_libpng_ver png_get_header_ver(NULL) + +/* This file is arranged in several sections: + * + * 1. Any configuration options that can be specified by for the application + * code when it is built. (Build time configuration is in pnglibconf.h) + * 2. Type definitions (base types are defined in pngconf.h), structure + * definitions. + * 3. Exported library functions. + * + * The library source code has additional files (principally pngpriv.h) that + * allow configuration of the library. + */ +/* Section 1: run time configuration + * See pnglibconf.h for build time configuration + * + * Run time configuration allows the application to choose between + * implementations of certain arithmetic APIs. The default is set + * at build time and recorded in pnglibconf.h, but it is safe to + * override these (and only these) settings. Note that this won't + * change what the library does, only application code, and the + * settings can (and probably should) be made on a per-file basis + * by setting the #defines before including png.h + * + * Use macros to read integers from PNG data or use the exported + * functions? + * PNG_USE_READ_MACROS: use the macros (see below) Note that + * the macros evaluate their argument multiple times. + * PNG_NO_USE_READ_MACROS: call the relevant library function. + * + * Use the alternative algorithm for compositing alpha samples that + * does not use division? + * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' + * algorithm. + * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. + * + * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is + * false? + * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error + * APIs to png_warning. + * Otherwise the calls are mapped to png_error. + */ + +/* Section 2: type definitions, including structures and compile time + * constants. + * See pngconf.h for base types that vary by machine/system + */ + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef char* png_libpng_version_1_5_9; + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color FAR * png_colorp; +typedef PNG_CONST png_color FAR * png_const_colorp; +typedef png_color FAR * FAR * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 FAR * png_color_16p; +typedef PNG_CONST png_color_16 FAR * png_const_color_16p; +typedef png_color_16 FAR * FAR * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 FAR * png_color_8p; +typedef PNG_CONST png_color_8 FAR * png_const_color_8p; +typedef png_color_8 FAR * FAR * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry FAR * png_sPLT_entryp; +typedef PNG_CONST png_sPLT_entry FAR * png_const_sPLT_entryp; +typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t FAR * png_sPLT_tp; +typedef PNG_CONST png_sPLT_t FAR * png_const_sPLT_tp; +typedef png_sPLT_t FAR * FAR * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text" fields can be a + * regular C string, an empty string, or a NULL pointer. + * However, the structure returned by png_get_text() will always contain + * the "text" field as a regular zero-terminated C string (possibly + * empty), never a NULL pointer, so it can be safely used in printf() and + * other string-handling functions. Note that the "itxt_length", "lang", and + * "lang_key" members of the structure only exist when the library is built + * with iTXt chunk support. Prior to libpng-1.4.0 the library was built by + * default without iTXt support. Also note that when iTXt *is* supported, + * the "lang" and "lang_key" fields contain NULL pointers when the + * "compression" field contains * PNG_TEXT_COMPRESSION_NONE or + * PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the + * same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag" + * which is always 0 or 1, or its "compression method" which is always 0. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + png_size_t text_length; /* length of the text string */ + png_size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +} png_text; +typedef png_text FAR * png_textp; +typedef PNG_CONST png_text FAR * png_const_textp; +typedef png_text FAR * FAR * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time FAR * png_timep; +typedef PNG_CONST png_time FAR * png_const_timep; +typedef png_time FAR * FAR * png_timepp; + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \ + defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; + png_byte *data; + png_size_t size; + + /* libpng-using applications should NOT directly modify this byte. */ + png_byte location; /* mode of operation at read time */ +} + + +png_unknown_chunk; +typedef png_unknown_chunk FAR * png_unknown_chunkp; +typedef PNG_CONST png_unknown_chunk FAR * png_const_unknown_chunkp; +typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp; +#endif + +/* Values for the unknown chunk location byte */ + +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_AFTER_IDAT 0x08 + +/* The complete definition of png_info has, as of libpng-1.5.0, + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_info_def png_info; +typedef png_info FAR * png_infop; +typedef PNG_CONST png_info FAR * png_const_infop; +typedef png_info FAR * FAR * png_infopp; + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) +#define PNG_UINT_32_MAX ((png_uint_32)(-1)) +#define PNG_SIZE_MAX ((png_size_t)(-1)) + +/* These are constants for fixed point values encoded in the + * PNG specification manner (x100000) + */ +#define PNG_FP_1 100000 +#define PNG_FP_HALF 50000 +#define PNG_FP_MAX ((png_fixed_point)0x7fffffffL) +#define PNG_FP_MIN (-PNG_FP_MAX) + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_<chunk> defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001 +#define PNG_INFO_sBIT 0x0002 +#define PNG_INFO_cHRM 0x0004 +#define PNG_INFO_PLTE 0x0008 +#define PNG_INFO_tRNS 0x0010 +#define PNG_INFO_bKGD 0x0020 +#define PNG_INFO_hIST 0x0040 +#define PNG_INFO_pHYs 0x0080 +#define PNG_INFO_oFFs 0x0100 +#define PNG_INFO_tIME 0x0200 +#define PNG_INFO_pCAL 0x0400 +#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000 /* ESR, 1.0.6 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + png_size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info FAR * png_row_infop; +typedef png_row_info FAR * FAR * png_row_infopp; + +/* The complete definition of png_struct has, as of libpng-1.5.0, + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_struct_def png_struct; +typedef PNG_CONST png_struct FAR * png_const_structp; +typedef png_struct FAR * png_structp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. Note that the 'write' function must not + * modify the buffer it is passed. The 'read' function, on the other hand, is + * expected to return the read data in the buffer. + */ +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); + +/* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, + png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in <setjmp.h>, and the application + * must include this before png.h to obtain the definition of jmp_buf. The + * function is required to be PNG_NORETURN, but this is not checked. If the + * function does return the application will crash via an abort() or similar + * system level call. + * + * If you get a warning here while building the library you may need to make + * changes to ensure that pnglibconf.h records the calling convention used by + * your compiler. This may be very difficult - try using a different compiler + * to build the library! + */ +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ +/* Added to libpng-1.5.4 */ +#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ +#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, + * this allowed the zlib default functions to be used on Windows + * platforms. In 1.5 the zlib default malloc (which just calls malloc and + * ignores the first argument) should be completely compatible with the + * following. + */ +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); + +typedef png_struct FAR * FAR * png_structpp; + +/* Section 3: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes + */ + +/* Returns the version number of the library */ +PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); + +/* Tell lib we have already handled the first <num_bytes> magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +PNG_EXPORT(2, void, png_set_sig_bytes, (png_structp png_ptr, int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, + png_size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +PNG_EXPORTA(4, png_structp, png_create_read_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +PNG_EXPORTA(5, png_structp, png_create_write_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn), + PNG_ALLOCATED); + +PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, + (png_const_structp png_ptr)); + +PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structp png_ptr, + png_size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structp png_ptr, + png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_structp png_ptr, int val), + PNG_NORETURN); + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +PNG_EXPORT(10, int, png_reset_zstream, (png_structp png_ptr)); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(11, png_structp, png_create_read_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +PNG_EXPORTA(12, png_structp, png_create_write_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +#endif + +/* Write the PNG file signature. */ +PNG_EXPORT(13, void, png_write_sig, (png_structp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +PNG_EXPORT(14, void, png_write_chunk, (png_structp png_ptr, png_const_bytep + chunk_name, png_const_bytep data, png_size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +PNG_EXPORT(15, void, png_write_chunk_start, (png_structp png_ptr, + png_const_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +PNG_EXPORT(16, void, png_write_chunk_data, (png_structp png_ptr, + png_const_bytep data, png_size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +PNG_EXPORT(17, void, png_write_chunk_end, (png_structp png_ptr)); + +/* Allocate and initialize the info structure */ +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_structp png_ptr), + PNG_ALLOCATED); + +PNG_EXPORT(19, void, png_info_init_3, (png_infopp info_ptr, + png_size_t png_info_struct_size)); + +/* Writes all the PNG information before the image. */ +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structp png_ptr, png_infop info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +PNG_EXPORT(22, void, png_read_info, + (png_structp png_ptr, png_infop info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +PNG_EXPORT(23, png_const_charp, png_convert_to_rfc1123, + (png_structp png_ptr, + png_const_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, + PNG_CONST struct tm FAR * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +PNG_EXPORT(25, void, png_convert_from_time_t, + (png_timep ptime, time_t ttime)); +#endif /* PNG_CONVERT_tIME_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +PNG_EXPORT(26, void, png_set_expand, (png_structp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structp png_ptr)); +PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structp png_ptr)); +PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion + * of a tRNS chunk if present. + */ +PNG_EXPORT(221, void, png_set_expand_16, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +PNG_EXPORT(30, void, png_set_bgr, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#define PNG_ERROR_ACTION_NONE 1 +#define PNG_ERROR_ACTION_WARN 2 +#define PNG_ERROR_ACTION_ERROR 3 +#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ + +PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr, + int error_action, double red, double green)); +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)); + +PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structp + png_ptr)); +#endif + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* How the alpha channel is interpreted - this affects how the color channels of + * a PNG file are returned when an alpha channel, or tRNS chunk in a palette + * file, is present. + * + * This has no effect on the way pixels are written into a PNG output + * datastream. The color samples in a PNG datastream are never premultiplied + * with the alpha samples. + * + * The default is to return data according to the PNG specification: the alpha + * channel is a linear measure of the contribution of the pixel to the + * corresponding composited pixel. The gamma encoded color channels must be + * scaled according to the contribution and to do this it is necessary to undo + * the encoding, scale the color values, perform the composition and reencode + * the values. This is the 'PNG' mode. + * + * The alternative is to 'associate' the alpha with the color information by + * storing color channel values that have been scaled by the alpha. The + * advantage is that the color channels can be resampled (the image can be + * scaled) in this form. The disadvantage is that normal practice is to store + * linear, not (gamma) encoded, values and this requires 16-bit channels for + * still images rather than the 8-bit channels that are just about sufficient if + * gamma encoding is used. In addition all non-transparent pixel values, + * including completely opaque ones, must be gamma encoded to produce the final + * image. This is the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' mode (the + * latter being the two common names for associated alpha color channels.) + * + * Since it is not necessary to perform arithmetic on opaque color values so + * long as they are not to be resampled and are in the final color space it is + * possible to optimize the handling of alpha by storing the opaque pixels in + * the PNG format (adjusted for the output color space) while storing partially + * opaque pixels in the standard, linear, format. The accuracy required for + * standard alpha composition is relatively low, because the pixels are + * isolated, therefore typically the accuracy loss in storing 8-bit linear + * values is acceptable. (This is not true if the alpha channel is used to + * simulate transparency over large areas - use 16 bits or the PNG mode in + * this case!) This is the 'OPTIMIZED' mode. For this mode a pixel is + * treated as opaque only if the alpha value is equal to the maximum value. + * + * The final choice is to gamma encode the alpha channel as well. This is + * broken because, in practice, no implementation that uses this choice + * correctly undoes the encoding before handling alpha composition. Use this + * choice only if other serious errors in the software or hardware you use + * mandate it; the typical serious error is for dark halos to appear around + * opaque areas of the composited PNG image because of arithmetic overflow. + * + * The API function png_set_alpha_mode specifies which of these choices to use + * with an enumerated 'mode' value and the gamma of the required output: + */ +#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ +#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ +#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ +#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ +#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ +#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structp png_ptr, int mode, + double output_gamma)); +PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structp png_ptr, + int mode, png_fixed_point output_gamma)); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* The output_gamma value is a screen gamma in libpng terminology: it expresses + * how to decode the output values, not how they are encoded. The values used + * correspond to the normal numbers used to describe the overall gamma of a + * computer display system; for example 2.2 for an sRGB conformant system. The + * values are scaled by 100000 in the _fixed version of the API (so 220000 for + * sRGB.) + * + * The inverse of the value is always used to provide a default for the PNG file + * encoding if it has no gAMA chunk and if png_set_gamma() has not been called + * to override the PNG gamma information. + * + * When the ALPHA_OPTIMIZED mode is selected the output gamma is used to encode + * opaque pixels however pixels with lower alpha values are not encoded, + * regardless of the output gamma setting. + * + * When the standard Porter Duff handling is requested with mode 1 the output + * encoding is set to be linear and the output_gamma value is only relevant + * as a default for input data that has no gamma information. The linear output + * encoding will be overridden if png_set_gamma() is called - the results may be + * highly unexpected! + * + * The following numbers are derived from the sRGB standard and the research + * behind it. sRGB is defined to be approximated by a PNG gAMA chunk value of + * 0.45455 (1/2.2) for PNG. The value implicitly includes any viewing + * correction required to take account of any differences in the color + * environment of the original scene and the intended display environment; the + * value expresses how to *decode* the image for display, not how the original + * data was *encoded*. + * + * sRGB provides a peg for the PNG standard by defining a viewing environment. + * sRGB itself, and earlier TV standards, actually use a more complex transform + * (a linear portion then a gamma 2.4 power law) than PNG can express. (PNG is + * limited to simple power laws.) By saying that an image for direct display on + * an sRGB conformant system should be stored with a gAMA chunk value of 45455 + * (11.3.3.2 and 11.3.3.5 of the ISO PNG specification) the PNG specification + * makes it possible to derive values for other display systems and + * environments. + * + * The Mac value is deduced from the sRGB based on an assumption that the actual + * extra viewing correction used in early Mac display systems was implemented as + * a power 1.45 lookup table. + * + * Any system where a programmable lookup table is used or where the behavior of + * the final display device characteristics can be changed requires system + * specific code to obtain the current characteristic. However this can be + * difficult and most PNG gamma correction only requires an approximate value. + * + * By default, if png_set_alpha_mode() is not called, libpng assumes that all + * values are unencoded, linear, values and that the output device also has a + * linear characteristic. This is only very rarely correct - it is invariably + * better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the + * default if you don't know what the right answer is! + * + * The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS + * 10.6) which used a correction table to implement a somewhat lower gamma on an + * otherwise sRGB system. + * + * Both these values are reserved (not simple gamma values) in order to allow + * more precise correction internally in the future. + * + * NOTE: the following values can be passed to either the fixed or floating + * point APIs, but the floating point API will also accept floating point + * values. + */ +#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ +#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ +#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ +#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ +#endif + +/* The following are examples of calls to png_set_alpha_mode to achieve the + * required overall gamma correction and, where necessary, alpha + * premultiplication. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * This is the default libpng handling of the alpha channel - it is not + * pre-multiplied into the color components. In addition the call states + * that the output is for a sRGB system and causes all PNG files without gAMA + * chunks to be assumed to be encoded using sRGB. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * In this case the output is assumed to be something like an sRGB conformant + * display preceeded by a power-law lookup table of power 1.45. This is how + * early Mac systems behaved. + * + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); + * This is the classic Jim Blinn approach and will work in academic + * environments where everything is done by the book. It has the shortcoming + * of assuming that input PNG data with no gamma information is linear - this + * is unlikely to be correct unless the PNG files where generated locally. + * Most of the time the output precision will be so low as to show + * significant banding in dark areas of the image. + * + * png_set_expand_16(pp); + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); + * This is a somewhat more realistic Jim Blinn inspired approach. PNG files + * are assumed to have the sRGB encoding if not marked with a gamma value and + * the output is always 16 bits per component. This permits accurate scaling + * and processing of the data. If you know that your input PNG files were + * generated locally you might need to replace PNG_DEFAULT_sRGB with the + * correct value for your system. + * + * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); + * If you just need to composite the PNG image onto an existing background + * and if you control the code that does this you can use the optimization + * setting. In this case you just copy completely opaque pixels to the + * output. For pixels that are not completely transparent (you just skip + * those) you do the composition math using png_composite or png_composite_16 + * below then encode the resultant 8-bit or 16-bit values to match the output + * encoding. + * + * Other cases + * If neither the PNG nor the standard linear encoding work for you because + * of the software or hardware you use then you have a big problem. The PNG + * case will probably result in halos around the image. The linear encoding + * will probably result in a washed out, too bright, image (it's actually too + * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably + * substantially reduce the halos. Alternatively try: + * + * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); + * This option will also reduce the halos, but there will be slight dark + * halos round the opaque parts of the image where the background is light. + * In the OPTIMIZED mode the halos will be light halos where the background + * is dark. Take your pick - the halos are unavoidable unless you can get + * your hardware/software fixed! (The OPTIMIZED approach is slightly + * faster.) + * + * When the default gamma of PNG files doesn't match the output gamma. + * If you have PNG files with no gamma information png_set_alpha_mode allows + * you to provide a default gamma, but it also sets the ouput gamma to the + * matching value. If you know your PNG files have a gamma that doesn't + * match the output you can take advantage of the fact that + * png_set_alpha_mode always sets the output gamma but only sets the PNG + * default if it is not already set: + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * The first call sets both the default and the output gamma values, the + * second call overrides the output gamma without changing the default. This + * is easier than achieving the same effect with png_set_gamma. You must use + * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will + * fire if more than one call to png_set_alpha_mode and png_set_background is + * made in the same read operation, however multiple calls with PNG_ALPHA_PNG + * are ignored. + */ + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXPORT(38, void, png_set_invert_alpha, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ +PNG_EXPORT(39, void, png_set_filler, (png_structp png_ptr, png_uint_32 filler, + int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +# define PNG_FILLER_BEFORE 0 +# define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ +PNG_EXPORT(40, void, png_set_add_alpha, + (png_structp png_ptr, png_uint_32 filler, + int flags)); +#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +PNG_EXPORT(41, void, png_set_swap, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +PNG_EXPORT(42, void, png_set_packing, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +PNG_EXPORT(43, void, png_set_packswap, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +PNG_EXPORT(44, void, png_set_shift, (png_structp png_ptr, png_const_color_8p + true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +PNG_EXPORT(46, void, png_set_invert_mono, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. Prior to + * libpng-1.5.4 this API must not be called before the PNG file header has been + * read. Doing so will result in unexpected behavior and possible warnings or + * errors if the PNG file contains a bKGD chunk. + */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)); +PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)); +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +# define PNG_BACKGROUND_GAMMA_SCREEN 1 +# define PNG_BACKGROUND_GAMMA_FILE 2 +# define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale a 16-bit depth file down to 8-bit, accurately. */ +PNG_EXPORT(229, void, png_set_scale_16, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_16_TO_8 SUPPORTED /* Name prior to 1.5.4 */ +/* Strip the second byte of information from a 16-bit depth file. */ +PNG_EXPORT(48, void, png_set_strip_16, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. + */ +PNG_EXPORT(49, void, png_set_quantize, + (png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_const_uint_16p histogram, + int full_quantize)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) + +/* Handle gamma correction. Screen_gamma=(display_exponent). + * NOTE: this API simply sets the screen and file gamma values. It will + * therefore override the value for gamma in a PNG file if it is called after + * the file header has been read - use with care - call before reading the PNG + * file for best results! + * + * These routines accept the same gamma values as png_set_alpha_mode (described + * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either + * API (floating point or fixed.) Notice, however, that the 'file_gamma' value + * is the inverse of a 'screen gamma' value. + */ +PNG_FP_EXPORT(50, void, png_set_gamma, + (png_structp png_ptr, double screen_gamma, + double override_file_gamma)); +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structp png_ptr, + png_fixed_point screen_gamma, png_fixed_point override_file_gamma)); +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +PNG_EXPORT(51, void, png_set_flush, (png_structp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +PNG_EXPORT(52, void, png_write_flush, (png_structp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +PNG_EXPORT(53, void, png_start_read_image, (png_structp png_ptr)); + +/* Optional call to update the users info structure */ +PNG_EXPORT(54, void, png_read_update_info, + (png_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +PNG_EXPORT(55, void, png_read_rows, (png_structp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +PNG_EXPORT(56, void, png_read_row, (png_structp png_ptr, png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +PNG_EXPORT(57, void, png_read_image, (png_structp png_ptr, png_bytepp image)); +#endif + +/* Write a row of image data */ +PNG_EXPORT(58, void, png_write_row, + (png_structp png_ptr, png_const_bytep row)); + +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * of libpng and to allow the 'display_row' array from read_rows to be passed + * unchanged to write_rows. + */ +PNG_EXPORT(59, void, png_write_rows, (png_structp png_ptr, png_bytepp row, + png_uint_32 num_rows)); + +/* Write the image data */ +PNG_EXPORT(60, void, png_write_image, + (png_structp png_ptr, png_bytepp image)); + +/* Write the end of the PNG file. */ +PNG_EXPORT(61, void, png_write_end, + (png_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +PNG_EXPORT(62, void, png_read_end, (png_structp png_ptr, png_infop info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +PNG_EXPORT(63, void, png_destroy_info_struct, (png_structp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +PNG_EXPORT(66, void, png_set_crc_action, + (png_structp png_ptr, int crit_action, int ancil_action)); + +/* Values for png_set_crc_action() say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +PNG_EXPORT(67, void, png_set_filter, + (png_structp png_ptr, int method, int filters)); + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ + PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */ +/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ + * defines, either the default (minimum-sum-of-absolute-differences), or + * the experimental method (weighted-minimum-sum-of-absolute-differences). + * + * Weights are factors >= 1.0, indicating how important it is to keep the + * filter type consistent between rows. Larger numbers mean the current + * filter is that many times as likely to be the same as the "num_weights" + * previous filters. This is cumulative for each previous row with a weight. + * There needs to be "num_weights" values in "filter_weights", or it can be + * NULL if the weights aren't being specified. Weights have no influence on + * the selection of the first row filter. Well chosen weights can (in theory) + * improve the compression for a given image. + * + * Costs are factors >= 1.0 indicating the relative decoding costs of a + * filter type. Higher costs indicate more decoding expense, and are + * therefore less likely to be selected over a filter with lower computational + * costs. There needs to be a value in "filter_costs" for each valid filter + * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't + * setting the costs. Costs try to improve the speed of decompression without + * unduly increasing the compressed image size. + * + * A negative weight or cost indicates the default value is to be used, and + * values in the range [0.0, 1.0) indicate the value is to remain unchanged. + * The default values for both weights and costs are currently 1.0, but may + * change if good general weighting/cost heuristics can be found. If both + * the weights and costs are set to 1.0, this degenerates the WEIGHTED method + * to the UNWEIGHTED method, but with added encoding time/computation. + */ +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs)); +PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, + (png_structp png_ptr, + int heuristic_method, int num_weights, png_const_fixed_point_p + filter_weights, png_const_fixed_point_p filter_costs)); +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +/* Heuristic used for row filter selection. These defines should NOT be + * changed. + */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +#ifdef PNG_WRITE_SUPPORTED +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +PNG_EXPORT(69, void, png_set_compression_level, + (png_structp png_ptr, int level)); + +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structp png_ptr, + int mem_level)); + +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structp png_ptr, + int window_bits)); + +PNG_EXPORT(73, void, png_set_compression_method, (png_structp png_ptr, + int method)); +#endif + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +/* Also set zlib parameters for compressing non-IDAT chunks */ +PNG_EXPORT(222, void, png_set_text_compression_level, + (png_structp png_ptr, int level)); + +PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structp png_ptr, + int mem_level)); + +PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(225, void, png_set_text_compression_window_bits, (png_structp + png_ptr, int window_bits)); + +PNG_EXPORT(226, void, png_set_text_compression_method, (png_structp png_ptr, + int method)); +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng-manual.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +PNG_EXPORT(74, void, png_init_io, (png_structp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +PNG_EXPORT(75, void, png_set_error_fn, + (png_structp png_ptr, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +PNG_EXPORT(77, void, png_set_write_fn, (png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +PNG_EXPORT(78, void, png_set_read_fn, (png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_structp png_ptr)); + +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structp png_ptr, + png_read_status_ptr read_row_fn)); + +PNG_EXPORT(81, void, png_set_write_status_fn, (png_structp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +PNG_EXPORT(82, void, png_set_mem_fn, (png_structp png_ptr, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structp png_ptr, + png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structp png_ptr, + png_user_transform_ptr write_user_transform_fn)); +#endif + +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +PNG_EXPORT(86, void, png_set_user_transform_info, (png_structp png_ptr, + png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* Return information about the row currently being processed. Note that these + * APIs do not fail but will return unexpected results if called outside a user + * transform callback. Also note that when transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structp)); +PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structp)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structp png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structp png_ptr, + png_voidp progressive_ptr, png_progressive_info_ptr info_fn, + png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, (png_const_structp png_ptr)); + +/* Function to be called when data becomes available */ +PNG_EXPORT(92, void, png_process_data, + (png_structp png_ptr, png_infop info_ptr, + png_bytep buffer, png_size_t buffer_size)); + +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. + */ +PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structp)); + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * stores its own version of the new data internally and ignores the passed + * in value. + */ +PNG_EXPORT(93, void, png_progressive_combine_row, (png_structp png_ptr, + png_bytep old_row, png_const_bytep new_row)); +#endif /* PNG_READ_INTERLACING_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +PNG_EXPORTA(94, png_voidp, png_malloc, + (png_structp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); +/* Added at libpng version 1.4.0 */ +PNG_EXPORTA(95, png_voidp, png_calloc, + (png_structp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); + +/* Added at libpng version 1.2.4 */ +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_structp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Frees a pointer allocated by png_malloc() */ +PNG_EXPORT(97, void, png_free, (png_structp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +PNG_EXPORT(98, void, png_free_data, + (png_structp png_ptr, png_infop info_ptr, png_uint_32 free_me, int num)); + +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application */ +PNG_EXPORT(99, void, png_data_freer, + (png_structp png_ptr, png_infop info_ptr, int freer, png_uint_32 mask)); + +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008 +#define PNG_FREE_ICCP 0x0010 +#define PNG_FREE_SPLT 0x0020 +#define PNG_FREE_ROWS 0x0040 +#define PNG_FREE_PCAL 0x0080 +#define PNG_FREE_SCAL 0x0100 +#define PNG_FREE_UNKN 0x0200 +#define PNG_FREE_LIST 0x0400 +#define PNG_FREE_PLTE 0x1000 +#define PNG_FREE_TRNS 0x2000 +#define PNG_FREE_TEXT 0x4000 +#define PNG_FREE_ALL 0x7fff +#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_structp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); +PNG_EXPORT(101, void, png_free_default, (png_structp png_ptr, png_voidp ptr)); +#endif + +#ifdef PNG_ERROR_TEXT_SUPPORTED +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(102, void, png_error, + (png_structp png_ptr, png_const_charp error_message), + PNG_NORETURN); + +/* The same, but the chunk name is prepended to the error string. */ +PNG_EXPORTA(103, void, png_chunk_error, (png_structp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#else +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(104, void, png_err, (png_structp png_ptr), PNG_NORETURN); +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +PNG_EXPORT(105, void, png_warning, (png_structp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +PNG_EXPORT(106, void, png_chunk_warning, (png_structp png_ptr, + png_const_charp warning_message)); +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +# undef png_benign_error +PNG_EXPORT(107, void, png_benign_error, (png_structp png_ptr, + png_const_charp warning_message)); + +/* Same, chunk name is prepended to message. */ +# undef png_chunk_benign_error +PNG_EXPORT(108, void, png_chunk_benign_error, (png_structp png_ptr, + png_const_charp warning_message)); + +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* The png_set_<chunk> functions are for storing values in the png_info_struct. + * Similarly, the png_get_<chunk> calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_<chunk> functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +PNG_EXPORT(110, png_uint_32, png_get_valid, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +PNG_EXPORT(112, png_bytepp, png_get_rows, + (png_const_structp png_ptr, png_const_infop info_ptr)); +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +PNG_EXPORT(113, void, png_set_rows, (png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +PNG_EXPORT(114, png_byte, png_get_channels, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image height in pixels. */ +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image bit_depth. */ +PNG_EXPORT(117, png_byte, png_get_bit_depth, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +/* Returns image color_type. */ +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image filter_type. */ +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image interlace_type. */ +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image compression_type. */ +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +/* Returns pointer to signature string read from PNG header */ +PNG_EXPORT(130, png_const_bytep, png_get_signature, + (png_const_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(131, png_uint_32, png_get_bKGD, + (png_const_structp png_ptr, png_infop info_ptr, + png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(132, void, png_set_bKGD, (png_structp png_ptr, png_infop info_ptr, + png_const_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structp png_ptr, + png_const_infop info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)); +PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_structp png_ptr, + png_const_infop info_ptr, double *red_X, double *red_Y, double *red_Z, + double *green_X, double *green_Y, double *green_Z, double *blue_X, + double *blue_Y, double *blue_Z)); +#ifdef PNG_FIXED_POINT_SUPPORTED /* Otherwise not implemented */ +PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, + (png_const_structp png_ptr, + png_const_infop info_ptr, png_fixed_point *int_white_x, + png_fixed_point *int_white_y, png_fixed_point *int_red_x, + png_fixed_point *int_red_y, png_fixed_point *int_green_x, + png_fixed_point *int_green_y, png_fixed_point *int_blue_x, + png_fixed_point *int_blue_y)); +#endif +PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, + (png_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(135, void, png_set_cHRM, + (png_structp png_ptr, png_infop info_ptr, + double white_x, double white_y, double red_x, double red_y, double green_x, + double green_y, double blue_x, double blue_y)); +PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_structp png_ptr, + png_infop info_ptr, double red_X, double red_Y, double red_Z, + double green_X, double green_Y, double green_Z, double blue_X, + double blue_Y, double blue_Z)); +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_white_x, + png_fixed_point int_white_y, png_fixed_point int_red_x, + png_fixed_point int_red_y, png_fixed_point int_green_x, + png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, + (png_const_structp png_ptr, png_const_infop info_ptr, + double *file_gamma)); +PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *int_file_gamma)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(139, void, png_set_gAMA, (png_structp png_ptr, + png_infop info_ptr, double file_gamma)); +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(141, png_uint_32, png_get_hIST, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_16p *hist)); +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(142, void, png_set_hIST, (png_structp png_ptr, + png_infop info_ptr, png_const_uint_16p hist)); +#endif + +PNG_EXPORT(143, png_uint_32, png_get_IHDR, + (png_structp png_ptr, png_infop info_ptr, + png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type, + int *interlace_method, int *compression_method, int *filter_method)); + +PNG_EXPORT(144, void, png_set_IHDR, + (png_structp png_ptr, png_infop info_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, + int interlace_method, int compression_method, int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(145, png_uint_32, png_get_oFFs, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(146, void, png_set_oFFs, + (png_structp png_ptr, png_infop info_ptr, + png_int_32 offset_x, png_int_32 offset_y, int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(147, png_uint_32, png_get_pCAL, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, + int *nparams, + png_charp *units, png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(148, void, png_set_pCAL, (png_structp png_ptr, + png_infop info_ptr, + png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, + int nparams, png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(149, png_uint_32, png_get_pHYs, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(150, void, png_set_pHYs, + (png_structp png_ptr, png_infop info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +PNG_EXPORT(151, png_uint_32, png_get_PLTE, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_colorp *palette, int *num_palette)); + +PNG_EXPORT(152, void, png_set_PLTE, + (png_structp png_ptr, png_infop info_ptr, + png_const_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(153, png_uint_32, png_get_sBIT, + (png_const_structp png_ptr, png_infop info_ptr, + png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(154, void, png_set_sBIT, + (png_structp png_ptr, png_infop info_ptr, png_const_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structp png_ptr, + png_const_infop info_ptr, int *file_srgb_intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(156, void, png_set_sRGB, + (png_structp png_ptr, png_infop info_ptr, int srgb_intent)); +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_structp png_ptr, + png_infop info_ptr, int srgb_intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(158, png_uint_32, png_get_iCCP, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_charpp name, int *compression_type, png_bytepp profile, + png_uint_32 *proflen)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(159, void, png_set_iCCP, + (png_structp png_ptr, png_infop info_ptr, + png_const_charp name, int compression_type, png_const_bytep profile, + png_uint_32 proflen)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(160, png_uint_32, png_get_sPLT, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(161, void, png_set_sPLT, + (png_structp png_ptr, png_infop info_ptr, + png_const_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +PNG_EXPORT(162, png_uint_32, png_get_text, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +PNG_EXPORT(163, void, png_set_text, + (png_structp png_ptr, png_infop info_ptr, + png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(164, png_uint_32, png_get_tIME, + (png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(165, void, png_set_tIME, + (png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(166, png_uint_32, png_get_tRNS, + (png_const_structp png_ptr, png_infop info_ptr, + png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(167, void, png_set_tRNS, + (png_structp png_ptr, png_infop info_ptr, + png_const_bytep trans_alpha, int num_trans, + png_const_color_16p trans_color)); +#endif + +#ifdef PNG_sCAL_SUPPORTED +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, + (png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, double *width, double *height)); +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED +/* NOTE: this API is currently implemented using floating point arithmetic, + * consequently it can only be used on systems with floating point support. + * In any case the range of values supported by png_fixed_point is small and it + * is highly recommended that png_get_sCAL_s be used instead. + */ +PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, + (png_structp png_ptr, png_const_infop info_ptr, int *unit, + png_fixed_point *width, + png_fixed_point *height)); +#endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, png_charpp swidth, png_charpp sheight)); + +PNG_FP_EXPORT(170, void, png_set_sCAL, + (png_structp png_ptr, png_infop info_ptr, + int unit, double width, double height)); +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_structp png_ptr, + png_infop info_ptr, int unit, png_fixed_point width, + png_fixed_point height)); +PNG_EXPORT(171, void, png_set_sCAL_s, + (png_structp png_ptr, png_infop info_ptr, + int unit, png_const_charp swidth, png_const_charp sheight)); +#endif /* PNG_sCAL_SUPPORTED */ + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +/* Provide a list of chunks and how they are to be handled, if the built-in + handling or default unknown chunk handling is not desired. Any chunks not + listed will be handled in the default manner. The IHDR and IEND chunks + must not be listed. Because this turns off the default handling for chunks + that would otherwise be recognized the behavior of libpng transformations may + well become incorrect! + keep = 0: PNG_HANDLE_CHUNK_AS_DEFAULT: follow default behavior + = 1: PNG_HANDLE_CHUNK_NEVER: do not keep + = 2: PNG_HANDLE_CHUNK_IF_SAFE: keep only if safe-to-copy + = 3: PNG_HANDLE_CHUNK_ALWAYS: keep even if unsafe-to-copy +*/ +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, + (png_structp png_ptr, int keep, + png_const_bytep chunk_list, int num_chunks)); + +/* The handling code is returned; the result is therefore true (non-zero) if + * special handling is required, false for the default handling. + */ +PNG_EXPORT(173, int, png_handle_as_unknown, (png_structp png_ptr, + png_const_bytep chunk_name)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structp png_ptr, + png_infop info_ptr, png_const_unknown_chunkp unknowns, + int num_unknowns)); +PNG_EXPORT(175, void, png_set_unknown_chunk_location, + (png_structp png_ptr, png_infop info_ptr, int chunk, int location)); +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structp png_ptr, + png_const_infop info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +PNG_EXPORT(177, void, png_set_invalid, + (png_structp png_ptr, png_infop info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +PNG_EXPORT(178, void, png_read_png, (png_structp png_ptr, png_infop info_ptr, + int transforms, png_voidp params)); +PNG_EXPORT(179, void, png_write_png, (png_structp png_ptr, png_infop info_ptr, + int transforms, png_voidp params)); +#endif + +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structp png_ptr, + png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +PNG_EXPORT(185, void, png_set_strip_error_numbers, + (png_structp png_ptr, + png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +PNG_EXPORT(186, void, png_set_user_limits, (png_structp png_ptr, + png_uint_32 user_width_max, png_uint_32 user_height_max)); +PNG_EXPORT(187, png_uint_32, png_get_user_width_max, + (png_const_structp png_ptr)); +PNG_EXPORT(188, png_uint_32, png_get_user_height_max, + (png_const_structp png_ptr)); +/* Added in libpng-1.4.0 */ +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structp png_ptr, + png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, + (png_const_structp png_ptr)); +/* Added in libpng-1.4.1 */ +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structp png_ptr, + png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, + (png_const_structp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +PNG_FP_EXPORT(196, float, png_get_x_offset_inches, + (png_const_structp png_ptr, png_const_infop info_ptr)); +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, + (png_structp png_ptr, png_const_infop info_ptr)); +#endif + +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structp png_ptr, + png_const_infop info_ptr)); +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, + (png_structp png_ptr, png_const_infop info_ptr)); +#endif + +# ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structp png_ptr, + png_const_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +# endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_structp png_ptr)); + +PNG_EXPORTA(200, png_const_bytep, png_get_io_chunk_name, + (png_structp png_ptr), PNG_DEPRECATED); +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_structp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +# define PNG_IO_READING 0x0001 /* currently reading */ +# define PNG_IO_WRITING 0x0002 /* currently writing */ +# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. + */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* A macro to return the offset between pixels in the output row for a pair of + * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that + * follows. Note that ROW_OFFSET is the offset from one row to the next whereas + * COL_OFFSET is from one column to the next, within a row. + */ +#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) +#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<<PNG_PASS_ROW_SHIFT(pass))\ + -1)-PNG_PASS_START_ROW(pass)))>>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<<PNG_PASS_COL_SHIFT(pass))\ + -1)-PNG_PASS_START_COL(pass)))>>PNG_PASS_COL_SHIFT(pass)) + +/* For the reader row callbacks (both progressive and sequential) it is + * necessary to find the row in the output image given a row in an interlaced + * image, so two more macros: + */ +#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \ + (((yIn)<<PNG_PASS_ROW_SHIFT(pass))+PNG_PASS_START_ROW(pass)) +#define PNG_COL_FROM_PASS_COL(xIn, pass) \ + (((xIn)<<PNG_PASS_COL_SHIFT(pass))+PNG_PASS_START_COL(pass)) + +/* Two macros which return a boolean (0 or 1) saying whether the given row + * or column is in a particular pass. These use a common utility macro that + * returns a mask for a given pass - the offset 'off' selects the row or + * column version. The mask has the appropriate bit set for each column in + * the tile. + */ +#define PNG_PASS_MASK(pass,off) ( \ + ((0x110145AF>>(((7-(off))-(pass))<<2)) & 0xF) | \ + ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + 128); \ + (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } + +# define png_composite_16(composite, fg, alpha, bg) \ + { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(65535 \ + - (png_uint_32)(alpha)) + 32768); \ + (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + 127) / 255) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ + 32767) / 65535) +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); +PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +#endif + +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_structp png_ptr, + png_const_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +# define png_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) + + /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the + * function) incorrectly returned a value of type png_uint_32. + */ +# define png_get_uint_16(buf) \ + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) + +# define png_get_int_32(buf) \ + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \ + : (png_int_32)png_get_uint_32(buf))) +#endif + +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project + * defs + */ + +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) Maintainer, remember to add an entry to + * scripts/symbols.def as well. + */ +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(233); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/plugins/snes9x_gx/portlibs/include/pngconf.h b/plugins/snes9x_gx/portlibs/include/pngconf.h new file mode 100644 index 00000000..1aa268be --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/pngconf.h @@ -0,0 +1,596 @@ + +/* pngconf.h - machine configurable file for libpng + * + * libpng version 1.5.9 - February 18, 2012 + * + * Copyright (c) 1998-2012 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + */ + +/* Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#ifndef PNG_BUILDING_SYMBOL_TABLE +/* PNG_NO_LIMITS_H may be used to turn off the use of the standard C + * definition file for machine specific limits, this may impact the + * correctness of the definitons below (see uses of INT_MAX). + */ +# ifndef PNG_NO_LIMITS_H +# include <limits.h> +# endif + +/* For the memory copy APIs (i.e. the standard definitions of these), + * because this file defines png_memcpy and so on the base APIs must + * be defined here. + */ +# ifdef BSD +# include <strings.h> +# else +# include <string.h> +# endif + +/* For png_FILE_p - this provides the standard definition of a + * FILE + */ +# ifdef PNG_STDIO_SUPPORTED +# include <stdio.h> +# endif +#endif + +/* This controls optimization of the reading of 16 and 32 bit values + * from PNG files. It can be set on a per-app-file basis - it + * just changes whether a macro is used to the function is called. + * The library builder sets the default, if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG macro protects us against machines that don't have function + * prototypes (ie K&R style headers). If your compiler does not handle + * function prototypes, define this macro and use the included ansi2knr. + * I've always been able to use _NO_PROTO as the indicator, but you may + * need to drag the empty declaration out in front of here, or change the + * ifdef to suit your own needs. + */ +#ifndef PNGARG + +# ifdef OF /* zlib prototype munger */ +# define PNGARG(arglist) OF(arglist) +# else + +# ifdef _NO_PROTO +# define PNGARG(arglist) () +# else +# define PNGARG(arglist) arglist +# endif /* _NO_PROTO */ + +# endif /* OF */ + +#endif /* PNGARG */ + +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows sytems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. + */ + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. Not used in the + * public header files; see pngpriv.h for how it is used + * in the libpng build. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows/x86 systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if ( defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ + defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) ) &&\ + ( defined(_X86_) || defined(_X64_) || defined(_M_IX86) ||\ + defined(_M_X64) || defined(_M_IA64) ) + /* Windows system (DOS doesn't support DLLs) running on x86/x64. Includes + * builds under Cygwin or MinGW. Also includes Watcom builds but these need + * special treatment because they are not compatible with GCC or Visual C + * because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) + ERROR: PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows/x86 */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* PNG_IMPEXP may be set on the compilation system command line or (if not set) + * then in an internal header file when building the library, otherwise (when + * using the library) it is set here. + */ +#ifndef PNG_IMPEXP +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP +# endif +#endif + +/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat + * 'attributes' as a storage class - the attributes go at the start of the + * function definition, and attributes are always appended regardless of the + * compiler. This considerably simplifies these macros but may cause problems + * if any compilers both need function attributes and fail to handle them as + * a storage class (this is unlikely.) + */ +#ifndef PNG_FUNCTION +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args +#endif + +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type +#endif + + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ +#ifndef PNG_EXPORTA + +# define PNG_EXPORTA(ordinal, type, name, args, attributes)\ + PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \ + extern attributes) +#endif + +/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, + * so make something non-empty to satisfy the requirement: + */ +#define PNG_EMPTY /*empty list*/ + +#define PNG_EXPORT(ordinal, type, name, args)\ + PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED + /* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. + */ +# if defined(__GNUC__) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif +# endif /* __GNUC__ */ + +# if defined(_MSC_VER) && (_MSC_VER >= 1300) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* not supported */ +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __declspec(noreturn) +# endif +# ifndef PNG_ALLOCATED +# if (_MSC_VER >= 1400) +# define PNG_ALLOCATED __declspec(restrict) +# endif +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __declspec(deprecated) +# endif +# ifndef PNG_PRIVATE +# define PNG_PRIVATE __declspec(deprecated) +# endif +# endif /* _MSC_VER */ +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args) +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args) +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif +#endif + +/* The following uses const char * instead of char * for error + * and warning message functions, so some compilers won't complain. + * If you do not want to use const, define PNG_NO_CONST here. + * + * This should not change how the APIs are called, so it can be done + * on a per-file basis in the application. + */ +#ifndef PNG_CONST +# ifndef PNG_NO_CONST +# define PNG_CONST const +# else +# define PNG_CONST +# endif +#endif + +/* Some typedefs to get us started. These should be safe on most of the + * common platforms. The typedefs should be at least as large as the + * numbers suggest (a png_uint_32 must be at least 32 bits long), but they + * don't have to be exactly that size. Some compilers dislike passing + * unsigned shorts as function parameters, so you may be better off using + * unsigned int for png_uint_16. + */ + +#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL) +typedef unsigned int png_uint_32; +typedef int png_int_32; +#else +typedef unsigned long png_uint_32; +typedef long png_int_32; +#endif +typedef unsigned short png_uint_16; +typedef short png_int_16; +typedef unsigned char png_byte; + +#ifdef PNG_NO_SIZE_T +typedef unsigned int png_size_t; +#else +typedef size_t png_size_t; +#endif +#define png_sizeof(x) (sizeof (x)) + +/* The following is needed for medium model support. It cannot be in the + * pngpriv.h header. Needs modification for other compilers besides + * MSC. Model independent support declares all arrays and pointers to be + * large using the far keyword. The zlib version used must also support + * model independent data. As of version zlib 1.0.4, the necessary changes + * have been made in zlib. The USE_FAR_KEYWORD define triggers other + * changes that are needed. (Tim Wegner) + */ + +/* Separate compiler dependencies (problem here is that zlib.h always + * defines FAR. (SJT) + */ +#ifdef __BORLANDC__ +# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) +# define LDATA 1 +# else +# define LDATA 0 +# endif + /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ +# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) +# define PNG_MAX_MALLOC_64K /* only used in build */ +# if (LDATA != 1) +# ifndef FAR +# define FAR __far +# endif +# define USE_FAR_KEYWORD +# endif /* LDATA != 1 */ + /* Possibly useful for moving data out of default segment. + * Uncomment it if you want. Could also define FARDATA as + * const if your compiler supports it. (SJT) +# define FARDATA FAR + */ +# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ +#endif /* __BORLANDC__ */ + + +/* Suggest testing for specific compiler first before testing for + * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, + * making reliance oncertain keywords suspect. (SJT) + */ + +/* MSC Medium model */ +#ifdef FAR +# ifdef M_I86MM +# define USE_FAR_KEYWORD +# define FARDATA FAR +# include <dos.h> +# endif +#endif + +/* SJT: default case */ +#ifndef FAR +# define FAR +#endif + +/* At this point FAR is always defined */ +#ifndef FARDATA +# define FARDATA +#endif + +/* Typedef for floating-point numbers that are converted + * to fixed-point with a multiple of 100,000, e.g., gamma + */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void FAR * png_voidp; +typedef PNG_CONST void FAR * png_const_voidp; +typedef png_byte FAR * png_bytep; +typedef PNG_CONST png_byte FAR * png_const_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef PNG_CONST png_uint_32 FAR * png_const_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef PNG_CONST png_int_32 FAR * png_const_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef PNG_CONST png_uint_16 FAR * png_const_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST png_int_16 FAR * png_const_int_16p; +typedef char FAR * png_charp; +typedef PNG_CONST char FAR * png_const_charp; +typedef png_fixed_point FAR * png_fixed_point_p; +typedef PNG_CONST png_fixed_point FAR * png_const_fixed_point_p; +typedef png_size_t FAR * png_size_tp; +typedef PNG_CONST png_size_t FAR * png_const_size_tp; + +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * png_doublep; +typedef PNG_CONST double FAR * png_const_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte FAR * FAR * png_bytepp; +typedef png_uint_32 FAR * FAR * png_uint_32pp; +typedef png_int_32 FAR * FAR * png_int_32pp; +typedef png_uint_16 FAR * FAR * png_uint_16pp; +typedef png_int_16 FAR * FAR * png_int_16pp; +typedef PNG_CONST char FAR * FAR * png_const_charpp; +typedef char FAR * FAR * png_charpp; +typedef png_fixed_point FAR * FAR * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * FAR * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char FAR * FAR * FAR * png_charppp; + +/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, + * and no smaller than png_uint_32. Casts from png_size_t or png_uint_32 + * to png_alloc_size_t are not necessary; in fact, it is recommended + * not to use them at all so that the compiler can complain when something + * turns out to be problematic. + * Casts in the other direction (from png_alloc_size_t to png_size_t or + * png_uint_32) should be explicitly applied; however, we do not expect + * to encounter practical situations that require such conversions. + */ +#if defined(__TURBOC__) && !defined(__FLAT__) + typedef unsigned long png_alloc_size_t; +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + typedef unsigned long png_alloc_size_t; +# else + /* This is an attempt to detect an old Windows system where (int) is + * actually 16 bits, in that case png_malloc must have an argument with a + * bigger size to accomodate the requirements of the library. + */ +# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) && \ + (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL) + typedef DWORD png_alloc_size_t; +# else + typedef png_size_t png_alloc_size_t; +# endif +# endif +#endif + +#endif /* PNGCONF_H */ diff --git a/plugins/snes9x_gx/portlibs/include/pnglibconf.h b/plugins/snes9x_gx/portlibs/include/pnglibconf.h new file mode 100644 index 00000000..c76480e7 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/pnglibconf.h @@ -0,0 +1,180 @@ +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.5.9 - February 18, 2012 */ + +/* Copyright (c) 1998-2011 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Machine generated file: DO NOT EDIT */ +/* Derived from: scripts/pnglibconf.dfa */ +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* settings */ +#define PNG_MAX_GAMMA_8 11 +#define PNG_CALLOC_SUPPORTED +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_USER_WIDTH_MAX 1000000 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_API_RULE 0 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_USER_CHUNK_CACHE_MAX 0 +#define PNG_USER_HEIGHT_MAX 1000000 +#define PNG_sCAL_PRECISION 5 +#define PNG_COST_SHIFT 3 +#define PNG_WEIGHT_SHIFT 8 +#define PNG_USER_CHUNK_MALLOC_MAX 0 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_ZBUF_SIZE 8192 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +/* end of settings */ +/* options */ +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +#define PNG_ALIGN_MEMORY_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_16BIT_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_zTXt_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_CHECK_cHRM_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_tEXt_SUPPORTED +/* end of options */ +#endif /* PNGLCONF_H */ diff --git a/plugins/snes9x_gx/portlibs/include/sevenzip/7zAlloc.h b/plugins/snes9x_gx/portlibs/include/sevenzip/7zAlloc.h new file mode 100644 index 00000000..91505d00 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/sevenzip/7zAlloc.h @@ -0,0 +1,15 @@ +/* 7zAlloc.h -- Allocation functions +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __7Z_ALLOC_H +#define __7Z_ALLOC_H + +#include <stddef.h> + +void *SzAlloc(void *p, size_t size); +void SzFree(void *p, void *address); + +void *SzAllocTemp(void *p, size_t size); +void SzFreeTemp(void *p, void *address); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/sevenzip/7zBuf.h b/plugins/snes9x_gx/portlibs/include/sevenzip/7zBuf.h new file mode 100644 index 00000000..49b2354b --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/sevenzip/7zBuf.h @@ -0,0 +1,31 @@ +/* 7zBuf.h -- Byte Buffer +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __7Z_BUF_H +#define __7Z_BUF_H + +#include "Types.h" + +typedef struct +{ + Byte *data; + size_t size; +} CBuf; + +void Buf_Init(CBuf *p); +int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); +void Buf_Free(CBuf *p, ISzAlloc *alloc); + +typedef struct +{ + Byte *data; + size_t size; + size_t pos; +} CDynBuf; + +void DynBuf_Construct(CDynBuf *p); +void DynBuf_SeekToBeg(CDynBuf *p); +int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); +void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/sevenzip/7zCrc.h b/plugins/snes9x_gx/portlibs/include/sevenzip/7zCrc.h new file mode 100644 index 00000000..ae230991 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/sevenzip/7zCrc.h @@ -0,0 +1,24 @@ +/* 7zCrc.h -- CRC32 calculation +2008-03-13 +Igor Pavlov +Public domain */ + +#ifndef __7Z_CRC_H +#define __7Z_CRC_H + +#include <stddef.h> + +#include "Types.h" + +extern UInt32 g_CrcTable[]; + +void MY_FAST_CALL CrcGenerateTable(void); + +#define CRC_INIT_VAL 0xFFFFFFFF +#define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF) +#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); +UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/sevenzip/7zDecode.h b/plugins/snes9x_gx/portlibs/include/sevenzip/7zDecode.h new file mode 100644 index 00000000..9607915b --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/sevenzip/7zDecode.h @@ -0,0 +1,13 @@ +/* 7zDecode.h -- Decoding from 7z folder +2008-11-23 : Igor Pavlov : Public domain */ + +#ifndef __7Z_DECODE_H +#define __7Z_DECODE_H + +#include "7zItem.h" + +SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, + ILookInStream *stream, UInt64 startPos, + Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/sevenzip/7zExtract.h b/plugins/snes9x_gx/portlibs/include/sevenzip/7zExtract.h new file mode 100644 index 00000000..e171f4ab --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/sevenzip/7zExtract.h @@ -0,0 +1,41 @@ +/* 7zExtract.h -- Extracting from 7z archive +2008-11-23 : Igor Pavlov : Public domain */ + +#ifndef __7Z_EXTRACT_H +#define __7Z_EXTRACT_H + +#include "7zIn.h" + +/* + SzExtract extracts file from archive + + *outBuffer must be 0 before first call for each new archive. + + Extracting cache: + If you need to decompress more than one file, you can send + these values from previous call: + *blockIndex, + *outBuffer, + *outBufferSize + You can consider "*outBuffer" as cache of solid block. If your archive is solid, + it will increase decompression speed. + + If you use external function, you can declare these 3 cache variables + (blockIndex, outBuffer, outBufferSize) as static in that external function. + + Free *outBuffer and set *outBuffer to 0, if you want to flush cache. +*/ + +SRes SzAr_Extract( + const CSzArEx *db, + ILookInStream *inStream, + UInt32 fileIndex, /* index of file */ + UInt32 *blockIndex, /* index of solid block */ + Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ + size_t *outBufferSize, /* buffer size for output buffer */ + size_t *offset, /* offset of stream for required file in *outBuffer */ + size_t *outSizeProcessed, /* size of file in *outBuffer */ + ISzAlloc *allocMain, + ISzAlloc *allocTemp); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/sevenzip/7zFile.h b/plugins/snes9x_gx/portlibs/include/sevenzip/7zFile.h new file mode 100644 index 00000000..4fd2936c --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/sevenzip/7zFile.h @@ -0,0 +1,74 @@ +/* 7zFile.h -- File IO +2008-11-22 : Igor Pavlov : Public domain */ + +#ifndef __7Z_FILE_H +#define __7Z_FILE_H + +#ifdef _WIN32 +#define USE_WINDOWS_FILE +#endif + +#ifdef USE_WINDOWS_FILE +#include <windows.h> +#else +#include <stdio.h> +#endif + +#include "Types.h" + + +/* ---------- File ---------- */ + +typedef struct +{ + #ifdef USE_WINDOWS_FILE + HANDLE handle; + #else + FILE *file; + #endif +} CSzFile; + +void File_Construct(CSzFile *p); +WRes InFile_Open(CSzFile *p, const char *name); +WRes OutFile_Open(CSzFile *p, const char *name); +WRes File_Close(CSzFile *p); + +/* reads max(*size, remain file's size) bytes */ +WRes File_Read(CSzFile *p, void *data, size_t *size); + +/* writes *size bytes */ +WRes File_Write(CSzFile *p, const void *data, size_t *size); + +WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); +WRes File_GetLength(CSzFile *p, UInt64 *length); + + +/* ---------- FileInStream ---------- */ + +typedef struct +{ + ISeqInStream s; + CSzFile file; +} CFileSeqInStream; + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p); + + +typedef struct +{ + ISeekInStream s; + CSzFile file; +} CFileInStream; + +void FileInStream_CreateVTable(CFileInStream *p); + + +typedef struct +{ + ISeqOutStream s; + CSzFile file; +} CFileOutStream; + +void FileOutStream_CreateVTable(CFileOutStream *p); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/sevenzip/7zHeader.h b/plugins/snes9x_gx/portlibs/include/sevenzip/7zHeader.h new file mode 100644 index 00000000..a8c85e8d --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/sevenzip/7zHeader.h @@ -0,0 +1,57 @@ +/* 7zHeader.h -- 7z Headers +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __7Z_HEADER_H +#define __7Z_HEADER_H + +#include "Types.h" + +#define k7zSignatureSize 6 +extern Byte k7zSignature[k7zSignatureSize]; + +#define k7zMajorVersion 0 + +#define k7zStartHeaderSize 0x20 + +enum EIdEnum +{ + k7zIdEnd, + + k7zIdHeader, + + k7zIdArchiveProperties, + + k7zIdAdditionalStreamsInfo, + k7zIdMainStreamsInfo, + k7zIdFilesInfo, + + k7zIdPackInfo, + k7zIdUnpackInfo, + k7zIdSubStreamsInfo, + + k7zIdSize, + k7zIdCRC, + + k7zIdFolder, + + k7zIdCodersUnpackSize, + k7zIdNumUnpackStream, + + k7zIdEmptyStream, + k7zIdEmptyFile, + k7zIdAnti, + + k7zIdName, + k7zIdCTime, + k7zIdATime, + k7zIdMTime, + k7zIdWinAttributes, + k7zIdComment, + + k7zIdEncodedHeader, + + k7zIdStartPos, + k7zIdDummy +}; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/sevenzip/7zIn.h b/plugins/snes9x_gx/portlibs/include/sevenzip/7zIn.h new file mode 100644 index 00000000..717fe52c --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/sevenzip/7zIn.h @@ -0,0 +1,41 @@ +/* 7zIn.h -- 7z Input functions +2008-11-23 : Igor Pavlov : Public domain */ + +#ifndef __7Z_IN_H +#define __7Z_IN_H + +#include "7zHeader.h" +#include "7zItem.h" + +typedef struct +{ + CSzAr db; + + UInt64 startPosAfterHeader; + UInt64 dataPos; + + UInt32 *FolderStartPackStreamIndex; + UInt64 *PackStreamStartPositions; + UInt32 *FolderStartFileIndex; + UInt32 *FileIndexToFolderIndexMap; +} CSzArEx; + +void SzArEx_Init(CSzArEx *p); +void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); +UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); +int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); + +/* +Errors: +SZ_ERROR_NO_ARCHIVE +SZ_ERROR_ARCHIVE +SZ_ERROR_UNSUPPORTED +SZ_ERROR_MEM +SZ_ERROR_CRC +SZ_ERROR_INPUT_EOF +SZ_ERROR_FAIL +*/ + +SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/sevenzip/7zItem.h b/plugins/snes9x_gx/portlibs/include/sevenzip/7zItem.h new file mode 100644 index 00000000..c7eb8f5f --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/sevenzip/7zItem.h @@ -0,0 +1,84 @@ +/* 7zItem.h -- 7z Items +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __7Z_ITEM_H +#define __7Z_ITEM_H + +#include "7zBuf.h" + +typedef struct +{ + UInt32 NumInStreams; + UInt32 NumOutStreams; + UInt64 MethodID; + CBuf Props; +} CSzCoderInfo; + +void SzCoderInfo_Init(CSzCoderInfo *p); +void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); + +typedef struct +{ + UInt32 InIndex; + UInt32 OutIndex; +} CBindPair; + +typedef struct +{ + CSzCoderInfo *Coders; + CBindPair *BindPairs; + UInt32 *PackStreams; + UInt64 *UnpackSizes; + UInt32 NumCoders; + UInt32 NumBindPairs; + UInt32 NumPackStreams; + int UnpackCRCDefined; + UInt32 UnpackCRC; + + UInt32 NumUnpackStreams; +} CSzFolder; + +void SzFolder_Init(CSzFolder *p); +UInt64 SzFolder_GetUnpackSize(CSzFolder *p); +int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); +UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); +UInt64 SzFolder_GetUnpackSize(CSzFolder *p); + +typedef struct +{ + UInt32 Low; + UInt32 High; +} CNtfsFileTime; + +typedef struct +{ + CNtfsFileTime MTime; + UInt64 Size; + char *Name; + UInt32 FileCRC; + + Byte HasStream; + Byte IsDir; + Byte IsAnti; + Byte FileCRCDefined; + Byte MTimeDefined; +} CSzFileItem; + +void SzFile_Init(CSzFileItem *p); + +typedef struct +{ + UInt64 *PackSizes; + Byte *PackCRCsDefined; + UInt32 *PackCRCs; + CSzFolder *Folders; + CSzFileItem *Files; + UInt32 NumPackStreams; + UInt32 NumFolders; + UInt32 NumFiles; +} CSzAr; + +void SzAr_Init(CSzAr *p); +void SzAr_Free(CSzAr *p, ISzAlloc *alloc); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/sevenzip/7zVersion.h b/plugins/snes9x_gx/portlibs/include/sevenzip/7zVersion.h new file mode 100644 index 00000000..5a6bcada --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/sevenzip/7zVersion.h @@ -0,0 +1,7 @@ +#define MY_VER_MAJOR 4 +#define MY_VER_MINOR 65 +#define MY_VER_BUILD 0 +#define MY_VERSION "4.65" +#define MY_DATE "2009-02-03" +#define MY_COPYRIGHT ": Igor Pavlov : Public domain" +#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE diff --git a/plugins/snes9x_gx/portlibs/include/sevenzip/Bcj2.h b/plugins/snes9x_gx/portlibs/include/sevenzip/Bcj2.h new file mode 100644 index 00000000..f58e3bcb --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/sevenzip/Bcj2.h @@ -0,0 +1,30 @@ +/* Bcj2.h -- Converter for x86 code (BCJ2) +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __BCJ2_H +#define __BCJ2_H + +#include "Types.h" + +/* +Conditions: + outSize <= FullOutputSize, + where FullOutputSize is full size of output stream of x86_2 filter. + +If buf0 overlaps outBuf, there are two required conditions: + 1) (buf0 >= outBuf) + 2) (buf0 + size0 >= outBuf + FullOutputSize). + +Returns: + SZ_OK + SZ_ERROR_DATA - Data error +*/ + +int Bcj2_Decode( + const Byte *buf0, SizeT size0, + const Byte *buf1, SizeT size1, + const Byte *buf2, SizeT size2, + const Byte *buf3, SizeT size3, + Byte *outBuf, SizeT outSize); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/sevenzip/Bra.h b/plugins/snes9x_gx/portlibs/include/sevenzip/Bra.h new file mode 100644 index 00000000..b9018eb9 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/sevenzip/Bra.h @@ -0,0 +1,60 @@ +/* Bra.h -- Branch converters for executables +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __BRA_H +#define __BRA_H + +#include "Types.h" + +/* +These functions convert relative addresses to absolute addresses +in CALL instructions to increase the compression ratio. + + In: + data - data buffer + size - size of data + ip - current virtual Instruction Pinter (IP) value + state - state variable for x86 converter + encoding - 0 (for decoding), 1 (for encoding) + + Out: + state - state variable for x86 converter + + Returns: + The number of processed bytes. If you call these functions with multiple calls, + you must start next call with first byte after block of processed bytes. + + Type Endian Alignment LookAhead + + x86 little 1 4 + ARMT little 2 2 + ARM little 4 0 + PPC big 4 0 + SPARC big 4 0 + IA64 little 16 0 + + size must be >= Alignment + LookAhead, if it's not last block. + If (size < Alignment + LookAhead), converter returns 0. + + Example: + + UInt32 ip = 0; + for () + { + ; size must be >= Alignment + LookAhead, if it's not last block + SizeT processed = Convert(data, size, ip, 1); + data += processed; + size -= processed; + ip += processed; + } +*/ + +#define x86_Convert_Init(state) { state = 0; } +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); +SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/sevenzip/CpuArch.h b/plugins/snes9x_gx/portlibs/include/sevenzip/CpuArch.h new file mode 100644 index 00000000..006361f2 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/sevenzip/CpuArch.h @@ -0,0 +1,69 @@ +/* CpuArch.h +2008-08-05 +Igor Pavlov +Public domain */ + +#ifndef __CPUARCH_H +#define __CPUARCH_H + +/* +LITTLE_ENDIAN_UNALIGN means: + 1) CPU is LITTLE_ENDIAN + 2) it's allowed to make unaligned memory accesses +if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know +about these properties of platform. +*/ + +#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) +#define LITTLE_ENDIAN_UNALIGN +#endif + +#ifdef LITTLE_ENDIAN_UNALIGN + +#define GetUi16(p) (*(const UInt16 *)(p)) +#define GetUi32(p) (*(const UInt32 *)(p)) +#define GetUi64(p) (*(const UInt64 *)(p)) +#define SetUi32(p, d) *(UInt32 *)(p) = (d); + +#else + +#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) + +#define GetUi32(p) ( \ + ((const Byte *)(p))[0] | \ + ((UInt32)((const Byte *)(p))[1] << 8) | \ + ((UInt32)((const Byte *)(p))[2] << 16) | \ + ((UInt32)((const Byte *)(p))[3] << 24)) + +#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) + +#define SetUi32(p, d) { UInt32 _x_ = (d); \ + ((Byte *)(p))[0] = (Byte)_x_; \ + ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ + ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ + ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } + +#endif + +#if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) + +#pragma intrinsic(_byteswap_ulong) +#pragma intrinsic(_byteswap_uint64) +#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) +#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) + +#else + +#define GetBe32(p) ( \ + ((UInt32)((const Byte *)(p))[0] << 24) | \ + ((UInt32)((const Byte *)(p))[1] << 16) | \ + ((UInt32)((const Byte *)(p))[2] << 8) | \ + ((const Byte *)(p))[3] ) + +#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) + +#endif + +#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/sevenzip/LzmaDec.h b/plugins/snes9x_gx/portlibs/include/sevenzip/LzmaDec.h new file mode 100644 index 00000000..ad7d7057 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/sevenzip/LzmaDec.h @@ -0,0 +1,223 @@ +/* LzmaDec.h -- LZMA Decoder +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZMADEC_H +#define __LZMADEC_H + +#include "Types.h" + +/* #define _LZMA_PROB32 */ +/* _LZMA_PROB32 can increase the speed on some CPUs, + but memory usage for CLzmaDec::probs will be doubled in that case */ + +#ifdef _LZMA_PROB32 +#define CLzmaProb UInt32 +#else +#define CLzmaProb UInt16 +#endif + + +/* ---------- LZMA Properties ---------- */ + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaProps +{ + unsigned lc, lp, pb; + UInt32 dicSize; +} CLzmaProps; + +/* LzmaProps_Decode - decodes properties +Returns: + SZ_OK + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); + + +/* ---------- LZMA Decoder state ---------- */ + +/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. + Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ + +#define LZMA_REQUIRED_INPUT_MAX 20 + +typedef struct +{ + CLzmaProps prop; + CLzmaProb *probs; + Byte *dic; + const Byte *buf; + UInt32 range, code; + SizeT dicPos; + SizeT dicBufSize; + UInt32 processedPos; + UInt32 checkDicSize; + unsigned state; + UInt32 reps[4]; + unsigned remainLen; + int needFlush; + int needInitState; + UInt32 numProbs; + unsigned tempBufSize; + Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; +} CLzmaDec; + +#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } + +void LzmaDec_Init(CLzmaDec *p); + +/* There are two types of LZMA streams: + 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. + 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ + +typedef enum +{ + LZMA_FINISH_ANY, /* finish at any point */ + LZMA_FINISH_END /* block must be finished at the end */ +} ELzmaFinishMode; + +/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! + + You must use LZMA_FINISH_END, when you know that current output buffer + covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. + + If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, + and output value of destLen will be less than output buffer size limit. + You can check status result also. + + You can use multiple checks to test data integrity after full decompression: + 1) Check Result and "status" variable. + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. + You must use correct finish mode in that case. */ + +typedef enum +{ + LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ + LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ + LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ + LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ +} ELzmaStatus; + +/* ELzmaStatus is used only as output value for function call */ + + +/* ---------- Interfaces ---------- */ + +/* There are 3 levels of interfaces: + 1) Dictionary Interface + 2) Buffer Interface + 3) One Call Interface + You can select any of these interfaces, but don't mix functions from different + groups for same object. */ + + +/* There are two variants to allocate state for Dictionary Interface: + 1) LzmaDec_Allocate / LzmaDec_Free + 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs + You can use variant 2, if you set dictionary buffer manually. + For Buffer Interface you must always use variant 1. + +LzmaDec_Allocate* can return: + SZ_OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); + +SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); +void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); + +/* ---------- Dictionary Interface ---------- */ + +/* You can use it, if you want to eliminate the overhead for data copying from + dictionary to some other external buffer. + You must work with CLzmaDec variables directly in this interface. + + STEPS: + LzmaDec_Constr() + LzmaDec_Allocate() + for (each new stream) + { + LzmaDec_Init() + while (it needs more decompression) + { + LzmaDec_DecodeToDic() + use data from CLzmaDec::dic and update CLzmaDec::dicPos + } + } + LzmaDec_Free() +*/ + +/* LzmaDec_DecodeToDic + + The decoding to internal dictionary buffer (CLzmaDec::dic). + You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! + +finishMode: + It has meaning only if the decoding reaches output limit (dicLimit). + LZMA_FINISH_ANY - Decode just dicLimit bytes. + LZMA_FINISH_END - Stream must be finished after dicLimit. + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error +*/ + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- Buffer Interface ---------- */ + +/* It's zlib-like interface. + See LzmaDec_DecodeToDic description for information about STEPS and return results, + but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need + to work with CLzmaDec variables manually. + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). +*/ + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- One Call Interface ---------- */ + +/* LzmaDecode + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +*/ + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc); + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/sevenzip/Types.h b/plugins/snes9x_gx/portlibs/include/sevenzip/Types.h new file mode 100644 index 00000000..2638196a --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/sevenzip/Types.h @@ -0,0 +1,208 @@ +/* Types.h -- Basic types +2008-11-23 : Igor Pavlov : Public domain */ + +#ifndef __7Z_TYPES_H +#define __7Z_TYPES_H + +#include <stddef.h> + +#ifdef _WIN32 +#include <windows.h> +#endif + +#define SZ_OK 0 + +#define SZ_ERROR_DATA 1 +#define SZ_ERROR_MEM 2 +#define SZ_ERROR_CRC 3 +#define SZ_ERROR_UNSUPPORTED 4 +#define SZ_ERROR_PARAM 5 +#define SZ_ERROR_INPUT_EOF 6 +#define SZ_ERROR_OUTPUT_EOF 7 +#define SZ_ERROR_READ 8 +#define SZ_ERROR_WRITE 9 +#define SZ_ERROR_PROGRESS 10 +#define SZ_ERROR_FAIL 11 +#define SZ_ERROR_THREAD 12 + +#define SZ_ERROR_ARCHIVE 16 +#define SZ_ERROR_NO_ARCHIVE 17 + +typedef int SRes; + +#ifdef _WIN32 +typedef DWORD WRes; +#else +typedef int WRes; +#endif + +#ifndef RINOK +#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +#endif + +typedef unsigned char Byte; +typedef short Int16; +typedef unsigned short UInt16; + +#ifdef _LZMA_UINT32_IS_ULONG +typedef long Int32; +typedef unsigned long UInt32; +#else +typedef int Int32; +typedef unsigned int UInt32; +#endif + +#ifdef _SZ_NO_INT_64 + +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. + NOTES: Some code will work incorrectly in that case! */ + +typedef long Int64; +typedef unsigned long UInt64; + +#else + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else +typedef long long int Int64; +typedef unsigned long long int UInt64; +#endif + +#endif + +#ifdef _LZMA_NO_SYSTEM_SIZE_T +typedef UInt32 SizeT; +#else +typedef size_t SizeT; +#endif + +typedef int Bool; +#define True 1 +#define False 0 + + +#ifdef _MSC_VER + +#if _MSC_VER >= 1300 +#define MY_NO_INLINE __declspec(noinline) +#else +#define MY_NO_INLINE +#endif + +#define MY_CDECL __cdecl +#define MY_STD_CALL __stdcall +#define MY_FAST_CALL MY_NO_INLINE __fastcall + +#else + +#define MY_CDECL +#define MY_STD_CALL +#define MY_FAST_CALL + +#endif + + +/* The following interfaces use first parameter as pointer to structure */ + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) < input(*size)) is allowed */ +} ISeqInStream; + +/* it can return SZ_ERROR_INPUT_EOF */ +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); + +typedef struct +{ + size_t (*Write)(void *p, const void *buf, size_t size); + /* Returns: result - the number of actually written bytes. + (result < size) means error */ +} ISeqOutStream; + +typedef enum +{ + SZ_SEEK_SET = 0, + SZ_SEEK_CUR = 1, + SZ_SEEK_END = 2 +} ESzSeek; + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ISeekInStream; + +typedef struct +{ + SRes (*Look)(void *p, void **buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) > input(*size)) is not allowed + (output(*size) < input(*size)) is allowed */ + SRes (*Skip)(void *p, size_t offset); + /* offset must be <= output(*size) of Look */ + + SRes (*Read)(void *p, void *buf, size_t *size); + /* reads directly (without buffer). It's same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ILookInStream; + +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); + +/* reads via ILookInStream::Read */ +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); + +#define LookToRead_BUF_SIZE (1 << 14) + +typedef struct +{ + ILookInStream s; + ISeekInStream *realStream; + size_t pos; + size_t size; + Byte buf[LookToRead_BUF_SIZE]; +} CLookToRead; + +void LookToRead_CreateVTable(CLookToRead *p, int lookahead); +void LookToRead_Init(CLookToRead *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToLook; + +void SecToLook_CreateVTable(CSecToLook *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToRead; + +void SecToRead_CreateVTable(CSecToRead *p); + +typedef struct +{ + SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); + /* Returns: result. (result != SZ_OK) means break. + Value (UInt64)(Int64)-1 for size means unknown value. */ +} ICompressProgress; + +typedef struct +{ + void *(*Alloc)(void *p, size_t size); + void (*Free)(void *p, void *address); /* address can be 0 */ +} ISzAlloc; + +#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) +#define IAlloc_Free(p, a) (p)->Free((p), a) + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/tif_config.h b/plugins/snes9x_gx/portlibs/include/tif_config.h new file mode 100644 index 00000000..2e208913 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/tif_config.h @@ -0,0 +1,260 @@ +/* libtiff/tif_config.h.in. Generated from configure.ac by autoheader. */ + +/* Use the Apple OpenGL framework. */ +///#define HAVE_APPLE_OPENGL_FRAMEWORK 1 + +/* Define to 1 if you have the <assert.h> header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the <dlfcn.h> header file. */ +///#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `floor' function. */ +#define HAVE_FLOOR 1 + +/* Define to 1 if you have the `getopt' function. */ +#define HAVE_GETOPT 1 + +/* Define as 0 or 1 according to the floating point format suported by the + machine */ +#define HAVE_IEEEFP 1 + +/* Define to 1 if the system has the type `int16'. */ +///#define HAVE_INT16 1 + +/* Define to 1 if the system has the type `int32'. */ +///#define HAVE_INT32 1 + +/* Define to 1 if the system has the type `int8'. */ +///#define HAVE_INT8 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `isascii' function. */ +#define HAVE_ISASCII 1 + +/* Define to 1 if you have the `lfind' function. */ +#define HAVE_LFIND 1 + +/* Define to 1 if you have the `c' library (-lc). */ +///#define HAVE_LIBC 1 + +/* Define to 1 if you have the `m' library (-lm). */ +///#define HAVE_LIBM 1 + +/* Define to 1 if you have the <limits.h> header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the <malloc.h> header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the <memory.h> header file. */ +///#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the `mmap' function. */ +///#define HAVE_MMAP 1 + +/* Define to 1 if you have the `pow' function. */ +///#define HAVE_POW 1 + +/* Define if you have POSIX threads libraries and header files. */ +#define HAVE_PTHREAD 1 + +/* Define to 1 if you have the <search.h> header file. */ +#define HAVE_SEARCH_H 1 + +/* Define to 1 if you have the `sqrt' function. */ +///#define HAVE_SQRT 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the <strings.h> header file. */ +///#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the `strtol' function. */ +#define HAVE_STRTOL 1 + +/* Define to 1 if you have the `strtoul' function. */ +#define HAVE_STRTOUL 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the <windows.h> header file. */ +///#define HAVE_WINDOWS_H 1 + +/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian + (Intel) */ +#define HOST_BIGENDIAN 1 + +/* Support JPEG compression (requires IJG JPEG library) */ +#define JPEG_SUPPORT 1 + +/* Support LogLuv high dynamic range encoding */ +#define LOGLUV_SUPPORT 1 + +/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */ +#define HOST_FILLORDER FILLORDER_MSB2LSB + +/* Support LZW algorithm */ +#define LZW_SUPPORT 1 + +/* Support Microsoft Document Imaging format */ +#define MDI_SUPPORT 1 + +/* Support NeXT 2-bit RLE algorithm */ +#define NEXT_SUPPORT 1 + +/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation + fails with unpatched IJG JPEG library) */ +///#define OJPEG_SUPPORT 1 + +/* Name of package */ +#define PACKAGE "libtiff" + +/* Define to the address where bug reports for this package should be sent. */ +///#define PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libtiff 3.8.2, compiled for Wii" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libtiff 3.8.2" + +/* Define to the one symbol short name of this package. */ +///#define PACKAGE_TARNAME + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "3.8.2" + +/* Support Macintosh PackBits algorithm */ +#define PACKBITS_SUPPORT 1 + +/* Support Pixar log-format algorithm (requires Zlib) */ +#define PIXARLOG_SUPPORT 1 + +/* Support CCITT Group 3 & 4 algorithms */ +//#define CCITT_SUPPORT 1 takes up to 200kb in the DOL + +/* Pick up YCbCr subsampling info from the JPEG data stream to support files + lacking the tag (default enabled). */ +#define CHECK_JPEG_YCBCR_SUBSAMPLING 1 + +/* Support C++ stream API (requires C++ compiler) */ +#define CXX_SUPPORT 1 + +/* Treat extra sample as alpha (default enabled). The RGBA interface will + treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many + packages produce RGBA files but don't mark the alpha properly. */ +#define DEFAULT_EXTRASAMPLE_AS_ALPHA 1 + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#define PTHREAD_CREATE_JOINABLE 1 + +/* The size of a `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of a `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Support strip chopping (whether or not to convert single-strip uncompressed + images to mutiple strips of specified size to reduce memory usage) */ +#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP + +/* Default size of the strip in bytes (when strip chopping enabled) */ +#define STRIP_SIZE_DEFAULT 1024*50 + +/* Enable SubIFD tag (330) support */ +#define SUBIFD_SUPPORT 1 + +/* Support ThunderScan 4-bit RLE algorithm */ +#define THUNDER_SUPPORT 1 + +/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to 1 if your <sys/time.h> declares `struct tm'. */ +#define TM_IN_SYS_TIME 1 + +/* Version number of package */ +#define VERSION "3.8.2" + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#define WORDS_BIGENDIAN 1 + +/* Define to 1 if the X Window System is missing or not being used. */ +///#define X_DISPLAY_MISSING 1 + +/* Support Deflate compression */ +#define ZIP_SUPPORT 1 + +/* Number of bits in a file offset, on hosts where this is settable. */ +#define _FILE_OFFSET_BITS 64 + +/* Define for large files, on AIX-style hosts. */ +#define _LARGE_FILES 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +///#define LT_OBJDIR 1 + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +///#define NO_MINUS_C_MINUS_O 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +///#undef const + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +//#ifndef __cplusplus +///#define __inline__ +//#endif + +/* Define to `long' if <sys/types.h> does not define. */ +///#undef off_t + +/* Define to `unsigned' if <sys/types.h> does not define. */ +///#undef size_t diff --git a/plugins/snes9x_gx/portlibs/include/tiff.h b/plugins/snes9x_gx/portlibs/include/tiff.h new file mode 100644 index 00000000..6330795b --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/tiff.h @@ -0,0 +1,647 @@ +/* $Id: tiff.h,v 1.42 2005/12/23 15:10:45 dron Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFF_ +#define _TIFF_ + +#include "tiffconf.h" + +/* + * Tag Image File Format (TIFF) + * + * Based on Rev 6.0 from: + * Developer's Desk + * Aldus Corporation + * 411 First Ave. South + * Suite 200 + * Seattle, WA 98104 + * 206-622-5500 + * + * (http://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf) + * + * For Big TIFF design notes see the following link + * http://gdal.maptools.org/twiki/bin/view/libtiff/BigTIFFDesign + */ +#define TIFF_VERSION 42 +#define TIFF_BIGTIFF_VERSION 43 + +#define TIFF_BIGENDIAN 0x4d4d +#define TIFF_LITTLEENDIAN 0x4949 +#define MDI_LITTLEENDIAN 0x5045 +#define MDI_BIGENDIAN 0x4550 +/* + * Intrinsic data types required by the file format: + * + * 8-bit quantities int8/uint8 + * 16-bit quantities int16/uint16 + * 32-bit quantities int32/uint32 + * strings unsigned char* + */ + +#ifndef HAVE_INT8 +typedef signed char int8; /* NB: non-ANSI compilers may not grok */ +#endif +typedef unsigned char uint8; +#ifndef HAVE_INT16 +typedef short int16; +#endif +typedef unsigned short uint16; /* sizeof (uint16) must == 2 */ +#if SIZEOF_INT == 4 +#ifndef HAVE_INT32 +typedef int int32; +#endif +typedef unsigned int uint32; /* sizeof (uint32) must == 4 */ +#elif SIZEOF_LONG == 4 +#ifndef HAVE_INT32 +typedef long int32; +#endif +typedef unsigned long uint32; /* sizeof (uint32) must == 4 */ +#endif + +/* For TIFFReassignTagToIgnore */ +enum TIFFIgnoreSense /* IGNORE tag table */ +{ + TIS_STORE, + TIS_EXTRACT, + TIS_EMPTY +}; + +/* + * TIFF header. + */ +typedef struct { + uint16 tiff_magic; /* magic number (defines byte order) */ +#define TIFF_MAGIC_SIZE 2 + uint16 tiff_version; /* TIFF version number */ +#define TIFF_VERSION_SIZE 2 + uint32 tiff_diroff; /* byte offset to first directory */ +#define TIFF_DIROFFSET_SIZE 4 +} TIFFHeader; + + +/* + * TIFF Image File Directories are comprised of a table of field + * descriptors of the form shown below. The table is sorted in + * ascending order by tag. The values associated with each entry are + * disjoint and may appear anywhere in the file (so long as they are + * placed on a word boundary). + * + * If the value is 4 bytes or less, then it is placed in the offset + * field to save space. If the value is less than 4 bytes, it is + * left-justified in the offset field. + */ +typedef struct { + uint16 tdir_tag; /* see below */ + uint16 tdir_type; /* data type; see below */ + uint32 tdir_count; /* number of items; length in spec */ + uint32 tdir_offset; /* byte offset to field data */ +} TIFFDirEntry; + +/* + * NB: In the comments below, + * - items marked with a + are obsoleted by revision 5.0, + * - items marked with a ! are introduced in revision 6.0. + * - items marked with a % are introduced post revision 6.0. + * - items marked with a $ are obsoleted by revision 6.0. + * - items marked with a & are introduced by Adobe DNG specification. + */ + +/* + * Tag data type information. + * + * Note: RATIONALs are the ratio of two 32-bit integer values. + */ +typedef enum { + TIFF_NOTYPE = 0, /* placeholder */ + TIFF_BYTE = 1, /* 8-bit unsigned integer */ + TIFF_ASCII = 2, /* 8-bit bytes w/ last byte null */ + TIFF_SHORT = 3, /* 16-bit unsigned integer */ + TIFF_LONG = 4, /* 32-bit unsigned integer */ + TIFF_RATIONAL = 5, /* 64-bit unsigned fraction */ + TIFF_SBYTE = 6, /* !8-bit signed integer */ + TIFF_UNDEFINED = 7, /* !8-bit untyped data */ + TIFF_SSHORT = 8, /* !16-bit signed integer */ + TIFF_SLONG = 9, /* !32-bit signed integer */ + TIFF_SRATIONAL = 10, /* !64-bit signed fraction */ + TIFF_FLOAT = 11, /* !32-bit IEEE floating point */ + TIFF_DOUBLE = 12, /* !64-bit IEEE floating point */ + TIFF_IFD = 13 /* %32-bit unsigned integer (offset) */ +} TIFFDataType; + +/* + * TIFF Tag Definitions. + */ +#define TIFFTAG_SUBFILETYPE 254 /* subfile data descriptor */ +#define FILETYPE_REDUCEDIMAGE 0x1 /* reduced resolution version */ +#define FILETYPE_PAGE 0x2 /* one page of many */ +#define FILETYPE_MASK 0x4 /* transparency mask */ +#define TIFFTAG_OSUBFILETYPE 255 /* +kind of data in subfile */ +#define OFILETYPE_IMAGE 1 /* full resolution image data */ +#define OFILETYPE_REDUCEDIMAGE 2 /* reduced size image data */ +#define OFILETYPE_PAGE 3 /* one page of many */ +#define TIFFTAG_IMAGEWIDTH 256 /* image width in pixels */ +#define TIFFTAG_IMAGELENGTH 257 /* image height in pixels */ +#define TIFFTAG_BITSPERSAMPLE 258 /* bits per channel (sample) */ +#define TIFFTAG_COMPRESSION 259 /* data compression technique */ +#define COMPRESSION_NONE 1 /* dump mode */ +#define COMPRESSION_CCITTRLE 2 /* CCITT modified Huffman RLE */ +#define COMPRESSION_CCITTFAX3 3 /* CCITT Group 3 fax encoding */ +#define COMPRESSION_CCITT_T4 3 /* CCITT T.4 (TIFF 6 name) */ +#define COMPRESSION_CCITTFAX4 4 /* CCITT Group 4 fax encoding */ +#define COMPRESSION_CCITT_T6 4 /* CCITT T.6 (TIFF 6 name) */ +#define COMPRESSION_LZW 5 /* Lempel-Ziv & Welch */ +#define COMPRESSION_OJPEG 6 /* !6.0 JPEG */ +#define COMPRESSION_JPEG 7 /* %JPEG DCT compression */ +#define COMPRESSION_NEXT 32766 /* NeXT 2-bit RLE */ +#define COMPRESSION_CCITTRLEW 32771 /* #1 w/ word alignment */ +#define COMPRESSION_PACKBITS 32773 /* Macintosh RLE */ +#define COMPRESSION_THUNDERSCAN 32809 /* ThunderScan RLE */ +/* codes 32895-32898 are reserved for ANSI IT8 TIFF/IT <dkelly@apago.com) */ +#define COMPRESSION_IT8CTPAD 32895 /* IT8 CT w/padding */ +#define COMPRESSION_IT8LW 32896 /* IT8 Linework RLE */ +#define COMPRESSION_IT8MP 32897 /* IT8 Monochrome picture */ +#define COMPRESSION_IT8BL 32898 /* IT8 Binary line art */ +/* compression codes 32908-32911 are reserved for Pixar */ +#define COMPRESSION_PIXARFILM 32908 /* Pixar companded 10bit LZW */ +#define COMPRESSION_PIXARLOG 32909 /* Pixar companded 11bit ZIP */ +#define COMPRESSION_DEFLATE 32946 /* Deflate compression */ +#define COMPRESSION_ADOBE_DEFLATE 8 /* Deflate compression, + as recognized by Adobe */ +/* compression code 32947 is reserved for Oceana Matrix <dev@oceana.com> */ +#define COMPRESSION_DCS 32947 /* Kodak DCS encoding */ +#define COMPRESSION_JBIG 34661 /* ISO JBIG */ +#define COMPRESSION_SGILOG 34676 /* SGI Log Luminance RLE */ +#define COMPRESSION_SGILOG24 34677 /* SGI Log 24-bit packed */ +#define COMPRESSION_JP2000 34712 /* Leadtools JPEG2000 */ +#define TIFFTAG_PHOTOMETRIC 262 /* photometric interpretation */ +#define PHOTOMETRIC_MINISWHITE 0 /* min value is white */ +#define PHOTOMETRIC_MINISBLACK 1 /* min value is black */ +#define PHOTOMETRIC_RGB 2 /* RGB color model */ +#define PHOTOMETRIC_PALETTE 3 /* color map indexed */ +#define PHOTOMETRIC_MASK 4 /* $holdout mask */ +#define PHOTOMETRIC_SEPARATED 5 /* !color separations */ +#define PHOTOMETRIC_YCBCR 6 /* !CCIR 601 */ +#define PHOTOMETRIC_CIELAB 8 /* !1976 CIE L*a*b* */ +#define PHOTOMETRIC_ICCLAB 9 /* ICC L*a*b* [Adobe TIFF Technote 4] */ +#define PHOTOMETRIC_ITULAB 10 /* ITU L*a*b* */ +#define PHOTOMETRIC_LOGL 32844 /* CIE Log2(L) */ +#define PHOTOMETRIC_LOGLUV 32845 /* CIE Log2(L) (u',v') */ +#define TIFFTAG_THRESHHOLDING 263 /* +thresholding used on data */ +#define THRESHHOLD_BILEVEL 1 /* b&w art scan */ +#define THRESHHOLD_HALFTONE 2 /* or dithered scan */ +#define THRESHHOLD_ERRORDIFFUSE 3 /* usually floyd-steinberg */ +#define TIFFTAG_CELLWIDTH 264 /* +dithering matrix width */ +#define TIFFTAG_CELLLENGTH 265 /* +dithering matrix height */ +#define TIFFTAG_FILLORDER 266 /* data order within a byte */ +#define FILLORDER_MSB2LSB 1 /* most significant -> least */ +#define FILLORDER_LSB2MSB 2 /* least significant -> most */ +#define TIFFTAG_DOCUMENTNAME 269 /* name of doc. image is from */ +#define TIFFTAG_IMAGEDESCRIPTION 270 /* info about image */ +#define TIFFTAG_MAKE 271 /* scanner manufacturer name */ +#define TIFFTAG_MODEL 272 /* scanner model name/number */ +#define TIFFTAG_STRIPOFFSETS 273 /* offsets to data strips */ +#define TIFFTAG_ORIENTATION 274 /* +image orientation */ +#define ORIENTATION_TOPLEFT 1 /* row 0 top, col 0 lhs */ +#define ORIENTATION_TOPRIGHT 2 /* row 0 top, col 0 rhs */ +#define ORIENTATION_BOTRIGHT 3 /* row 0 bottom, col 0 rhs */ +#define ORIENTATION_BOTLEFT 4 /* row 0 bottom, col 0 lhs */ +#define ORIENTATION_LEFTTOP 5 /* row 0 lhs, col 0 top */ +#define ORIENTATION_RIGHTTOP 6 /* row 0 rhs, col 0 top */ +#define ORIENTATION_RIGHTBOT 7 /* row 0 rhs, col 0 bottom */ +#define ORIENTATION_LEFTBOT 8 /* row 0 lhs, col 0 bottom */ +#define TIFFTAG_SAMPLESPERPIXEL 277 /* samples per pixel */ +#define TIFFTAG_ROWSPERSTRIP 278 /* rows per strip of data */ +#define TIFFTAG_STRIPBYTECOUNTS 279 /* bytes counts for strips */ +#define TIFFTAG_MINSAMPLEVALUE 280 /* +minimum sample value */ +#define TIFFTAG_MAXSAMPLEVALUE 281 /* +maximum sample value */ +#define TIFFTAG_XRESOLUTION 282 /* pixels/resolution in x */ +#define TIFFTAG_YRESOLUTION 283 /* pixels/resolution in y */ +#define TIFFTAG_PLANARCONFIG 284 /* storage organization */ +#define PLANARCONFIG_CONTIG 1 /* single image plane */ +#define PLANARCONFIG_SEPARATE 2 /* separate planes of data */ +#define TIFFTAG_PAGENAME 285 /* page name image is from */ +#define TIFFTAG_XPOSITION 286 /* x page offset of image lhs */ +#define TIFFTAG_YPOSITION 287 /* y page offset of image lhs */ +#define TIFFTAG_FREEOFFSETS 288 /* +byte offset to free block */ +#define TIFFTAG_FREEBYTECOUNTS 289 /* +sizes of free blocks */ +#define TIFFTAG_GRAYRESPONSEUNIT 290 /* $gray scale curve accuracy */ +#define GRAYRESPONSEUNIT_10S 1 /* tenths of a unit */ +#define GRAYRESPONSEUNIT_100S 2 /* hundredths of a unit */ +#define GRAYRESPONSEUNIT_1000S 3 /* thousandths of a unit */ +#define GRAYRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */ +#define GRAYRESPONSEUNIT_100000S 5 /* hundred-thousandths */ +#define TIFFTAG_GRAYRESPONSECURVE 291 /* $gray scale response curve */ +#define TIFFTAG_GROUP3OPTIONS 292 /* 32 flag bits */ +#define TIFFTAG_T4OPTIONS 292 /* TIFF 6.0 proper name alias */ +#define GROUP3OPT_2DENCODING 0x1 /* 2-dimensional coding */ +#define GROUP3OPT_UNCOMPRESSED 0x2 /* data not compressed */ +#define GROUP3OPT_FILLBITS 0x4 /* fill to byte boundary */ +#define TIFFTAG_GROUP4OPTIONS 293 /* 32 flag bits */ +#define TIFFTAG_T6OPTIONS 293 /* TIFF 6.0 proper name */ +#define GROUP4OPT_UNCOMPRESSED 0x2 /* data not compressed */ +#define TIFFTAG_RESOLUTIONUNIT 296 /* units of resolutions */ +#define RESUNIT_NONE 1 /* no meaningful units */ +#define RESUNIT_INCH 2 /* english */ +#define RESUNIT_CENTIMETER 3 /* metric */ +#define TIFFTAG_PAGENUMBER 297 /* page numbers of multi-page */ +#define TIFFTAG_COLORRESPONSEUNIT 300 /* $color curve accuracy */ +#define COLORRESPONSEUNIT_10S 1 /* tenths of a unit */ +#define COLORRESPONSEUNIT_100S 2 /* hundredths of a unit */ +#define COLORRESPONSEUNIT_1000S 3 /* thousandths of a unit */ +#define COLORRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */ +#define COLORRESPONSEUNIT_100000S 5 /* hundred-thousandths */ +#define TIFFTAG_TRANSFERFUNCTION 301 /* !colorimetry info */ +#define TIFFTAG_SOFTWARE 305 /* name & release */ +#define TIFFTAG_DATETIME 306 /* creation date and time */ +#define TIFFTAG_ARTIST 315 /* creator of image */ +#define TIFFTAG_HOSTCOMPUTER 316 /* machine where created */ +#define TIFFTAG_PREDICTOR 317 /* prediction scheme w/ LZW */ +#define PREDICTOR_NONE 1 /* no prediction scheme used */ +#define PREDICTOR_HORIZONTAL 2 /* horizontal differencing */ +#define PREDICTOR_FLOATINGPOINT 3 /* floating point predictor */ +#define TIFFTAG_WHITEPOINT 318 /* image white point */ +#define TIFFTAG_PRIMARYCHROMATICITIES 319 /* !primary chromaticities */ +#define TIFFTAG_COLORMAP 320 /* RGB map for pallette image */ +#define TIFFTAG_HALFTONEHINTS 321 /* !highlight+shadow info */ +#define TIFFTAG_TILEWIDTH 322 /* !tile width in pixels */ +#define TIFFTAG_TILELENGTH 323 /* !tile height in pixels */ +#define TIFFTAG_TILEOFFSETS 324 /* !offsets to data tiles */ +#define TIFFTAG_TILEBYTECOUNTS 325 /* !byte counts for tiles */ +#define TIFFTAG_BADFAXLINES 326 /* lines w/ wrong pixel count */ +#define TIFFTAG_CLEANFAXDATA 327 /* regenerated line info */ +#define CLEANFAXDATA_CLEAN 0 /* no errors detected */ +#define CLEANFAXDATA_REGENERATED 1 /* receiver regenerated lines */ +#define CLEANFAXDATA_UNCLEAN 2 /* uncorrected errors exist */ +#define TIFFTAG_CONSECUTIVEBADFAXLINES 328 /* max consecutive bad lines */ +#define TIFFTAG_SUBIFD 330 /* subimage descriptors */ +#define TIFFTAG_INKSET 332 /* !inks in separated image */ +#define INKSET_CMYK 1 /* !cyan-magenta-yellow-black color */ +#define INKSET_MULTIINK 2 /* !multi-ink or hi-fi color */ +#define TIFFTAG_INKNAMES 333 /* !ascii names of inks */ +#define TIFFTAG_NUMBEROFINKS 334 /* !number of inks */ +#define TIFFTAG_DOTRANGE 336 /* !0% and 100% dot codes */ +#define TIFFTAG_TARGETPRINTER 337 /* !separation target */ +#define TIFFTAG_EXTRASAMPLES 338 /* !info about extra samples */ +#define EXTRASAMPLE_UNSPECIFIED 0 /* !unspecified data */ +#define EXTRASAMPLE_ASSOCALPHA 1 /* !associated alpha data */ +#define EXTRASAMPLE_UNASSALPHA 2 /* !unassociated alpha data */ +#define TIFFTAG_SAMPLEFORMAT 339 /* !data sample format */ +#define SAMPLEFORMAT_UINT 1 /* !unsigned integer data */ +#define SAMPLEFORMAT_INT 2 /* !signed integer data */ +#define SAMPLEFORMAT_IEEEFP 3 /* !IEEE floating point data */ +#define SAMPLEFORMAT_VOID 4 /* !untyped data */ +#define SAMPLEFORMAT_COMPLEXINT 5 /* !complex signed int */ +#define SAMPLEFORMAT_COMPLEXIEEEFP 6 /* !complex ieee floating */ +#define TIFFTAG_SMINSAMPLEVALUE 340 /* !variable MinSampleValue */ +#define TIFFTAG_SMAXSAMPLEVALUE 341 /* !variable MaxSampleValue */ +#define TIFFTAG_CLIPPATH 343 /* %ClipPath + [Adobe TIFF technote 2] */ +#define TIFFTAG_XCLIPPATHUNITS 344 /* %XClipPathUnits + [Adobe TIFF technote 2] */ +#define TIFFTAG_YCLIPPATHUNITS 345 /* %YClipPathUnits + [Adobe TIFF technote 2] */ +#define TIFFTAG_INDEXED 346 /* %Indexed + [Adobe TIFF Technote 3] */ +#define TIFFTAG_JPEGTABLES 347 /* %JPEG table stream */ +#define TIFFTAG_OPIPROXY 351 /* %OPI Proxy [Adobe TIFF technote] */ +/* + * Tags 512-521 are obsoleted by Technical Note #2 which specifies a + * revised JPEG-in-TIFF scheme. + */ +#define TIFFTAG_JPEGPROC 512 /* !JPEG processing algorithm */ +#define JPEGPROC_BASELINE 1 /* !baseline sequential */ +#define JPEGPROC_LOSSLESS 14 /* !Huffman coded lossless */ +#define TIFFTAG_JPEGIFOFFSET 513 /* !pointer to SOI marker */ +#define TIFFTAG_JPEGIFBYTECOUNT 514 /* !JFIF stream length */ +#define TIFFTAG_JPEGRESTARTINTERVAL 515 /* !restart interval length */ +#define TIFFTAG_JPEGLOSSLESSPREDICTORS 517 /* !lossless proc predictor */ +#define TIFFTAG_JPEGPOINTTRANSFORM 518 /* !lossless point transform */ +#define TIFFTAG_JPEGQTABLES 519 /* !Q matrice offsets */ +#define TIFFTAG_JPEGDCTABLES 520 /* !DCT table offsets */ +#define TIFFTAG_JPEGACTABLES 521 /* !AC coefficient offsets */ +#define TIFFTAG_YCBCRCOEFFICIENTS 529 /* !RGB -> YCbCr transform */ +#define TIFFTAG_YCBCRSUBSAMPLING 530 /* !YCbCr subsampling factors */ +#define TIFFTAG_YCBCRPOSITIONING 531 /* !subsample positioning */ +#define YCBCRPOSITION_CENTERED 1 /* !as in PostScript Level 2 */ +#define YCBCRPOSITION_COSITED 2 /* !as in CCIR 601-1 */ +#define TIFFTAG_REFERENCEBLACKWHITE 532 /* !colorimetry info */ +#define TIFFTAG_XMLPACKET 700 /* %XML packet + [Adobe XMP Specification, + January 2004 */ +#define TIFFTAG_OPIIMAGEID 32781 /* %OPI ImageID + [Adobe TIFF technote] */ +/* tags 32952-32956 are private tags registered to Island Graphics */ +#define TIFFTAG_REFPTS 32953 /* image reference points */ +#define TIFFTAG_REGIONTACKPOINT 32954 /* region-xform tack point */ +#define TIFFTAG_REGIONWARPCORNERS 32955 /* warp quadrilateral */ +#define TIFFTAG_REGIONAFFINE 32956 /* affine transformation mat */ +/* tags 32995-32999 are private tags registered to SGI */ +#define TIFFTAG_MATTEING 32995 /* $use ExtraSamples */ +#define TIFFTAG_DATATYPE 32996 /* $use SampleFormat */ +#define TIFFTAG_IMAGEDEPTH 32997 /* z depth of image */ +#define TIFFTAG_TILEDEPTH 32998 /* z depth/data tile */ +/* tags 33300-33309 are private tags registered to Pixar */ +/* + * TIFFTAG_PIXAR_IMAGEFULLWIDTH and TIFFTAG_PIXAR_IMAGEFULLLENGTH + * are set when an image has been cropped out of a larger image. + * They reflect the size of the original uncropped image. + * The TIFFTAG_XPOSITION and TIFFTAG_YPOSITION can be used + * to determine the position of the smaller image in the larger one. + */ +#define TIFFTAG_PIXAR_IMAGEFULLWIDTH 33300 /* full image size in x */ +#define TIFFTAG_PIXAR_IMAGEFULLLENGTH 33301 /* full image size in y */ + /* Tags 33302-33306 are used to identify special image modes and data + * used by Pixar's texture formats. + */ +#define TIFFTAG_PIXAR_TEXTUREFORMAT 33302 /* texture map format */ +#define TIFFTAG_PIXAR_WRAPMODES 33303 /* s & t wrap modes */ +#define TIFFTAG_PIXAR_FOVCOT 33304 /* cotan(fov) for env. maps */ +#define TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN 33305 +#define TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA 33306 +/* tag 33405 is a private tag registered to Eastman Kodak */ +#define TIFFTAG_WRITERSERIALNUMBER 33405 /* device serial number */ +/* tag 33432 is listed in the 6.0 spec w/ unknown ownership */ +#define TIFFTAG_COPYRIGHT 33432 /* copyright string */ +/* IPTC TAG from RichTIFF specifications */ +#define TIFFTAG_RICHTIFFIPTC 33723 +/* 34016-34029 are reserved for ANSI IT8 TIFF/IT <dkelly@apago.com) */ +#define TIFFTAG_IT8SITE 34016 /* site name */ +#define TIFFTAG_IT8COLORSEQUENCE 34017 /* color seq. [RGB,CMYK,etc] */ +#define TIFFTAG_IT8HEADER 34018 /* DDES Header */ +#define TIFFTAG_IT8RASTERPADDING 34019 /* raster scanline padding */ +#define TIFFTAG_IT8BITSPERRUNLENGTH 34020 /* # of bits in short run */ +#define TIFFTAG_IT8BITSPEREXTENDEDRUNLENGTH 34021/* # of bits in long run */ +#define TIFFTAG_IT8COLORTABLE 34022 /* LW colortable */ +#define TIFFTAG_IT8IMAGECOLORINDICATOR 34023 /* BP/BL image color switch */ +#define TIFFTAG_IT8BKGCOLORINDICATOR 34024 /* BP/BL bg color switch */ +#define TIFFTAG_IT8IMAGECOLORVALUE 34025 /* BP/BL image color value */ +#define TIFFTAG_IT8BKGCOLORVALUE 34026 /* BP/BL bg color value */ +#define TIFFTAG_IT8PIXELINTENSITYRANGE 34027 /* MP pixel intensity value */ +#define TIFFTAG_IT8TRANSPARENCYINDICATOR 34028 /* HC transparency switch */ +#define TIFFTAG_IT8COLORCHARACTERIZATION 34029 /* color character. table */ +#define TIFFTAG_IT8HCUSAGE 34030 /* HC usage indicator */ +#define TIFFTAG_IT8TRAPINDICATOR 34031 /* Trapping indicator + (untrapped=0, trapped=1) */ +#define TIFFTAG_IT8CMYKEQUIVALENT 34032 /* CMYK color equivalents */ +/* tags 34232-34236 are private tags registered to Texas Instruments */ +#define TIFFTAG_FRAMECOUNT 34232 /* Sequence Frame Count */ +/* tag 34377 is private tag registered to Adobe for PhotoShop */ +#define TIFFTAG_PHOTOSHOP 34377 +/* tags 34665, 34853 and 40965 are documented in EXIF specification */ +#define TIFFTAG_EXIFIFD 34665 /* Pointer to EXIF private directory */ +/* tag 34750 is a private tag registered to Adobe? */ +#define TIFFTAG_ICCPROFILE 34675 /* ICC profile data */ +/* tag 34750 is a private tag registered to Pixel Magic */ +#define TIFFTAG_JBIGOPTIONS 34750 /* JBIG options */ +#define TIFFTAG_GPSIFD 34853 /* Pointer to GPS private directory */ +/* tags 34908-34914 are private tags registered to SGI */ +#define TIFFTAG_FAXRECVPARAMS 34908 /* encoded Class 2 ses. parms */ +#define TIFFTAG_FAXSUBADDRESS 34909 /* received SubAddr string */ +#define TIFFTAG_FAXRECVTIME 34910 /* receive time (secs) */ +#define TIFFTAG_FAXDCS 34911 /* encoded fax ses. params, Table 2/T.30 */ +/* tags 37439-37443 are registered to SGI <gregl@sgi.com> */ +#define TIFFTAG_STONITS 37439 /* Sample value to Nits */ +/* tag 34929 is a private tag registered to FedEx */ +#define TIFFTAG_FEDEX_EDR 34929 /* unknown use */ +#define TIFFTAG_INTEROPERABILITYIFD 40965 /* Pointer to Interoperability private directory */ +/* Adobe Digital Negative (DNG) format tags */ +#define TIFFTAG_DNGVERSION 50706 /* &DNG version number */ +#define TIFFTAG_DNGBACKWARDVERSION 50707 /* &DNG compatibility version */ +#define TIFFTAG_UNIQUECAMERAMODEL 50708 /* &name for the camera model */ +#define TIFFTAG_LOCALIZEDCAMERAMODEL 50709 /* &localized camera model + name */ +#define TIFFTAG_CFAPLANECOLOR 50710 /* &CFAPattern->LinearRaw space + mapping */ +#define TIFFTAG_CFALAYOUT 50711 /* &spatial layout of the CFA */ +#define TIFFTAG_LINEARIZATIONTABLE 50712 /* &lookup table description */ +#define TIFFTAG_BLACKLEVELREPEATDIM 50713 /* &repeat pattern size for + the BlackLevel tag */ +#define TIFFTAG_BLACKLEVEL 50714 /* &zero light encoding level */ +#define TIFFTAG_BLACKLEVELDELTAH 50715 /* &zero light encoding level + differences (columns) */ +#define TIFFTAG_BLACKLEVELDELTAV 50716 /* &zero light encoding level + differences (rows) */ +#define TIFFTAG_WHITELEVEL 50717 /* &fully saturated encoding + level */ +#define TIFFTAG_DEFAULTSCALE 50718 /* &default scale factors */ +#define TIFFTAG_DEFAULTCROPORIGIN 50719 /* &origin of the final image + area */ +#define TIFFTAG_DEFAULTCROPSIZE 50720 /* &size of the final image + area */ +#define TIFFTAG_COLORMATRIX1 50721 /* &XYZ->reference color space + transformation matrix 1 */ +#define TIFFTAG_COLORMATRIX2 50722 /* &XYZ->reference color space + transformation matrix 2 */ +#define TIFFTAG_CAMERACALIBRATION1 50723 /* &calibration matrix 1 */ +#define TIFFTAG_CAMERACALIBRATION2 50724 /* &calibration matrix 2 */ +#define TIFFTAG_REDUCTIONMATRIX1 50725 /* &dimensionality reduction + matrix 1 */ +#define TIFFTAG_REDUCTIONMATRIX2 50726 /* &dimensionality reduction + matrix 2 */ +#define TIFFTAG_ANALOGBALANCE 50727 /* &gain applied the stored raw + values*/ +#define TIFFTAG_ASSHOTNEUTRAL 50728 /* &selected white balance in + linear reference space */ +#define TIFFTAG_ASSHOTWHITEXY 50729 /* &selected white balance in + x-y chromaticity + coordinates */ +#define TIFFTAG_BASELINEEXPOSURE 50730 /* &how much to move the zero + point */ +#define TIFFTAG_BASELINENOISE 50731 /* &relative noise level */ +#define TIFFTAG_BASELINESHARPNESS 50732 /* &relative amount of + sharpening */ +#define TIFFTAG_BAYERGREENSPLIT 50733 /* &how closely the values of + the green pixels in the + blue/green rows track the + values of the green pixels + in the red/green rows */ +#define TIFFTAG_LINEARRESPONSELIMIT 50734 /* &non-linear encoding range */ +#define TIFFTAG_CAMERASERIALNUMBER 50735 /* &camera's serial number */ +#define TIFFTAG_LENSINFO 50736 /* info about the lens */ +#define TIFFTAG_CHROMABLURRADIUS 50737 /* &chroma blur radius */ +#define TIFFTAG_ANTIALIASSTRENGTH 50738 /* &relative strength of the + camera's anti-alias filter */ +#define TIFFTAG_SHADOWSCALE 50739 /* &used by Adobe Camera Raw */ +#define TIFFTAG_DNGPRIVATEDATA 50740 /* &manufacturer's private data */ +#define TIFFTAG_MAKERNOTESAFETY 50741 /* &whether the EXIF MakerNote + tag is safe to preserve + along with the rest of the + EXIF data */ +#define TIFFTAG_CALIBRATIONILLUMINANT1 50778 /* &illuminant 1 */ +#define TIFFTAG_CALIBRATIONILLUMINANT2 50779 /* &illuminant 2 */ +#define TIFFTAG_BESTQUALITYSCALE 50780 /* &best quality multiplier */ +#define TIFFTAG_RAWDATAUNIQUEID 50781 /* &unique identifier for + the raw image data */ +#define TIFFTAG_ORIGINALRAWFILENAME 50827 /* &file name of the original + raw file */ +#define TIFFTAG_ORIGINALRAWFILEDATA 50828 /* &contents of the original + raw file */ +#define TIFFTAG_ACTIVEAREA 50829 /* &active (non-masked) pixels + of the sensor */ +#define TIFFTAG_MASKEDAREAS 50830 /* &list of coordinates + of fully masked pixels */ +#define TIFFTAG_ASSHOTICCPROFILE 50831 /* &these two tags used to */ +#define TIFFTAG_ASSHOTPREPROFILEMATRIX 50832 /* map cameras's color space + into ICC profile space */ +#define TIFFTAG_CURRENTICCPROFILE 50833 /* & */ +#define TIFFTAG_CURRENTPREPROFILEMATRIX 50834 /* & */ +/* tag 65535 is an undefined tag used by Eastman Kodak */ +#define TIFFTAG_DCSHUESHIFTVALUES 65535 /* hue shift correction data */ + +/* + * The following are ``pseudo tags'' that can be used to control + * codec-specific functionality. These tags are not written to file. + * Note that these values start at 0xffff+1 so that they'll never + * collide with Aldus-assigned tags. + * + * If you want your private pseudo tags ``registered'' (i.e. added to + * this file), please post a bug report via the tracking system at + * http://www.remotesensing.org/libtiff/bugs.html with the appropriate + * C definitions to add. + */ +#define TIFFTAG_FAXMODE 65536 /* Group 3/4 format control */ +#define FAXMODE_CLASSIC 0x0000 /* default, include RTC */ +#define FAXMODE_NORTC 0x0001 /* no RTC at end of data */ +#define FAXMODE_NOEOL 0x0002 /* no EOL code at end of row */ +#define FAXMODE_BYTEALIGN 0x0004 /* byte align row */ +#define FAXMODE_WORDALIGN 0x0008 /* word align row */ +#define FAXMODE_CLASSF FAXMODE_NORTC /* TIFF Class F */ +#define TIFFTAG_JPEGQUALITY 65537 /* Compression quality level */ +/* Note: quality level is on the IJG 0-100 scale. Default value is 75 */ +#define TIFFTAG_JPEGCOLORMODE 65538 /* Auto RGB<=>YCbCr convert? */ +#define JPEGCOLORMODE_RAW 0x0000 /* no conversion (default) */ +#define JPEGCOLORMODE_RGB 0x0001 /* do auto conversion */ +#define TIFFTAG_JPEGTABLESMODE 65539 /* What to put in JPEGTables */ +#define JPEGTABLESMODE_QUANT 0x0001 /* include quantization tbls */ +#define JPEGTABLESMODE_HUFF 0x0002 /* include Huffman tbls */ +/* Note: default is JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF */ +#define TIFFTAG_FAXFILLFUNC 65540 /* G3/G4 fill function */ +#define TIFFTAG_PIXARLOGDATAFMT 65549 /* PixarLogCodec I/O data sz */ +#define PIXARLOGDATAFMT_8BIT 0 /* regular u_char samples */ +#define PIXARLOGDATAFMT_8BITABGR 1 /* ABGR-order u_chars */ +#define PIXARLOGDATAFMT_11BITLOG 2 /* 11-bit log-encoded (raw) */ +#define PIXARLOGDATAFMT_12BITPICIO 3 /* as per PICIO (1.0==2048) */ +#define PIXARLOGDATAFMT_16BIT 4 /* signed short samples */ +#define PIXARLOGDATAFMT_FLOAT 5 /* IEEE float samples */ +/* 65550-65556 are allocated to Oceana Matrix <dev@oceana.com> */ +#define TIFFTAG_DCSIMAGERTYPE 65550 /* imager model & filter */ +#define DCSIMAGERMODEL_M3 0 /* M3 chip (1280 x 1024) */ +#define DCSIMAGERMODEL_M5 1 /* M5 chip (1536 x 1024) */ +#define DCSIMAGERMODEL_M6 2 /* M6 chip (3072 x 2048) */ +#define DCSIMAGERFILTER_IR 0 /* infrared filter */ +#define DCSIMAGERFILTER_MONO 1 /* monochrome filter */ +#define DCSIMAGERFILTER_CFA 2 /* color filter array */ +#define DCSIMAGERFILTER_OTHER 3 /* other filter */ +#define TIFFTAG_DCSINTERPMODE 65551 /* interpolation mode */ +#define DCSINTERPMODE_NORMAL 0x0 /* whole image, default */ +#define DCSINTERPMODE_PREVIEW 0x1 /* preview of image (384x256) */ +#define TIFFTAG_DCSBALANCEARRAY 65552 /* color balance values */ +#define TIFFTAG_DCSCORRECTMATRIX 65553 /* color correction values */ +#define TIFFTAG_DCSGAMMA 65554 /* gamma value */ +#define TIFFTAG_DCSTOESHOULDERPTS 65555 /* toe & shoulder points */ +#define TIFFTAG_DCSCALIBRATIONFD 65556 /* calibration file desc */ +/* Note: quality level is on the ZLIB 1-9 scale. Default value is -1 */ +#define TIFFTAG_ZIPQUALITY 65557 /* compression quality level */ +#define TIFFTAG_PIXARLOGQUALITY 65558 /* PixarLog uses same scale */ +/* 65559 is allocated to Oceana Matrix <dev@oceana.com> */ +#define TIFFTAG_DCSCLIPRECTANGLE 65559 /* area of image to acquire */ +#define TIFFTAG_SGILOGDATAFMT 65560 /* SGILog user data format */ +#define SGILOGDATAFMT_FLOAT 0 /* IEEE float samples */ +#define SGILOGDATAFMT_16BIT 1 /* 16-bit samples */ +#define SGILOGDATAFMT_RAW 2 /* uninterpreted data */ +#define SGILOGDATAFMT_8BIT 3 /* 8-bit RGB monitor values */ +#define TIFFTAG_SGILOGENCODE 65561 /* SGILog data encoding control*/ +#define SGILOGENCODE_NODITHER 0 /* do not dither encoded values*/ +#define SGILOGENCODE_RANDITHER 1 /* randomly dither encd values */ + +/* + * EXIF tags + */ +#define EXIFTAG_EXPOSURETIME 33434 /* Exposure time */ +#define EXIFTAG_FNUMBER 33437 /* F number */ +#define EXIFTAG_EXPOSUREPROGRAM 34850 /* Exposure program */ +#define EXIFTAG_SPECTRALSENSITIVITY 34852 /* Spectral sensitivity */ +#define EXIFTAG_ISOSPEEDRATINGS 34855 /* ISO speed rating */ +#define EXIFTAG_OECF 34856 /* Optoelectric conversion + factor */ +#define EXIFTAG_EXIFVERSION 36864 /* Exif version */ +#define EXIFTAG_DATETIMEORIGINAL 36867 /* Date and time of original + data generation */ +#define EXIFTAG_DATETIMEDIGITIZED 36868 /* Date and time of digital + data generation */ +#define EXIFTAG_COMPONENTSCONFIGURATION 37121 /* Meaning of each component */ +#define EXIFTAG_COMPRESSEDBITSPERPIXEL 37122 /* Image compression mode */ +#define EXIFTAG_SHUTTERSPEEDVALUE 37377 /* Shutter speed */ +#define EXIFTAG_APERTUREVALUE 37378 /* Aperture */ +#define EXIFTAG_BRIGHTNESSVALUE 37379 /* Brightness */ +#define EXIFTAG_EXPOSUREBIASVALUE 37380 /* Exposure bias */ +#define EXIFTAG_MAXAPERTUREVALUE 37381 /* Maximum lens aperture */ +#define EXIFTAG_SUBJECTDISTANCE 37382 /* Subject distance */ +#define EXIFTAG_METERINGMODE 37383 /* Metering mode */ +#define EXIFTAG_LIGHTSOURCE 37384 /* Light source */ +#define EXIFTAG_FLASH 37385 /* Flash */ +#define EXIFTAG_FOCALLENGTH 37386 /* Lens focal length */ +#define EXIFTAG_SUBJECTAREA 37396 /* Subject area */ +#define EXIFTAG_MAKERNOTE 37500 /* Manufacturer notes */ +#define EXIFTAG_USERCOMMENT 37510 /* User comments */ +#define EXIFTAG_SUBSECTIME 37520 /* DateTime subseconds */ +#define EXIFTAG_SUBSECTIMEORIGINAL 37521 /* DateTimeOriginal subseconds */ +#define EXIFTAG_SUBSECTIMEDIGITIZED 37522 /* DateTimeDigitized subseconds */ +#define EXIFTAG_FLASHPIXVERSION 40960 /* Supported Flashpix version */ +#define EXIFTAG_COLORSPACE 40961 /* Color space information */ +#define EXIFTAG_PIXELXDIMENSION 40962 /* Valid image width */ +#define EXIFTAG_PIXELYDIMENSION 40963 /* Valid image height */ +#define EXIFTAG_RELATEDSOUNDFILE 40964 /* Related audio file */ +#define EXIFTAG_FLASHENERGY 41483 /* Flash energy */ +#define EXIFTAG_SPATIALFREQUENCYRESPONSE 41484 /* Spatial frequency response */ +#define EXIFTAG_FOCALPLANEXRESOLUTION 41486 /* Focal plane X resolution */ +#define EXIFTAG_FOCALPLANEYRESOLUTION 41487 /* Focal plane Y resolution */ +#define EXIFTAG_FOCALPLANERESOLUTIONUNIT 41488 /* Focal plane resolution unit */ +#define EXIFTAG_SUBJECTLOCATION 41492 /* Subject location */ +#define EXIFTAG_EXPOSUREINDEX 41493 /* Exposure index */ +#define EXIFTAG_SENSINGMETHOD 41495 /* Sensing method */ +#define EXIFTAG_FILESOURCE 41728 /* File source */ +#define EXIFTAG_SCENETYPE 41729 /* Scene type */ +#define EXIFTAG_CFAPATTERN 41730 /* CFA pattern */ +#define EXIFTAG_CUSTOMRENDERED 41985 /* Custom image processing */ +#define EXIFTAG_EXPOSUREMODE 41986 /* Exposure mode */ +#define EXIFTAG_WHITEBALANCE 41987 /* White balance */ +#define EXIFTAG_DIGITALZOOMRATIO 41988 /* Digital zoom ratio */ +#define EXIFTAG_FOCALLENGTHIN35MMFILM 41989 /* Focal length in 35 mm film */ +#define EXIFTAG_SCENECAPTURETYPE 41990 /* Scene capture type */ +#define EXIFTAG_GAINCONTROL 41991 /* Gain control */ +#define EXIFTAG_CONTRAST 41992 /* Contrast */ +#define EXIFTAG_SATURATION 41993 /* Saturation */ +#define EXIFTAG_SHARPNESS 41994 /* Sharpness */ +#define EXIFTAG_DEVICESETTINGDESCRIPTION 41995 /* Device settings description */ +#define EXIFTAG_SUBJECTDISTANCERANGE 41996 /* Subject distance range */ +#define EXIFTAG_GAINCONTROL 41991 /* Gain control */ +#define EXIFTAG_GAINCONTROL 41991 /* Gain control */ +#define EXIFTAG_IMAGEUNIQUEID 42016 /* Unique image ID */ + +#endif /* _TIFF_ */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/plugins/snes9x_gx/portlibs/include/tiffconf.h b/plugins/snes9x_gx/portlibs/include/tiffconf.h new file mode 100644 index 00000000..3912781d --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/tiffconf.h @@ -0,0 +1,104 @@ +/* libtiff/tiffconf.h. Generated by configure. */ +/* + Configuration defines for installed libtiff. + This file maintained for backward compatibility. Do not use definitions + from this file in your programs. +*/ + +#ifndef _TIFFCONF_ +#define _TIFFCONF_ + +#include "tif_config.h" +// +///* Define to 1 if the system has the type `int16'. */ +///* #undef HAVE_INT16 */ +// +///* Define to 1 if the system has the type `int32'. */ +///* #undef HAVE_INT32 */ +// +///* Define to 1 if the system has the type `int8'. */ +///* #undef HAVE_INT8 */ +// +///* The size of a `int', as computed by sizeof. */ +//#define SIZEOF_INT 4 +// +///* The size of a `long', as computed by sizeof. */ +//#define SIZEOF_LONG 4 +// +///* Compatibility stuff. */ +// +///* Define as 0 or 1 according to the floating point format suported by the +// machine */ +//#define HAVE_IEEEFP 1 +// +///* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */ +//#define HOST_FILLORDER FILLORDER_LSB2MSB +// +///* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian +// (Intel) */ +//#define HOST_BIGENDIAN 1 +// +///* Support CCITT Group 3 & 4 algorithms */ +//#undef CCITT_SUPPORT +// +///* Support JPEG compression (requires IJG JPEG library) */ +//#define JPEG_SUPPORT 1 +// +///* Support LogLuv high dynamic range encoding */ +//#undef LOGLUV_SUPPORT +// +///* Support LZW algorithm */ +//#undef LZW_SUPPORT +// +///* Support NeXT 2-bit RLE algorithm */ +//#undef NEXT_SUPPORT +// +///* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation +// fails with unpatched IJG JPEG library) */ +///* #undef OJPEG_SUPPORT */ +// +///* Support Macintosh PackBits algorithm */ +//#undef PACKBITS_SUPPORT +// +///* Support Pixar log-format algorithm (requires Zlib) */ +//#undef PIXARLOG_SUPPORT +// +///* Support ThunderScan 4-bit RLE algorithm */ +//#undef THUNDER_SUPPORT +// +///* Support Deflate compression */ +//#undef ZIP_SUPPORT +// +///* Support strip chopping (whether or not to convert single-strip uncompressed +// images to mutiple strips of ~8Kb to reduce memory usage) */ +//#undef STRIPCHOP_DEFAULT //TIFF_STRIPCHOP +// +///* Enable SubIFD tag (330) support */ +//#undef SUBIFD_SUPPORT +// +///* Treat extra sample as alpha (default enabled). The RGBA interface will +// treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many +// packages produce RGBA files but don't mark the alpha properly. */ +//#undef DEFAULT_EXTRASAMPLE_AS_ALPHA +// +///* Pick up YCbCr subsampling info from the JPEG data stream to support files +// lacking the tag (default enabled). */ +//#undef CHECK_JPEG_YCBCR_SUBSAMPLING +// +///* Support MS MDI magic number files as TIFF */ +//#undef MDI_SUPPORT + +/* + * Feature support definitions. + * XXX: These macros are obsoleted. Don't use them in your apps! + * Macros stays here for backward compatibility and should be always defined. + */ + /* +#define COLORIMETRY_SUPPORT +#define YCBCR_SUPPORT +#define CMYK_SUPPORT +#define ICC_SUPPORT +#define PHOTOSHOP_SUPPORT +#define IPTC_SUPPORT +*/ +#endif /* _TIFFCONF_ */ diff --git a/plugins/snes9x_gx/portlibs/include/tiffio.h b/plugins/snes9x_gx/portlibs/include/tiffio.h new file mode 100644 index 00000000..7aaf5613 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/tiffio.h @@ -0,0 +1,515 @@ +/* $Id: tiffio.h,v 1.50 2006/03/21 16:37:51 dron Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFIO_ +#define _TIFFIO_ + +/* + * TIFF I/O Library Definitions. + */ +#include "tiff.h" +#include "tiffvers.h" + +/* + * TIFF is defined as an incomplete type to hide the + * library's internal data structures from clients. + */ +typedef struct tiff TIFF; + +/* + * The following typedefs define the intrinsic size of + * data types used in the *exported* interfaces. These + * definitions depend on the proper definition of types + * in tiff.h. Note also that the varargs interface used + * to pass tag types and values uses the types defined in + * tiff.h directly. + * + * NB: ttag_t is unsigned int and not unsigned short because + * ANSI C requires that the type before the ellipsis be a + * promoted type (i.e. one of int, unsigned int, pointer, + * or double) and because we defined pseudo-tags that are + * outside the range of legal Aldus-assigned tags. + * NB: tsize_t is int32 and not uint32 because some functions + * return -1. + * NB: toff_t is not off_t for many reasons; TIFFs max out at + * 32-bit file offsets being the most important, and to ensure + * that it is unsigned, rather than signed. + */ +typedef uint32 ttag_t; /* directory tag */ +typedef uint16 tdir_t; /* directory index */ +typedef uint16 tsample_t; /* sample number */ +typedef uint32 tstrip_t; /* strip number */ +typedef uint32 ttile_t; /* tile number */ +typedef int32 tsize_t; /* i/o size in bytes */ +typedef void* tdata_t; /* image data ref */ +typedef uint32 toff_t; /* file offset */ + +#if !defined(__WIN32__) && (defined(_WIN32) || defined(WIN32)) +#define __WIN32__ +#endif + +/* + * On windows you should define USE_WIN32_FILEIO if you are using tif_win32.c + * or AVOID_WIN32_FILEIO if you are using something else (like tif_unix.c). + * + * By default tif_unix.c is assumed. + */ + +#if defined(_WINDOWS) || defined(__WIN32__) || defined(_Windows) +# if !defined(__CYGWIN) && !defined(AVOID_WIN32_FILEIO) && !defined(USE_WIN32_FILEIO) +# define AVOID_WIN32_FILEIO +# endif +#endif + +#if defined(USE_WIN32_FILEIO) +# define VC_EXTRALEAN +# include <windows.h> +# ifdef __WIN32__ +DECLARE_HANDLE(thandle_t); /* Win32 file handle */ +# else +typedef HFILE thandle_t; /* client data handle */ +# endif /* __WIN32__ */ +#else +typedef void* thandle_t; /* client data handle */ +#endif /* USE_WIN32_FILEIO */ + +#ifndef NULL +# define NULL (void *)0 +#endif + +/* + * Flags to pass to TIFFPrintDirectory to control + * printing of data structures that are potentially + * very large. Bit-or these flags to enable printing + * multiple items. + */ +#define TIFFPRINT_NONE 0x0 /* no extra info */ +#define TIFFPRINT_STRIPS 0x1 /* strips/tiles info */ +#define TIFFPRINT_CURVES 0x2 /* color/gray response curves */ +#define TIFFPRINT_COLORMAP 0x4 /* colormap */ +#define TIFFPRINT_JPEGQTABLES 0x100 /* JPEG Q matrices */ +#define TIFFPRINT_JPEGACTABLES 0x200 /* JPEG AC tables */ +#define TIFFPRINT_JPEGDCTABLES 0x200 /* JPEG DC tables */ + +/* + * Colour conversion stuff + */ + +/* reference white */ +#define D65_X0 (95.0470F) +#define D65_Y0 (100.0F) +#define D65_Z0 (108.8827F) + +#define D50_X0 (96.4250F) +#define D50_Y0 (100.0F) +#define D50_Z0 (82.4680F) + +/* Structure for holding information about a display device. */ + +typedef unsigned char TIFFRGBValue; /* 8-bit samples */ + +typedef struct { + float d_mat[3][3]; /* XYZ -> luminance matrix */ + float d_YCR; /* Light o/p for reference white */ + float d_YCG; + float d_YCB; + uint32 d_Vrwr; /* Pixel values for ref. white */ + uint32 d_Vrwg; + uint32 d_Vrwb; + float d_Y0R; /* Residual light for black pixel */ + float d_Y0G; + float d_Y0B; + float d_gammaR; /* Gamma values for the three guns */ + float d_gammaG; + float d_gammaB; +} TIFFDisplay; + +typedef struct { /* YCbCr->RGB support */ + TIFFRGBValue* clamptab; /* range clamping table */ + int* Cr_r_tab; + int* Cb_b_tab; + int32* Cr_g_tab; + int32* Cb_g_tab; + int32* Y_tab; +} TIFFYCbCrToRGB; + +typedef struct { /* CIE Lab 1976->RGB support */ + int range; /* Size of conversion table */ +#define CIELABTORGB_TABLE_RANGE 1500 + float rstep, gstep, bstep; + float X0, Y0, Z0; /* Reference white point */ + TIFFDisplay display; + float Yr2r[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yr to r */ + float Yg2g[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yg to g */ + float Yb2b[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yb to b */ +} TIFFCIELabToRGB; + +/* + * RGBA-style image support. + */ +typedef struct _TIFFRGBAImage TIFFRGBAImage; +/* + * The image reading and conversion routines invoke + * ``put routines'' to copy/image/whatever tiles of + * raw image data. A default set of routines are + * provided to convert/copy raw image data to 8-bit + * packed ABGR format rasters. Applications can supply + * alternate routines that unpack the data into a + * different format or, for example, unpack the data + * and draw the unpacked raster on the display. + */ +typedef void (*tileContigRoutine) + (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32, + unsigned char*); +typedef void (*tileSeparateRoutine) + (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32, + unsigned char*, unsigned char*, unsigned char*, unsigned char*); +/* + * RGBA-reader state. + */ +struct _TIFFRGBAImage { + TIFF* tif; /* image handle */ + int stoponerr; /* stop on read error */ + int isContig; /* data is packed/separate */ + int alpha; /* type of alpha data present */ + uint32 width; /* image width */ + uint32 height; /* image height */ + uint16 bitspersample; /* image bits/sample */ + uint16 samplesperpixel; /* image samples/pixel */ + uint16 orientation; /* image orientation */ + uint16 req_orientation; /* requested orientation */ + uint16 photometric; /* image photometric interp */ + uint16* redcmap; /* colormap pallete */ + uint16* greencmap; + uint16* bluecmap; + /* get image data routine */ + int (*get)(TIFFRGBAImage*, uint32*, uint32, uint32); + union { + void (*any)(TIFFRGBAImage*); + tileContigRoutine contig; + tileSeparateRoutine separate; + } put; /* put decoded strip/tile */ + TIFFRGBValue* Map; /* sample mapping array */ + uint32** BWmap; /* black&white map */ + uint32** PALmap; /* palette image map */ + TIFFYCbCrToRGB* ycbcr; /* YCbCr conversion state */ + TIFFCIELabToRGB* cielab; /* CIE L*a*b conversion state */ + + int row_offset; + int col_offset; +}; + +/* + * Macros for extracting components from the + * packed ABGR form returned by TIFFReadRGBAImage. + */ +#define TIFFGetR(abgr) ((abgr) & 0xff) +#define TIFFGetG(abgr) (((abgr) >> 8) & 0xff) +#define TIFFGetB(abgr) (((abgr) >> 16) & 0xff) +#define TIFFGetA(abgr) (((abgr) >> 24) & 0xff) + +/* + * A CODEC is a software package that implements decoding, + * encoding, or decoding+encoding of a compression algorithm. + * The library provides a collection of builtin codecs. + * More codecs may be registered through calls to the library + * and/or the builtin implementations may be overridden. + */ +typedef int (*TIFFInitMethod)(TIFF*, int); +typedef struct { + char* name; + uint16 scheme; + TIFFInitMethod init; +} TIFFCodec; + +#include <stdio.h> +#include <stdarg.h> + +/* share internal LogLuv conversion routines? */ +#ifndef LOGLUV_PUBLIC +#define LOGLUV_PUBLIC 1 +#endif + +#if defined(c_plusplus) || defined(__cplusplus) +extern "C" { +#endif +typedef void (*TIFFErrorHandler)(const char*, const char*, va_list); +typedef void (*TIFFErrorHandlerExt)(thandle_t, const char*, const char*, va_list); +typedef tsize_t (*TIFFReadWriteProc)(thandle_t, tdata_t, tsize_t); +typedef toff_t (*TIFFSeekProc)(thandle_t, toff_t, int); +typedef int (*TIFFCloseProc)(thandle_t); +typedef toff_t (*TIFFSizeProc)(thandle_t); +typedef int (*TIFFMapFileProc)(thandle_t, tdata_t*, toff_t*); +typedef void (*TIFFUnmapFileProc)(thandle_t, tdata_t, toff_t); +typedef void (*TIFFExtendProc)(TIFF*); + +extern const char* TIFFGetVersion(void); + +extern const TIFFCodec* TIFFFindCODEC(uint16); +extern TIFFCodec* TIFFRegisterCODEC(uint16, const char*, TIFFInitMethod); +extern void TIFFUnRegisterCODEC(TIFFCodec*); +extern int TIFFIsCODECConfigured(uint16); +extern TIFFCodec* TIFFGetConfiguredCODECs(void); + +/* + * Auxiliary functions. + */ + +extern tdata_t _TIFFmalloc(tsize_t); +extern tdata_t _TIFFrealloc(tdata_t, tsize_t); +extern void _TIFFmemset(tdata_t, int, tsize_t); +extern void _TIFFmemcpy(tdata_t, const tdata_t, tsize_t); +extern int _TIFFmemcmp(const tdata_t, const tdata_t, tsize_t); +extern void _TIFFfree(tdata_t); + +/* +** Stuff, related to tag handling and creating custom tags. +*/ +extern int TIFFGetTagListCount( TIFF * ); +extern ttag_t TIFFGetTagListEntry( TIFF *, int tag_index ); + +#define TIFF_ANY TIFF_NOTYPE /* for field descriptor searching */ +#define TIFF_VARIABLE -1 /* marker for variable length tags */ +#define TIFF_SPP -2 /* marker for SamplesPerPixel tags */ +#define TIFF_VARIABLE2 -3 /* marker for uint32 var-length tags */ + +#define FIELD_CUSTOM 65 + +typedef struct { + ttag_t field_tag; /* field's tag */ + short field_readcount; /* read count/TIFF_VARIABLE/TIFF_SPP */ + short field_writecount; /* write count/TIFF_VARIABLE */ + TIFFDataType field_type; /* type of associated data */ + unsigned short field_bit; /* bit in fieldsset bit vector */ + unsigned char field_oktochange; /* if true, can change while writing */ + unsigned char field_passcount; /* if true, pass dir count on set */ + char *field_name; /* ASCII name */ +} TIFFFieldInfo; + +typedef struct _TIFFTagValue { + const TIFFFieldInfo *info; + int count; + void *value; +} TIFFTagValue; + +extern void TIFFMergeFieldInfo(TIFF*, const TIFFFieldInfo[], int); +extern const TIFFFieldInfo* TIFFFindFieldInfo(TIFF*, ttag_t, TIFFDataType); +extern const TIFFFieldInfo* TIFFFindFieldInfoByName(TIFF* , const char *, + TIFFDataType); +extern const TIFFFieldInfo* TIFFFieldWithTag(TIFF*, ttag_t); +extern const TIFFFieldInfo* TIFFFieldWithName(TIFF*, const char *); + +typedef int (*TIFFVSetMethod)(TIFF*, ttag_t, va_list); +typedef int (*TIFFVGetMethod)(TIFF*, ttag_t, va_list); +typedef void (*TIFFPrintMethod)(TIFF*, FILE*, long); + +typedef struct { + TIFFVSetMethod vsetfield; /* tag set routine */ + TIFFVGetMethod vgetfield; /* tag get routine */ + TIFFPrintMethod printdir; /* directory print routine */ +} TIFFTagMethods; + +extern TIFFTagMethods *TIFFAccessTagMethods( TIFF * ); +extern void *TIFFGetClientInfo( TIFF *, const char * ); +extern void TIFFSetClientInfo( TIFF *, void *, const char * ); + +extern void TIFFCleanup(TIFF*); +extern void TIFFClose(TIFF*); +extern int TIFFFlush(TIFF*); +extern int TIFFFlushData(TIFF*); +extern int TIFFGetField(TIFF*, ttag_t, ...); +extern int TIFFVGetField(TIFF*, ttag_t, va_list); +extern int TIFFGetFieldDefaulted(TIFF*, ttag_t, ...); +extern int TIFFVGetFieldDefaulted(TIFF*, ttag_t, va_list); +extern int TIFFReadDirectory(TIFF*); +extern int TIFFReadCustomDirectory(TIFF*, toff_t, const TIFFFieldInfo[], + size_t); +extern int TIFFReadEXIFDirectory(TIFF*, toff_t); +extern tsize_t TIFFScanlineSize(TIFF*); +extern tsize_t TIFFRasterScanlineSize(TIFF*); +extern tsize_t TIFFStripSize(TIFF*); +extern tsize_t TIFFRawStripSize(TIFF*, tstrip_t); +extern tsize_t TIFFVStripSize(TIFF*, uint32); +extern tsize_t TIFFTileRowSize(TIFF*); +extern tsize_t TIFFTileSize(TIFF*); +extern tsize_t TIFFVTileSize(TIFF*, uint32); +extern uint32 TIFFDefaultStripSize(TIFF*, uint32); +extern void TIFFDefaultTileSize(TIFF*, uint32*, uint32*); +extern int TIFFFileno(TIFF*); +extern int TIFFSetFileno(TIFF*, int); +extern thandle_t TIFFClientdata(TIFF*); +extern thandle_t TIFFSetClientdata(TIFF*, thandle_t); +extern int TIFFGetMode(TIFF*); +extern int TIFFSetMode(TIFF*, int); +extern int TIFFIsTiled(TIFF*); +extern int TIFFIsByteSwapped(TIFF*); +extern int TIFFIsUpSampled(TIFF*); +extern int TIFFIsMSB2LSB(TIFF*); +extern int TIFFIsBigEndian(TIFF*); +extern TIFFReadWriteProc TIFFGetReadProc(TIFF*); +extern TIFFReadWriteProc TIFFGetWriteProc(TIFF*); +extern TIFFSeekProc TIFFGetSeekProc(TIFF*); +extern TIFFCloseProc TIFFGetCloseProc(TIFF*); +extern TIFFSizeProc TIFFGetSizeProc(TIFF*); +extern TIFFMapFileProc TIFFGetMapFileProc(TIFF*); +extern TIFFUnmapFileProc TIFFGetUnmapFileProc(TIFF*); +extern uint32 TIFFCurrentRow(TIFF*); +extern tdir_t TIFFCurrentDirectory(TIFF*); +extern tdir_t TIFFNumberOfDirectories(TIFF*); +extern uint32 TIFFCurrentDirOffset(TIFF*); +extern tstrip_t TIFFCurrentStrip(TIFF*); +extern ttile_t TIFFCurrentTile(TIFF*); +extern int TIFFReadBufferSetup(TIFF*, tdata_t, tsize_t); +extern int TIFFWriteBufferSetup(TIFF*, tdata_t, tsize_t); +extern int TIFFSetupStrips(TIFF *); +extern int TIFFWriteCheck(TIFF*, int, const char *); +extern void TIFFFreeDirectory(TIFF*); +extern int TIFFCreateDirectory(TIFF*); +extern int TIFFLastDirectory(TIFF*); +extern int TIFFSetDirectory(TIFF*, tdir_t); +extern int TIFFSetSubDirectory(TIFF*, uint32); +extern int TIFFUnlinkDirectory(TIFF*, tdir_t); +extern int TIFFSetField(TIFF*, ttag_t, ...); +extern int TIFFVSetField(TIFF*, ttag_t, va_list); +extern int TIFFWriteDirectory(TIFF *); +extern int TIFFCheckpointDirectory(TIFF *); +extern int TIFFRewriteDirectory(TIFF *); +extern int TIFFReassignTagToIgnore(enum TIFFIgnoreSense, int); + +#if defined(c_plusplus) || defined(__cplusplus) +extern void TIFFPrintDirectory(TIFF*, FILE*, long = 0); +extern int TIFFReadScanline(TIFF*, tdata_t, uint32, tsample_t = 0); +extern int TIFFWriteScanline(TIFF*, tdata_t, uint32, tsample_t = 0); +extern int TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int = 0); +extern int TIFFReadRGBAImageOriented(TIFF*, uint32, uint32, uint32*, + int = ORIENTATION_BOTLEFT, int = 0); +#else +extern void TIFFPrintDirectory(TIFF*, FILE*, long); +extern int TIFFReadScanline(TIFF*, tdata_t, uint32, tsample_t); +extern int TIFFWriteScanline(TIFF*, tdata_t, uint32, tsample_t); +extern int TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int); +extern int TIFFReadRGBAImageOriented(TIFF*, uint32, uint32, uint32*, int, int); +#endif + +extern int TIFFReadRGBAStrip(TIFF*, tstrip_t, uint32 * ); +extern int TIFFReadRGBATile(TIFF*, uint32, uint32, uint32 * ); +extern int TIFFRGBAImageOK(TIFF*, char [1024]); +extern int TIFFRGBAImageBegin(TIFFRGBAImage*, TIFF*, int, char [1024]); +extern int TIFFRGBAImageGet(TIFFRGBAImage*, uint32*, uint32, uint32); +extern void TIFFRGBAImageEnd(TIFFRGBAImage*); +extern TIFF* TIFFOpen(const char*, const char*); +# ifdef __WIN32__ +extern TIFF* TIFFOpenW(const wchar_t*, const char*); +# endif /* __WIN32__ */ +extern TIFF* TIFFFdOpen(int, const char*, const char*); +extern TIFF* TIFFClientOpen(const char*, const char*, + thandle_t, + TIFFReadWriteProc, TIFFReadWriteProc, + TIFFSeekProc, TIFFCloseProc, + TIFFSizeProc, + TIFFMapFileProc, TIFFUnmapFileProc); +extern const char* TIFFFileName(TIFF*); +extern const char* TIFFSetFileName(TIFF*, const char *); +extern void TIFFError(const char*, const char*, ...); +extern void TIFFErrorExt(thandle_t, const char*, const char*, ...); +extern void TIFFWarning(const char*, const char*, ...); +extern void TIFFWarningExt(thandle_t, const char*, const char*, ...); +extern TIFFErrorHandler TIFFSetErrorHandler(TIFFErrorHandler); +extern TIFFErrorHandlerExt TIFFSetErrorHandlerExt(TIFFErrorHandlerExt); +extern TIFFErrorHandler TIFFSetWarningHandler(TIFFErrorHandler); +extern TIFFErrorHandlerExt TIFFSetWarningHandlerExt(TIFFErrorHandlerExt); +extern TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc); +extern ttile_t TIFFComputeTile(TIFF*, uint32, uint32, uint32, tsample_t); +extern int TIFFCheckTile(TIFF*, uint32, uint32, uint32, tsample_t); +extern ttile_t TIFFNumberOfTiles(TIFF*); +extern tsize_t TIFFReadTile(TIFF*, + tdata_t, uint32, uint32, uint32, tsample_t); +extern tsize_t TIFFWriteTile(TIFF*, + tdata_t, uint32, uint32, uint32, tsample_t); +extern tstrip_t TIFFComputeStrip(TIFF*, uint32, tsample_t); +extern tstrip_t TIFFNumberOfStrips(TIFF*); +extern tsize_t TIFFReadEncodedStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFReadRawStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFReadEncodedTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern tsize_t TIFFReadRawTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteEncodedStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteRawStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteEncodedTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteRawTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern int TIFFDataWidth(TIFFDataType); /* table of tag datatype widths */ +extern void TIFFSetWriteOffset(TIFF*, toff_t); +extern void TIFFSwabShort(uint16*); +extern void TIFFSwabLong(uint32*); +extern void TIFFSwabDouble(double*); +extern void TIFFSwabArrayOfShort(uint16*, unsigned long); +extern void TIFFSwabArrayOfTriples(uint8*, unsigned long); +extern void TIFFSwabArrayOfLong(uint32*, unsigned long); +extern void TIFFSwabArrayOfDouble(double*, unsigned long); +extern void TIFFReverseBits(unsigned char *, unsigned long); +extern const unsigned char* TIFFGetBitRevTable(int); + +#ifdef LOGLUV_PUBLIC +#define U_NEU 0.210526316 +#define V_NEU 0.473684211 +#define UVSCALE 410. +extern double LogL16toY(int); +extern double LogL10toY(int); +extern void XYZtoRGB24(float*, uint8*); +extern int uv_decode(double*, double*, int); +extern void LogLuv24toXYZ(uint32, float*); +extern void LogLuv32toXYZ(uint32, float*); +#if defined(c_plusplus) || defined(__cplusplus) +extern int LogL16fromY(double, int = SGILOGENCODE_NODITHER); +extern int LogL10fromY(double, int = SGILOGENCODE_NODITHER); +extern int uv_encode(double, double, int = SGILOGENCODE_NODITHER); +extern uint32 LogLuv24fromXYZ(float*, int = SGILOGENCODE_NODITHER); +extern uint32 LogLuv32fromXYZ(float*, int = SGILOGENCODE_NODITHER); +#else +extern int LogL16fromY(double, int); +extern int LogL10fromY(double, int); +extern int uv_encode(double, double, int); +extern uint32 LogLuv24fromXYZ(float*, int); +extern uint32 LogLuv32fromXYZ(float*, int); +#endif +#endif /* LOGLUV_PUBLIC */ + +extern int TIFFCIELabToRGBInit(TIFFCIELabToRGB*, TIFFDisplay *, float*); +extern void TIFFCIELabToXYZ(TIFFCIELabToRGB *, uint32, int32, int32, + float *, float *, float *); +extern void TIFFXYZToRGB(TIFFCIELabToRGB *, float, float, float, + uint32 *, uint32 *, uint32 *); + +extern int TIFFYCbCrToRGBInit(TIFFYCbCrToRGB*, float*, float*); +extern void TIFFYCbCrtoRGB(TIFFYCbCrToRGB *, uint32, int32, int32, + uint32 *, uint32 *, uint32 *); + +#if defined(c_plusplus) || defined(__cplusplus) +} +#endif + +#endif /* _TIFFIO_ */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/plugins/snes9x_gx/portlibs/include/tiffvers.h b/plugins/snes9x_gx/portlibs/include/tiffvers.h new file mode 100644 index 00000000..9744f8d3 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/tiffvers.h @@ -0,0 +1,9 @@ +#define TIFFLIB_VERSION_STR "LIBTIFF, Version 3.8.2\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc." +/* + * This define can be used in code that requires + * compilation-related definitions specific to a + * version or versions of the library. Runtime + * version checking should be done based on the + * string returned by TIFFGetVersion. + */ +#define TIFFLIB_VERSION 20060323 diff --git a/plugins/snes9x_gx/portlibs/include/tremor/config_types.h b/plugins/snes9x_gx/portlibs/include/tremor/config_types.h new file mode 100644 index 00000000..4f07a037 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/tremor/config_types.h @@ -0,0 +1,26 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * + * * + ******************************************************************** + + function: #ifdef jail to whip a few platforms into the UNIX ideal. + + ********************************************************************/ +#ifndef _OS_CVTYPES_H +#define _OS_CVTYPES_H + +typedef long long ogg_int64_t; +typedef int ogg_int32_t; +typedef unsigned int ogg_uint32_t; +typedef short ogg_int16_t; +typedef unsigned short ogg_uint16_t; + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/tremor/ivorbiscodec.h b/plugins/snes9x_gx/portlibs/include/tremor/ivorbiscodec.h new file mode 100644 index 00000000..0eea9eb8 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/tremor/ivorbiscodec.h @@ -0,0 +1,104 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * + * * + ******************************************************************** + + function: libvorbis codec headers + + ********************************************************************/ + +#ifndef _vorbis_codec_h_ +#define _vorbis_codec_h_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include "ogg.h" + +struct vorbis_dsp_state; +typedef struct vorbis_dsp_state vorbis_dsp_state; + +typedef struct vorbis_info{ + int version; + int channels; + long rate; + + /* The below bitrate declarations are *hints*. + Combinations of the three values carry the following implications: + + all three set to the same value: + implies a fixed rate bitstream + only nominal set: + implies a VBR stream that averages the nominal bitrate. No hard + upper/lower limit + upper and or lower set: + implies a VBR bitstream that obeys the bitrate limits. nominal + may also be set to give a nominal rate. + none set: + the coder does not care to speculate. + */ + + long bitrate_upper; + long bitrate_nominal; + long bitrate_lower; + long bitrate_window; + + void *codec_setup; +} vorbis_info; + +typedef struct vorbis_comment{ + char **user_comments; + int *comment_lengths; + int comments; + char *vendor; + +} vorbis_comment; + + +/* Vorbis PRIMITIVES: general ***************************************/ + +extern void vorbis_info_init(vorbis_info *vi); +extern void vorbis_info_clear(vorbis_info *vi); +extern int vorbis_info_blocksize(vorbis_info *vi,int zo); +extern void vorbis_comment_init(vorbis_comment *vc); +extern void vorbis_comment_add(vorbis_comment *vc, char *comment); +extern void vorbis_comment_add_tag(vorbis_comment *vc, + char *tag, char *contents); +extern char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count); +extern int vorbis_comment_query_count(vorbis_comment *vc, char *tag); +extern void vorbis_comment_clear(vorbis_comment *vc); + +/* Vorbis ERRORS and return codes ***********************************/ + +#define OV_FALSE -1 +#define OV_EOF -2 +#define OV_HOLE -3 + +#define OV_EREAD -128 +#define OV_EFAULT -129 +#define OV_EIMPL -130 +#define OV_EINVAL -131 +#define OV_ENOTVORBIS -132 +#define OV_EBADHEADER -133 +#define OV_EVERSION -134 +#define OV_ENOTAUDIO -135 +#define OV_EBADPACKET -136 +#define OV_EBADLINK -137 +#define OV_ENOSEEK -138 + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/plugins/snes9x_gx/portlibs/include/tremor/ivorbisfile.h b/plugins/snes9x_gx/portlibs/include/tremor/ivorbisfile.h new file mode 100644 index 00000000..7ebc0427 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/tremor/ivorbisfile.h @@ -0,0 +1,122 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * + * * + ******************************************************************** + + function: stdio-based convenience library for opening/seeking/decoding + + ********************************************************************/ + +#ifndef _OV_FILE_H_ +#define _OV_FILE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include <stdio.h> +#include "ivorbiscodec.h" + +/* The function prototypes for the callbacks are basically the same as for + * the stdio functions fread, fseek, fclose, ftell. + * The one difference is that the FILE * arguments have been replaced with + * a void * - this is to be used as a pointer to whatever internal data these + * functions might need. In the stdio case, it's just a FILE * cast to a void * + * + * If you use other functions, check the docs for these functions and return + * the right values. For seek_func(), you *MUST* return -1 if the stream is + * unseekable + */ +typedef struct { + size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource); + int (*seek_func) (void *datasource, ogg_int64_t offset, int whence); + int (*close_func) (void *datasource); + long (*tell_func) (void *datasource); +} ov_callbacks; + +typedef struct OggVorbis_File { + void *datasource; /* Pointer to a FILE *, etc. */ + int seekable; + ogg_int64_t offset; + ogg_int64_t end; + ogg_sync_state *oy; + + /* If the FILE handle isn't seekable (eg, a pipe), only the current + stream appears */ + int links; + ogg_int64_t *offsets; + ogg_int64_t *dataoffsets; + ogg_uint32_t *serialnos; + ogg_int64_t *pcmlengths; + vorbis_info vi; + vorbis_comment vc; + + /* Decoding working state local storage */ + ogg_int64_t pcm_offset; + int ready_state; + ogg_uint32_t current_serialno; + int current_link; + + ogg_int64_t bittrack; + ogg_int64_t samptrack; + + ogg_stream_state *os; /* take physical pages, weld into a logical + stream of packets */ + vorbis_dsp_state *vd; /* central working state for the packet->PCM decoder */ + + ov_callbacks callbacks; + +} OggVorbis_File; + +extern int ov_clear(OggVorbis_File *vf); +extern int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes); +extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf, + char *initial, long ibytes, ov_callbacks callbacks); + +extern int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes); +extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf, + char *initial, long ibytes, ov_callbacks callbacks); +extern int ov_test_open(OggVorbis_File *vf); + +extern long ov_bitrate(OggVorbis_File *vf,int i); +extern long ov_bitrate_instant(OggVorbis_File *vf); +extern long ov_streams(OggVorbis_File *vf); +extern long ov_seekable(OggVorbis_File *vf); +extern long ov_serialnumber(OggVorbis_File *vf,int i); + +extern ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i); +extern ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i); +extern ogg_int64_t ov_time_total(OggVorbis_File *vf,int i); + +extern int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_time_seek(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_time_seek_page(OggVorbis_File *vf,ogg_int64_t pos); + +extern ogg_int64_t ov_raw_tell(OggVorbis_File *vf); +extern ogg_int64_t ov_pcm_tell(OggVorbis_File *vf); +extern ogg_int64_t ov_time_tell(OggVorbis_File *vf); + +extern vorbis_info *ov_info(OggVorbis_File *vf,int link); +extern vorbis_comment *ov_comment(OggVorbis_File *vf,int link); + +extern long ov_read(OggVorbis_File *vf,void *buffer,int length, + int *bitstream); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + + diff --git a/plugins/snes9x_gx/portlibs/include/tremor/ogg.h b/plugins/snes9x_gx/portlibs/include/tremor/ogg.h new file mode 100644 index 00000000..85cb41b6 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/tremor/ogg.h @@ -0,0 +1,206 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * + * * + ******************************************************************** + + function: subsumed libogg includes + + ********************************************************************/ +#ifndef _OGG_H +#define _OGG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "os_types.h" + +typedef struct ogg_buffer_state{ + struct ogg_buffer *unused_buffers; + struct ogg_reference *unused_references; + int outstanding; + int shutdown; +} ogg_buffer_state; + +typedef struct ogg_buffer { + unsigned char *data; + long size; + int refcount; + + union { + ogg_buffer_state *owner; + struct ogg_buffer *next; + } ptr; +} ogg_buffer; + +typedef struct ogg_reference { + ogg_buffer *buffer; + long begin; + long length; + + struct ogg_reference *next; +} ogg_reference; + +typedef struct oggpack_buffer { + int headbit; + unsigned char *headptr; + long headend; + + /* memory management */ + ogg_reference *head; + ogg_reference *tail; + + /* render the byte/bit counter API constant time */ + long count; /* doesn't count the tail */ +} oggpack_buffer; + +typedef struct oggbyte_buffer { + ogg_reference *baseref; + + ogg_reference *ref; + unsigned char *ptr; + long pos; + long end; +} oggbyte_buffer; + +typedef struct ogg_sync_state { + /* decode memory management pool */ + ogg_buffer_state *bufferpool; + + /* stream buffers */ + ogg_reference *fifo_head; + ogg_reference *fifo_tail; + long fifo_fill; + + /* stream sync management */ + int unsynced; + int headerbytes; + int bodybytes; + +} ogg_sync_state; + +typedef struct ogg_stream_state { + ogg_reference *header_head; + ogg_reference *header_tail; + ogg_reference *body_head; + ogg_reference *body_tail; + + int e_o_s; /* set when we have buffered the last + packet in the logical bitstream */ + int b_o_s; /* set after we've written the initial page + of a logical bitstream */ + long serialno; + long pageno; + ogg_int64_t packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a seperate abstraction + layer) also knows about the gap */ + ogg_int64_t granulepos; + + int lacing_fill; + ogg_uint32_t body_fill; + + /* decode-side state data */ + int holeflag; + int spanflag; + int clearflag; + int laceptr; + ogg_uint32_t body_fill_next; + +} ogg_stream_state; + +typedef struct { + ogg_reference *packet; + long bytes; + long b_o_s; + long e_o_s; + ogg_int64_t granulepos; + ogg_int64_t packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a seperate abstraction + layer) also knows about the gap */ +} ogg_packet; + +typedef struct { + ogg_reference *header; + int header_len; + ogg_reference *body; + long body_len; +} ogg_page; + +/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/ + +extern void oggpack_readinit(oggpack_buffer *b,ogg_reference *r); +extern long oggpack_look(oggpack_buffer *b,int bits); +extern void oggpack_adv(oggpack_buffer *b,int bits); +extern long oggpack_read(oggpack_buffer *b,int bits); +extern long oggpack_bytes(oggpack_buffer *b); +extern long oggpack_bits(oggpack_buffer *b); +extern int oggpack_eop(oggpack_buffer *b); + +/* Ogg BITSTREAM PRIMITIVES: decoding **************************/ + +extern ogg_sync_state *ogg_sync_create(void); +extern int ogg_sync_destroy(ogg_sync_state *oy); +extern int ogg_sync_reset(ogg_sync_state *oy); + +extern unsigned char *ogg_sync_bufferin(ogg_sync_state *oy, long size); +extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes); +extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og); +extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og); +extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op); +extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op); + +/* Ogg BITSTREAM PRIMITIVES: general ***************************/ + +extern ogg_stream_state *ogg_stream_create(int serialno); +extern int ogg_stream_destroy(ogg_stream_state *os); +extern int ogg_stream_reset(ogg_stream_state *os); +extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno); +extern int ogg_stream_eos(ogg_stream_state *os); + +extern int ogg_page_checksum_set(ogg_page *og); + +extern int ogg_page_version(ogg_page *og); +extern int ogg_page_continued(ogg_page *og); +extern int ogg_page_bos(ogg_page *og); +extern int ogg_page_eos(ogg_page *og); +extern ogg_int64_t ogg_page_granulepos(ogg_page *og); +extern ogg_uint32_t ogg_page_serialno(ogg_page *og); +extern ogg_uint32_t ogg_page_pageno(ogg_page *og); +extern int ogg_page_packets(ogg_page *og); +extern int ogg_page_getbuffer(ogg_page *og, unsigned char **buffer); + +extern int ogg_packet_release(ogg_packet *op); +extern int ogg_page_release(ogg_page *og); + +extern void ogg_page_dup(ogg_page *d, ogg_page *s); + +/* Ogg BITSTREAM PRIMITIVES: return codes ***************************/ + +#define OGG_SUCCESS 0 + +#define OGG_HOLE -10 +#define OGG_SPAN -11 +#define OGG_EVERSION -12 +#define OGG_ESERIAL -13 +#define OGG_EINVAL -14 +#define OGG_EEOS -15 + + +#ifdef __cplusplus +} +#endif + +#endif /* _OGG_H */ diff --git a/plugins/snes9x_gx/portlibs/include/tremor/os_types.h b/plugins/snes9x_gx/portlibs/include/tremor/os_types.h new file mode 100644 index 00000000..2761aa42 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/tremor/os_types.h @@ -0,0 +1,94 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * + * * + ******************************************************************** + + function: #ifdef jail to whip a few platforms into the UNIX ideal. + + ********************************************************************/ +#ifndef _OS_TYPES_H +#define _OS_TYPES_H + +#ifdef _LOW_ACCURACY_ +# define X(n) (((((n)>>22)+1)>>1) - ((((n)>>22)+1)>>9)) +# define LOOKUP_T const unsigned char +#else +# define X(n) (n) +# define LOOKUP_T const ogg_int32_t +#endif + +/* make it easy on the folks that want to compile the libs with a + different malloc than stdlib */ +#define _ogg_malloc malloc +#define _ogg_calloc calloc +#define _ogg_realloc realloc +#define _ogg_free free + +#ifdef _WIN32 + +# ifndef __GNUC__ + /* MSVC/Borland */ + typedef __int64 ogg_int64_t; + typedef __int32 ogg_int32_t; + typedef unsigned __int32 ogg_uint32_t; + typedef __int16 ogg_int16_t; + typedef unsigned __int16 ogg_uint16_t; +# else + /* Cygwin */ + #include <_G_config.h> + typedef _G_int64_t ogg_int64_t; + typedef _G_int32_t ogg_int32_t; + typedef _G_uint32_t ogg_uint32_t; + typedef _G_int16_t ogg_int16_t; + typedef _G_uint16_t ogg_uint16_t; +# endif + +#elif defined(__MACOS__) + +# include <sys/types.h> + typedef SInt16 ogg_int16_t; + typedef UInt16 ogg_uint16_t; + typedef SInt32 ogg_int32_t; + typedef UInt32 ogg_uint32_t; + typedef SInt64 ogg_int64_t; + +#elif defined(__MACOSX__) /* MacOS X Framework build */ + +# include <sys/types.h> + typedef int16_t ogg_int16_t; + typedef u_int16_t ogg_uint16_t; + typedef int32_t ogg_int32_t; + typedef u_int32_t ogg_uint32_t; + typedef int64_t ogg_int64_t; + +#elif defined(__BEOS__) + + /* Be */ +# include <inttypes.h> + +#elif defined (__EMX__) + + /* OS/2 GCC */ + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + +#else + +# include <sys/types.h> +# include <sys/param.h> +# include "config_types.h" + +#endif + +#endif /* _OS_TYPES_H */ diff --git a/plugins/snes9x_gx/portlibs/include/wupc/wupc.h b/plugins/snes9x_gx/portlibs/include/wupc/wupc.h new file mode 100644 index 00000000..02653964 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/wupc/wupc.h @@ -0,0 +1,49 @@ +/**************************************************************************** + * Copyright (C) 2014 FIX94 + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + ****************************************************************************/ +#ifndef _WUPC_H_ +#define _WUPC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct WUPCData { + s16 xAxisL; + s16 xAxisR; + s16 yAxisL; + s16 yAxisR; + u32 button; +}; + +void WUPC_Init(); +void WUPC_Shutdown(); +struct WUPCData *WUPC_Data(u8 chan); +void WUPC_Rumble(u8 chan, bool rumble); +u32 WUPC_UpdateButtonStats(); +u32 WUPC_ButtonsUp(u8 chan); +u32 WUPC_ButtonsDown(u8 chan); +u32 WUPC_ButtonsHeld(u8 chan); +s16 WUPC_lStickX(u8 chan); +s16 WUPC_lStickY(u8 chan); +s16 WUPC_rStickX(u8 chan); +s16 WUPC_rStickY(u8 chan); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/snes9x_gx/portlibs/include/zconf.h b/plugins/snes9x_gx/portlibs/include/zconf.h new file mode 100644 index 00000000..b2343874 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/zconf.h @@ -0,0 +1,428 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# define uncompress z_uncompress +# define zError z_zError +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# define gzFile z_gzFile +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include <windows.h> + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 1 /* was set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef STDC +# include <sys/types.h> /* for off_t */ +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include <unistd.h> /* for SEEK_* and off_t */ +# ifdef VMS +# include <unixio.h> /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define z_off64_t off64_t +#else +# define z_off64_t z_off_t +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/plugins/snes9x_gx/portlibs/include/zip/ioapi.h b/plugins/snes9x_gx/portlibs/include/zip/ioapi.h new file mode 100644 index 00000000..7d457baa --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/zip/ioapi.h @@ -0,0 +1,75 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#ifndef _ZLIBIOAPI_H +#define _ZLIBIOAPI_H + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + +#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) +#define ZCALLBACK CALLBACK +#else +#define ZCALLBACK +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); + +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + + + +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) +#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) +#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) +#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) +#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/plugins/snes9x_gx/portlibs/include/zip/unzip.h b/plugins/snes9x_gx/portlibs/include/zip/unzip.h new file mode 100644 index 00000000..c3206a05 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/zip/unzip.h @@ -0,0 +1,354 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + + Multi volume ZipFile (span) are not supported. + Encryption compatible with pkzip 2.04g only supported + Old compressions used by old PKZip 1.x are not supported + + + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip + http://www.info-zip.org/pub/infozip/doc/ + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern unzFile ZEXPORT unzOpen2 OF((const char *path, + zlib_filefunc_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +/* ****************************************** */ + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, + const char* password)); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, + int* method, + int* level, + int raw)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, + int* method, + int* level, + int raw, + const char* password)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +extern uLong ZEXPORT unzGetOffset (unzFile file); + +/* Set the current file offset */ +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/plugins/snes9x_gx/portlibs/include/zip/zip.h b/plugins/snes9x_gx/portlibs/include/zip/zip.h new file mode 100644 index 00000000..acacce83 --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/zip/zip.h @@ -0,0 +1,235 @@ +/* zip.h -- IO for compress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This unzip package allow creates .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Multi volume ZipFile (span) are not supported. + Encryption compatible with pkzip 2.04g only supported + Old compressions used by old PKZip 1.x are not supported + + For uncompress .zip file, look at unzip.h + + + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.html for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip + http://www.info-zip.org/pub/infozip/doc/ + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _zip_H +#define _zip_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagzipFile__ { int unused; } zipFile__; +typedef zipFile__ *zipFile; +#else +typedef voidp zipFile; +#endif + +#define ZIP_OK (0) +#define ZIP_EOF (0) +#define ZIP_ERRNO (Z_ERRNO) +#define ZIP_PARAMERROR (-102) +#define ZIP_BADZIPFILE (-103) +#define ZIP_INTERNALERROR (-104) + +#ifndef DEF_MEM_LEVEL +# if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +# else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +# endif +#endif +/* default memLevel */ + +/* tm_zip contain date/time info */ +typedef struct tm_zip_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_zip; + +typedef struct +{ + tm_zip tmz_date; /* date in understandable format */ + uLong dosDate; /* if dos_date == 0, tmu_date is used */ +/* uLong flag; */ /* general purpose bit flag 2 bytes */ + + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ +} zip_fileinfo; + +typedef const char* zipcharpc; + + +#define APPEND_STATUS_CREATE (0) +#define APPEND_STATUS_CREATEAFTER (1) +#define APPEND_STATUS_ADDINZIP (2) + +extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); +/* + Create a zipfile. + pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on + an Unix computer "zlib/zlib113.zip". + if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip + will be created at the end of the file. + (useful if the file contain a self extractor code) + if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will + add files in existing zip (be sure you don't add file that doesn't exist) + If the zipfile cannot be opened, the return value is NULL. + Else, the return value is a zipFile Handle, usable with other function + of this zip package. +*/ + +/* Note : there is no delete function into a zipfile. + If you want delete file into a zipfile, you must open a zipfile, and create another + Of couse, you can use RAW reading and writing to copy the file you did not want delte +*/ + +extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc_def* pzlib_filefunc_def)); + +extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level)); +/* + Open a file in the ZIP for writing. + filename : the filename in zip (if NULL, '-' without quote will be used + *zipfi contain supplemental information + if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local + contains the extrafield data the the local header + if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global + contains the extrafield data the the local header + if comment != NULL, comment contain the comment string + method contain the compression method (0 for store, Z_DEFLATED for deflate) + level contain the level of compression (can be Z_DEFAULT_COMPRESSION) +*/ + + +extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw)); + +/* + Same than zipOpenNewFileInZip, except if raw=1, we write raw file + */ + +extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCtypting)); + +/* + Same than zipOpenNewFileInZip2, except + windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 + password : crypting password (NULL for no crypting) + crcForCtypting : crc of file to compress (needed for crypting) + */ + + +extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, + const void* buf, + unsigned len)); +/* + Write data in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +/* + Close the current file in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, + uLong uncompressed_size, + uLong crc32)); +/* + Close the current file in the zipfile, for fiel opened with + parameter raw=1 in zipOpenNewFileInZip2 + uncompressed_size and crc32 are value for the uncompressed size +*/ + +extern int ZEXPORT zipClose OF((zipFile file, + const char* global_comment)); +/* + Close the zipfile +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _zip_H */ diff --git a/plugins/snes9x_gx/portlibs/include/zlib.h b/plugins/snes9x_gx/portlibs/include/zlib.h new file mode 100644 index 00000000..bfbba83e --- /dev/null +++ b/plugins/snes9x_gx/portlibs/include/zlib.h @@ -0,0 +1,1613 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.5, April 19th, 2010 + + Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.5" +#define ZLIB_VERNUM 0x1250 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 5 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use in the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). Some + output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the stream + are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least the + value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect the + compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the + exact value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing will + resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all the uncompressed data. (The size + of the uncompressed data may have been saved by the compressor for this + purpose.) The next operation on this stream must be inflateEnd to deallocate + the decompression state. The use of Z_FINISH is never required, but can be + used to inform inflate that a faster approach may be used for the single + inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK or Z_TREES is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained, so applications that need that information should + instead use raw inflate, see inflateInit2() below, or inflateBack() and + perform their own processing of the gzip header and trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any call + of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. The + stream will keep the same compression level and any other attributes that + may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression level is changed, the input available so far is + compressed with the old level (and may be flushed); the new level will take + effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to be + compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if + strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been + found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the + success case, the application may save the current current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the normal + behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef voidp gzFile; /* opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) Also "a" + can be used instead of "w" to request that the gzip stream that will be + written be appended to the file. "+" will result in an error, since reading + and writing to the same gzip file is not supported. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file was not in gzip format, gzread copies the given number of + bytes into the buffer. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream, or failing that, reading the rest + of the input file directly without decompression. The entire input file + will be read if gzread is called until it returns less than the requested + len. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will return an error (0) with + nothing written. In this case, there may also be a buffer overflow with + unpredictable consequences, which is possible only if zlib was compiled with + the insecure functions sprintf() or vsprintf() because the secure snprintf() + or vsnprintf() functions were not available. This can be determined using + zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. This state can change from + false to true while reading the input file if the end of a gzip stream is + reached, but is followed by data that is not another gzip stream. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the for the crc. Pre- and post-conditioning (one's + complement) is performed within this function so it shouldn't be done by the + application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# ifdef _LARGEFILE64_SOURCE + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +/* hack for buggy compilers */ +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; +#endif + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/plugins/snes9x_gx/readme.txt b/plugins/snes9x_gx/readme.txt new file mode 100644 index 00000000..8134cb85 --- /dev/null +++ b/plugins/snes9x_gx/readme.txt @@ -0,0 +1,880 @@ +_____________________________________________________________________________ +|0O×øo· Snes9x GX ·oø×O0| +| http://code.google.com/p/snes9x-gx | +| (Under GPL License) | +|___________________________________________________________________________| + +Snes9x GX is a Super Nintendo™ / Super Famicom emulator for the Nintendo Wii. +Snes9x GX is a port of Snes9x (http://www.snes9x.com). + +Snes9x GX is a "homebrew application" which means you will need a way to run +unsigned code on your Nintendo Wii. The best website for getting started with +Wii homebrew is WiiBrew (www.wiibrew.org). + +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• +| FEATURES | +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• + +* Based on Snes9x 1.52 +* Wiimote, Nunchuk, Classic, and Gamecube controller support +* SNES Superscope, Mouse, Justifier support +* Cheat support +* Auto Load/Save Game Snapshots and SRAM +* Custom controller configurations +* SD, USB, DVD, SMB, Zip, and 7z support +* Autodetect PAL/NTSC, 16:9 widescreen support +* Original/filtered/unfiltered video modes +* Turbo Mode - up to 2x the normal speed +* Zoom option to zoom in/out +* Open Source! + +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• +| UPDATE HISTORY | +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• + +[4.3.4 - February 2, 2016] + +* Fixed screenshot image dimensions +* Fixed screenshot option, it no longer creates an additional "dummy" file +* Fixed performance issues, reverted to previous vsync method +* Compiled with devkitPPC r26 + Note: If compiled with devkitPPC r27 some games, like Final Fantasy III + and Chrono Trigger would crash on a battle + +[4.3.3 - September 3, 2015July 7, 2015] + +* Added Cebolleto's preview image support +* Added WiiUPro controller support +* Added a Scanline filter option +* Increase preview image size and reduce game list width +* Added a background to the preview image +* Added a Screenshot button +* Added a "WiiuPro" button on the button mapping menu +* Fixed the inverted color button selection that was in some option windows + +[4.3.2 - November 9, 2012] + +* Fixed lag with GameCube controllers + +[4.3.1 - July 7, 2012] + +* Fixed PAL support + +[4.3.0 - July 6, 2012] + +* Support for newer Wiimotes +* Fixed screen flicker when going back to menu +* Improved L/R buttons for GameCube - trigger button press when 50%+ depressed +* Improved controller behavior - allow two directions to be pressed simultaneously +* Timing changes +* Compiled with devkitPPC r26 and libogc 1.8.11 + +[4.2.9 - January 14, 2012] + +* More accurate pixel scaling (thanks eke-eke!) +* Other minor changes + +[4.2.8 - May 15, 2011] + +* Ported a few upstream game fixes for: Mutant Chronicles - Doom Troopers, + Porky Pig's Haunted Holiday, Big Sky Trooper, and Mechwarrior 3050 / Battle + Tech 3050 +* Added Turkish translation + +[4.2.7 - March 23, 2011] + +* Fixed browser regressions with stability and speed +* Reverted zones' changes to IRQ and SA-1 - these caused a performance hit + +[4.2.6 - March 19, 2011] + +* Improved game compatibility (updated core to latest Snes9x) +* Fixed issue with cheats not persisting +* Improved USB and controller compatibility (recompiled with latest libogc) +* Enabled SMB on GameCube (thanks Extrems!) +* Added Catalan translation +* Translation updates + +[4.2.5 - October 7, 2010] + +* Sync with upstream SVN - fixes a few specific game issues +* Fixed "blank listing" issue for SMB +* Improved USB compatibility and speed +* Added Portuguese and Brazilian Portuguese translations +* Other minor changes + +[4.2.4 - August 14, 2010] + +* IOS 202 support removed +* USB 2.0 support via IOS 58 added - requires that IOS58 be pre-installed +* DVD support via AHBPROT - requires latest HBC + +[4.2.3 - July 22, 2010] + +* Fixed broken auto-update + +[4.2.2 - July 20, 2010] + +* Reverted USB2 changes +* Fixed return-to-menu crash with Filtered mode + +[4.2.1 - July 14, 2010] + +* Improved audio timing +* Fixed 16:9 correction in Original mode +* Ability to use both USB ports (requires updated IOS 202 - WARNING: older + versions of IOS 202 are NO LONGER supported) +* Fixed issue with IPS patch files +* Hide non-ROM files +* Other minor improvements + +[4.2.0 - June 20, 2010] + +* Fixed incorrect aspect ratio issue +* Fixed choppy framerate issue +* Fixed IPS/UPS patching +* USB improvements +* GameCube improvements - audio, SD Gecko, show thumbnails for saves +* Other minor changes + +[4.1.9 - May 19, 2010] + +* DVD support fixed +* Fixed some cheats issues +* Fixed some potential hangs when returning to menu +* Video/audio code changes +* Fixed scrolling text bug +* Other minor changes + +[4.1.8 - April 9, 2010] + +* Fix auto-save bug + +[4.1.7 - April 9, 2010] + +* Freezing issue fixed +* Core timing fixes, should solve some problems with some games +* Most 3rd party controllers should work now (you're welcome!) +* 7z crash fixed +* GameCube only - DVD/SD Gecko fixed (thanks emukidid!) +* Translation updates (German and Dutch) +* Other minor changes + +[4.1.6 - March 30, 2010] + +* New core! Updated to Snes9x 1.52. Old save states will not work! +* DVD / USB 2.0 support via IOS 202. DVDx support has been dropped. It is + highly recommended to install IOS 202 via the included installer +* Multi-language support (only French translation is fully complete) +* Thank you to everyone who submitted translations +* SMB improvements/bug fixes +* Minor video & input performance optimizations +* Now uses .srm files without "Auto" appended, if found +* Added option to disable crosshair + +[4.1.5 - December 23, 2009] + +* Changed default folders to snes9xgx/roms and snes9xgx/saves. Old folders + will be automatically moved to the new location +* File browser now scrolls down to the last game when returning to browser +* Auto update for those using USB now works +* Fixed scrollbar up/down buttons +* Minor optimizations + +[4.1.4 - December 2, 2009] + +* Fixed SMB (for real this time!) +* Fixed snapshot loading regression + +[4.1.3 - November 30, 2009] + +* Fixed SMB +* Added separate horizontal/vertical zoom options +* Improved scrolling timing - the more you scroll, the fast it goes +* Fixed reset button on Wii console - now you can reset multiple times +* Minor code optimizations +* Reduce memory fragmentation - fixes out of memory crashes + +[4.1.2 - October 7, 2009] + +* Revamped filebrowser and file I/O +* Many, many other bug fixes + +[4.1.1 - September 19, 2009] + +* Fixed black screen bug + +[4.1.0 - September 16, 2009] + +* Text rendering corrections +* SMB improvements +* Built with latest libraries +* Video mode switching now works properly +* Other minor bugfixes and cleanup + +[4.0.9 - July 22, 2009] + +* Fixed "No game saves found." message when there are actually saves. +* Fixed shift key on keyboard +* Text scrolling works again +* Change default prompt window selection to "Cancel" button + +[4.0.8 - July 9, 2009] + +* Faster SMB/USB browsing +* Last browsed folder is now remembered +* Fixed controller mapping reset button +* Fixed no sound on GameCube version +* Directory names are no longer altered +* Preferences now only saved on exit +* Fixed on-screen keyboard glitches +* SRAM auto-saved on power-off from within a game +* Prevent 7z lockups, better 7z error messages +* Increase cheats limit from 30 to 150 +* Cheats no longer effect next game loaded - they are cleared properly + +[4.0.7 - June 30, 2009] + +* Fixed auto-update +* Increased file browser listing to 10 entries, decreased font size +* Added text scrolling on file browser +* Added reset button for controller mappings +* Settings are now loaded from USB when loading the app from USB on HBC +* Fixed menu crashes caused by ogg player bugs +* Fixed memory card saving verification bug +* Fixed game savebrowser bugs +* Miscellaneous code cleanup/corrections + +[4.0.6 - May 30, 2009] + +* Fixed SD/USB corruption bug +* SMB works again +* GUI bugs fixed, GUI behavioral improvements + +[4.0.5 - May 26, 2009] + +* Improved stability +* Fixed broken SDHC from HBC 1.0.2 update +* Fixed issues with returning to menu from in-game +* Add option to disable rumble +* Auto-determines if HBC is present - returns to Wii menu otherwise +* Fixed Super Scope turbo button issue +* Miscellaneous bugfixes + +[4.0.4 - April 30, 2009] + +* Improved scrollbar +* Built with more stable libogc/libfat +* Fixed rumble bug in filebrowser +* Added confirmation prompts +* Fixed settings saving glitches + +[4.0.3 - April 23, 2009] + +* Settings resetting glitch fixed + +[4.0.2 - April 22, 2009] + +* GameCube controller home trigger fixed +* USB support fixed +* More stable SMB support +* Corrections/improvements to game saving/loading +* Video mode corrections +* hq2x filter no longer crashes hi-res games on unfiltered/filtered modes +* Corrections to cheat file parsing +* Super Scope turbo now activated when holding Down button +* Settings are now saved when exiting game menu settings area +* Super Scope pause button now works +* Invalid VRAM access is now allowed - should fix some homebrew games +* New video mode selection in menu (forcing a video mode is not recommended) + +[4.0.1 - April 13, 2009] + +* Fixed turning off autosave in menu +* Keyboard fixed, more keys added +* Fixed 7z loading from DVD +* Enable auto loading and renaming of SRAM save without "Auto" in the name +* PAL resolution fixed - no more letterboxing +* File browser scrollbar box now draggable, arrow buttons now scroll list +* Better handling of multiple on-screen wiimotes +* Menu restructured - new "Game Settings" menu + +[4.0.0 - April 4, 2009] + +* New GX-based menu, with a completely redesigned layout. Has Wiimote IR + support, sounds, graphics, animation effects, and more +* Thanks to the3seashells for designing some top-notch artwork, to + Peter de Man for composing the music, and a special thanks to shagkur for + fixing libogc bugs that would have otherwise prevented the release +* Onscreen keyboard for changing save/load folders and network settings +* Menu configuration options (configurable exit button, wiimote orientation, + volumes) +* Configurable button mapping for superscope, mouse and justifier +* New save manager, allowing multiple saves and save browsing. Shows + screenshots for Snapshot saves, and save dates/times +* Experimental hq2x filter, contributed by michniewski + +[009 - January 27, 2009] + +* Faster SD/USB - new read-ahead cache +* Removed trigger of back to menu for Classic Controller right joystick +* Fixed a bug with reading files < 2048 bytes +* Fixed some memory leaks, buffer overflows, etc +* Code cleanup, other general bugfixes + +[008 - December 24, 2008] + +* Fixed unstable SD card access +* Proper SD/USB hotswap (Wii only) +* Auto-update feature (Wii only) +* Rewritten SMB access - speed boost, NTLM now supported (Wii only) +* Improved file access code +* Resetting preferences now resets controls +* Fixed "invalid file size" error on smaller games (eg: Space Invaders) +* Fixed hangup in Super Mario RPG +* Minor bug fixes + +[007 - November 19, 2008] + +* added: SDHC support +* added: SD/USB hot-swapping +* added: zoom saving +* added: IPS/UPS/PPF patch support +* added: Qoob modchip support (thanks emukidid!) +* added: Added console/remote power button support (Wii only) +* added: Added reset button support - resets game (Wii only) +* changed: Settings file is now named settings.xml and is stored in the same + folder as the DOL - eg: apps/Snes9xGX/settings.xml (Wii only) +* fixed: swc, sfc file support +* fixed: inverted sound channels +* fixed: some game crashes +* fixed: snapshot saving for games with SPC7110, BS, DSP, or CX4 +* fixed: justifier support +* fixed: superscope turbo button +* fixed: widescreen support +* fixed: ActRaiser 2 issues +* fixed: Invalid memory accesses in C4 and OBC1. MMX3 Toxic Seahorse stage + now can be emulated with HDMA. (zones) +* fixed: Updated snapshot to prevent desync. Added some variables related to + APU and HDMA. (gocha) +* fixed: zoom issues (thanks eke-eke!) +* fixed: original modes (thanks eke-eke!) +* fixed: vertical scaling for filtered/unfiltered modes (thanks eke-eke!) + +[006 - October 15, 2008] + +Tantric +* added: 480p for GameCube +* added: Sound sync +* added: 7z support +* changed: Faster SD/USB access (readahead cache enabled) +* fixed: Video offset issues +* fixed: BS-X games work now +* fixed: Wii DVD works now +* fixed: DVD re-enabled for GameCube +* fixed: Nunchuk analog stick issues +* fixed: Many crashes, memory leaks, etc + +michniewski +* added: Video shift options +* changed: Turn DVD motor off option re-enabled for GameCube + +[005 - September 23, 2008] + +michniewski +* added: Superscope/mouse/justifier support, with Wii remote +* added: 3 render modes - Original, Filtered, Unfiltered +* added: widescreen compensation option +* added: DVD support on the Wii +* changed: zoom - limited range, added reset zoom option + +Tantric +* added: now uses SNES 1.51 core (thanks to eke-eke for help with this) +* added: cheats menu! Loads .CHT file from /snes9x/cheats folder, + .CHT file name must match file name of ROM +* added: load/save preference selector. ROM, SRAM, Freeze, and preferences + are saved/loaded according to these +* added: preliminary Windows file share loading/saving (SMB) support on Wii: + You can input your network settings into snes9xGX.xml, or edit + s9xconfig.cpp from the source code and compile. +* added: 'Auto' settings for save/load - attempts to automatically determine + your load/save device(s) - SD, USB, Memory Card, DVD, SMB +* added: ROM Information page +* added: Game Menu - all game-specific options are here now: + SRAM save/load, Snapshot save/load, game reload, etc +* added: Credits page +* fixed: sd gecko works now +* fixed: full USB support +* changed: menu structure +* changed: preferences are now loaded and saved in XML format. You can open + snes9xGX.xml edit all settings, including some not available within + the program +* changed: if Home button is pressed when a game is running, Game Menu pops up +* changed: if preferences can't be loaded at the start and/or are reset, + preferences menu pops up - remove to save your preferences! +* changed: SRAM load - game reloaded automatically after loading SRAM + +[004 - August 5, 2008] + +* added: option to disable AA filtering + (snes graphics 'crisper', AA now default OFF) +* added: mapped zooming and turbo mode to classic controller +* added: preliminary usb support (loading) +* changed: sram and freezes now saved by filename, not internal romname. + If you have multiple versions of the same game, you can now have + srams and freezes for each version. A prompt to convert to the + new naming is provided for sram only. +* changed: by default, autoload/save sram and freeze enabled + +[003 - July 25, 2008] +* added: alphabetical file sorting +* added: background logo/backdrop + nicer menus +* added: scrolling in ROM selector +* fixed: switching between pal/ntsc ROMS doesn't mess up timings +* fixed: GC controller config works now +* fixed: freeze autoloading on ROM load +* fixed: zipped ROMS should now load in a reasonable time +* fixed: precompiled dols for autosaving to various locations (see readme) +* changed: GC default quickload slot (to sd) (thanks kerframil) +* changed: default load/save dirs are now "/snes9x/roms" and + "/snes9x/saves/" (thanks kerframil) +* changed: Classic X and Y defaults aren't switched +* changed: if autosave is enabled, it doesn't ask to save SRAM + anymore. It is saved in the background. +* updated README + +[002 - July 21, 2008] +* added: classic and nunchuk support +* added: all controllers can now be configured +* added: GC version (untested) +* changed: mappings are no longer stored in SRAM, but in config file. + This means no per-game configurations, but one global + config per controller. +* one makefile to make all versions. (thanks to snes9x143 SVN) + + +[001 - July 12, 2008] +* compiles with latest devkitppc (r15) +* now uses libfat (can use front sd slot on wii) +* updated menu items a bit +* wiimote support +* fixed: autoload sram/freeze +* fixed: rom plays immediately after loading + +[older update history at the bottom] + +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• +| INSTALLATION | +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• + +To install Snes9x GX you will need to copy over the "apps" and "snes9xgx" +folders (directories) from this archive to your SD Card. It comes +pre-packaged in the Homebrew Channel format (which you will use to launch +the emulator). Once you've copied the directories to your SD Card you will +need to place your ROM image(s) into "\snes9xgx\roms" directory and place any +cheat code files (optional) in the "\snes9xgx\cheats" directory. Once this is +done you can proceed to run the emulator via the Homebrew Channel. + +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• +| INITIAL SETUP | +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• + +The first time you run Snes9x GX it will create a new "settings.xml" file on +the SD Card which stores the configuration of the emulator. So when you run +Snes9x GX it will automatically detect your storage medium and will bring you +to the ROM selection screen. If you want to run a game with the default +settings then just highlight the game and press "A" on it and it will load. +However, you can configure Snes9x GX to your liking. + +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• +| CONFIGURATION | +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• + +To configure Snes9x GX press "A" on the "Settings" box. This will brings up +the "Settings" screen where you can configure the Button Mappings, Video, +Saving, Menu and Network. You can also restore the settings to their initial +values by clicking on the "Reset Settings" and you can return to the ROM +selection screen by clicking on "Go Back". + +--•[ Button Mappings ]•-- + +Once in the Button Mappings settings menu you'll have the option to pick to +configure the SNES Controller, Super Scope, SNES Mouse and the Justifier. +Once you select a controller to configure you will be presented with which +input device you would like to configure. To set the button simply click on +the input device you wish to use and then pick the button you wish to map. +After you select a button to configure Snes9x GX will prompt you to press +the button you wish to assign to the button you've selected. Below is a list +of each controller followed by the input devices and the default values for +those devices. + + [ SNES Controller ] + + • GameCube Controller + + A = A + B = B + X = X + Y = Y + L = L + R = R + START = START + SELECT = Z + UP = UP + DOWN = DOWN + LEFT = LEFT + RIGHT = RIGHT + + • Wiimote + + A = B + B = 2 + X = 1 + Y = A + START = PLUS + SELECT = MINUS + UP = UP + DOWN = DOWN + LEFT = LEFT + RIGHT = RIGHT + + • Classic Controller + + A = A + B = B + X = X + Y = Y + L = L + R = R + UP = UP + DOWN = DOWN + LEFT = LEFT + RIGHT = RIGHT + + • Wiimote Nunchuck + Wiimote + + A = A + B = B + X = C + Y = Z + L = 2 + R = 1 + START = PLUS + SELECT = MINUS + UP = UP + DOWN = DOWN + LEFT = LEFT + RIGHT = RIGHT + + [ Super Scope ] + + • GameCube Controller + + FIRE = A + AIM OFFSCREEN = B + CURSOR = Z + TURBO ON = Y + TURBO OFF = X + PAUSE = START + + • Wiimote + + FIRE = B + AIM OFFSCREEN = A + CURSOR = MINUS + TURBO ON = UP + TURBO OFF = DOWN + PAUSE = PLUS + + [ SNES Mouse ] + + • GameCube Controller + + LEFT BUTTON = A + RIGHT BUTTON = B + + • Wiimote + + LEFT BUTTON = A + RIGHT BUTTON = B + + [ Justifier ] + + • GameCube Controller + + FIRE = B + AIM OFFSCREEN = A + START = START + + • Wiimote + + FIRE = B + AIM OFFSCREEN = A + START = PLUS + +--•[ VIDEO ]•-- + +The Video settings screen will allow you to configure various video settings +including the Rendering method, Scaling, Filtering, Screen Zoom and Screen +Position. You can toggle the options for the first three selections by +clicking on them. To make the Filtering option you select you must enable +Filtering under the Rendering setting. + +• Rendering - Unfiltered + - Original + - Filtered + +• Scaling - Default + - 16:9 Correction + +• Filtering - None + - hq2x + - hq2x Soft + - hq2x Bold + +Screen Zoom will bring up a menu where you can adjust the Zoom level by using +the left and right arrows that you can click on. The default setting is 100%. + +The Screen Position option will bring up a screen with four arrows that +allows you to move the position of the output. You'll only need to use this +option if the screen is not centered. Combining this with the Zoom and +Scaling you should be able to get a proper display on your television. + +--•[ SAVING & LOADING ]•-- + +From this setup option you can configure the way Snes9x GX loads and saves. +Your options are Load Method, Load Folder, Save Method, Save Folder, Auto +Load and Auto Save. Clicking on all of the options except the folders will +let you toggle through their settings. Clicking on the folder options will +bring up a text box where you can enter in the folder you wish to use for +your save data. Snes9x GX has two types of saves - one is the SRAM which is +the save game data (this is only applicable if the game you're playing +supports saving) and the other is Snapshots which are real time saves. Real +time saves allow you to save your game in it's current state and resume it +at a later time. + + • Load Method - SD, USB, DVD, Network and Auto + + • Save Method - SD, USB, Network and Auto + + • Auto Load - SRAM, Snapshot and Off + + • Auto Save - SRAM, Snapshot and Off + +--•[ MENU ]•-- + +This settings screen will allow you to customize a few aspects on how the +Menu works including the Exit Action, Wiimote Orientation, Music Volume and +the Sound Effects Volume. The Exit Action can be set to "Return to Loader", +"Return to Wii Menu" and "Power off Wii". The Wiimote Orientation can be set +to Vertical or Horizontal and then you can increase and decrease the Music +and Sound Effects Volume. + +--•[ NETWORK ]•-- + +If you're going to be using your Network (LAN) to load and/or save from you +will need to enter in the SMB share settings you've setup on your computer +via this settings menu. You will need to enter in the SMB Share IP, Share +Name, Share Username and Share Password. If you do not have a password on +your SMB share then set the SMB Share Password to "0". + +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• +| FILE BROWSER | +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• + +The File Browser will automatically load when you start the emulator and it +will automatically list the contents of the "\snes9xgx\roms\" directory on +your SD card. Like mentioned above in the Configuration -> Saving & Loading +you can specifically a different directory to load from. To launch a game +(the game can either be uncompressed or inside a ZIP archive) simply click +on it and it will load. You may also change the directory you're in by +clicking on "Up One Level". + +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• +| GAMEPLAY | +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• + +Once you load a game you can access another option menu by pressing the +"Home" button. This will bring up the Save, Load, Reset, Controller and +Cheats options. From this menu you can also return to the File Browser by +selecting "Main Menu". To leave the menu and resume game play select "Close". + +The Save option will allow you to save either your SRAM or a Snapshot. Once +you've selected Save two options will appear named "New SRAM" and "New +Snapshot". Clicking on these will create a new save. Once you have a save +you can save over it by selecting it instead of a "New" option. The Load +option will allow you to load your saved SRAM or Snapshot. Reset will reset +the game. If you pick Controller you can toggle between which controller you +wish to use to control your game with. The last option, Cheats, will allow you +to toggle your cheat codes (see below). + +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• +| CHEATS | +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• + +Cheats are loaded from the "\snes9xgx\cheats" directory and must be in the +SNES9X .CHT file format. They also must be named the same name as the game +you're playing with the .cht extentsion. An example would be if you have a +ROM called "Super Mario World.smc" you would need to name your .cht file to +"Super Mario World.cht". You can find a link to a massive collection of Super +NES cheat codes in the Links section (below). + +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• +| TURBO MODE | +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• + +TurboMode increases the playback speed of the game by about 2x. To use +TurboMode simply press the c-stick (yellow control stick) to the right and +hold it right as long as you want playback to be double-speed. Release the +c-stick when you want normal playback speed to resume. + +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• +| IMPORTING AND EXPORTING SRAM | +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• + +Snes9x GX now includes the ability to load SRAM from Snes9x on other +platforms (Mac/PC/Linux/etc) and to save back to those platforms. + +To load a SRAM file on the Wii or Gamecube from another platform, ensure the +name of the SRM file matches the filename of the ROM (except with an SRM +extension). + +To use a Wii/GameCube SRAM file on another platform just do the opposite: +copy the saved SRAM file to the other platform. You may have to rename the +file to be what that version of snes9x expects it to be. + +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• +| UPDATE HISTORY (OLD) | +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• + +[2.0.1b8] +* Added: SD slot B options for freezes, sram and loading of roms +* Changed: SMB options no longer displayed in menus when run on a Wii +* Changed: Game auto resumes running after resetting when choosing the "Reset + Game" menu option +* Fixed (maybe): Reading of DVDs past the 1.36 GB barrier (Wii only) please + test! - svpe + +[2.0.1b7] +* Fixed: Zip compressed freezes to memory card could become corrupted as the + file size changed - fixed this by deleting the existing file before writing + a new one if the file size increased. If the file got smaller or stayed the + same the original file is updated, using less of the existing file if the + actual file size is smaller. A check is made before deleting the existing + freeze file to ensure that there is enough space available for the new + file. Note that additional space equivalent to the new file size must be + available. If not enough space is available the original freeze is retained + and the user is informed of the lack of space. +* Fixed: If option to auto-load freeze was selected, joypad config would not + be restored since that is stored in SRAM. Resolved this for now by first + loading SRAM if any and then loading the freeze. Obviously having to have + both SRAM and freeze is not ideal, but this gets the job done if you have + enough space on your memory card, SD card, etc. +* Added prompt when returning to the menu with autosave enabled allowing the + user choose whether or not to perform the save. Press A to save or B if you + don't wish to save. +* Added optional verification of Gamecube memory card saves. After writing + the file it reads it back in and verifies that the written file matches + what was to be saved. If it doesn't or if there was a problem opening the + file it reports the problem to the user. Set this option in the preferences + if desired. +* Added Reset Gamecube/Wii menu item +* Experimental DVD support for reading beyond 1.36 GB barrier on Wii. I have + no way to test this, so please report on whether or not it works! Based on + svpe's code. + +NOTE: due to changes in the settings, this version will reset your emulator +options settings, so if you had saved preferences you will need to make your +changes to the emulator settings again and save them. + +[2.0.1b6a] +* Fixed: Going up a directory when selecting a rom on a DVD wasn't working + +[2.0.1b6] +* PAL Wii support - no separate version necessary! - eke-eke +* PAL roms now play at correct speed via internal timer, ntsc roms still use + more accurate VSYNC timing - eke-eke +* Zipped freezes to memory card - take 9-12 blocks or so - based on denman's + code +* Added option for auto save and load of freezes. For saving, can do both SRAM + and Freeze if desired +* Memory card saving and loading shows a progress bar +* More miscellaneous ease-of-use improvements and cleanup +* Fixed: pressing B to get out of a rom file selection screen no longer drops + you all the way back to the main menu. Now goes back to choice of where to + load ROM (the "Load from DVD", "Load from SMB"... screen) +* Fixed: loading of joypad configuration in SRAM works again - no longer gets + messed up + +[2.0.1b5] +* B button implemented in all menus (returns to previous menu) +* Fixed bug when freezing state to SD card - would crash if SD support was not + previously initialized +* Fixed double A button press needed after manual prefs/sram save to memory card +* Fixed delay after pressing A button after saving freeze to SD card +* Fixed problem of ".srm" SRAM file being created when SRAM was saved with no + ROM loaded +* Fixed version number in SRAM and preferences +* Minor other code revisions + +[2.0.1b1 through 2.0.1b4] +* SRAM saving and loading from snes9x on other platforms via SD card or SMB +* Games now autostart once loaded +* After manually loading SRAM the emulator is automatically reset +* Optional auto-loading of SRAM from memory card, SD or SMB after game loads +* Optional auto-saving of SRAM to memory card, SD or SMB when returning to menu +* TurboMode +* Global emulator preferences +* Menus redesigned (hopefully for the better!) +* Comes in 6 variants, each auto-loading/saving preferences/sram to a different + location: mcslota, mcslotb, sdslota, sdslotb, smb, and noload +* ROM injector works again +* A number of small improvements and bug fixes + +[2.0 WIP6] +* Port of SNES9X 1.50 +* SMB support +* SD support +* Greatly improved emulation and timing for NTSC roms +* Save states (freezes) to SD and SMB +* Screen zoom +* Improved font and display +* ROM injector +* ... and more ... + +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• +| CREDITS | +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• + + Coding & menu design Tantric + Additional coding michniewski + Menu artwork the3seashells + Menu sound Peter de Man + + ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ + Snes9x GX GameCube SoftDev, crunchy2, + eke-eke, others + + Snes9x Snes9x Team + libogc/devkitPPC shagkur & wintermute + FreeTypeGX Armin Tamzarian + +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• +| LINKS | +•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————• + + SNES9X GX Project Page + http://code.google.com/p/snes9x-gx + + Wii Homebrew Community + www.wiibrew.org + + Free (Public Domain) ROMs + www.pdroms.de + + Cheat Codes + www.cheatzilla.com + +×—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬ +|0O×øo· ·oø×O0| +`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨' \ No newline at end of file diff --git a/plugins/snes9x_gx/source/audio.cpp b/plugins/snes9x_gx/source/audio.cpp new file mode 100644 index 00000000..1667ed9e --- /dev/null +++ b/plugins/snes9x_gx/source/audio.cpp @@ -0,0 +1,166 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * Tantric 2008-2010 + * + * audio.cpp + * + * Audio driver + * Audio is fixed to 32Khz/16bit/Stereo + ***************************************************************************/ + +#include <gccore.h> +#include <ogcsys.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <asndlib.h> + +#include "video.h" + +#include "snes9x/snes9x.h" +#include "snes9x/memmap.h" +#include "snes9x/cpuexec.h" +#include "snes9x/ppu.h" +#include "snes9x/apu/apu.h" +#include "snes9x/display.h" +#include "snes9x/gfx.h" +#include "snes9x/spc7110.h" +#include "snes9x/controls.h" + +extern int ConfigRequested; + +/*** Double buffered audio ***/ +#define AUDIOBUFFER 2048 +static unsigned char soundbuffer[2][AUDIOBUFFER] __attribute__ ((__aligned__ (32))); +static int whichab = 0; /*** Audio buffer flip switch ***/ + +#define AUDIOSTACK 16384 +static lwpq_t audioqueue; +static lwp_t athread; +static uint8 astack[AUDIOSTACK]; +static mutex_t audiomutex = LWP_MUTEX_NULL; + +/**************************************************************************** + * Audio Threading + ***************************************************************************/ +static void * +AudioThread (void *arg) +{ + LWP_InitQueue (&audioqueue); + + while (1) + { + if (ConfigRequested) + memset (soundbuffer[whichab], 0, AUDIOBUFFER); + else + { + LWP_MutexLock(audiomutex); + S9xMixSamples (soundbuffer[whichab], AUDIOBUFFER >> 1); + LWP_MutexUnlock(audiomutex); + } + DCFlushRange (soundbuffer[whichab], AUDIOBUFFER); + LWP_ThreadSleep (audioqueue); + } + + return NULL; +} + +/**************************************************************************** + * MixSamples + * This continually calls S9xMixSamples On each DMA Completion + ***************************************************************************/ +static void +GCMixSamples () +{ + if (!ConfigRequested) + { + whichab ^= 1; + AUDIO_InitDMA ((u32) soundbuffer[whichab], AUDIOBUFFER); + LWP_ThreadSignal (audioqueue); + } +} + +static void FinalizeSamplesCallback (void *data) +{ + LWP_MutexLock(audiomutex); + S9xFinalizeSamples(); + LWP_MutexUnlock(audiomutex); +} + +/**************************************************************************** + * InitAudio + ***************************************************************************/ +void +InitAudio () +{ + #ifdef NO_SOUND + AUDIO_Init (NULL); + AUDIO_SetDSPSampleRate(AI_SAMPLERATE_32KHZ); + AUDIO_RegisterDMACallback(GCMixSamples); + #else + ASND_Init(); + #endif + LWP_MutexInit(&audiomutex, false); + LWP_CreateThread (&athread, AudioThread, NULL, astack, AUDIOSTACK, 70); +} + +/**************************************************************************** + * SwitchAudioMode + * + * Switches between menu sound and emulator sound + ***************************************************************************/ +void +SwitchAudioMode(int mode) +{ + if(mode == 0) // emulator + { + #ifndef NO_SOUND + ASND_Pause(1); + AUDIO_StopDMA(); + AUDIO_SetDSPSampleRate(AI_SAMPLERATE_32KHZ); + AUDIO_RegisterDMACallback(GCMixSamples); + #endif + memset(soundbuffer[0],0,AUDIOBUFFER); + memset(soundbuffer[1],0,AUDIOBUFFER); + DCFlushRange(soundbuffer[0],AUDIOBUFFER); + DCFlushRange(soundbuffer[1],AUDIOBUFFER); + AUDIO_InitDMA((u32)soundbuffer[whichab],AUDIOBUFFER); + AUDIO_StartDMA(); + + S9xSetSamplesAvailableCallback(FinalizeSamplesCallback, NULL); + } + else // menu + { + S9xSetSamplesAvailableCallback(NULL, NULL); + #ifndef NO_SOUND + ASND_Init(); + ASND_Pause(0); + #else + AUDIO_StopDMA(); + #endif + } +} + +/**************************************************************************** + * ShutdownAudio + * + * Shuts down audio subsystem. Useful to avoid unpleasant sounds if a + * crash occurs during shutdown. + ***************************************************************************/ +void ShutdownAudio() +{ + AUDIO_StopDMA(); +} + +/**************************************************************************** + * AudioStart + * + * Called to kick off the Audio Queue + ***************************************************************************/ +void +AudioStart () +{ + GCMixSamples (); +} diff --git a/plugins/snes9x_gx/source/audio.h b/plugins/snes9x_gx/source/audio.h new file mode 100644 index 00000000..4f09cfd3 --- /dev/null +++ b/plugins/snes9x_gx/source/audio.h @@ -0,0 +1,16 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * Tantric 2008-2010 + * + * audio.h + * + * Audio driver + * Audio is fixed to 32Khz/16bit/Stereo + ***************************************************************************/ + +void InitAudio (); +void AudioStart (); +void SwitchAudioMode(int mode); +void ShutdownAudio(); diff --git a/plugins/snes9x_gx/source/button_mapping.c b/plugins/snes9x_gx/source/button_mapping.c new file mode 100644 index 00000000..b3c5ff19 --- /dev/null +++ b/plugins/snes9x_gx/source/button_mapping.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * michniewski August 2008 + * Tantric 2008-2010 + * + * button_mapping.c + * + * Controller button mapping + ***************************************************************************/ + +#include <gccore.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ogcsys.h> +#include <unistd.h> +#include <wiiuse/wpad.h> + +#include "button_mapping.h" + +/**************************************************************************** + * Controller Button Descriptions: + * used for identifying which buttons have been pressed when configuring + * and for displaying the name of said button + ***************************************************************************/ + +CtrlrMap ctrlr_def[4] = { +// Gamecube controller btn def +{ + CTRLR_GCPAD, + 13, + { + {PAD_BUTTON_DOWN, "DOWN"}, + {PAD_BUTTON_UP, "UP"}, + {PAD_BUTTON_LEFT, "LEFT"}, + {PAD_BUTTON_RIGHT, "RIGHT"}, + {PAD_BUTTON_A, "A"}, + {PAD_BUTTON_B, "B"}, + {PAD_BUTTON_X, "X"}, + {PAD_BUTTON_Y, "Y"}, + {PAD_BUTTON_MENU, "START"}, + {PAD_BUTTON_START, "START"}, + {PAD_TRIGGER_L, "L"}, + {PAD_TRIGGER_R, "R"}, + {PAD_TRIGGER_Z, "Z"}, + {0, ""}, + {0, ""} + } +}, +// Wiimote btn def +{ + CTRLR_WIIMOTE, + 11, + { + {WPAD_BUTTON_DOWN, "DOWN"}, + {WPAD_BUTTON_UP, "UP"}, + {WPAD_BUTTON_LEFT, "LEFT"}, + {WPAD_BUTTON_RIGHT, "RIGHT"}, + {WPAD_BUTTON_A, "A"}, + {WPAD_BUTTON_B, "B"}, + {WPAD_BUTTON_1, "1"}, + {WPAD_BUTTON_2, "2"}, + {WPAD_BUTTON_PLUS, "PLUS"}, + {WPAD_BUTTON_MINUS, "MINUS"}, + {WPAD_BUTTON_HOME, "HOME"}, + {0, ""}, + {0, ""}, + {0, ""}, + {0, ""} + } +}, +// Nunchuk btn def +{ + CTRLR_NUNCHUK, + 13, + { + {WPAD_BUTTON_DOWN, "DOWN"}, + {WPAD_BUTTON_UP, "UP"}, + {WPAD_BUTTON_LEFT, "LEFT"}, + {WPAD_BUTTON_RIGHT, "RIGHT"}, + {WPAD_BUTTON_A, "A"}, + {WPAD_BUTTON_B, "B"}, + {WPAD_BUTTON_1, "1"}, + {WPAD_BUTTON_2, "2"}, + {WPAD_BUTTON_PLUS, "PLUS"}, + {WPAD_BUTTON_MINUS, "MINUS"}, + {WPAD_BUTTON_HOME, "HOME"}, + {WPAD_NUNCHUK_BUTTON_Z, "Z"}, + {WPAD_NUNCHUK_BUTTON_C, "C"}, + {0, ""}, + {0, ""} + } +}, +// Classic btn def +{ + CTRLR_CLASSIC, + 15, + { + {WPAD_CLASSIC_BUTTON_DOWN, "DOWN"}, + {WPAD_CLASSIC_BUTTON_UP, "UP"}, + {WPAD_CLASSIC_BUTTON_LEFT, "LEFT"}, + {WPAD_CLASSIC_BUTTON_RIGHT, "RIGHT"}, + {WPAD_CLASSIC_BUTTON_A, "A"}, + {WPAD_CLASSIC_BUTTON_B, "B"}, + {WPAD_CLASSIC_BUTTON_X, "X"}, + {WPAD_CLASSIC_BUTTON_Y, "Y"}, + {WPAD_CLASSIC_BUTTON_PLUS, "PLUS"}, + {WPAD_CLASSIC_BUTTON_MINUS, "MINUS"}, + {WPAD_CLASSIC_BUTTON_HOME, "HOME"}, + {WPAD_CLASSIC_BUTTON_FULL_L, "L"}, + {WPAD_CLASSIC_BUTTON_FULL_R, "R"}, + {WPAD_CLASSIC_BUTTON_ZL, "ZL"}, + {WPAD_CLASSIC_BUTTON_ZR, "ZR"} + } +} +}; diff --git a/plugins/snes9x_gx/source/button_mapping.h b/plugins/snes9x_gx/source/button_mapping.h new file mode 100644 index 00000000..ed5ee1f0 --- /dev/null +++ b/plugins/snes9x_gx/source/button_mapping.h @@ -0,0 +1,39 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * michniewski August 2008 + * Tantric 2008-2010 + * + * button_mapping.h + * + * Controller button mapping + ***************************************************************************/ + +#ifndef BTN_MAP_H +#define BTN_MAP_H + +enum { + CTRLR_NONE = -1, + CTRLR_GCPAD, + CTRLR_WIIMOTE, + CTRLR_NUNCHUK, + CTRLR_CLASSIC +}; + +const char ctrlrName[4][20] = +{ "GameCube Controller", "Wiimote", "Nunchuk + Wiimote", "Classic Controller" }; + +typedef struct _btn_map { + u32 btn; // button 'id' + char* name; // button name +} BtnMap; + +typedef struct _ctrlr_map { + u16 type; // controller type + int num_btns; // number of buttons on the controller + BtnMap map[15]; // controller button map +} CtrlrMap; + +extern CtrlrMap ctrlr_def[4]; + +#endif diff --git a/plugins/snes9x_gx/source/cheatmgr.cpp b/plugins/snes9x_gx/source/cheatmgr.cpp new file mode 100644 index 00000000..738cb3c8 --- /dev/null +++ b/plugins/snes9x_gx/source/cheatmgr.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * Tantric 2008-2010 + * + * cheatmgr.cpp + * + * Cheat handling + ***************************************************************************/ + + +#include "port.h" +#include "cheats.h" + +#include "snes9xgx.h" +#include "fileop.h" +#include "filebrowser.h" + +extern SCheatData Cheat; + +/**************************************************************************** + * LoadCheatFile + * + * Loads cheat file from save buffer + * Custom version of S9xLoadCheatFile() + ***************************************************************************/ + +static bool LoadCheatFile (int length) +{ + uint8 data [28]; + int offset = 0; + + while (offset < length) + { + if(Cheat.num_cheats >= MAX_CHEATS || (length - offset) < 28) + break; + + memcpy (data, savebuffer+offset, 28); + offset += 28; + + Cheat.c [Cheat.num_cheats].enabled = 0; // cheats always off + Cheat.c [Cheat.num_cheats].byte = data [1]; + Cheat.c [Cheat.num_cheats].address = data [2] | (data [3] << 8) | (data [4] << 16); + Cheat.c [Cheat.num_cheats].saved_byte = data [5]; + Cheat.c [Cheat.num_cheats].saved = (data [0] & 8) != 0; + memcpy (Cheat.c [Cheat.num_cheats].name, &data[8], 20); + Cheat.c [Cheat.num_cheats].name[20] = 0; + Cheat.num_cheats++; + } + return true; +} + +/**************************************************************************** + * SetupCheats + * + * Erases any prexisting cheats, loads cheats from a cheat file + * Called when a ROM is first loaded + ***************************************************************************/ +void +WiiSetupCheats() +{ + memset(Cheat.c, 0, sizeof(Cheat.c)); + Cheat.num_cheats = 0; + + char filepath[1024]; + int offset = 0; + + if(!MakeFilePath(filepath, FILE_CHEAT)) + return; + + AllocSaveBuffer(); + + offset = LoadFile(filepath, SILENT); + + // load cheat file if present + if(offset > 0) + LoadCheatFile (offset); + + FreeSaveBuffer (); +} diff --git a/plugins/snes9x_gx/source/filebrowser.cpp b/plugins/snes9x_gx/source/filebrowser.cpp new file mode 100644 index 00000000..88b2a08b --- /dev/null +++ b/plugins/snes9x_gx/source/filebrowser.cpp @@ -0,0 +1,666 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * svpe June 2007 + * crunchy2 May-July 2007 + * Michniewski 2008 + * Tantric 2008-2010 + * + * filebrowser.cpp + * + * Generic file routines - reading, writing, browsing + ***************************************************************************/ + +#include <gccore.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wiiuse/wpad.h> +#include <sys/dir.h> +#include <malloc.h> + +#ifdef HW_RVL +#include <di/di.h> +#endif + +#include "snes9xgx.h" +#include "filebrowser.h" +#include "menu.h" +#include "video.h" +#include "networkop.h" +#include "fileop.h" +#include "input.h" +#include "gcunzip.h" +#include "freeze.h" +#include "sram.h" + +#include "snes9x/snes9x.h" +#include "snes9x/memmap.h" +#include "snes9x/cheats.h" + +BROWSERINFO browser; +BROWSERENTRY * browserList = NULL; // list of files/folders in browser + +static char szpath[MAXPATHLEN]; +char szname[MAXPATHLEN]; +bool inSz = false; + +unsigned long SNESROMSize = 0; +bool loadingFile = false; + +/**************************************************************************** +* autoLoadMethod() +* Auto-determines and sets the load device +* Returns device set +****************************************************************************/ +int autoLoadMethod() +{ + ShowAction ("Attempting to determine load device..."); + + int device = DEVICE_AUTO; + + if(ChangeInterface(DEVICE_SD, SILENT)) + device = DEVICE_SD; + else if(ChangeInterface(DEVICE_USB, SILENT)) + device = DEVICE_USB; + else if(ChangeInterface(DEVICE_SD_SLOTA, SILENT)) + device = DEVICE_SD_SLOTA; + else if(ChangeInterface(DEVICE_SD_SLOTB, SILENT)) + device = DEVICE_SD_SLOTB; + else if(ChangeInterface(DEVICE_DVD, SILENT)) + device = DEVICE_DVD; + else if(ChangeInterface(DEVICE_SMB, SILENT)) + device = DEVICE_SMB; + else + ErrorPrompt("Unable to locate a load device!"); + + if(GCSettings.LoadMethod == DEVICE_AUTO) + GCSettings.LoadMethod = device; // save device found for later use + CancelAction(); + return device; +} + +/**************************************************************************** +* autoSaveMethod() +* Auto-determines and sets the save device +* Returns device set +****************************************************************************/ +int autoSaveMethod(bool silent) +{ + if(!silent) + ShowAction ("Attempting to determine save device..."); + + int device = DEVICE_AUTO; + + if(ChangeInterface(DEVICE_SD, SILENT)) + device = DEVICE_SD; + else if(ChangeInterface(DEVICE_USB, SILENT)) + device = DEVICE_USB; + else if(ChangeInterface(DEVICE_SD_SLOTA, SILENT)) + device = DEVICE_SD_SLOTA; + else if(ChangeInterface(DEVICE_SD_SLOTB, SILENT)) + device = DEVICE_SD_SLOTB; + else if(ChangeInterface(DEVICE_SMB, SILENT)) + device = DEVICE_SMB; + else if(!silent) + ErrorPrompt("Unable to locate a save device!"); + + if(GCSettings.SaveMethod == DEVICE_AUTO) + GCSettings.SaveMethod = device; // save device found for later use + + CancelAction(); + return device; +} + +/**************************************************************************** + * ResetBrowser() + * Clears the file browser memory, and allocates one initial entry + ***************************************************************************/ +void ResetBrowser() +{ + browser.numEntries = 0; + browser.selIndex = 0; + browser.pageIndex = 0; + browser.size = 0; +} + +bool AddBrowserEntry() +{ + if(browser.size >= MAX_BROWSER_SIZE) + { + ErrorPrompt("Out of memory: too many files!"); + return false; // out of space + } + + memset(&(browserList[browser.size]), 0, sizeof(BROWSERENTRY)); // clear the new entry + browser.size++; + return true; +} + +/**************************************************************************** + * CleanupPath() + * Cleans up the filepath, removing double // and replacing \ with / + ***************************************************************************/ +static void CleanupPath(char * path) +{ + if(!path || path[0] == 0) + return; + + int pathlen = strlen(path); + int j = 0; + for(int i=0; i < pathlen && i < MAXPATHLEN; i++) + { + if(path[i] == '\\') + path[i] = '/'; + + if(j == 0 || !(path[j-1] == '/' && path[i] == '/')) + path[j++] = path[i]; + } + path[j] = 0; +} + +bool IsDeviceRoot(char * path) +{ + if(path == NULL || path[0] == 0) + return false; + + if( strcmp(path, "sd:/") == 0 || + strcmp(path, "usb:/") == 0 || + strcmp(path, "dvd:/") == 0 || + strcmp(path, "smb:/") == 0 || + strcmp(path, "carda:/") == 0 || + strcmp(path, "cardb:/") == 0) + { + return true; + } + return false; +} + +/**************************************************************************** + * UpdateDirName() + * Update curent directory name for file browser + ***************************************************************************/ +int UpdateDirName() +{ + int size=0; + char * test; + char temp[1024]; + int device = 0; + + if(browser.numEntries == 0) + return 1; + + FindDevice(browser.dir, &device); + + /* current directory doesn't change */ + if (strcmp(browserList[browser.selIndex].filename,".") == 0) + { + return 0; + } + /* go up to parent directory */ + else if (strcmp(browserList[browser.selIndex].filename,"..") == 0) + { + // already at the top level + if(IsDeviceRoot(browser.dir)) + { + browser.dir[0] = 0; // remove device - we are going to the device listing screen + } + else + { + /* determine last subdirectory namelength */ + sprintf(temp,"%s",browser.dir); + test = strtok(temp,"/"); + while (test != NULL) + { + size = strlen(test); + test = strtok(NULL,"/"); + } + + /* remove last subdirectory name */ + size = strlen(browser.dir) - size - 1; + strncpy(GCSettings.LastFileLoaded, &browser.dir[size], strlen(browser.dir) - size - 1); //set as loaded file the previous dir + GCSettings.LastFileLoaded[strlen(browser.dir) - size - 1] = 0; + browser.dir[size] = 0; + } + + return 1; + } + /* Open a directory */ + else + { + /* test new directory namelength */ + if ((strlen(browser.dir)+1+strlen(browserList[browser.selIndex].filename)) < MAXPATHLEN) + { + /* update current directory name */ + sprintf(browser.dir, "%s%s/",browser.dir, browserList[browser.selIndex].filename); + return 1; + } + else + { + ErrorPrompt("Directory name is too long!"); + return -1; + } + } +} + +bool MakeFilePath(char filepath[], int type, char * filename, int filenum) +{ + char file[512]; + char folder[1024]; + char ext[4]; + char temppath[MAXPATHLEN]; + + if(type == FILE_ROM) + { + // Check path length + if ((strlen(browser.dir)+1+strlen(browserList[browser.selIndex].filename)) >= MAXPATHLEN) + { + ErrorPrompt("Maximum filepath length reached!"); + filepath[0] = 0; + return false; + } + else + { + sprintf(temppath, "%s%s",browser.dir,browserList[browser.selIndex].filename); + } + } + else + { + if(GCSettings.SaveMethod == DEVICE_AUTO) + GCSettings.SaveMethod = autoSaveMethod(SILENT); + + if(GCSettings.SaveMethod == DEVICE_AUTO) + return false; + + switch(type) + { + case FILE_SRAM: + case FILE_SNAPSHOT: + sprintf(folder, GCSettings.SaveFolder); + + if(type == FILE_SRAM) sprintf(ext, "srm"); + else sprintf(ext, "frz"); + + if(filenum >= -1) + { + if(filenum == -1) + sprintf(file, "%s.%s", filename, ext); + else if(filenum == 0) + sprintf(file, "%s Auto.%s", filename, ext); + else + sprintf(file, "%s %i.%s", filename, filenum, ext); + } + else + { + sprintf(file, "%s", filename); + } + break; + case FILE_CHEAT: + sprintf(folder, GCSettings.CheatFolder); + sprintf(file, "%s.cht", Memory.ROMFilename); + break; + } + sprintf (temppath, "%s%s/%s", pathPrefix[GCSettings.SaveMethod], folder, file); + } + CleanupPath(temppath); // cleanup path + snprintf(filepath, MAXPATHLEN, "%s", temppath); + return true; +} + +/**************************************************************************** + * FileSortCallback + * + * Quick sort callback to sort file entries with the following order: + * . + * .. + * <dirs> + * <files> + ***************************************************************************/ +int FileSortCallback(const void *f1, const void *f2) +{ + /* Special case for implicit directories */ + if(((BROWSERENTRY *)f1)->filename[0] == '.' || ((BROWSERENTRY *)f2)->filename[0] == '.') + { + if(strcmp(((BROWSERENTRY *)f1)->filename, ".") == 0) { return -1; } + if(strcmp(((BROWSERENTRY *)f2)->filename, ".") == 0) { return 1; } + if(strcmp(((BROWSERENTRY *)f1)->filename, "..") == 0) { return -1; } + if(strcmp(((BROWSERENTRY *)f2)->filename, "..") == 0) { return 1; } + } + + /* If one is a file and one is a directory the directory is first. */ + if(((BROWSERENTRY *)f1)->isdir && !(((BROWSERENTRY *)f2)->isdir)) return -1; + if(!(((BROWSERENTRY *)f1)->isdir) && ((BROWSERENTRY *)f2)->isdir) return 1; + + return stricmp(((BROWSERENTRY *)f1)->filename, ((BROWSERENTRY *)f2)->filename); +} + +/**************************************************************************** + * IsValidROM + * + * Checks if the specified file is a valid ROM + * For now we will just check the file extension and file size + * If the file is a zip, we will check the file extension / file size of the + * first file inside + ***************************************************************************/ +static bool IsValidROM() +{ + // file size should be between 96K and 8MB + if(browserList[browser.selIndex].length < (1024*96) || + browserList[browser.selIndex].length > Memory.MAX_ROM_SIZE) + { + ErrorPrompt("Invalid file size!"); + return false; + } + + if (strlen(browserList[browser.selIndex].filename) > 4) + { + char * p = strrchr(browserList[browser.selIndex].filename, '.'); + + if (p != NULL) + { + char * zippedFilename = NULL; + + if(stricmp(p, ".zip") == 0 && !inSz) + { + // we need to check the file extension of the first file in the archive + zippedFilename = GetFirstZipFilename (); + + if(zippedFilename && strlen(zippedFilename) > 4) + p = strrchr(zippedFilename, '.'); + else + p = NULL; + } + + if(p != NULL) + { + if (stricmp(p, ".smc") == 0 || + stricmp(p, ".fig") == 0 || + stricmp(p, ".sfc") == 0 || + stricmp(p, ".swc") == 0) + { + if(zippedFilename) free(zippedFilename); + return true; + } + } + if(zippedFilename) free(zippedFilename); + } + } + ErrorPrompt("Unknown file type!"); + return false; +} + +/**************************************************************************** + * IsSz + * + * Checks if the specified file is a 7z + ***************************************************************************/ +bool IsSz() +{ + if (strlen(browserList[browser.selIndex].filename) > 4) + { + char * p = strrchr(browserList[browser.selIndex].filename, '.'); + + if (p != NULL) + if(stricmp(p, ".7z") == 0) + return true; + } + return false; +} + +/**************************************************************************** + * StripExt + * + * Strips an extension from a filename + ***************************************************************************/ +void StripExt(char* returnstring, char * inputstring) +{ + char* loc_dot; + + snprintf (returnstring, MAXJOLIET, "%s", inputstring); + + if(inputstring == NULL || strlen(inputstring) < 4) + return; + + loc_dot = strrchr(returnstring,'.'); + if (loc_dot != NULL) + *loc_dot = 0; // strip file extension +} + +/**************************************************************************** + * BrowserLoadSz + * + * Opens the selected 7z file, and parses a listing of the files within + ***************************************************************************/ +int BrowserLoadSz() +{ + memset(szpath, 0, MAXPATHLEN); + strncpy(szpath, browser.dir, strlen(browser.dir) - 1); + + strncpy(szname, strrchr(szpath, '/') + 1, strrchr(szpath, '.') - strrchr(szpath, '/')); + *strrchr(szname, '.') = '\0'; + + int szfiles = SzParse(szpath); + if(szfiles) + { + browser.numEntries = szfiles; + inSz = true; + } + else + ErrorPrompt("Error opening archive!"); + + return szfiles; +} + +int WiiFileLoader() +{ + int size; + char filepath[1024]; + + memset(Memory.NSRTHeader, 0, sizeof(Memory.NSRTHeader)); + Memory.HeaderCount = 0; + loadingFile = true; + + if(!inSz) + { + if(!MakeFilePath(filepath, FILE_ROM)) + return 0; + + size = LoadFile ((char *)Memory.ROM, filepath, browserList[browser.selIndex].length, NOTSILENT); + } + else + { + size = LoadSzFile(szpath, (unsigned char *)Memory.ROM); + + if(size <= 0) + { + browser.selIndex = 0; + BrowserChangeFolder(); + } + } + loadingFile = false; + + if(size <= 0) + return 0; + + SNESROMSize = Memory.HeaderRemove(size, Memory.HeaderCount, Memory.ROM); + return SNESROMSize; +} + +/**************************************************************************** + * BrowserLoadFile + * + * Loads the selected ROM + ***************************************************************************/ +int BrowserLoadFile() +{ + int loaded = 0; + int device; + + if(!FindDevice(browser.dir, &device)) + return 0; + + GetFileSize(browser.selIndex); + + // check that this is a valid ROM + if(!IsValidROM()) + goto done; + + // store the filename (w/o ext) - used for sram/freeze naming + StripExt(Memory.ROMFilename, browserList[browser.selIndex].filename); + snprintf(GCSettings.LastFileLoaded, MAXPATHLEN, "%s", browserList[browser.selIndex].filename); + + SNESROMSize = 0; + S9xDeleteCheats(); + Memory.LoadROM("ROM"); + + if (SNESROMSize <= 0) + { + ErrorPrompt("Error loading game!"); + } + else + { + // load SRAM or snapshot + if (GCSettings.AutoLoad == 1) + LoadSRAMAuto(SILENT); + else if (GCSettings.AutoLoad == 2) + LoadSnapshotAuto(SILENT); + + ResetBrowser(); + loaded = 1; + } +done: + CancelAction(); + return loaded; +} + +/**************************************************************************** + * BrowserChangeFolder + * + * Update current directory and set new entry list if directory has changed + ***************************************************************************/ +int BrowserChangeFolder() +{ + int device = 0; + FindDevice(browser.dir, &device); + + if(inSz && browser.selIndex == 0) // inside a 7z, requesting to leave + { + inSz = false; + SzClose(); + } + + if(!UpdateDirName()) + return -1; + + HaltParseThread(); + CleanupPath(browser.dir); + ResetBrowser(); + + if(browser.dir[0] != 0) + { + if(strstr(browser.dir, ".7z")) + { + BrowserLoadSz(); + } + else + { + ParseDirectory(true, true); + } + FindAndSelectLastLoadedFile(); + } + + if(browser.numEntries == 0) + { + browser.dir[0] = 0; + int i=0; + +#ifdef HW_RVL + AddBrowserEntry(); + sprintf(browserList[i].filename, "sd:/"); + sprintf(browserList[i].displayname, "SD Card"); + browserList[i].length = 0; + browserList[i].isdir = 1; + browserList[i].icon = ICON_SD; + i++; + + AddBrowserEntry(); + sprintf(browserList[i].filename, "usb:/"); + sprintf(browserList[i].displayname, "USB Mass Storage"); + browserList[i].length = 0; + browserList[i].isdir = 1; + browserList[i].icon = ICON_USB; + i++; +#else + AddBrowserEntry(); + sprintf(browserList[i].filename, "carda:/"); + sprintf(browserList[i].displayname, "SD Gecko Slot A"); + browserList[i].length = 0; + browserList[i].isdir = 1; + browserList[i].icon = ICON_SD; + i++; + + AddBrowserEntry(); + sprintf(browserList[i].filename, "cardb:/"); + sprintf(browserList[i].displayname, "SD Gecko Slot B"); + browserList[i].length = 0; + browserList[i].isdir = 1; + browserList[i].icon = ICON_SD; + i++; +#endif + AddBrowserEntry(); + sprintf(browserList[i].filename, "smb:/"); + sprintf(browserList[i].displayname, "Network Share"); + browserList[i].length = 0; + browserList[i].isdir = 1; + browserList[i].icon = ICON_SMB; + i++; + + AddBrowserEntry(); + sprintf(browserList[i].filename, "dvd:/"); + sprintf(browserList[i].displayname, "Data DVD"); + browserList[i].length = 0; + browserList[i].isdir = 1; + browserList[i].icon = ICON_DVD; + i++; + + browser.numEntries += i; + } + + if(browser.dir[0] == 0) + { + GCSettings.LoadFolder[0] = 0; + GCSettings.LoadMethod = 0; + } + else + { + char * path = StripDevice(browser.dir); + if(path != NULL) + strcpy(GCSettings.LoadFolder, path); + FindDevice(browser.dir, &GCSettings.LoadMethod); + } + + return browser.numEntries; +} + +/**************************************************************************** + * OpenROM + * Displays a list of ROMS on load device + ***************************************************************************/ +int +OpenGameList () +{ + int device = GCSettings.LoadMethod; + + if(device == DEVICE_AUTO && strlen(GCSettings.LoadFolder) > 0) + device = autoLoadMethod(); + + // change current dir to roms directory + if(device > 0) + sprintf(browser.dir, "%s%s/", pathPrefix[device], GCSettings.LoadFolder); + else + browser.dir[0] = 0; + + BrowserChangeFolder(); + return browser.numEntries; +} diff --git a/plugins/snes9x_gx/source/filebrowser.h b/plugins/snes9x_gx/source/filebrowser.h new file mode 100644 index 00000000..5065a487 --- /dev/null +++ b/plugins/snes9x_gx/source/filebrowser.h @@ -0,0 +1,79 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * crunchy2 May 2007 + * Michniewski 2008 + * Tantric 2008-2010 + * + * filebrowser.h + * + * Generic file routines - reading, writing, browsing + ****************************************************************************/ + +#ifndef _FILEBROWSER_H_ +#define _FILEBROWSER_H_ + +#include <unistd.h> +#include <gccore.h> + +#define MAXJOLIET 255 +#ifdef HW_DOL +#define MAX_BROWSER_SIZE 1000 +#else +#define MAX_BROWSER_SIZE 5000 +#endif + +typedef struct +{ + char dir[MAXPATHLEN + 1]; // directory path of browserList + int numEntries; // # of entries in browserList + int selIndex; // currently selected index of browserList + int pageIndex; // starting index of browserList page display + int size; // # of entries browerList has space allocated to store +} BROWSERINFO; + +typedef struct +{ + size_t length; // file length + int isdir; // 0 - file, 1 - directory + char filename[MAXJOLIET + 1]; // full filename + char displayname[MAXJOLIET + 1]; // name for browser display + int filenum; // file # (for 7z support) + int icon; // icon to display +} BROWSERENTRY; + +extern BROWSERINFO browser; +extern BROWSERENTRY * browserList; + +enum +{ + ICON_NONE, + ICON_FOLDER, + ICON_SD, + ICON_USB, + ICON_DVD, + ICON_SMB +}; + +extern unsigned long SNESROMSize; +extern bool loadingFile; +extern char szname[MAXPATHLEN]; +extern bool inSz; + +bool MakeFilePath(char filepath[], int type, char * filename = NULL, int filenum = -2); +int UpdateDirName(); +int OpenGameList(); +int autoLoadMethod(); +int autoSaveMethod(bool silent); +int FileSortCallback(const void *f1, const void *f2); +void StripExt(char* returnstring, char * inputstring); +bool IsSz(); +void ResetBrowser(); +bool AddBrowserEntry(); +bool IsDeviceRoot(char * path); +int BrowserLoadSz(); +int BrowserChangeFolder(); +int BrowserLoadFile(); + +#endif diff --git a/plugins/snes9x_gx/source/filelist.h b/plugins/snes9x_gx/source/filelist.h new file mode 100644 index 00000000..e15a85f8 --- /dev/null +++ b/plugins/snes9x_gx/source/filelist.h @@ -0,0 +1,327 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * Tantric 2009-2010 + * + * filelist.h + * + * Contains a list of all of the files stored in the images/, fonts/, and + * sounds/ folders + ***************************************************************************/ + +#ifndef _FILELIST_H_ +#define _FILELIST_H_ + +#include <gccore.h> + +// Fonts +extern const u8 font_ttf[]; +extern const u32 font_ttf_size; + +// Languages +extern const u8 jp_lang[]; +extern const u32 jp_lang_size; +extern const u8 en_lang[]; +extern const u32 en_lang_size; +extern const u8 de_lang[]; +extern const u32 de_lang_size; +extern const u8 fr_lang[]; +extern const u32 fr_lang_size; +extern const u8 es_lang[]; +extern const u32 es_lang_size; +extern const u8 it_lang[]; +extern const u32 it_lang_size; +extern const u8 nl_lang[]; +extern const u32 nl_lang_size; +extern const u8 zh_lang[]; +extern const u32 zh_lang_size; +extern const u8 ko_lang[]; +extern const u32 ko_lang_size; +extern const u8 pt_lang[]; +extern const u32 pt_lang_size; +extern const u8 pt_br_lang[]; +extern const u32 pt_br_lang_size; +extern const u8 ca_lang[]; +extern const u32 ca_lang_size; +extern const u8 tr_lang[]; +extern const u32 tr_lang_size; + +// Sounds + +extern const u8 bg_music_ogg[]; +extern const u32 bg_music_ogg_size; + +extern const u8 enter_ogg[]; +extern const u32 enter_ogg_size; + +extern const u8 exit_ogg[]; +extern const u32 exit_ogg_size; + +extern const u8 button_over_pcm[]; +extern const u32 button_over_pcm_size; + +extern const u8 button_click_pcm[]; +extern const u32 button_click_pcm_size; + +// Graphics + +extern const u8 logo_png[]; +extern const u32 logo_png_size; + +extern const u8 logo_over_png[]; +extern const u32 logo_over_png_size; + +extern const u8 bg_top_png[]; +extern const u32 bg_top_png_size; + +extern const u8 bg_bottom_png[]; +extern const u32 bg_bottom_png_size; + +extern const u8 icon_settings_png[]; +extern const u32 icon_settings_png_size; + +extern const u8 icon_home_png[]; +extern const u32 icon_home_png_size; + +extern const u8 icon_game_settings_png[]; +extern const u32 icon_game_settings_png_size; +extern const u8 icon_game_cheats_png[]; +extern const u32 icon_game_cheats_png_size; +extern const u8 icon_game_controllers_png[]; +extern const u32 icon_game_controllers_png_size; +extern const u8 icon_game_load_png[]; +extern const u32 icon_game_load_png_size; +extern const u8 icon_game_save_png[]; +extern const u32 icon_game_save_png_size; +extern const u8 icon_game_reset_png[]; +extern const u32 icon_game_reset_png_size; + +extern const u8 icon_settings_wiimote_png[]; +extern const u32 icon_settings_wiimote_png_size; +extern const u8 icon_settings_classic_png[]; +extern const u32 icon_settings_classic_png_size; +extern const u8 icon_settings_gamecube_png[]; +extern const u32 icon_settings_gamecube_png_size; +extern const u8 icon_settings_nunchuk_png[]; +extern const u32 icon_settings_nunchuk_png_size; +extern const u8 icon_settings_wiiupro_png[]; +extern const u32 icon_settings_wiiupro_png_size; + +extern const u8 icon_settings_snescontroller_png[]; +extern const u32 icon_settings_snescontroller_png_size; +extern const u8 icon_settings_superscope_png[]; +extern const u32 icon_settings_superscope_png_size; +extern const u8 icon_settings_justifier_png[]; +extern const u32 icon_settings_justifier_png_size; +extern const u8 icon_settings_mouse_png[]; +extern const u32 icon_settings_mouse_png_size; + +extern const u8 icon_settings_file_png[]; +extern const u32 icon_settings_file_png_size; +extern const u8 icon_settings_mappings_png[]; +extern const u32 icon_settings_mappings_png_size; +extern const u8 icon_settings_menu_png[]; +extern const u32 icon_settings_menu_png_size; +extern const u8 icon_settings_network_png[]; +extern const u32 icon_settings_network_png_size; +extern const u8 icon_settings_video_png[]; +extern const u32 icon_settings_video_png_size; +extern const u8 icon_settings_screenshot_png[]; +extern const u32 icon_settings_screenshot_png_size; + +extern const u8 button_png[]; +extern const u32 button_png_size; + +extern const u8 button_over_png[]; +extern const u32 button_over_png_size; + +extern const u8 button_prompt_png[]; +extern const u32 button_prompt_png_size; + +extern const u8 button_prompt_over_png[]; +extern const u32 button_prompt_over_png_size; + +extern const u8 button_long_png[]; +extern const u32 button_long_png_size; + +extern const u8 button_long_over_png[]; +extern const u32 button_long_over_png_size; + +extern const u8 button_short_png[]; +extern const u32 button_short_png_size; + +extern const u8 button_short_over_png[]; +extern const u32 button_short_over_png_size; + +extern const u8 button_small_png[]; +extern const u32 button_small_png_size; + +extern const u8 button_small_over_png[]; +extern const u32 button_small_over_png_size; + +extern const u8 button_large_png[]; +extern const u32 button_large_png_size; + +extern const u8 button_large_over_png[]; +extern const u32 button_large_over_png_size; + +extern const u8 button_arrow_left_png[]; +extern const u32 button_arrow_left_png_size; + +extern const u8 button_arrow_right_png[]; +extern const u32 button_arrow_right_png_size; + +extern const u8 button_arrow_up_png[]; +extern const u32 button_arrow_up_png_size; + +extern const u8 button_arrow_down_png[]; +extern const u32 button_arrow_down_png_size; + +extern const u8 button_arrow_left_over_png[]; +extern const u32 button_arrow_left_over_png_size; + +extern const u8 button_arrow_right_over_png[]; +extern const u32 button_arrow_right_over_png_size; + +extern const u8 button_arrow_up_over_png[]; +extern const u32 button_arrow_up_over_png_size; + +extern const u8 button_arrow_down_over_png[]; +extern const u32 button_arrow_down_over_png_size; + +extern const u8 button_gamesave_png[]; +extern const u32 button_gamesave_png_size; + +extern const u8 button_gamesave_over_png[]; +extern const u32 button_gamesave_over_png_size; + +extern const u8 button_gamesave_blank_png[]; +extern const u32 button_gamesave_blank_png_size; + +extern const u8 screen_position_png[]; +extern const u32 screen_position_png_size; + +extern const u8 dialogue_box_png[]; +extern const u32 dialogue_box_png_size; + +extern const u8 credits_box_png[]; +extern const u32 credits_box_png_size; + +extern const u8 progressbar_png[]; +extern const u32 progressbar_png_size; + +extern const u8 progressbar_empty_png[]; +extern const u32 progressbar_empty_png_size; + +extern const u8 progressbar_outline_png[]; +extern const u32 progressbar_outline_png_size; + +extern const u8 throbber_png[]; +extern const u32 throbber_png_size; + +extern const u8 icon_folder_png[]; +extern const u32 icon_folder_png_size; + +extern const u8 icon_sd_png[]; +extern const u32 icon_sd_png_size; + +extern const u8 icon_usb_png[]; +extern const u32 icon_usb_png_size; + +extern const u8 icon_dvd_png[]; +extern const u32 icon_dvd_png_size; + +extern const u8 icon_smb_png[]; +extern const u32 icon_smb_png_size; + +extern const u8 battery_png[]; +extern const u32 battery_png_size; + +extern const u8 battery_red_png[]; +extern const u32 battery_red_png_size; + +extern const u8 battery_bar_png[]; +extern const u32 battery_bar_png_size; + +extern const u8 bg_options_png[]; +extern const u32 bg_options_png_size; + +extern const u8 bg_options_entry_png[]; +extern const u32 bg_options_entry_png_size; + +extern const u8 bg_game_selection_png[]; +extern const u32 bg_game_selection_png_size; + +extern const u8 bg_game_selection_entry_png[]; +extern const u32 bg_game_selection_entry_png_size; + +extern const u8 bg_preview_png[]; +extern const u32 bg_preview_png_size; + +extern const u8 scrollbar_png[]; +extern const u32 scrollbar_png_size; + +extern const u8 scrollbar_arrowup_png[]; +extern const u32 scrollbar_arrowup_png_size; + +extern const u8 scrollbar_arrowup_over_png[]; +extern const u32 scrollbar_arrowup_over_png_size; + +extern const u8 scrollbar_arrowdown_png[]; +extern const u32 scrollbar_arrowdown_png_size; + +extern const u8 scrollbar_arrowdown_over_png[]; +extern const u32 scrollbar_arrowdown_over_png_size; + +extern const u8 scrollbar_box_png[]; +extern const u32 scrollbar_box_png_size; + +extern const u8 scrollbar_box_over_png[]; +extern const u32 scrollbar_box_over_png_size; + +extern const u8 keyboard_textbox_png[]; +extern const u32 keyboard_textbox_png_size; + +extern const u8 keyboard_key_png[]; +extern const u32 keyboard_key_png_size; + +extern const u8 keyboard_key_over_png[]; +extern const u32 keyboard_key_over_png_size; + +extern const u8 keyboard_mediumkey_png[]; +extern const u32 keyboard_mediumkey_png_size; + +extern const u8 keyboard_mediumkey_over_png[]; +extern const u32 keyboard_mediumkey_over_png_size; + +extern const u8 keyboard_largekey_png[]; +extern const u32 keyboard_largekey_png_size; + +extern const u8 keyboard_largekey_over_png[]; +extern const u32 keyboard_largekey_over_png_size; + +extern const u8 player1_point_png[]; +extern const u32 player1_point_png_size; + +extern const u8 player2_point_png[]; +extern const u32 player2_point_png_size; + +extern const u8 player3_point_png[]; +extern const u32 player3_point_png_size; + +extern const u8 player4_point_png[]; +extern const u32 player4_point_png_size; + +extern const u8 player1_grab_png[]; +extern const u32 player1_grab_png_size; + +extern const u8 player2_grab_png[]; +extern const u32 player2_grab_png_size; + +extern const u8 player3_grab_png[]; +extern const u32 player3_grab_png_size; + +extern const u8 player4_grab_png[]; +extern const u32 player4_grab_png_size; + +#endif diff --git a/plugins/snes9x_gx/source/fileop.cpp b/plugins/snes9x_gx/source/fileop.cpp new file mode 100644 index 00000000..98c066e1 --- /dev/null +++ b/plugins/snes9x_gx/source/fileop.cpp @@ -0,0 +1,962 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * crunchy2 May 2007 + * Michniewski 2008 + * Tantric 2008-2010 + * + * fileop.cpp + * + * File operations + ***************************************************************************/ + +#include <gccore.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ogcsys.h> +#include <dirent.h> +#include <sys/stat.h> +#include <zlib.h> +#include <malloc.h> +#include <sdcard/wiisd_io.h> +#include <sdcard/gcsd.h> +#include <ogc/usbstorage.h> +#include <di/di.h> +#include <ogc/dvd.h> +#include <iso9660.h> + +#include "snes9xgx.h" +#include "fileop.h" +#include "networkop.h" +#include "gcunzip.h" +#include "menu.h" +#include "filebrowser.h" +#include "gui/gui.h" + +#define THREAD_SLEEP 100 + +unsigned char *savebuffer = NULL; +static mutex_t bufferLock = LWP_MUTEX_NULL; +FILE * file; // file pointer - the only one we should ever use! +bool unmountRequired[7] = { false, false, false, false, false, false, false }; +bool isMounted[7] = { false, false, false, false, false, false, false }; + +#ifdef HW_RVL + const DISC_INTERFACE* sd = &__io_wiisd; + const DISC_INTERFACE* usb = &__io_usbstorage; + const DISC_INTERFACE* dvd = &__io_wiidvd; +#else + const DISC_INTERFACE* carda = &__io_gcsda; + const DISC_INTERFACE* cardb = &__io_gcsdb; + const DISC_INTERFACE* dvd = &__io_gcdvd; +#endif + +// folder parsing thread +static lwp_t parsethread = LWP_THREAD_NULL; +static DIR *dir = NULL; +static bool parseHalt = true; +static bool parseFilter = true; +static bool ParseDirEntries(); +int selectLoadedFile = 0; + +// device thread +static lwp_t devicethread = LWP_THREAD_NULL; +static bool deviceHalt = true; + +/**************************************************************************** + * ResumeDeviceThread + * + * Signals the device thread to start, and resumes the thread. + ***************************************************************************/ +void +ResumeDeviceThread() +{ + deviceHalt = false; + LWP_ResumeThread(devicethread); +} + +/**************************************************************************** + * HaltGui + * + * Signals the device thread to stop. + ***************************************************************************/ +void +HaltDeviceThread() +{ +#ifdef HW_RVL + deviceHalt = true; + + // wait for thread to finish + while(!LWP_ThreadIsSuspended(devicethread)) + usleep(THREAD_SLEEP); +#endif +} + +/**************************************************************************** + * HaltParseThread + * + * Signals the parse thread to stop. + ***************************************************************************/ +void +HaltParseThread() +{ + parseHalt = true; + + while(!LWP_ThreadIsSuspended(parsethread)) + usleep(THREAD_SLEEP); +} + + +/**************************************************************************** + * devicecallback + * + * This checks our devices for changes (SD/USB/DVD removed) + ***************************************************************************/ +#ifdef HW_RVL +static int devsleep; + +static void * +devicecallback (void *arg) +{ + while (1) + { + if(isMounted[DEVICE_SD]) + { + if(!sd->isInserted()) // check if the device was removed + { + unmountRequired[DEVICE_SD] = true; + isMounted[DEVICE_SD] = false; + } + } + + if(isMounted[DEVICE_USB]) + { + if(!usb->isInserted()) // check if the device was removed + { + unmountRequired[DEVICE_USB] = true; + isMounted[DEVICE_USB] = false; + } + } + + if(isMounted[DEVICE_DVD]) + { + if(!dvd->isInserted()) // check if the device was removed + { + unmountRequired[DEVICE_DVD] = true; + isMounted[DEVICE_DVD] = false; + } + } + + devsleep = 1000*1000; // 1 sec + + while(devsleep > 0) + { + if(deviceHalt) + LWP_SuspendThread(devicethread); + usleep(THREAD_SLEEP); + devsleep -= THREAD_SLEEP; + } + UpdateCheck(); + } + return NULL; +} +#endif + +static void * +parsecallback (void *arg) +{ + while(1) + { + while(ParseDirEntries()) + usleep(THREAD_SLEEP); + LWP_SuspendThread(parsethread); + } + return NULL; +} + +/**************************************************************************** + * InitDeviceThread + * + * libOGC provides a nice wrapper for LWP access. + * This function sets up a new local queue and attaches the thread to it. + ***************************************************************************/ +void +InitDeviceThread() +{ +#ifdef HW_RVL + LWP_CreateThread (&devicethread, devicecallback, NULL, NULL, 0, 40); +#endif + LWP_CreateThread (&parsethread, parsecallback, NULL, NULL, 0, 80); +} + +/**************************************************************************** + * UnmountAllFAT + * Unmounts all FAT devices + ***************************************************************************/ +void UnmountAllFAT() +{ +#ifdef HW_RVL + fatUnmount("sd:"); + fatUnmount("usb:"); +#else + fatUnmount("carda:"); + fatUnmount("cardb:"); +#endif +} + +/**************************************************************************** + * MountFAT + * Checks if the device needs to be (re)mounted + * If so, unmounts the device + * Attempts to mount the device specified + * Sets libfat to use the device by default + ***************************************************************************/ + +static bool MountFAT(int device, int silent) +{ + bool mounted = false; + int retry = 1; + char name[10], name2[10]; + const DISC_INTERFACE* disc = NULL; + + switch(device) + { +#ifdef HW_RVL + case DEVICE_SD: + sprintf(name, "sd"); + sprintf(name2, "sd:"); + disc = sd; + break; + case DEVICE_USB: + sprintf(name, "usb"); + sprintf(name2, "usb:"); + disc = usb; + break; +#else + case DEVICE_SD_SLOTA: + sprintf(name, "carda"); + sprintf(name2, "carda:"); + disc = carda; + break; + + case DEVICE_SD_SLOTB: + sprintf(name, "cardb"); + sprintf(name2, "cardb:"); + disc = cardb; + break; +#endif + default: + return false; // unknown device + } + + if(unmountRequired[device]) + { + unmountRequired[device] = false; + fatUnmount(name2); + disc->shutdown(); + isMounted[device] = false; + } + + while(retry) + { + if(disc->startup() && fatMountSimple(name, disc)) + mounted = true; + + if(mounted || silent) + break; + +#ifdef HW_RVL + if(device == DEVICE_SD) + retry = ErrorPromptRetry("SD card not found!"); + else + retry = ErrorPromptRetry("USB drive not found!"); +#else + retry = ErrorPromptRetry("SD card not found!"); +#endif + } + + isMounted[device] = mounted; + return mounted; +} + +void MountAllFAT() +{ +#ifdef HW_RVL + MountFAT(DEVICE_SD, SILENT); + MountFAT(DEVICE_USB, SILENT); +#else + MountFAT(DEVICE_SD_SLOTA, SILENT); + MountFAT(DEVICE_SD_SLOTB, SILENT); +#endif +} + +/**************************************************************************** + * MountDVD() + * + * Tests if a ISO9660 DVD is inserted and available, and mounts it + ***************************************************************************/ +bool MountDVD(bool silent) +{ + bool mounted = false; + int retry = 1; + + if(unmountRequired[DEVICE_DVD]) + { + unmountRequired[DEVICE_DVD] = false; + ISO9660_Unmount("dvd:"); + } + + while(retry) + { + ShowAction("Loading DVD..."); + + if(!dvd->isInserted()) + { + if(silent) + break; + + retry = ErrorPromptRetry("No disc inserted!"); + } + else if(!ISO9660_Mount("dvd", dvd)) + { + if(silent) + break; + + retry = ErrorPromptRetry("Unrecognized DVD format."); + } + else + { + mounted = true; + break; + } + } + CancelAction(); + isMounted[DEVICE_DVD] = mounted; + return mounted; +} + +bool FindDevice(char * filepath, int * device) +{ + if(!filepath || filepath[0] == 0) + return false; + + if(strncmp(filepath, "sd:", 3) == 0) + { + *device = DEVICE_SD; + return true; + } + else if(strncmp(filepath, "usb:", 4) == 0) + { + *device = DEVICE_USB; + return true; + } + else if(strncmp(filepath, "smb:", 4) == 0) + { + *device = DEVICE_SMB; + return true; + } + else if(strncmp(filepath, "carda:", 6) == 0) + { + *device = DEVICE_SD_SLOTA; + return true; + } + else if(strncmp(filepath, "cardb:", 6) == 0) + { + *device = DEVICE_SD_SLOTB; + return true; + } + else if(strncmp(filepath, "dvd:", 4) == 0) + { + *device = DEVICE_DVD; + return true; + } + return false; +} + +char * StripDevice(char * path) +{ + if(path == NULL) + return NULL; + + char * newpath = strchr(path,'/'); + + if(newpath != NULL) + newpath++; + + return newpath; +} + +/**************************************************************************** + * ChangeInterface + * Attempts to mount/configure the device specified + ***************************************************************************/ +bool ChangeInterface(int device, bool silent) +{ + if(isMounted[device]) + return true; + + bool mounted = false; + + switch(device) + { +#ifdef HW_RVL + case DEVICE_SD: + case DEVICE_USB: +#else + case DEVICE_SD_SLOTA: + case DEVICE_SD_SLOTB: +#endif + mounted = MountFAT(device, silent); + break; + case DEVICE_DVD: + mounted = MountDVD(silent); + break; + case DEVICE_SMB: + mounted = ConnectShare(silent); + break; + } + + return mounted; +} + +bool ChangeInterface(char * filepath, bool silent) +{ + int device = -1; + + if(!FindDevice(filepath, &device)) + return false; + + return ChangeInterface(device, silent); +} + +void CreateAppPath(char * origpath) +{ + if(!origpath || origpath[0] == 0) + return; + + char * path = strdup(origpath); // make a copy so we don't mess up original + + if(!path) + return; + + char * loc = strrchr(path,'/'); + if (loc != NULL) + *loc = 0; // strip file name + + int pos = 0; + + // replace fat:/ with sd:/ + if(strncmp(path, "fat:/", 5) == 0) + { + pos++; + path[1] = 's'; + path[2] = 'd'; + } + if(ChangeInterface(&path[pos], SILENT)) + snprintf(appPath, MAXPATHLEN-1, "%s", &path[pos]); + + free(path); +} + +static char *GetExt(char *file) +{ + if(!file) + return NULL; + + char *ext = strrchr(file,'.'); + if(ext != NULL) + { + ext++; + int extlen = strlen(ext); + if(extlen > 5) + return NULL; + } + return ext; +} + +bool GetFileSize(int i) +{ + if(browserList[i].length > 0) + return true; + + struct stat filestat; + char path[MAXPATHLEN+1]; + snprintf(path, MAXPATHLEN, "%s%s", browser.dir, browserList[i].filename); + + if(stat(path, &filestat) < 0) + return false; + + browserList[i].length = filestat.st_size; + return true; +} + +void FindAndSelectLastLoadedFile () +{ + int indexFound = -1; + + for(int j=1; j < browser.numEntries; j++) + { + if(strcmp(browserList[j].filename, GCSettings.LastFileLoaded) == 0) + { + indexFound = j; + break; + } + } + + // move to this file + if(indexFound > 0) + { + if(indexFound >= FILE_PAGESIZE) + { + int newIndex = (floor(indexFound/(float)FILE_PAGESIZE)) * FILE_PAGESIZE; + + if(newIndex + FILE_PAGESIZE > browser.numEntries) + newIndex = browser.numEntries - FILE_PAGESIZE; + + if(newIndex < 0) + newIndex = 0; + + browser.pageIndex = newIndex; + } + browser.selIndex = indexFound; + } + + selectLoadedFile = 2; // selecting done +} + +static bool ParseDirEntries() +{ + if(!dir) + return false; + + char *ext; + struct dirent *entry = NULL; + int isdir; + + int i = 0; + + while(i < 20 && !parseHalt) + { + entry = readdir(dir); + + if(entry == NULL) + break; + + if(entry->d_name[0] == '.' && entry->d_name[1] != '.') + continue; + + if(strcmp(entry->d_name, "..") == 0) + { + isdir = 1; + } + else + { + if(entry->d_type==DT_DIR) + isdir = 1; + else + isdir = 0; + + // don't show the file if it's not a valid ROM + if(parseFilter && !isdir) + { + ext = GetExt(entry->d_name); + + if(ext == NULL) + continue; + + if( stricmp(ext, "smc") != 0 && stricmp(ext, "fig") != 0 && + stricmp(ext, "sfc") != 0 && stricmp(ext, "swc") != 0 && + stricmp(ext, "zip") != 0 && stricmp(ext, "7z") != 0) + continue; + } + } + + if(!AddBrowserEntry()) + { + parseHalt = true; + break; + } + + snprintf(browserList[browser.numEntries+i].filename, MAXJOLIET, "%s", entry->d_name); + browserList[browser.numEntries+i].isdir = isdir; // flag this as a dir + + if(isdir) + { + if(strcmp(entry->d_name, "..") == 0) + sprintf(browserList[browser.numEntries+i].displayname, "Up One Level"); + else + snprintf(browserList[browser.numEntries+i].displayname, MAXJOLIET, "%s", browserList[browser.numEntries+i].filename); + browserList[browser.numEntries+i].icon = ICON_FOLDER; + } + else + { + StripExt(browserList[browser.numEntries+i].displayname, browserList[browser.numEntries+i].filename); // hide file extension + } + i++; + } + + if(!parseHalt) + { + // Sort the file list + if(i >= 0) + qsort(browserList, browser.numEntries+i, sizeof(BROWSERENTRY), FileSortCallback); + + browser.numEntries += i; + } + + if(entry == NULL || parseHalt) + { + closedir(dir); // close directory + dir = NULL; + + // try to find and select the last loaded file + if(selectLoadedFile == 1 && !parseHalt && loadedFile[0] != 0 && browser.dir[0] != 0) + { + int indexFound = -1; + + for(int j=1; j < browser.numEntries; j++) + { + if(strcmp(browserList[j].filename, loadedFile) == 0) + { + indexFound = j; + break; + } + } + + // move to this file + if(indexFound > 0) + { + if(indexFound >= FILE_PAGESIZE) + { + int newIndex = (floor(indexFound/(float)FILE_PAGESIZE)) * FILE_PAGESIZE; + + if(newIndex + FILE_PAGESIZE > browser.numEntries) + newIndex = browser.numEntries - FILE_PAGESIZE; + + if(newIndex < 0) + newIndex = 0; + + browser.pageIndex = newIndex; + } + browser.selIndex = indexFound; + } + selectLoadedFile = 2; // selecting done + } + return false; // no more entries + } + return true; // more entries +} + +/*************************************************************************** + * Browse subdirectories + **************************************************************************/ +int +ParseDirectory(bool waitParse, bool filter) +{ + int retry = 1; + bool mounted = false; + parseFilter = filter; + + ResetBrowser(); // reset browser + + // add trailing slash + if(browser.dir[strlen(browser.dir)-1] != '/') + strcat(browser.dir, "/"); + + // open the directory + while(dir == NULL && retry == 1) + { + mounted = ChangeInterface(browser.dir, NOTSILENT); + + if(mounted) + dir = opendir(browser.dir); + else + return -1; + + if(dir == NULL) + { + retry = ErrorPromptRetry("Error opening directory!"); + } + } + + // if we can't open the dir, try higher levels + if (dir == NULL) + { + char * devEnd = strrchr(browser.dir, '/'); + + while(!IsDeviceRoot(browser.dir)) + { + devEnd[0] = 0; // strip slash + devEnd = strrchr(browser.dir, '/'); + + if(devEnd == NULL) + break; + + devEnd[1] = 0; // strip remaining file listing + dir = opendir(browser.dir); + if (dir) + break; + } + } + + if(dir == NULL) + return -1; + + if(IsDeviceRoot(browser.dir)) + { + AddBrowserEntry(); + sprintf(browserList[0].filename, ".."); + sprintf(browserList[0].displayname, "Up One Level"); + browserList[0].length = 0; + browserList[0].isdir = 1; // flag this as a dir + browserList[0].icon = ICON_FOLDER; + browser.numEntries++; + } + + parseHalt = false; + ParseDirEntries(); // index first 20 entries + + LWP_ResumeThread(parsethread); // index remaining entries + + if(waitParse) // wait for complete parsing + { + ShowAction("Loading..."); + + while(!LWP_ThreadIsSuspended(parsethread)) + usleep(THREAD_SLEEP); + + CancelAction(); + } + + return browser.numEntries; +} + +/**************************************************************************** + * AllocSaveBuffer () + * Clear and allocate the savebuffer + ***************************************************************************/ +void +AllocSaveBuffer () +{ + if(bufferLock == LWP_MUTEX_NULL) + LWP_MutexInit(&bufferLock, false); + + if(bufferLock != LWP_MUTEX_NULL) + LWP_MutexLock(bufferLock); + memset (savebuffer, 0, SAVEBUFFERSIZE); +} + +/**************************************************************************** + * FreeSaveBuffer () + * Free the savebuffer memory + ***************************************************************************/ +void +FreeSaveBuffer () +{ + if(bufferLock != LWP_MUTEX_NULL) + LWP_MutexUnlock(bufferLock); +} + +/**************************************************************************** + * LoadSzFile + * Loads the selected file # from the specified 7z into rbuffer + * Returns file size + ***************************************************************************/ +size_t +LoadSzFile(char * filepath, unsigned char * rbuffer) +{ + size_t size = 0; + + // stop checking if devices were removed/inserted + // since we're loading a file + HaltDeviceThread(); + + // halt parsing + HaltParseThread(); + + file = fopen (filepath, "rb"); + if (file > 0) + { + size = SzExtractFile(browserList[browser.selIndex].filenum, rbuffer); + fclose (file); + } + else + { + ErrorPrompt("Error opening file!"); + } + + // go back to checking if devices were inserted/removed + ResumeDeviceThread(); + + return size; +} + +/**************************************************************************** + * LoadFile + ***************************************************************************/ +size_t +LoadFile (char * rbuffer, char *filepath, size_t length, bool silent) +{ + char zipbuffer[2048]; + size_t size = 0, offset = 0, readsize = 0; + int retry = 1; + int device; + + if(!FindDevice(filepath, &device)) + return 0; + + // stop checking if devices were removed/inserted + // since we're loading a file + HaltDeviceThread(); + + // halt parsing + HaltParseThread(); + + // open the file + while(retry) + { + if(!ChangeInterface(device, silent)) + break; + + file = fopen (filepath, "rb"); + + if(!file) + { + if(silent) + break; + + retry = ErrorPromptRetry("Error opening file!"); + continue; + } + + if(length > 0 && length <= 2048) // do a partial read (eg: to check file header) + { + size = fread (rbuffer, 1, length, file); + } + else // load whole file + { + readsize = fread (zipbuffer, 1, 32, file); + + if(!readsize) + { + unmountRequired[device] = true; + retry = ErrorPromptRetry("Error reading file!"); + fclose (file); + continue; + } + + if (IsZipFile (zipbuffer)) + { + size = UnZipBuffer ((unsigned char *)rbuffer); // unzip + } + else + { + fseeko(file,0,SEEK_END); + size = ftello(file); + fseeko(file,0,SEEK_SET); + + while(!feof(file)) + { + ShowProgress ("Loading...", offset, size); + readsize = fread (rbuffer + offset, 1, 4096, file); // read in next chunk + + if(readsize <= 0) + break; // reading finished (or failed) + + offset += readsize; + } + size = offset; + CancelAction(); + } + } + retry = 0; + fclose (file); + } + + // go back to checking if devices were inserted/removed + ResumeDeviceThread(); + CancelAction(); + return size; +} + +size_t LoadFile(char * filepath, bool silent) +{ + return LoadFile((char *)savebuffer, filepath, 0, silent); +} + +/**************************************************************************** + * SaveFile + * Write buffer to file + ***************************************************************************/ +size_t +SaveFile (char * buffer, char *filepath, size_t datasize, bool silent) +{ + size_t written = 0; + size_t writesize, nextwrite; + int retry = 1; + int device; + + if(!FindDevice(filepath, &device)) + return 0; + + if(datasize == 0) + return 0; + + // stop checking if devices were removed/inserted + // since we're saving a file + HaltDeviceThread(); + + // halt parsing + HaltParseThread(); + + ShowAction("Saving..."); + + while(!written && retry == 1) + { + if(!ChangeInterface(device, silent)) + break; + + file = fopen (filepath, "wb"); + + if(!file) + { + if(silent) + break; + + retry = ErrorPromptRetry("Error creating file!"); + continue; + } + + while(written < datasize) + { + if(datasize - written > 4096) nextwrite=4096; + else nextwrite = datasize-written; + writesize = fwrite (buffer+written, 1, nextwrite, file); + if(writesize != nextwrite) break; // write failure + written += writesize; + } + fclose (file); + + if(written != datasize) written = 0; + + if(!written) + { + unmountRequired[device] = true; + if(silent) break; + retry = ErrorPromptRetry("Error saving file!"); + } + } + + // go back to checking if devices were inserted/removed + ResumeDeviceThread(); + + CancelAction(); + return written; +} + +size_t SaveFile(char * filepath, size_t datasize, bool silent) +{ + return SaveFile((char *)savebuffer, filepath, datasize, silent); +} diff --git a/plugins/snes9x_gx/source/fileop.h b/plugins/snes9x_gx/source/fileop.h new file mode 100644 index 00000000..8bd7454b --- /dev/null +++ b/plugins/snes9x_gx/source/fileop.h @@ -0,0 +1,54 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * crunchy2 May 2007 + * Michniewski 2008 + * Tantric 2008-2010 + * + * fileop.h + * + * File operations + ****************************************************************************/ + +#ifndef _FILEOP_H_ +#define _FILEOP_H_ + +#include <gccore.h> +#include <stdio.h> +#include <string.h> +#include <ogcsys.h> +#include <fat.h> +#include <unistd.h> + +#define SAVEBUFFERSIZE (1024 * 512) + +void InitDeviceThread(); +void ResumeDeviceThread(); +void HaltDeviceThread(); +void HaltParseThread(); +void MountAllFAT(); +void UnmountAllFAT(); +bool FindDevice(char * filepath, int * device); +char * StripDevice(char * path); +bool ChangeInterface(int device, bool silent); +bool ChangeInterface(char * filepath, bool silent); +void CreateAppPath(char * origpath); +bool GetFileSize(int i); +void FindAndSelectLastLoadedFile(); +int ParseDirectory(bool waitParse = false, bool filter = true); +void AllocSaveBuffer(); +void FreeSaveBuffer(); +size_t LoadFile(char * rbuffer, char *filepath, size_t length, bool silent); +size_t LoadFile(char * filepath, bool silent); +size_t LoadSzFile(char * filepath, unsigned char * rbuffer); +size_t SaveFile(char * buffer, char *filepath, size_t datasize, bool silent); +size_t SaveFile(char * filepath, size_t datasize, bool silent); + +extern unsigned char *savebuffer; +extern FILE * file; +extern bool unmountRequired[]; +extern bool isMounted[]; +extern int selectLoadedFile; + +#endif diff --git a/plugins/snes9x_gx/source/filter.cpp b/plugins/snes9x_gx/source/filter.cpp new file mode 100644 index 00000000..567af538 --- /dev/null +++ b/plugins/snes9x_gx/source/filter.cpp @@ -0,0 +1,561 @@ +/**************************************************************************** + * Snes9x 1.51 Nintendo Wii/Gamecube Port + * + * Michniewski 2008 + * + * HQ2x, HQ3x, HQ4x filters + * (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + * + * filter.cpp + * + * Adapted from Snes9x Win32/MacOSX ports + * Video Filter Code (hq2x) + ****************************************************************************/ +#include <gccore.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ogcsys.h> +#include <unistd.h> +#include <malloc.h> + +#include "filter.h" +#include "video.h" +#include "snes9xGX.h" +#include "memmap.h" + +#include "menu.h" + +#define NUMBITS (16) + +static int RGBtoYUV[1<<NUMBITS]; +static uint16 RGBtoBright[1<<NUMBITS]; + +TFilterMethod FilterMethod = RenderPlain; +//TFilterMethod FilterMethodHiRes = RenderPlain; + +// +// Functions: +// + +bool +GetFilterHiResSupport (RenderFilter filterID) +{ + switch(filterID) + { + case FILTER_NONE: + return true; + + default: + return false; + } +} + +const char* +GetFilterName (RenderFilter filterID) +{ + switch(filterID) + { + default: return "Unknown"; + case FILTER_NONE: return "None"; + case FILTER_HQ2X: return "hq2x"; + case FILTER_HQ2XS: return "hq2x Soft"; + case FILTER_HQ2XBOLD: return "hq2x Bold"; + case FILTER_SCANLINES: return "Scanlines"; + } +} + +// Return pointer to appropriate function +TFilterMethod +FilterToMethod (RenderFilter filterID) +{ + switch(filterID) + { + default: + case FILTER_NONE: return RenderPlain; + case FILTER_HQ2X: return RenderHQ2X<FILTER_HQ2X>; + case FILTER_HQ2XS: return RenderHQ2X<FILTER_HQ2XS>; + case FILTER_HQ2XBOLD: return RenderHQ2X<FILTER_HQ2XBOLD>; + case FILTER_SCANLINES: return Scanlines<FILTER_SCANLINES>; + } +} + +int GetFilterScale(RenderFilter filterID) +{ + switch(filterID) + { + case FILTER_NONE: + return 1; + + default: + case FILTER_HQ2X: + case FILTER_HQ2XS: + case FILTER_HQ2XBOLD: + case FILTER_SCANLINES: + return 2; + } +} + +void +SelectFilterMethod () +{ + //InfoPrompt((char*)"Select Filter Method."); // debug + + FilterMethod = FilterToMethod((RenderFilter)GCSettings.FilterMethod); + //FilterMethodHiRes = FilterToMethod((RenderFilter)GCSettings.FilterMethodHiRes); + + // check whether or not we need filter memory (alloc or free it) +} + +// +// Filter Codes: +// + +// No enlargement, just render to the screen +void +RenderPlain (uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + if (dstPtr == NULL) + { + ErrorPrompt((char*)"dstPtr is NULL. exiting!"); + exit(1); + } + //memcpy (dstPtr, srcPtr, width*height*srcPitch); + return; +} + +// +// HQ2X Filter Code: +// + +#define Mask_2 0x07E0 // 00000 111111 00000 +#define Mask13 0xF81F // 11111 000000 11111 + +#define Ymask 0xFF0000 +#define Umask 0x00FF00 +#define Vmask 0x0000FF +#define trY 0x300000 +#define trU 0x000700 +#define trV 0x000006 + +#define Interp01(c1, c2) \ + ((((c1) == (c2)) ? (c1) : \ + (((((((c1) & Mask_2) * 3) + ((c2) & Mask_2)) >> 2) & Mask_2) + \ + ((((((c1) & Mask13) * 3) + ((c2) & Mask13)) >> 2) & Mask13)))) + +#define Interp02(c1, c2, c3) \ + ((((((c1) & Mask_2) * 2 + ((c2) & Mask_2) + ((c3) & Mask_2) ) >> 2) & Mask_2) + \ + (((((c1) & Mask13) * 2 + ((c2) & Mask13) + ((c3) & Mask13) ) >> 2) & Mask13)) + +#define Interp06(c1, c2, c3) \ + ((((((c1) & Mask_2) * 5 + ((c2) & Mask_2) * 2 + ((c3) & Mask_2) ) >> 3) & Mask_2) + \ + (((((c1) & Mask13) * 5 + ((c2) & Mask13) * 2 + ((c3) & Mask13) ) >> 3) & Mask13)) + +#define Interp07(c1, c2, c3) \ + ((((((c1) & Mask_2) * 6 + ((c2) & Mask_2) + ((c3) & Mask_2) ) >> 3) & Mask_2) + \ + (((((c1) & Mask13) * 6 + ((c2) & Mask13) + ((c3) & Mask13) ) >> 3) & Mask13)) + +#define Interp09(c1, c2, c3) \ + ((((((c1) & Mask_2) * 2 + ((c2) & Mask_2) * 3 + ((c3) & Mask_2) * 3) >> 3) & Mask_2) + \ + (((((c1) & Mask13) * 2 + ((c2) & Mask13) * 3 + ((c3) & Mask13) * 3) >> 3) & Mask13)) + +#define Interp10(c1, c2, c3) \ + ((((((c1) & Mask_2) * 14 + ((c2) & Mask_2) + ((c3) & Mask_2) ) >> 4) & Mask_2) + \ + (((((c1) & Mask13) * 14 + ((c2) & Mask13) + ((c3) & Mask13) ) >> 4) & Mask13)) + +#define PIXEL00_0 *(dp) = w5 +#define PIXEL00_10 *(dp) = Interp01(w5, w1) +#define PIXEL00_11 *(dp) = Interp01(w5, w4) +#define PIXEL00_12 *(dp) = Interp01(w5, w2) +#define PIXEL00_20 *(dp) = Interp02(w5, w4, w2) +#define PIXEL00_21 *(dp) = Interp02(w5, w1, w2) +#define PIXEL00_22 *(dp) = Interp02(w5, w1, w4) +#define PIXEL00_60 *(dp) = Interp06(w5, w2, w4) +#define PIXEL00_61 *(dp) = Interp06(w5, w4, w2) +#define PIXEL00_70 *(dp) = Interp07(w5, w4, w2) +#define PIXEL00_90 *(dp) = Interp09(w5, w4, w2) +#define PIXEL00_100 *(dp) = Interp10(w5, w4, w2) + +#define PIXEL01_0 *(dp + 1) = w5 +#define PIXEL01_10 *(dp + 1) = Interp01(w5, w3) +#define PIXEL01_11 *(dp + 1) = Interp01(w5, w2) +#define PIXEL01_12 *(dp + 1) = Interp01(w5, w6) +#define PIXEL01_20 *(dp + 1) = Interp02(w5, w2, w6) +#define PIXEL01_21 *(dp + 1) = Interp02(w5, w3, w6) +#define PIXEL01_22 *(dp + 1) = Interp02(w5, w3, w2) +#define PIXEL01_60 *(dp + 1) = Interp06(w5, w6, w2) +#define PIXEL01_61 *(dp + 1) = Interp06(w5, w2, w6) +#define PIXEL01_70 *(dp + 1) = Interp07(w5, w2, w6) +#define PIXEL01_90 *(dp + 1) = Interp09(w5, w2, w6) +#define PIXEL01_100 *(dp + 1) = Interp10(w5, w2, w6) + +#define PIXEL10_0 *(dp + dst1line) = w5 +#define PIXEL10_10 *(dp + dst1line) = Interp01(w5, w7) +#define PIXEL10_11 *(dp + dst1line) = Interp01(w5, w8) +#define PIXEL10_12 *(dp + dst1line) = Interp01(w5, w4) +#define PIXEL10_20 *(dp + dst1line) = Interp02(w5, w8, w4) +#define PIXEL10_21 *(dp + dst1line) = Interp02(w5, w7, w4) +#define PIXEL10_22 *(dp + dst1line) = Interp02(w5, w7, w8) +#define PIXEL10_60 *(dp + dst1line) = Interp06(w5, w4, w8) +#define PIXEL10_61 *(dp + dst1line) = Interp06(w5, w8, w4) +#define PIXEL10_70 *(dp + dst1line) = Interp07(w5, w8, w4) +#define PIXEL10_90 *(dp + dst1line) = Interp09(w5, w8, w4) +#define PIXEL10_100 *(dp + dst1line) = Interp10(w5, w8, w4) + +#define PIXEL11_0 *(dp + dst1line + 1) = w5 +#define PIXEL11_10 *(dp + dst1line + 1) = Interp01(w5, w9) +#define PIXEL11_11 *(dp + dst1line + 1) = Interp01(w5, w6) +#define PIXEL11_12 *(dp + dst1line + 1) = Interp01(w5, w8) +#define PIXEL11_20 *(dp + dst1line + 1) = Interp02(w5, w6, w8) +#define PIXEL11_21 *(dp + dst1line + 1) = Interp02(w5, w9, w8) +#define PIXEL11_22 *(dp + dst1line + 1) = Interp02(w5, w9, w6) +#define PIXEL11_60 *(dp + dst1line + 1) = Interp06(w5, w8, w6) +#define PIXEL11_61 *(dp + dst1line + 1) = Interp06(w5, w6, w8) +#define PIXEL11_70 *(dp + dst1line + 1) = Interp07(w5, w6, w8) +#define PIXEL11_90 *(dp + dst1line + 1) = Interp09(w5, w6, w8) +#define PIXEL11_100 *(dp + dst1line + 1) = Interp10(w5, w6, w8) + +#define Absolute(c) \ +(!(c & (1 << 31)) ? c : (~c + 1)) + +static inline bool Diff(int c1, int c2) +{ + int c1y = (c1 & Ymask) - (c2 & Ymask); + if (Absolute(c1y) > trY) return true; + int c1u = (c1 & Umask) - (c2 & Umask); + if (Absolute(c1u) > trU) return true; + int c1v = (c1 & Vmask) - (c2 & Vmask); + if (Absolute(c1v) > trV) return true; + + return false; +} + +void InitLUTs(void) +{ + int c, r, g, b, y, u, v; + + for (c = 0 ; c < (1<<NUMBITS) ; c++) + { +//#ifdef R5G6B5 + b = (int)((c & 0x1F)) << 3; + g = (int)((c & 0x7E0)) >> 3; + r = (int)((c & 0xF800)) >> 8; + +//#else +// b = (int)((c & 0x1F)) << 3; +// g = (int)((c & 0x3E0)) >> 2; +// r = (int)((c & 0x7C00)) >> 7; +//#endif + + RGBtoBright[c] = r+r+r + g+g+g + b+b; + + y = (int)( 0.256788f*r + 0.504129f*g + 0.097906f*b + 0.5f) + 16; + u = (int)(-0.148223f*r - 0.290993f*g + 0.439216f*b + 0.5f) + 128; + v = (int)( 0.439216f*r - 0.367788f*g - 0.071427f*b + 0.5f) + 128; + + RGBtoYUV[c] = (y << 16) + (u << 8) + v; + + } +} + +#define HQ2XCASES \ + case 0: case 1: case 4: case 32: case 128: case 5: case 132: case 160: case 33: case 129: case 36: case 133: case 164: case 161: case 37: case 165: PIXEL00_20; PIXEL01_20; PIXEL10_20; PIXEL11_20; break; \ + case 2: case 34: case 130: case 162: PIXEL00_22; PIXEL01_21; PIXEL10_20; PIXEL11_20; break; \ + case 16: case 17: case 48: case 49: PIXEL00_20; PIXEL01_22; PIXEL10_20; PIXEL11_21; break; \ + case 64: case 65: case 68: case 69: PIXEL00_20; PIXEL01_20; PIXEL10_21; PIXEL11_22; break; \ + case 8: case 12: case 136: case 140: PIXEL00_21; PIXEL01_20; PIXEL10_22; PIXEL11_20; break; \ + case 3: case 35: case 131: case 163: PIXEL00_11; PIXEL01_21; PIXEL10_20; PIXEL11_20; break; \ + case 6: case 38: case 134: case 166: PIXEL00_22; PIXEL01_12; PIXEL10_20; PIXEL11_20; break; \ + case 20: case 21: case 52: case 53: PIXEL00_20; PIXEL01_11; PIXEL10_20; PIXEL11_21; break; \ + case 144: case 145: case 176: case 177: PIXEL00_20; PIXEL01_22; PIXEL10_20; PIXEL11_12; break; \ + case 192: case 193: case 196: case 197: PIXEL00_20; PIXEL01_20; PIXEL10_21; PIXEL11_11; break; \ + case 96: case 97: case 100: case 101: PIXEL00_20; PIXEL01_20; PIXEL10_12; PIXEL11_22; break; \ + case 40: case 44: case 168: case 172: PIXEL00_21; PIXEL01_20; PIXEL10_11; PIXEL11_20; break; \ + case 9: case 13: case 137: case 141: PIXEL00_12; PIXEL01_20; PIXEL10_22; PIXEL11_20; break; \ + case 18: case 50: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_20; PIXEL10_20; PIXEL11_21; break; \ + case 80: case 81: PIXEL00_20; PIXEL01_22; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_20; break; \ + case 72: case 76: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_20; PIXEL11_22; break; \ + case 10: case 138: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_20; PIXEL01_21; PIXEL10_22; PIXEL11_20; break; \ + case 66: PIXEL00_22; PIXEL01_21; PIXEL10_21; PIXEL11_22; break; \ + case 24: PIXEL00_21; PIXEL01_22; PIXEL10_22; PIXEL11_21; break; \ + case 7: case 39: case 135: PIXEL00_11; PIXEL01_12; PIXEL10_20; PIXEL11_20; break; \ + case 148: case 149: case 180: PIXEL00_20; PIXEL01_11; PIXEL10_20; PIXEL11_12; break; \ + case 224: case 228: case 225: PIXEL00_20; PIXEL01_20; PIXEL10_12; PIXEL11_11; break; \ + case 41: case 169: case 45: PIXEL00_12; PIXEL01_20; PIXEL10_11; PIXEL11_20; break; \ + case 22: case 54: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_20; PIXEL11_21; break; \ + case 208: case 209: PIXEL00_20; PIXEL01_22; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 104: case 108: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \ + case 11: case 139: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; PIXEL10_22; PIXEL11_20; break; \ + case 19: case 51: if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL00_11, PIXEL01_10; else PIXEL00_60, PIXEL01_90; PIXEL10_20; PIXEL11_21; break; \ + case 146: case 178: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10, PIXEL11_12; else PIXEL01_90, PIXEL11_61; PIXEL10_20; break; \ + case 84: case 85: PIXEL00_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL01_11, PIXEL11_10; else PIXEL01_60, PIXEL11_90; PIXEL10_21; break; \ + case 112: case 113: PIXEL00_20; PIXEL01_22; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL10_12, PIXEL11_10; else PIXEL10_61, PIXEL11_90; break; \ + case 200: case 204: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10, PIXEL11_11; else PIXEL10_90, PIXEL11_60; break; \ + case 73: case 77: if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL00_12, PIXEL10_10; else PIXEL00_61, PIXEL10_90; PIXEL01_20; PIXEL11_22; break; \ + case 42: case 170: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10, PIXEL10_11; else PIXEL00_90, PIXEL10_60; PIXEL01_21; PIXEL11_20; break; \ + case 14: case 142: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10, PIXEL01_12; else PIXEL00_90, PIXEL01_61; PIXEL10_22; PIXEL11_20; break; \ + case 67: PIXEL00_11; PIXEL01_21; PIXEL10_21; PIXEL11_22; break; \ + case 70: PIXEL00_22; PIXEL01_12; PIXEL10_21; PIXEL11_22; break; \ + case 28: PIXEL00_21; PIXEL01_11; PIXEL10_22; PIXEL11_21; break; \ + case 152: PIXEL00_21; PIXEL01_22; PIXEL10_22; PIXEL11_12; break; \ + case 194: PIXEL00_22; PIXEL01_21; PIXEL10_21; PIXEL11_11; break; \ + case 98: PIXEL00_22; PIXEL01_21; PIXEL10_12; PIXEL11_22; break; \ + case 56: PIXEL00_21; PIXEL01_22; PIXEL10_11; PIXEL11_21; break; \ + case 25: PIXEL00_12; PIXEL01_22; PIXEL10_22; PIXEL11_21; break; \ + case 26: case 31: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_22; PIXEL11_21; break; \ + case 82: case 214: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 88: case 248: PIXEL00_21; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 74: case 107: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \ + case 27: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; PIXEL10_22; PIXEL11_21; break; \ + case 86: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_21; PIXEL11_10; break; \ + case 216: PIXEL00_21; PIXEL01_22; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 106: PIXEL00_10; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \ + case 30: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_22; PIXEL11_21; break; \ + case 210: PIXEL00_22; PIXEL01_10; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 120: PIXEL00_21; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \ + case 75: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; PIXEL10_10; PIXEL11_22; break; \ + case 29: PIXEL00_12; PIXEL01_11; PIXEL10_22; PIXEL11_21; break; \ + case 198: PIXEL00_22; PIXEL01_12; PIXEL10_21; PIXEL11_11; break; \ + case 184: PIXEL00_21; PIXEL01_22; PIXEL10_11; PIXEL11_12; break; \ + case 99: PIXEL00_11; PIXEL01_21; PIXEL10_12; PIXEL11_22; break; \ + case 57: PIXEL00_12; PIXEL01_22; PIXEL10_11; PIXEL11_21; break; \ + case 71: PIXEL00_11; PIXEL01_12; PIXEL10_21; PIXEL11_22; break; \ + case 156: PIXEL00_21; PIXEL01_11; PIXEL10_22; PIXEL11_12; break; \ + case 226: PIXEL00_22; PIXEL01_21; PIXEL10_12; PIXEL11_11; break; \ + case 60: PIXEL00_21; PIXEL01_11; PIXEL10_11; PIXEL11_21; break; \ + case 195: PIXEL00_11; PIXEL01_21; PIXEL10_21; PIXEL11_11; break; \ + case 102: PIXEL00_22; PIXEL01_12; PIXEL10_12; PIXEL11_22; break; \ + case 153: PIXEL00_12; PIXEL01_22; PIXEL10_22; PIXEL11_12; break; \ + case 58: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_11; PIXEL11_21; break; \ + case 83: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 92: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 202: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_11; break; \ + case 78: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_22; break; \ + case 154: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_22; PIXEL11_12; break; \ + case 114: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 89: PIXEL00_12; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 90: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 55: case 23: if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL00_11, PIXEL01_0; else PIXEL00_60, PIXEL01_90; PIXEL10_20; PIXEL11_21; break; \ + case 182: case 150: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0, PIXEL11_12; else PIXEL01_90, PIXEL11_61; PIXEL10_20; break; \ + case 213: case 212: PIXEL00_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL01_11, PIXEL11_0; else PIXEL01_60, PIXEL11_90; PIXEL10_21; break; \ + case 241: case 240: PIXEL00_20; PIXEL01_22; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL10_12, PIXEL11_0; else PIXEL10_61, PIXEL11_90; break; \ + case 236: case 232: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0, PIXEL11_11; else PIXEL10_90, PIXEL11_60; break; \ + case 109: case 105: if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL00_12, PIXEL10_0; else PIXEL00_61, PIXEL10_90; PIXEL01_20; PIXEL11_22; break; \ + case 171: case 43: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL10_11; else PIXEL00_90, PIXEL10_60; PIXEL01_21; PIXEL11_20; break; \ + case 143: case 15: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL01_12; else PIXEL00_90, PIXEL01_61; PIXEL10_22; PIXEL11_20; break; \ + case 124: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \ + case 203: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; PIXEL10_10; PIXEL11_11; break; \ + case 62: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_11; PIXEL11_21; break; \ + case 211: PIXEL00_11; PIXEL01_10; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 118: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_12; PIXEL11_10; break; \ + case 217: PIXEL00_12; PIXEL01_22; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 110: PIXEL00_10; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \ + case 155: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; PIXEL10_22; PIXEL11_12; break; \ + case 188: PIXEL00_21; PIXEL01_11; PIXEL10_11; PIXEL11_12; break; \ + case 185: PIXEL00_12; PIXEL01_22; PIXEL10_11; PIXEL11_12; break; \ + case 61: PIXEL00_12; PIXEL01_11; PIXEL10_11; PIXEL11_21; break; \ + case 157: PIXEL00_12; PIXEL01_11; PIXEL10_22; PIXEL11_12; break; \ + case 103: PIXEL00_11; PIXEL01_12; PIXEL10_12; PIXEL11_22; break; \ + case 227: PIXEL00_11; PIXEL01_21; PIXEL10_12; PIXEL11_11; break; \ + case 230: PIXEL00_22; PIXEL01_12; PIXEL10_12; PIXEL11_11; break; \ + case 199: PIXEL00_11; PIXEL01_12; PIXEL10_21; PIXEL11_11; break; \ + case 220: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 158: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_22; PIXEL11_12; break; \ + case 234: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_11; break; \ + case 242: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 59: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_11; PIXEL11_21; break; \ + case 121: PIXEL00_12; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 87: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 79: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_22; break; \ + case 122: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 94: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 218: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 91: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 229: PIXEL00_20; PIXEL01_20; PIXEL10_12; PIXEL11_11; break; \ + case 167: PIXEL00_11; PIXEL01_12; PIXEL10_20; PIXEL11_20; break; \ + case 173: PIXEL00_12; PIXEL01_20; PIXEL10_11; PIXEL11_20; break; \ + case 181: PIXEL00_20; PIXEL01_11; PIXEL10_20; PIXEL11_12; break; \ + case 186: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_11; PIXEL11_12; break; \ + case 115: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 93: PIXEL00_12; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 206: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_11; break; \ + case 205: case 201: PIXEL00_12; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_11; break; \ + case 174: case 46: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_12; PIXEL10_11; PIXEL11_20; break; \ + case 179: case 147: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_20; PIXEL11_12; break; \ + case 117: case 116: PIXEL00_20; PIXEL01_11; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 189: PIXEL00_12; PIXEL01_11; PIXEL10_11; PIXEL11_12; break; \ + case 231: PIXEL00_11; PIXEL01_12; PIXEL10_12; PIXEL11_11; break; \ + case 126: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \ + case 219: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 125: if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL00_12, PIXEL10_0; else PIXEL00_61, PIXEL10_90; PIXEL01_11; PIXEL11_10; break; \ + case 221: PIXEL00_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL01_11, PIXEL11_0; else PIXEL01_60, PIXEL11_90; PIXEL10_10; break; \ + case 207: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL01_12; else PIXEL00_90, PIXEL01_61; PIXEL10_10; PIXEL11_11; break; \ + case 238: PIXEL00_10; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0, PIXEL11_11; else PIXEL10_90, PIXEL11_60; break; \ + case 190: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0, PIXEL11_12; else PIXEL01_90, PIXEL11_61; PIXEL10_11; break; \ + case 187: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL10_11; else PIXEL00_90, PIXEL10_60; PIXEL01_10; PIXEL11_12; break; \ + case 243: PIXEL00_11; PIXEL01_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL10_12, PIXEL11_0; else PIXEL10_61, PIXEL11_90; break; \ + case 119: if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL00_11, PIXEL01_0; else PIXEL00_60, PIXEL01_90; PIXEL10_12; PIXEL11_10; break; \ + case 237: case 233: PIXEL00_12; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; PIXEL11_11; break; \ + case 175: case 47: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; PIXEL01_12; PIXEL10_11; PIXEL11_20; break; \ + case 183: case 151: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_20; PIXEL11_12; break; \ + case 245: case 244: PIXEL00_20; PIXEL01_11; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 250: PIXEL00_10; PIXEL01_10; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 123: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \ + case 95: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_10; PIXEL11_10; break; \ + case 222: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 252: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 249: PIXEL00_12; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 235: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; PIXEL11_11; break; \ + case 111: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \ + case 63: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_11; PIXEL11_21; break; \ + case 159: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_22; PIXEL11_12; break; \ + case 215: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 246: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 254: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 253: PIXEL00_12; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 251: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 239: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; PIXEL11_11; break; \ + case 127: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \ + case 191: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_11; PIXEL11_12; break; \ + case 223: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 247: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 255: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; + +template<int GuiScale> +void RenderHQ2X (uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + // If Snes9x is rendering anything in HiRes, then just copy, don't interpolate + if (height > SNES_HEIGHT_EXTENDED || width == 512) + { + //RenderSimple2X (Src, Dst, rect); + return; + } + + int w1, w2, w3, w4, w5, w6, w7, w8, w9; + + uint32 src1line = srcPitch >> 1; + uint32 dst1line = dstPitch >> 1; + uint16 *sp = (uint16 *) srcPtr; + uint16 *dp = (uint16 *) dstPtr; + + const int* RGBtoYUVtable = RGBtoYUV; + + uint32 pattern; + int l, y; + + while (height--) + { + sp--; + + w1 = *(sp - src1line); + w4 = *(sp); + w7 = *(sp + src1line); + + sp++; + + w2 = *(sp - src1line); + w5 = *(sp); + w8 = *(sp + src1line); + + for (l = width; l; l--) + { + sp++; + + w3 = *(sp - src1line); + w6 = *(sp); + w9 = *(sp + src1line); + + pattern = 0; + + switch(GuiScale) + { + case FILTER_HQ2XBOLD: { + const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9; + const bool diff5 = RGBtoBright[w5] > avg; + if ((w1 != w5) && ((RGBtoBright[w1] > avg) != diff5)) pattern |= (1 << 0); + if ((w2 != w5) && ((RGBtoBright[w2] > avg) != diff5)) pattern |= (1 << 1); + if ((w3 != w5) && ((RGBtoBright[w3] > avg) != diff5)) pattern |= (1 << 2); + if ((w4 != w5) && ((RGBtoBright[w4] > avg) != diff5)) pattern |= (1 << 3); + if ((w6 != w5) && ((RGBtoBright[w6] > avg) != diff5)) pattern |= (1 << 4); + if ((w7 != w5) && ((RGBtoBright[w7] > avg) != diff5)) pattern |= (1 << 5); + if ((w8 != w5) && ((RGBtoBright[w8] > avg) != diff5)) pattern |= (1 << 6); + if ((w9 != w5) && ((RGBtoBright[w9] > avg) != diff5)) pattern |= (1 << 7); + } break; + + case FILTER_HQ2XS: { + bool nosame = true; + if(w1 == w5 || w3 == w5 || w7 == w5 || w9 == w5) + nosame = false; + + if(nosame) + { + const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9; + const bool diff5 = RGBtoBright[w5] > avg; + if((RGBtoBright[w1] > avg) != diff5) pattern |= (1 << 0); + if((RGBtoBright[w2] > avg) != diff5) pattern |= (1 << 1); + if((RGBtoBright[w3] > avg) != diff5) pattern |= (1 << 2); + if((RGBtoBright[w4] > avg) != diff5) pattern |= (1 << 3); + if((RGBtoBright[w6] > avg) != diff5) pattern |= (1 << 4); + if((RGBtoBright[w7] > avg) != diff5) pattern |= (1 << 5); + if((RGBtoBright[w8] > avg) != diff5) pattern |= (1 << 6); + if((RGBtoBright[w9] > avg) != diff5) pattern |= (1 << 7); + } + else + { + y = RGBtoYUV[w5]; + if ((w1 != w5) && (Diff(y, RGBtoYUV[w1]))) pattern |= (1 << 0); + if ((w2 != w5) && (Diff(y, RGBtoYUV[w2]))) pattern |= (1 << 1); + if ((w3 != w5) && (Diff(y, RGBtoYUV[w3]))) pattern |= (1 << 2); + if ((w4 != w5) && (Diff(y, RGBtoYUV[w4]))) pattern |= (1 << 3); + if ((w6 != w5) && (Diff(y, RGBtoYUV[w6]))) pattern |= (1 << 4); + if ((w7 != w5) && (Diff(y, RGBtoYUV[w7]))) pattern |= (1 << 5); + if ((w8 != w5) && (Diff(y, RGBtoYUV[w8]))) pattern |= (1 << 6); + if ((w9 != w5) && (Diff(y, RGBtoYUV[w9]))) pattern |= (1 << 7); + } + } break; + default: + case FILTER_HQ2X: + y = RGBtoYUVtable[w5]; + if ((w1 != w5) && (Diff(y, RGBtoYUVtable[w1]))) pattern |= (1 << 0); + if ((w2 != w5) && (Diff(y, RGBtoYUVtable[w2]))) pattern |= (1 << 1); + if ((w3 != w5) && (Diff(y, RGBtoYUVtable[w3]))) pattern |= (1 << 2); + if ((w4 != w5) && (Diff(y, RGBtoYUVtable[w4]))) pattern |= (1 << 3); + if ((w6 != w5) && (Diff(y, RGBtoYUVtable[w6]))) pattern |= (1 << 4); + if ((w7 != w5) && (Diff(y, RGBtoYUVtable[w7]))) pattern |= (1 << 5); + if ((w8 != w5) && (Diff(y, RGBtoYUVtable[w8]))) pattern |= (1 << 6); + if ((w9 != w5) && (Diff(y, RGBtoYUVtable[w9]))) pattern |= (1 << 7); + break; + } + + switch (pattern) + { + HQ2XCASES + } + + w1 = w2; w4 = w5; w7 = w8; + w2 = w3; w5 = w6; w8 = w9; + + dp += 2; + } + + dp += ((dst1line - width) << 1); + sp += (src1line - width); + } +} + +template<int GuiScale> +void Scanlines (uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + while (height--) { + uint16 *dp = (uint16 *) dstPtr; + for (int i = 0; i < width; ++i, dp += 2) { + uint16 sp = *((uint16 *)srcPtr + i); + *(dp) = sp; + *(dp + 1) = sp; + *(dp + dstPitch) = 0; + *(dp + dstPitch + 1) = 0; + } + dstPtr += dstPitch<<1; + srcPtr += srcPitch; + } +} \ No newline at end of file diff --git a/plugins/snes9x_gx/source/filter.h b/plugins/snes9x_gx/source/filter.h new file mode 100644 index 00000000..cacbcb6c --- /dev/null +++ b/plugins/snes9x_gx/source/filter.h @@ -0,0 +1,64 @@ +/**************************************************************************** + * Snes9x 1.51 Nintendo Wii/Gamecube Port + * + * Michniewski 2008 + * + * filter.h + * + * Filters Header File + ****************************************************************************/ +#ifndef _FILTER_H_ +#define _FILTER_H_ + +#include <gccore.h> +#include <ogcsys.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> + +#include "snes9x.h" + +enum RenderFilter{ + FILTER_NONE = 0, + + FILTER_HQ2X, + FILTER_HQ2XS, + FILTER_HQ2XBOLD, + FILTER_SCANLINES, + + NUM_FILTERS +}; + +#define EXT_WIDTH (MAX_SNES_WIDTH + 4) +#define EXT_PITCH (EXT_WIDTH * 2) +#define EXT_HEIGHT (MAX_SNES_HEIGHT + 4) +// Offset into buffer to allow a two pixel border around the whole rendered +// SNES image. This is a speed up hack to allow some of the image processing +// routines to access black pixel data outside the normal bounds of the buffer. +#define EXT_OFFSET (EXT_PITCH * 2 + 2 * 2) + +typedef void (*TFilterMethod)(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height); + +extern TFilterMethod FilterMethod; +extern TFilterMethod FilterMethodHiRes; + +extern unsigned char * filtermem; + +// +// Prototypes +// +void SelectFilterMethod (); +void RenderPlain (uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height); +void SelectFilterMethod (); +TFilterMethod FilterToMethod (RenderFilter filterID); +const char* GetFilterName (RenderFilter filterID); +bool GetFilterHiResSupport (RenderFilter filterID); +int GetFilterScale(RenderFilter filterID); +template<int GuiScale> void RenderHQ2X (uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height); +template<int GuiScale> void Scanlines (uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height); +void InitLUTs(); + +#endif + diff --git a/plugins/snes9x_gx/source/fonts/font.ttf b/plugins/snes9x_gx/source/fonts/font.ttf new file mode 100644 index 00000000..01ce5816 Binary files /dev/null and b/plugins/snes9x_gx/source/fonts/font.ttf differ diff --git a/plugins/snes9x_gx/source/freeze.cpp b/plugins/snes9x_gx/source/freeze.cpp new file mode 100644 index 00000000..234e7641 --- /dev/null +++ b/plugins/snes9x_gx/source/freeze.cpp @@ -0,0 +1,168 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * crunchy2 May 2007-July 2007 + * Michniewski 2008 + * Tantric 2008-2010 + * + * freeze.cpp + ***************************************************************************/ + +#include <malloc.h> +#include <gccore.h> +#include <stdio.h> + +#include "snes9xgx.h" +#include "fileop.h" +#include "filebrowser.h" +#include "menu.h" +#include "video.h" +#include "utils/pngu.h" + +#include "snes9x/snes9x.h" +#include "snes9x/port.h" +#include "snes9x/memmap.h" +#include "snes9x/snapshot.h" +#include "snes9x/language.h" + +bool8 S9xOpenSnapshotFile(const char *filepath, bool8 readonly, STREAM *file) +{ + return FALSE; +} + +void S9xCloseSnapshotFile(STREAM s) +{ + +} + +/**************************************************************************** + * SaveSnapshot + ***************************************************************************/ + +int +SaveSnapshot (char * filepath, bool silent) +{ + int device; + + if(!FindDevice(filepath, &device)) + return 0; + + // save screenshot + if(gameScreenPngSize > 0) + { + char screenpath[1024]; + strcpy(screenpath, filepath); + screenpath[strlen(screenpath)-4] = 0; + sprintf(screenpath, "%s.png", screenpath); + SaveFile((char *)gameScreenPng, screenpath, gameScreenPngSize, silent); + } + + STREAM fp = OPEN_STREAM(filepath, "wb"); + + if(!fp) + { + if(!silent) + ErrorPrompt("Save failed!"); + return 0; + } + + S9xFreezeToStream(fp); + CLOSE_STREAM(fp); + + if(!silent) + InfoPrompt("Save successful"); + return 1; +} + +int +SaveSnapshotAuto (bool silent) +{ + char filepath[1024]; + + if(!MakeFilePath(filepath, FILE_SNAPSHOT, Memory.ROMFilename, 0)) + return false; + + return SaveSnapshot(filepath, silent); +} + +/**************************************************************************** + * LoadSnapshot + ***************************************************************************/ +int +LoadSnapshot (char * filepath, bool silent) +{ + int device; + + if(!FindDevice(filepath, &device)) + return 0; + + STREAM fp = OPEN_STREAM(filepath, "rb"); + + if(!fp) + { + if(!silent) + ErrorPrompt("Unable to open snapshot!"); + return 0; + } + + int result = S9xUnfreezeFromStream(fp); + CLOSE_STREAM(fp); + + if (result == SUCCESS) + return 1; + + switch (result) + { + case WRONG_FORMAT: + ErrorPrompt(SAVE_ERR_WRONG_FORMAT); + break; + + case WRONG_VERSION: + ErrorPrompt(SAVE_ERR_WRONG_VERSION); + break; + + case SNAPSHOT_INCONSISTENT: + ErrorPrompt(MOVIE_ERR_SNAPSHOT_INCONSISTENT); + break; + } + return 0; +} + +int +LoadSnapshotAuto (bool silent) +{ + char filepath[1024]; + + if(!MakeFilePath(filepath, FILE_SNAPSHOT, Memory.ROMFilename, 0)) + return false; + + return LoadSnapshot(filepath, silent); +} + +/**************************************************************************** + * SavePreview + ***************************************************************************/ + +int +SavePreviewImg (char * filepath, bool silent) +{ + int device; + + if(!FindDevice(filepath, &device)) + return 0; + + // save screenshot + if(gameScreenPngSize > 0) + { + char screenpath[1024]; + strcpy(screenpath, filepath); + screenpath[strlen(screenpath)] = 0; + sprintf(screenpath, "%s.png", screenpath); + SaveFile((char *)gameScreenPng, screenpath, gameScreenPngSize, silent); + } + + if(!silent) + InfoPrompt("Save successful"); + return 1; +} \ No newline at end of file diff --git a/plugins/snes9x_gx/source/freeze.h b/plugins/snes9x_gx/source/freeze.h new file mode 100644 index 00000000..9615bfda --- /dev/null +++ b/plugins/snes9x_gx/source/freeze.h @@ -0,0 +1,20 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * crunchy2 May 2007-July 2007 + * Michniewski 2008 + * Tantric 2008-2010 + * + * freeze.h + ***************************************************************************/ + +#ifndef _FREEZE_H_ +#define _FREEZE_H_ + +int SaveSnapshot (char * filepath, bool silent); +int SaveSnapshotAuto (bool silent); +int LoadSnapshot (char * filepath, bool silent); +int LoadSnapshotAuto (bool silent); +int SavePreviewImg (char * filepath, bool silent); +#endif diff --git a/plugins/snes9x_gx/source/gcunzip.cpp b/plugins/snes9x_gx/source/gcunzip.cpp new file mode 100644 index 00000000..01562d67 --- /dev/null +++ b/plugins/snes9x_gx/source/gcunzip.cpp @@ -0,0 +1,529 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * Michniewski 2008 + * Tantric 2008-2010 + * + * gcunzip.cpp + * + * File unzip routines + ***************************************************************************/ + +#include <gccore.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <zlib.h> +#include <sys/stat.h> + +#include "snes9xgx.h" +#include "fileop.h" +#include "filebrowser.h" +#include "menu.h" +#include "gcunzip.h" + +extern "C" { +#include "utils/sz/7zCrc.h" +#include "utils/sz/7zIn.h" +#include "utils/sz/7zExtract.h" +} + +#define ZIPCHUNK 2048 + +/* + * Zip file header definition + */ +typedef struct +{ + unsigned int zipid __attribute__ ((__packed__)); // 0x04034b50 + unsigned short zipversion __attribute__ ((__packed__)); + unsigned short zipflags __attribute__ ((__packed__)); + unsigned short compressionMethod __attribute__ ((__packed__)); + unsigned short lastmodtime __attribute__ ((__packed__)); + unsigned short lastmoddate __attribute__ ((__packed__)); + unsigned int crc32 __attribute__ ((__packed__)); + unsigned int compressedSize __attribute__ ((__packed__)); + unsigned int uncompressedSize __attribute__ ((__packed__)); + unsigned short filenameLength __attribute__ ((__packed__)); + unsigned short extraDataLength __attribute__ ((__packed__)); +} +PKZIPHEADER; + +/* + * Zip files are stored little endian + * Support functions for short and int types + */ +static u32 +FLIP32 (u32 b) +{ + unsigned int c; + + c = (b & 0xff000000) >> 24; + c |= (b & 0xff0000) >> 8; + c |= (b & 0xff00) << 8; + c |= (b & 0xff) << 24; + + return c; +} + +static u16 +FLIP16 (u16 b) +{ + u16 c; + + c = (b & 0xff00) >> 8; + c |= (b & 0xff) << 8; + + return c; +} + +/**************************************************************************** + * IsZipFile + * + * Returns TRUE when 0x504b0304 is first four characters of buffer + ***************************************************************************/ +int +IsZipFile (char *buffer) +{ + unsigned int *check = (unsigned int *) buffer; + + if (check[0] == 0x504b0304) + return 1; + + return 0; +} + +/***************************************************************************** +* UnZipBuffer +******************************************************************************/ + +size_t +UnZipBuffer (unsigned char *outbuffer) +{ + PKZIPHEADER pkzip; + size_t zipoffset = 0; + size_t zipchunk = 0; + char out[ZIPCHUNK]; + z_stream zs; + int res; + size_t bufferoffset = 0; + size_t have = 0; + char readbuffer[ZIPCHUNK]; + size_t sizeread = 0; + + // Read Zip Header + fseek(file, 0, SEEK_SET); + sizeread = fread (readbuffer, 1, ZIPCHUNK, file); + + if(sizeread <= 0) + return 0; + + /*** Copy PKZip header to local, used as info ***/ + memcpy (&pkzip, readbuffer, sizeof (PKZIPHEADER)); + + pkzip.uncompressedSize = FLIP32 (pkzip.uncompressedSize); + + ShowProgress ("Loading...", 0, pkzip.uncompressedSize); + + /*** Prepare the zip stream ***/ + memset (&zs, 0, sizeof (z_stream)); + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + zs.avail_in = 0; + zs.next_in = Z_NULL; + res = inflateInit2 (&zs, -MAX_WBITS); + + if (res != Z_OK) + goto done; + + /*** Set ZipChunk for first pass ***/ + zipoffset = + (sizeof (PKZIPHEADER) + FLIP16 (pkzip.filenameLength) + + FLIP16 (pkzip.extraDataLength)); + zipchunk = ZIPCHUNK - zipoffset; + + /*** Now do it! ***/ + do + { + zs.avail_in = zipchunk; + zs.next_in = (Bytef *) & readbuffer[zipoffset]; + + /*** Now inflate until input buffer is exhausted ***/ + do + { + zs.avail_out = ZIPCHUNK; + zs.next_out = (Bytef *) & out; + + res = inflate (&zs, Z_NO_FLUSH); + + if (res == Z_MEM_ERROR) + { + goto done; + } + + have = ZIPCHUNK - zs.avail_out; + if (have) + { + /*** Copy to normal block buffer ***/ + memcpy (&outbuffer[bufferoffset], &out, have); + bufferoffset += have; + } + } + while (zs.avail_out == 0); + + // Readup the next 2k block + zipoffset = 0; + zipchunk = ZIPCHUNK; + + sizeread = fread (readbuffer, 1, ZIPCHUNK, file); + if(sizeread <= 0) + goto done; // read failure + + ShowProgress ("Loading...", bufferoffset, pkzip.uncompressedSize); + } + while (res != Z_STREAM_END); + +done: + inflateEnd (&zs); + CancelAction(); + + if (res == Z_STREAM_END) + return pkzip.uncompressedSize; + else + return 0; +} + +/**************************************************************************** +* GetFirstZipFilename +* +* Returns the filename of the first file in the zipped archive +* The idea here is to do the least amount of work required +***************************************************************************/ + +char * +GetFirstZipFilename () +{ + char * firstFilename = NULL; + char tempbuffer[ZIPCHUNK]; + char filepath[1024]; + + if(!MakeFilePath(filepath, FILE_ROM)) + return NULL; + + // read start of ZIP + if(LoadFile (tempbuffer, filepath, ZIPCHUNK, NOTSILENT) < 35) + return NULL; + + tempbuffer[28] = 0; // truncate - filename length is 2 bytes long (bytes 26-27) + int namelength = tempbuffer[26]; // filename length starts 26 bytes in + + if(namelength < 0 || namelength > 200) // filename is not a reasonable length + { + ErrorPrompt("Error - Invalid ZIP file!"); + return NULL; + } + + firstFilename = &tempbuffer[30]; // first filename of a ZIP starts 31 bytes in + firstFilename[namelength] = 0; // truncate at filename length + return strdup(firstFilename); +} + +/**************************************************************************** +* 7z functions +***************************************************************************/ + +typedef struct _SzFileInStream +{ + ISzInStream InStream; + u64 offset; // offset of the file + unsigned int len; // length of the file + u64 pos; // current position of the file pointer +} SzFileInStream; + +// 7zip error list +static char szerrormsg[][100] = { + "File is corrupt.", // 7z: Data error + "Archive contains too many files.", // 7z: Out of memory + "File is corrupt (CRC mismatch).", // 7z: CRC Error + "File uses unsupported compression settings.", // 7z: Not implemented + "File is corrupt.", // 7z: Fail + "Failed to read file data.", // 7z: Data read failure + "File is corrupt.", // 7z: Archive error + "File uses too high of compression settings (dictionary size is too large).", // 7z: Dictionary too large +}; + +static SZ_RESULT SzRes; +static SzFileInStream SzArchiveStream; +static CArchiveDatabaseEx SzDb; +static ISzAlloc SzAllocImp; +static ISzAlloc SzAllocTempImp; +static UInt32 SzBlockIndex = 0xFFFFFFFF; +static size_t SzBufferSize; +static size_t SzOffset; +static size_t SzOutSizeProcessed; +static CFileItem *SzF; + +static char sz_buffer[2048]; +static int szMethod = 0; + +/**************************************************************************** +* Is7ZipFile +* +* Returns 1 when 7z signature is found +****************************************************************************/ +int +Is7ZipFile (char *buffer) +{ + // 7z signature + static Byte Signature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; + + int i; + for(i = 0; i < 6; i++) + if(buffer[i] != Signature[i]) + return 0; + + return 1; // 7z archive found +} + +// display an error message +static void SzDisplayError(SZ_RESULT res) +{ + char msg[1024]; + sprintf(msg, "7z decompression failed: %s", szerrormsg[(res - 1)]); + ErrorPrompt(msg); +} + +// function used by the 7zip SDK to read data from SD/USB/DVD/SMB +static SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize) +{ + size_t sizeread = 0; + + if(maxRequiredSize == 0) + return SZ_OK; + + // the void* object is a SzFileInStream + SzFileInStream *s = (SzFileInStream *) object; + + if (maxRequiredSize > 2048) + maxRequiredSize = 2048; + + // read data + sizeread = fread(sz_buffer, 1, maxRequiredSize, file); + + if(sizeread <= 0) + return SZE_FAILREAD; + + *buffer = sz_buffer; + *processedSize = sizeread; + s->pos += sizeread; + + if(sizeread > 1024) // only show progress for large reads + // this isn't quite right, but oh well + ShowProgress ("Loading...", s->pos, browserList[browser.selIndex].length); + + return SZ_OK; +} + +// function used by the 7zip SDK to change the filepointer +static SZ_RESULT SzFileSeekImp(void *object, CFileSize pos) +{ + // the void* object is a SzFileInStream + SzFileInStream *s = (SzFileInStream *) object; + + // check if the 7z SDK wants to move the pointer to somewhere after the EOF + if (pos >= s->len) + return SZE_FAIL; + + // save new position and return + if(fseek(file, (long)pos, SEEK_SET) != 0) + return SZE_FAIL; + + s->pos = pos; + return SZ_OK; +} + +/**************************************************************************** +* SzClose +* +* Closes a 7z file +***************************************************************************/ + +void SzClose() +{ + if(SzDb.Database.NumFiles > 0) + SzArDbExFree(&SzDb, SzAllocImp.Free); +} + + +/**************************************************************************** +* SzParse +* +* Opens a 7z file, and parses it +* It parses the entire 7z for full browsing capability +***************************************************************************/ + +int SzParse(char * filepath) +{ + if(!filepath) + return 0; + + int device; + + struct stat filestat; + if(stat(filepath, &filestat) < 0) + return 0; + unsigned int filelen = filestat.st_size; + + if(!FindDevice(filepath, &device) || !filelen) + return 0; + + int nbfiles = 0; + // setup archive stream + SzArchiveStream.offset = 0; + SzArchiveStream.len = filelen; + SzArchiveStream.pos = 0; + + // open file + file = fopen (filepath, "rb"); + if(!file) + return 0; + + // set szMethod to current chosen load device + szMethod = device; + + // set handler functions for reading data from SD/USB/SMB/DVD + SzArchiveStream.InStream.Read = SzFileReadImp; + SzArchiveStream.InStream.Seek = SzFileSeekImp; + + // set default 7Zip SDK handlers for allocation and freeing memory + SzAllocImp.Alloc = SzAlloc; + SzAllocImp.Free = SzFree; + SzAllocTempImp.Alloc = SzAllocTemp; + SzAllocTempImp.Free = SzFreeTemp; + + // prepare CRC and 7Zip database structures + InitCrcTable(); + SzArDbExInit(&SzDb); + + // open the archive + SzRes = SzArchiveOpen(&SzArchiveStream.InStream, &SzDb, &SzAllocImp, + &SzAllocTempImp); + + if (SzRes != SZ_OK) + { + SzDisplayError(SzRes); + // free memory used by the 7z SDK + SzClose(); + } + else // archive opened successfully + { + if(SzDb.Database.NumFiles > 0) + { + // Parses the 7z into a full file listing + + HaltParseThread(); // halt parsing + ResetBrowser(); // reset browser + + // add '..' folder in case the user wants exit the 7z + AddBrowserEntry(); + sprintf(browserList[0].filename, ".."); + sprintf(browserList[0].displayname, "Up One Level"); + browserList[0].isdir = 1; + browserList[0].length = filelen; + browserList[0].icon = ICON_FOLDER; + + // get contents and parse them into file list structure + unsigned int SzI, SzJ; + SzJ = 1; + for (SzI = 0; SzI < SzDb.Database.NumFiles; SzI++) + { + SzF = SzDb.Database.Files + SzI; + + // skip directories + if (SzF->IsDirectory) + continue; + + if(!AddBrowserEntry()) + { + ResetBrowser(); + ErrorPrompt("Out of memory: too many files!"); + SzClose(); + SzJ = 0; + break; + } + + // parse information about this file to the file list structure + snprintf(browserList[SzJ].filename, MAXJOLIET, "%s", SzF->Name); + StripExt(browserList[SzJ].displayname, browserList[SzJ].filename); + char* strPos = strstr(browserList[SzJ].displayname, szname); + if(strPos) + { + snprintf(browserList[SzJ].displayname, MAXJOLIET, "%s", strPos + strlen(szname)); + } + + browserList[SzJ].length = SzF->Size; // filesize + browserList[SzJ].isdir = 0; // only files will be displayed (-> no flags) + browserList[SzJ].filenum = SzI; // the extraction function identifies the file with this number + SzJ++; + } + nbfiles = SzJ; + } + else + { + SzClose(); + } + } + + CancelAction(); + + // close file + fclose(file); + return nbfiles; +} + +/**************************************************************************** +* SzExtractFile +* +* Extracts the given file # into the buffer specified +* Must parse the 7z BEFORE running this function +***************************************************************************/ + +size_t SzExtractFile(int i, unsigned char *buffer) +{ + // prepare some variables + SzBlockIndex = 0xFFFFFFFF; + SzOffset = 0; + + // Unzip the file + + SzRes = SzExtract2( + &SzArchiveStream.InStream, + &SzDb, + i, // index of file + &SzBlockIndex, // index of solid block + &buffer, + &SzBufferSize, + &SzOffset, // offset of stream for required file in *outBuffer + &SzOutSizeProcessed, // size of file in *outBuffer + &SzAllocImp, + &SzAllocTempImp); + + // close 7Zip archive and free memory + SzClose(); + + CancelAction(); + + // check for errors + if(SzRes != SZ_OK) + { + // display error message + SzDisplayError(SzRes); + return 0; + } + else + { + return SzOutSizeProcessed; + } +} diff --git a/plugins/snes9x_gx/source/gcunzip.h b/plugins/snes9x_gx/source/gcunzip.h new file mode 100644 index 00000000..9b606bf5 --- /dev/null +++ b/plugins/snes9x_gx/source/gcunzip.h @@ -0,0 +1,22 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * Michniewski 2008 + * Tantric 2008-2010 + * + * gcunzip.h + * + * File unzip routines + ****************************************************************************/ +#ifndef _GCUNZIP_H_ +#define _GCUNZIP_H_ + +int IsZipFile (char *buffer); +char * GetFirstZipFilename(); +size_t UnZipBuffer (unsigned char *outbuffer); +int SzParse(char * filepath); +size_t SzExtractFile(int i, unsigned char *buffer); +void SzClose(); + +#endif diff --git a/plugins/snes9x_gx/source/gui/gui.h b/plugins/snes9x_gx/source/gui/gui.h new file mode 100644 index 00000000..7f31cc05 --- /dev/null +++ b/plugins/snes9x_gx/source/gui/gui.h @@ -0,0 +1,1064 @@ +/*!\mainpage libwiigui Documentation + * + * \section Introduction + * libwiigui is a GUI library for the Wii, created to help structure the + * design of a complicated GUI interface, and to enable an author to create + * a sophisticated, feature-rich GUI. It was originally conceived and written + * after I started to design a GUI for Snes9x GX, and found libwiisprite and + * GRRLIB inadequate for the purpose. It uses GX for drawing, and makes use + * of PNGU for displaying images and FreeTypeGX for text. It was designed to + * be flexible and is easy to modify - don't be afraid to change the way it + * works or expand it to suit your GUI's purposes! If you do, and you think + * your changes might benefit others, please share them so they might be + * added to the project! + * + * \section Quickstart + * Start from the supplied template example. For more advanced uses, see the + * source code for Snes9x GX, FCE Ultra GX, and Visual Boy Advance GX. + + * \section Contact + * If you have any suggestions for the library or documentation, or want to + * contribute, please visit the libwiigui website: + * http://code.google.com/p/libwiigui/ + + * \section Credits + * This library was wholly designed and written by Tantric. Thanks to the + * authors of PNGU and FreeTypeGX, of which this library makes use. Thanks + * also to the authors of GRRLIB and libwiisprite for laying the foundations. + * +*/ + +#ifndef LIBWIIGUI_H +#define LIBWIIGUI_H + +#include <gccore.h> +#include <malloc.h> +#include <stdlib.h> +#include <string.h> +#include <vector> +#include <exception> +#include <wchar.h> +#include <math.h> +#include <asndlib.h> +#include <wiiuse/wpad.h> + +#include "snes9xgx.h" +#include "video.h" +#include "filelist.h" +#include "fileop.h" +#include "input.h" +#include "../utils/pngu.h" +#include "../utils/FreeTypeGX.h" +#include "../utils/oggplayer.h" + +extern FreeTypeGX *fontSystem[]; + +#define SCROLL_DELAY_INITIAL 200000 +#define SCROLL_DELAY_LOOP 30000 +#define SCROLL_DELAY_DECREASE 300 +#define FILE_PAGESIZE 10 +#define PAGESIZE 8 +#define SAVELISTSIZE 6 +#define MAX_SAVES 100 +#define MAX_OPTIONS 150 +#define MAX_KEYBOARD_DISPLAY 32 + +typedef void (*UpdateCallback)(void * e); + +enum +{ + ALIGN_LEFT, + ALIGN_RIGHT, + ALIGN_CENTRE, + ALIGN_TOP, + ALIGN_BOTTOM, + ALIGN_MIDDLE +}; + +enum +{ + STATE_DEFAULT, + STATE_SELECTED, + STATE_CLICKED, + STATE_HELD, + STATE_DISABLED +}; + +enum +{ + SOUND_PCM, + SOUND_OGG +}; + +enum +{ + IMAGE_TEXTURE, + IMAGE_COLOR, + IMAGE_DATA +}; + +enum +{ + TRIGGER_SIMPLE, + TRIGGER_HELD, + TRIGGER_BUTTON_ONLY, + TRIGGER_BUTTON_ONLY_IN_FOCUS +}; + +enum +{ + SCROLL_NONE, + SCROLL_HORIZONTAL +}; + +typedef struct _paddata { + u16 btns_d; + u16 btns_u; + u16 btns_h; + s8 stickX; + s8 stickY; + s8 substickX; + s8 substickY; + u8 triggerL; + u8 triggerR; +} PADData; + +typedef struct _wupcfulldata { + u32 btns_d; + u32 btns_u; + u32 btns_h; + s16 stickX; + s16 stickY; + s16 substickX; + s16 substickY; +} WUPCFullData; + +#define EFFECT_SLIDE_TOP 1 +#define EFFECT_SLIDE_BOTTOM 2 +#define EFFECT_SLIDE_RIGHT 4 +#define EFFECT_SLIDE_LEFT 8 +#define EFFECT_SLIDE_IN 16 +#define EFFECT_SLIDE_OUT 32 +#define EFFECT_FADE 64 +#define EFFECT_SCALE 128 +#define EFFECT_COLOR_TRANSITION 256 + +//!Sound conversion and playback. A wrapper for other sound libraries - ASND, libmad, ltremor, etc +class GuiSound +{ + public: + //!Constructor + //!\param s Pointer to the sound data + //!\param l Length of sound data + //!\param t Sound format type (SOUND_PCM or SOUND_OGG) + GuiSound(const u8 * s, s32 l, int t); + //!Destructor + ~GuiSound(); + //!Start sound playback + void Play(); + //!Stop sound playback + void Stop(); + //!Pause sound playback + void Pause(); + //!Resume sound playback + void Resume(); + //!Checks if the sound is currently playing + //!\return true if sound is playing, false otherwise + bool IsPlaying(); + //!Set sound volume + //!\param v Sound volume (0-100) + void SetVolume(int v); + //!Set the sound to loop playback (only applies to OGG) + //!\param l Loop (true to loop) + void SetLoop(bool l); + protected: + const u8 * sound; //!< Pointer to the sound data + int type; //!< Sound format type (SOUND_PCM or SOUND_OGG) + s32 length; //!< Length of sound data + s32 voice; //!< Currently assigned ASND voice channel + s32 volume; //!< Sound volume (0-100) + bool loop; //!< Loop sound playback +}; + +//!Menu input trigger management. Determine if action is neccessary based on input data by comparing controller input data to a specific trigger element. +class GuiTrigger +{ + public: + //!Constructor + GuiTrigger(); + //!Destructor + ~GuiTrigger(); + //!Sets a simple trigger. Requires: element is selected, and trigger button is pressed + //!\param ch Controller channel number + //!\param wiibtns Wii controller trigger button(s) - classic controller buttons are considered separately + //!\param gcbtns GameCube controller trigger button(s) + void SetSimpleTrigger(s32 ch, u32 wiibtns, u16 gcbtns); + //!Sets a held trigger. Requires: element is selected, and trigger button is pressed + //!\param ch Controller channel number + //!\param wiibtns Wii controller trigger button(s) - classic controller buttons are considered separately + //!\param gcbtns GameCube controller trigger button(s) + void SetHeldTrigger(s32 ch, u32 wiibtns, u16 gcbtns); + //!Sets a button-only trigger. Requires: Trigger button is pressed + //!\param ch Controller channel number + //!\param wiibtns Wii controller trigger button(s) - classic controller buttons are considered separately + //!\param gcbtns GameCube controller trigger button(s) + void SetButtonOnlyTrigger(s32 ch, u32 wiibtns, u16 gcbtns); + //!Sets a button-only trigger. Requires: trigger button is pressed and parent window of element is in focus + //!\param ch Controller channel number + //!\param wiibtns Wii controller trigger button(s) - classic controller buttons are considered separately + //!\param gcbtns GameCube controller trigger button(s) + void SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns); + //!Get X or Y value from Wii Joystick (classic, nunchuk) input + //!\param stick Controller stick (left = 0, right = 1) + //!\param axis Controller stick axis (x-axis = 0, y-axis = 1) + //!\return Stick value + s8 WPAD_Stick(u8 stick, int axis); + //!Get X value from Wii Joystick (classic, nunchuk) input + //!\param stick Controller stick (left = 0, right = 1) + //!\return Stick value + s8 WPAD_StickX(u8 stick); + //!Get Y value from Wii Joystick (classic, nunchuk) input + //!\param stick Controller stick (left = 0, right = 1) + //!\return Stick value + s8 WPAD_StickY(u8 stick); + //!Move menu selection left (via pad/joystick). Allows scroll delay and button overriding + //!\return true if selection should be moved left, false otherwise + bool Left(); + //!Move menu selection right (via pad/joystick). Allows scroll delay and button overriding + //!\return true if selection should be moved right, false otherwise + bool Right(); + //!Move menu selection up (via pad/joystick). Allows scroll delay and button overriding + //!\return true if selection should be moved up, false otherwise + bool Up(); + //!Move menu selection down (via pad/joystick). Allows scroll delay and button overriding + //!\return true if selection should be moved down, false otherwise + bool Down(); + + WPADData wpaddata; //!< Wii controller trigger data + PADData pad; //!< GameCube controller trigger data + WUPCFullData wupcdata; //!< WiiU Pro controller trigger data + WPADData * wpad; //!< Wii controller trigger + s32 chan; //!< Trigger controller channel (0-3, -1 for all) + u8 type; //!< trigger type (TRIGGER_SIMPLE, TRIGGER_HELD, TRIGGER_BUTTON_ONLY, TRIGGER_BUTTON_ONLY_IN_FOCUS) +}; + +extern GuiTrigger userInput[4]; + +//!Primary GUI class. Most other classes inherit from this class. +class GuiElement +{ + public: + //!Constructor + GuiElement(); + //!Destructor + virtual ~GuiElement(); + //!Set the element's parent + //!\param e Pointer to parent element + void SetParent(GuiElement * e); + //!Gets the element's parent + //!\return Pointer to parent element + GuiElement * GetParent(); + //!Gets the current leftmost coordinate of the element + //!Considers horizontal alignment, x offset, width, and parent element's GetLeft() / GetWidth() values + //!\return left coordinate + int GetLeft(); + //!Gets the current topmost coordinate of the element + //!Considers vertical alignment, y offset, height, and parent element's GetTop() / GetHeight() values + //!\return top coordinate + int GetTop(); + //!Sets the minimum y offset of the element + //!\param y Y offset + void SetMinY(int y); + //!Gets the minimum y offset of the element + //!\return Minimum Y offset + int GetMinY(); + //!Sets the maximum y offset of the element + //!\param y Y offset + void SetMaxY(int y); + //!Gets the maximum y offset of the element + //!\return Maximum Y offset + int GetMaxY(); + //!Sets the minimum x offset of the element + //!\param x X offset + void SetMinX(int x); + //!Gets the minimum x offset of the element + //!\return Minimum X offset + int GetMinX(); + //!Sets the maximum x offset of the element + //!\param x X offset + void SetMaxX(int x); + //!Gets the maximum x offset of the element + //!\return Maximum X offset + int GetMaxX(); + //!Gets the current width of the element. Does not currently consider the scale + //!\return width + int GetWidth(); + //!Gets the height of the element. Does not currently consider the scale + //!\return height + int GetHeight(); + //!Sets the size (width/height) of the element + //!\param w Width of element + //!\param h Height of element + void SetSize(int w, int h); + //!Checks whether or not the element is visible + //!\return true if visible, false otherwise + bool IsVisible(); + //!Checks whether or not the element is selectable + //!\return true if selectable, false otherwise + bool IsSelectable(); + //!Checks whether or not the element is clickable + //!\return true if clickable, false otherwise + bool IsClickable(); + //!Checks whether or not the element is holdable + //!\return true if holdable, false otherwise + bool IsHoldable(); + //!Sets whether or not the element is selectable + //!\param s Selectable + void SetSelectable(bool s); + //!Sets whether or not the element is clickable + //!\param c Clickable + void SetClickable(bool c); + //!Sets whether or not the element is holdable + //!\param h Holdable + void SetHoldable(bool h); + //!Gets the element's current state + //!\return state + int GetState(); + //!Gets the controller channel that last changed the element's state + //!\return Channel number (0-3, -1 = no channel) + int GetStateChan(); + //!Sets the element's alpha value + //!\param a alpha value + void SetAlpha(int a); + //!Gets the element's alpha value + //!Considers alpha, alphaDyn, and the parent element's GetAlpha() value + //!\return alpha + int GetAlpha(); + //!Sets the element's x and y scale + //!\param s scale (1 is 100%) + void SetScale(float s); + //!Sets the element's x scale + //!\param s scale (1 is 100%) + void SetScaleX(float s); + //!Sets the element's y scale + //!\param s scale (1 is 100%) + void SetScaleY(float s); + //!Sets the element's x and y scale, using the provided max width/height + //!\param w Maximum width + //!\param h Maximum height + void SetScale(int w, int h); + //!Gets the element's current scale + //!Considers scale, scaleDyn, and the parent element's GetScale() value + float GetScale(); + //!Gets the element's current x scale + //!Considers scale, scaleDyn, and the parent element's GetScale() value + float GetScaleX(); + //!Gets the element's current y scale + //!Considers scale, scaleDyn, and the parent element's GetScale() value + float GetScaleY(); + //!Set a new GuiTrigger for the element + //!\param t Pointer to GuiTrigger + void SetTrigger(GuiTrigger * t); + //!\overload + //!\param i Index of trigger array to set + //!\param t Pointer to GuiTrigger + void SetTrigger(u8 i, GuiTrigger * t); + //!Checks whether rumble was requested by the element + //!\return true is rumble was requested, false otherwise + bool Rumble(); + //!Sets whether or not the element is requesting a rumble event + //!\param r true if requesting rumble, false if not + void SetRumble(bool r); + //!Set an effect for the element + //!\param e Effect to enable + //!\param a Amount of the effect (usage varies on effect) + //!\param t Target amount of the effect (usage varies on effect) + void SetEffect(int e, int a, int t=0); + //!Sets an effect to be enabled on wiimote cursor over + //!\param e Effect to enable + //!\param a Amount of the effect (usage varies on effect) + //!\param t Target amount of the effect (usage varies on effect) + void SetEffectOnOver(int e, int a, int t=0); + //!Shortcut to SetEffectOnOver(EFFECT_SCALE, 4, 110) + void SetEffectGrow(); + //!Gets the current element effects + //!\return element effects + int GetEffect(); + //!Checks whether the specified coordinates are within the element's boundaries + //!\param x X coordinate + //!\param y Y coordinate + //!\return true if contained within, false otherwise + bool IsInside(int x, int y); + //!Sets the element's position + //!\param x X coordinate + //!\param y Y coordinate + void SetPosition(int x, int y); + //!Updates the element's effects (dynamic values) + //!Called by Draw(), used for animation purposes + void UpdateEffects(); + //!Sets a function to called after after Update() + //!Callback function can be used to response to changes in the state of the element, and/or update the element's attributes + void SetUpdateCallback(UpdateCallback u); + //!Checks whether the element is in focus + //!\return true if element is in focus, false otherwise + int IsFocused(); + //!Sets the element's visibility + //!\param v Visibility (true = visible) + virtual void SetVisible(bool v); + //!Sets the element's focus + //!\param f Focus (true = in focus) + virtual void SetFocus(int f); + //!Sets the element's state + //!\param s State (STATE_DEFAULT, STATE_SELECTED, STATE_CLICKED, STATE_DISABLED) + //!\param c Controller channel (0-3, -1 = none) + virtual void SetState(int s, int c = -1); + //!Resets the element's state to STATE_DEFAULT + virtual void ResetState(); + //!Gets whether or not the element is in STATE_SELECTED + //!\return true if selected, false otherwise + virtual int GetSelected(); + //!Sets the element's alignment respective to its parent element + //!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE) + //!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE) + virtual void SetAlignment(int hor, int vert); + //!Called when the language has changed, to obtain new text values for all text elements + virtual void ResetText(); + //!Called constantly to allow the element to respond to the current input data + //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD + virtual void Update(GuiTrigger * t); + //!Called constantly to redraw the element + virtual void Draw(); + //!Called constantly to redraw the element's tooltip + virtual void DrawTooltip(); + protected: + GuiTrigger * trigger[3]; //!< GuiTriggers (input actions) that this element responds to + UpdateCallback updateCB; //!< Callback function to call when this element is updated + GuiElement * parentElement; //!< Parent element + int focus; //!< Element focus (-1 = focus disabled, 0 = not focused, 1 = focused) + int width; //!< Element width + int height; //!< Element height + int xoffset; //!< Element X offset + int yoffset; //!< Element Y offset + int ymin; //!< Element's min Y offset allowed + int ymax; //!< Element's max Y offset allowed + int xmin; //!< Element's min X offset allowed + int xmax; //!< Element's max X offset allowed + int xoffsetDyn; //!< Element X offset, dynamic (added to xoffset value for animation effects) + int yoffsetDyn; //!< Element Y offset, dynamic (added to yoffset value for animation effects) + int alpha; //!< Element alpha value (0-255) + int alphaDyn; //!< Element alpha, dynamic (multiplied by alpha value for blending/fading effects) + f32 xscale; //!< Element X scale (1 = 100%) + f32 yscale; //!< Element Y scale (1 = 100%) + f32 scaleDyn; //!< Element scale, dynamic (multiplied by alpha value for blending/fading effects) + int effects; //!< Currently enabled effect(s). 0 when no effects are enabled + int effectAmount; //!< Effect amount. Used by different effects for different purposes + int effectTarget; //!< Effect target amount. Used by different effects for different purposes + int effectsOver; //!< Effects to enable when wiimote cursor is over this element. Copied to effects variable on over event + int effectAmountOver; //!< EffectAmount to set when wiimote cursor is over this element + int effectTargetOver; //!< EffectTarget to set when wiimote cursor is over this element + int alignmentHor; //!< Horizontal element alignment, respective to parent element (LEFT, RIGHT, CENTRE) + int alignmentVert; //!< Horizontal element alignment, respective to parent element (TOP, BOTTOM, MIDDLE) + int state; //!< Element state (DEFAULT, SELECTED, CLICKED, DISABLED) + int stateChan; //!< Which controller channel is responsible for the last change in state + bool selectable; //!< Whether or not this element selectable (can change to SELECTED state) + bool clickable; //!< Whether or not this element is clickable (can change to CLICKED state) + bool holdable; //!< Whether or not this element is holdable (can change to HELD state) + bool visible; //!< Visibility of the element. If false, Draw() is skipped + bool rumble; //!< Wiimote rumble (on/off) - set to on when this element requests a rumble event +}; + +//!Allows GuiElements to be grouped together into a "window" +class GuiWindow : public GuiElement +{ + public: + //!Constructor + GuiWindow(); + //!\overload + //!\param w Width of window + //!\param h Height of window + GuiWindow(int w, int h); + //!Destructor + ~GuiWindow(); + //!Appends a GuiElement to the GuiWindow + //!\param e The GuiElement to append. If it is already in the GuiWindow, it is removed first + void Append(GuiElement* e); + //!Inserts a GuiElement into the GuiWindow at the specified index + //!\param e The GuiElement to insert. If it is already in the GuiWindow, it is removed first + //!\param i Index in which to insert the element + void Insert(GuiElement* e, u32 i); + //!Removes the specified GuiElement from the GuiWindow + //!\param e GuiElement to be removed + void Remove(GuiElement* e); + //!Removes all GuiElements + void RemoveAll(); + //!Looks for the specified GuiElement + //!\param e The GuiElement to find + //!\return true if found, false otherwise + bool Find(GuiElement* e); + //!Returns the GuiElement at the specified index + //!\param index The index of the element + //!\return A pointer to the element at the index, NULL on error (eg: out of bounds) + GuiElement* GetGuiElementAt(u32 index) const; + //!Returns the size of the list of elements + //!\return The size of the current element list + u32 GetSize(); + //!Sets the visibility of the window + //!\param v visibility (true = visible) + void SetVisible(bool v); + //!Resets the window's state to STATE_DEFAULT + void ResetState(); + //!Sets the window's state + //!\param s State + void SetState(int s); + //!Gets the index of the GuiElement inside the window that is currently selected + //!\return index of selected GuiElement + int GetSelected(); + //!Sets the window focus + //!\param f Focus + void SetFocus(int f); + //!Change the focus to the specified element + //!This is intended for the primary GuiWindow only + //!\param e GuiElement that should have focus + void ChangeFocus(GuiElement * e); + //!Changes window focus to the next focusable window or element + //!If no element is in focus, changes focus to the first available element + //!If B or 1 button is pressed, changes focus to the next available element + //!This is intended for the primary GuiWindow only + //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD + void ToggleFocus(GuiTrigger * t); + //!Moves the selected element to the element to the left or right + //!\param d Direction to move (-1 = left, 1 = right) + void MoveSelectionHor(int d); + //!Moves the selected element to the element above or below + //!\param d Direction to move (-1 = up, 1 = down) + void MoveSelectionVert(int d); + //!Resets the text for all contained elements + void ResetText(); + //!Draws all the elements in this GuiWindow + void Draw(); + //!Draws all of the tooltips in this GuiWindow + void DrawTooltip(); + //!Updates the window and all elements contains within + //!Allows the GuiWindow and all elements to respond to the input data specified + //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD + void Update(GuiTrigger * t); + protected: + std::vector<GuiElement*> _elements; //!< Contains all elements within the GuiWindow +}; + +//!Converts image data into GX-useable RGBA8. Currently designed for use only with PNG files +class GuiImageData +{ + public: + //!Constructor + //!Converts the image data to RGBA8 - expects PNG format + //!\param i Image data + //!\param w Max image width (0 = not set) + //!\param h Max image height (0 = not set) + GuiImageData(const u8 * i, int w=0, int h=0); + //!Destructor + ~GuiImageData(); + //!Gets a pointer to the image data + //!\return pointer to image data + u8 * GetImage(); + //!Gets the image width + //!\return image width + int GetWidth(); + //!Gets the image height + //!\return image height + int GetHeight(); + protected: + u8 * data; //!< Image data + int height; //!< Height of image + int width; //!< Width of image +}; + +//!Display, manage, and manipulate images in the GUI +class GuiImage : public GuiElement +{ + public: + //!Constructor + GuiImage(); + //!\overload + //!\param img Pointer to GuiImageData element + GuiImage(GuiImageData * img); + //!\overload + //!Sets up a new image from the image data specified + //!\param img + //!\param w Image width + //!\param h Image height + GuiImage(u8 * img, int w, int h); + //!\overload + //!Creates an image filled with the specified color + //!\param w Image width + //!\param h Image height + //!\param c Image color + GuiImage(int w, int h, GXColor c); + //!Destructor + ~GuiImage(); + //!Sets the image rotation angle for drawing + //!\param a Angle (in degrees) + void SetAngle(float a); + //!Sets the number of times to draw the image horizontally + //!\param t Number of times to draw the image + void SetTile(int t); + //!Constantly called to draw the image + void Draw(); + //!Gets the image data + //!\return pointer to image data + u8 * GetImage(); + //!Sets up a new image using the GuiImageData object specified + //!\param img Pointer to GuiImageData object + void SetImage(GuiImageData * img); + //!\overload + //!\param img Pointer to image data + //!\param w Width + //!\param h Height + void SetImage(u8 * img, int w, int h); + //!Gets the pixel color at the specified coordinates of the image + //!\param x X coordinate + //!\param y Y coordinate + GXColor GetPixel(int x, int y); + //!Sets the pixel color at the specified coordinates of the image + //!\param x X coordinate + //!\param y Y coordinate + //!\param color Pixel color + void SetPixel(int x, int y, GXColor color); + //!Directly modifies the image data to create a color-striped effect + //!Alters the RGB values by the specified amount + //!\param s Amount to increment/decrement the RGB values in the image + void ColorStripe(int s); + //!Sets a stripe effect on the image, overlaying alpha blended rectangles + //!Does not alter the image data + //!\param s Alpha amount to draw over the image + void SetStripe(int s); + protected: + int imgType; //!< Type of image data (IMAGE_TEXTURE, IMAGE_COLOR, IMAGE_DATA) + u8 * image; //!< Poiner to image data. May be shared with GuiImageData data + f32 imageangle; //!< Angle to draw the image + int tile; //!< Number of times to draw (tile) the image horizontally + int stripe; //!< Alpha value (0-255) to apply a stripe effect to the texture +}; + +//!Display, manage, and manipulate text in the GUI +class GuiText : public GuiElement +{ + public: + //!Constructor + //!\param t Text + //!\param s Font size + //!\param c Font color + GuiText(const char * t, int s, GXColor c); + //!\overload + //!Assumes SetPresets() has been called to setup preferred text attributes + //!\param t Text + GuiText(const char * t); + //!Destructor + ~GuiText(); + //!Sets the text of the GuiText element + //!\param t Text + void SetText(const char * t); + //!Sets the text of the GuiText element + //!\param t UTF-8 Text + void SetWText(wchar_t * t); + //!Gets the translated text length of the GuiText element + int GetLength(); + //!Sets up preset values to be used by GuiText(t) + //!Useful when printing multiple text elements, all with the same attributes set + //!\param sz Font size + //!\param c Font color + //!\param w Maximum width of texture image (for text wrapping) + //!\param s Font size + //!\param h Text alignment (horizontal) + //!\param v Text alignment (vertical) + void SetPresets(int sz, GXColor c, int w, u16 s, int h, int v); + //!Sets the font size + //!\param s Font size + void SetFontSize(int s); + //!Sets the maximum width of the drawn texture image + //!\param w Maximum width + void SetMaxWidth(int w); + //!Gets the width of the text when rendered + int GetTextWidth(); + //!Enables/disables text scrolling + //!\param s Scrolling on/off + void SetScroll(int s); + //!Enables/disables text wrapping + //!\param w Wrapping on/off + //!\param width Maximum width (0 to disable) + void SetWrap(bool w, int width = 0); + //!Sets the font color + //!\param c Font color + void SetColor(GXColor c); + //!Sets the FreeTypeGX style attributes + //!\param s Style attributes + void SetStyle(u16 s); + //!Sets the text alignment + //!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE) + //!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE) + void SetAlignment(int hor, int vert); + //!Updates the text to the selected language + void ResetText(); + //!Constantly called to draw the text + void Draw(); + protected: + GXColor color; //!< Font color + wchar_t* text; //!< Translated Unicode text value + wchar_t *textDyn[20]; //!< Text value, if max width, scrolling, or wrapping enabled + int textDynNum; //!< Number of text lines + char * origText; //!< Original text data (English) + int size; //!< Font size + int maxWidth; //!< Maximum width of the generated text object (for text wrapping) + int textScroll; //!< Scrolling toggle + int textScrollPos; //!< Current starting index of text string for scrolling + int textScrollInitialDelay; //!< Delay to wait before starting to scroll + int textScrollDelay; //!< Scrolling speed + u16 style; //!< FreeTypeGX style attributes + bool wrap; //!< Wrapping toggle +}; + +//!Display, manage, and manipulate tooltips in the GUI +class GuiTooltip : public GuiElement +{ + public: + //!Constructor + //!\param t Text + GuiTooltip(const char *t); + //!Destructor + ~GuiTooltip(); + //!Gets the element's current scale + float GetScale(); + //!Sets the text of the GuiTooltip element + //!\param t Text + void SetText(const char * t); + //!Constantly called to draw the GuiTooltip + void DrawTooltip(); + + time_t time1, time2; //!< Tooltip times + + protected: + GuiImage leftImage; //!< Tooltip left image + GuiImage tileImage; //!< Tooltip tile image + GuiImage rightImage; //!< Tooltip right image + GuiText *text; //!< Tooltip text +}; + +//!Display, manage, and manipulate buttons in the GUI. Buttons can have images, icons, text, and sound set (all of which are optional) +class GuiButton : public GuiElement +{ + public: + //!Constructor + //!\param w Width + //!\param h Height + GuiButton(int w = 0, int h = 0); + //!Destructor + ~GuiButton(); + //!Sets the button's image + //!\param i Pointer to GuiImage object + void SetImage(GuiImage* i); + //!Sets the button's image on over + //!\param i Pointer to GuiImage object + void SetImageOver(GuiImage* i); + //!Sets the button's image on hold + //!\param i Pointer to GuiImage object + void SetImageHold(GuiImage* i); + //!Sets the button's image on click + //!\param i Pointer to GuiImage object + void SetImageClick(GuiImage* i); + //!Sets the button's icon + //!\param i Pointer to GuiImage object + void SetIcon(GuiImage* i); + //!Sets the button's icon on over + //!\param i Pointer to GuiImage object + void SetIconOver(GuiImage* i); + //!Sets the button's icon on hold + //!\param i Pointer to GuiImage object + void SetIconHold(GuiImage* i); + //!Sets the button's icon on click + //!\param i Pointer to GuiImage object + void SetIconClick(GuiImage* i); + //!Sets the button's label + //!\param t Pointer to GuiText object + //!\param n Index of label to set (optional, default is 0) + void SetLabel(GuiText* t, int n = 0); + //!Sets the button's label on over (eg: different colored text) + //!\param t Pointer to GuiText object + //!\param n Index of label to set (optional, default is 0) + void SetLabelOver(GuiText* t, int n = 0); + //!Sets the button's label on hold + //!\param t Pointer to GuiText object + //!\param n Index of label to set (optional, default is 0) + void SetLabelHold(GuiText* t, int n = 0); + //!Sets the button's label on click + //!\param t Pointer to GuiText object + //!\param n Index of label to set (optional, default is 0) + void SetLabelClick(GuiText* t, int n = 0); + //!Sets the sound to play on over + //!\param s Pointer to GuiSound object + void SetSoundOver(GuiSound * s); + //!Sets the sound to play on hold + //!\param s Pointer to GuiSound object + void SetSoundHold(GuiSound * s); + //!Sets the sound to play on click + //!\param s Pointer to GuiSound object + void SetSoundClick(GuiSound * s); + //!Sets the tooltip for the button + //!\param t Tooltip + void SetTooltip(GuiTooltip * t); + //!Constantly called to draw the GuiButton + void Draw(); + //!Constantly called to draw the GuiButton's tooltip + void DrawTooltip(); + //!Resets the text for all contained elements + void ResetText(); + //!Constantly called to allow the GuiButton to respond to updated input data + //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD + void Update(GuiTrigger * t); + protected: + GuiImage * image; //!< Button image (default) + GuiImage * imageOver; //!< Button image for STATE_SELECTED + GuiImage * imageHold; //!< Button image for STATE_HELD + GuiImage * imageClick; //!< Button image for STATE_CLICKED + GuiImage * icon; //!< Button icon (drawn after button image) + GuiImage * iconOver; //!< Button icon for STATE_SELECTED + GuiImage * iconHold; //!< Button icon for STATE_HELD + GuiImage * iconClick; //!< Button icon for STATE_CLICKED + GuiText * label[3]; //!< Label(s) to display (default) + GuiText * labelOver[3]; //!< Label(s) to display for STATE_SELECTED + GuiText * labelHold[3]; //!< Label(s) to display for STATE_HELD + GuiText * labelClick[3]; //!< Label(s) to display for STATE_CLICKED + GuiSound * soundOver; //!< Sound to play for STATE_SELECTED + GuiSound * soundHold; //!< Sound to play for STATE_HELD + GuiSound * soundClick; //!< Sound to play for STATE_CLICKED + GuiTooltip * tooltip; //!< Tooltip to display on over +}; + +typedef struct _keytype { + char ch, chShift; +} Key; + +//!On-screen keyboard +class GuiKeyboard : public GuiWindow +{ + public: + GuiKeyboard(char * t, u32 m); + ~GuiKeyboard(); + void Update(GuiTrigger * t); + char kbtextstr[256]; + protected: + u32 kbtextmaxlen; + int shift; + int caps; + GuiText * kbText; + GuiImage * keyTextboxImg; + GuiText * keyCapsText; + GuiImage * keyCapsImg; + GuiImage * keyCapsOverImg; + GuiButton * keyCaps; + GuiText * keyShiftText; + GuiImage * keyShiftImg; + GuiImage * keyShiftOverImg; + GuiButton * keyShift; + GuiText * keyBackText; + GuiImage * keyBackImg; + GuiImage * keyBackOverImg; + GuiButton * keyBack; + GuiImage * keySpaceImg; + GuiImage * keySpaceOverImg; + GuiButton * keySpace; + GuiButton * keyBtn[4][11]; + GuiImage * keyImg[4][11]; + GuiImage * keyImgOver[4][11]; + GuiText * keyTxt[4][11]; + GuiImageData * keyTextbox; + GuiImageData * key; + GuiImageData * keyOver; + GuiImageData * keyMedium; + GuiImageData * keyMediumOver; + GuiImageData * keyLarge; + GuiImageData * keyLargeOver; + GuiSound * keySoundOver; + GuiSound * keySoundClick; + GuiTrigger * trigA; + GuiTrigger * trig2; + Key keys[4][11]; // two chars = less space than one pointer +}; + +typedef struct _optionlist { + int length; + char name[MAX_OPTIONS][50]; + char value[MAX_OPTIONS][50]; +} OptionList; + +//!Display a list of menu options +class GuiOptionBrowser : public GuiElement +{ + public: + GuiOptionBrowser(int w, int h, OptionList * l); + ~GuiOptionBrowser(); + void SetCol1Position(int x); + void SetCol2Position(int x); + int FindMenuItem(int c, int d); + int GetClickedOption(); + void ResetState(); + void SetFocus(int f); + void Draw(); + void TriggerUpdate(); + void ResetText(); + void Update(GuiTrigger * t); + GuiText * optionVal[PAGESIZE]; + protected: + int optionIndex[PAGESIZE]; + GuiButton * optionBtn[PAGESIZE]; + GuiText * optionTxt[PAGESIZE]; + GuiImage * optionBg[PAGESIZE]; + + int selectedItem; + int listOffset; + OptionList * options; + + GuiButton * arrowUpBtn; + GuiButton * arrowDownBtn; + + GuiImage * bgOptionsImg; + GuiImage * scrollbarImg; + GuiImage * arrowDownImg; + GuiImage * arrowDownOverImg; + GuiImage * arrowUpImg; + GuiImage * arrowUpOverImg; + + GuiImageData * bgOptions; + GuiImageData * bgOptionsEntry; + GuiImageData * scrollbar; + GuiImageData * arrowDown; + GuiImageData * arrowDownOver; + GuiImageData * arrowUp; + GuiImageData * arrowUpOver; + + GuiSound * btnSoundOver; + GuiSound * btnSoundClick; + GuiTrigger * trigA; + GuiTrigger * trig2; + + bool listChanged; +}; + +typedef struct _savelist { + int length; + char filename[MAX_SAVES+1][256]; + GuiImageData * previewImg[MAX_SAVES+1]; + char date[MAX_SAVES+1][20]; + char time[MAX_SAVES+1][10]; + int type[MAX_SAVES+1]; + int files[2][MAX_SAVES+1]; +} SaveList; + +//!Display a list of game save files, with screenshots and file information +class GuiSaveBrowser : public GuiElement +{ + public: + GuiSaveBrowser(int w, int h, SaveList * l, int a); + ~GuiSaveBrowser(); + int GetClickedSave(); + void ResetState(); + void SetFocus(int f); + void Draw(); + void Update(GuiTrigger * t); + protected: + int selectedItem; + int action; + int listOffset; + SaveList * saves; + GuiButton * saveBtn[SAVELISTSIZE]; + GuiText * saveDate[SAVELISTSIZE]; + GuiText * saveTime[SAVELISTSIZE]; + GuiText * saveType[SAVELISTSIZE]; + + GuiImage * saveBgImg[SAVELISTSIZE]; + GuiImage * saveBgOverImg[SAVELISTSIZE]; + GuiImage * savePreviewImg[SAVELISTSIZE]; + + GuiButton * arrowUpBtn; + GuiButton * arrowDownBtn; + + GuiImage * scrollbarImg; + GuiImage * arrowDownImg; + GuiImage * arrowDownOverImg; + GuiImage * arrowUpImg; + GuiImage * arrowUpOverImg; + + GuiImageData * gameSave; + GuiImageData * gameSaveOver; + GuiImageData * gameSaveBlank; + GuiImageData * scrollbar; + GuiImageData * arrowDown; + GuiImageData * arrowDownOver; + GuiImageData * arrowUp; + GuiImageData * arrowUpOver; + + GuiSound * btnSoundOver; + GuiSound * btnSoundClick; + GuiTrigger * trigA; + GuiTrigger * trig2; + + bool saveBtnLastOver[SAVELISTSIZE]; +}; + +//!Display a list of files +class GuiFileBrowser : public GuiElement +{ + public: + GuiFileBrowser(int w, int h); + ~GuiFileBrowser(); + void ResetState(); + void SetFocus(int f); + void Draw(); + void DrawTooltip(); + void TriggerUpdate(); + void Update(GuiTrigger * t); + GuiButton * fileList[FILE_PAGESIZE]; + protected: + GuiText * fileListText[FILE_PAGESIZE]; + GuiImage * fileListBg[FILE_PAGESIZE]; + GuiImage * fileListIcon[FILE_PAGESIZE]; + + GuiButton * arrowUpBtn; + GuiButton * arrowDownBtn; + GuiButton * scrollbarBoxBtn; + + GuiImage * bgFileSelectionImg; + GuiImage * scrollbarImg; + GuiImage * arrowDownImg; + GuiImage * arrowDownOverImg; + GuiImage * arrowUpImg; + GuiImage * arrowUpOverImg; + GuiImage * scrollbarBoxImg; + GuiImage * scrollbarBoxOverImg; + + GuiImageData * bgFileSelection; + GuiImageData * bgFileSelectionEntry; + GuiImageData * iconFolder; + GuiImageData * iconSD; + GuiImageData * iconUSB; + GuiImageData * iconDVD; + GuiImageData * iconSMB; + GuiImageData * scrollbar; + GuiImageData * arrowDown; + GuiImageData * arrowDownOver; + GuiImageData * arrowUp; + GuiImageData * arrowUpOver; + GuiImageData * scrollbarBox; + GuiImageData * scrollbarBoxOver; + + GuiSound * btnSoundOver; + GuiSound * btnSoundClick; + GuiTrigger * trigA; + GuiTrigger * trig2; + GuiTrigger * trigHeldA; + + int selectedItem; + int numEntries; + bool listChanged; +}; + +#endif diff --git a/plugins/snes9x_gx/source/gui/gui_button.cpp b/plugins/snes9x_gx/source/gui/gui_button.cpp new file mode 100644 index 00000000..0703933c --- /dev/null +++ b/plugins/snes9x_gx/source/gui/gui_button.cpp @@ -0,0 +1,372 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_button.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" +/** + * Constructor for the GuiButton class. + */ + +GuiButton::GuiButton(int w, int h) +{ + width = w; + height = h; + image = NULL; + imageOver = NULL; + imageHold = NULL; + imageClick = NULL; + icon = NULL; + iconOver = NULL; + iconHold = NULL; + iconClick = NULL; + + for(int i=0; i < 3; i++) + { + label[i] = NULL; + labelOver[i] = NULL; + labelHold[i] = NULL; + labelClick[i] = NULL; + } + + soundOver = NULL; + soundHold = NULL; + soundClick = NULL; + tooltip = NULL; + selectable = true; + holdable = false; + clickable = true; +} + +/** + * Destructor for the GuiButton class. + */ +GuiButton::~GuiButton() +{ +} + +void GuiButton::SetImage(GuiImage* img) +{ + image = img; + if(img) img->SetParent(this); +} +void GuiButton::SetImageOver(GuiImage* img) +{ + imageOver = img; + if(img) img->SetParent(this); +} +void GuiButton::SetImageHold(GuiImage* img) +{ + imageHold = img; + if(img) img->SetParent(this); +} +void GuiButton::SetImageClick(GuiImage* img) +{ + imageClick = img; + if(img) img->SetParent(this); +} +void GuiButton::SetIcon(GuiImage* img) +{ + icon = img; + if(img) img->SetParent(this); +} +void GuiButton::SetIconOver(GuiImage* img) +{ + iconOver = img; + if(img) img->SetParent(this); +} +void GuiButton::SetIconHold(GuiImage* img) +{ + iconHold = img; + if(img) img->SetParent(this); +} +void GuiButton::SetIconClick(GuiImage* img) +{ + iconClick = img; + if(img) img->SetParent(this); +} +void GuiButton::SetLabel(GuiText* txt, int n) +{ + label[n] = txt; + if(txt) txt->SetParent(this); +} +void GuiButton::SetLabelOver(GuiText* txt, int n) +{ + labelOver[n] = txt; + if(txt) txt->SetParent(this); +} +void GuiButton::SetLabelHold(GuiText* txt, int n) +{ + labelHold[n] = txt; + if(txt) txt->SetParent(this); +} +void GuiButton::SetLabelClick(GuiText* txt, int n) +{ + labelClick[n] = txt; + if(txt) txt->SetParent(this); +} +void GuiButton::SetSoundOver(GuiSound * snd) +{ + soundOver = snd; +} +void GuiButton::SetSoundHold(GuiSound * snd) +{ + soundHold = snd; +} +void GuiButton::SetSoundClick(GuiSound * snd) +{ + soundClick = snd; +} +void GuiButton::SetTooltip(GuiTooltip* t) +{ + tooltip = t; + if(t) + tooltip->SetParent(this); +} + +/** + * Draw the button on screen + */ +void GuiButton::Draw() +{ + if(!this->IsVisible()) + return; + + if(state == STATE_SELECTED || state == STATE_HELD) + { + if(imageOver) + imageOver->Draw(); + else if(image) // draw image + image->Draw(); + + if(iconOver) + iconOver->Draw(); + else if(icon) // draw icon + icon->Draw(); + + // draw text + if(labelOver[0]) + labelOver[0]->Draw(); + else if(label[0]) + label[0]->Draw(); + + if(labelOver[1]) + + labelOver[1]->Draw(); + else if(label[1]) + label[1]->Draw(); + + if(labelOver[2]) + labelOver[2]->Draw(); + else if(label[2]) + label[2]->Draw(); + } + else + { + if(image) // draw image + image->Draw(); + if(icon) // draw icon + icon->Draw(); + + // draw text + if(label[0]) + label[0]->Draw(); + if(label[1]) + label[1]->Draw(); + if(label[2]) + label[2]->Draw(); + } + + this->UpdateEffects(); +} + +void GuiButton::DrawTooltip() +{ + if(tooltip) + tooltip->DrawTooltip(); +} + +void GuiButton::ResetText() +{ + for(int i=0; i<3; i++) + { + if(label[i]) + label[i]->ResetText(); + if(labelOver[i]) + labelOver[i]->ResetText(); + } + if(tooltip) + tooltip->ResetText(); +} + +void GuiButton::Update(GuiTrigger * t) +{ + if(state == STATE_CLICKED || state == STATE_DISABLED || !t) + return; + else if(parentElement && parentElement->GetState() == STATE_DISABLED) + return; + + #ifdef HW_RVL + // cursor + if(t->wpad->ir.valid && t->chan >= 0) + { + if(this->IsInside(t->wpad->ir.x, t->wpad->ir.y)) + { + if(state == STATE_DEFAULT) // we weren't on the button before! + { + this->SetState(STATE_SELECTED, t->chan); + + if(this->Rumble()) + rumbleRequest[t->chan] = 1; + + if(soundOver) + soundOver->Play(); + + if(effectsOver && !effects) + { + // initiate effects + effects = effectsOver; + effectAmount = effectAmountOver; + effectTarget = effectTargetOver; + } + } + } + else + { + if(state == STATE_SELECTED && (stateChan == t->chan || stateChan == -1)) + this->ResetState(); + + if(effectTarget == effectTargetOver && effectAmount == effectAmountOver) + { + // initiate effects (in reverse) + effects = effectsOver; + effectAmount = -effectAmountOver; + effectTarget = 100; + } + } + } + #endif + + // button triggers + if(this->IsClickable()) + { + s32 wm_btns, wm_btns_trig, cc_btns, cc_btns_trig, wupc_btns, wupc_btns_trig; + for(int i=0; i<3; i++) + { + if(trigger[i] && (trigger[i]->chan == -1 || trigger[i]->chan == t->chan)) + { + // higher 16 bits only (wiimote) + wm_btns = t->wpad->btns_d << 16; + wm_btns_trig = trigger[i]->wpad->btns_d << 16; + + // lower 16 bits only (classic controller) + cc_btns = t->wpad->btns_d >> 16; + cc_btns_trig = trigger[i]->wpad->btns_d >> 16; + + // lower 16 bits only (WiiU Pro controller) + wupc_btns = t->wupcdata.btns_d >> 16; + wupc_btns_trig = trigger[i]->wupcdata.btns_d >> 16; + + if( + (t->wpad->btns_d > 0 && + (wm_btns == wm_btns_trig || + (cc_btns == cc_btns_trig && t->wpad->exp.type == EXP_CLASSIC))) || + (t->pad.btns_d == trigger[i]->pad.btns_d && t->pad.btns_d > 0) || + (wupc_btns == wupc_btns_trig && wupc_btns_trig > 0)) + + { + if(t->chan == stateChan || stateChan == -1) + { + if(state == STATE_SELECTED) + { + if(!t->wpad->ir.valid || this->IsInside(t->wpad->ir.x, t->wpad->ir.y)) + { + this->SetState(STATE_CLICKED, t->chan); + + if(soundClick) + soundClick->Play(); + } + } + else if(trigger[i]->type == TRIGGER_BUTTON_ONLY) + { + this->SetState(STATE_CLICKED, t->chan); + } + else if(trigger[i]->type == TRIGGER_BUTTON_ONLY_IN_FOCUS && + parentElement->IsFocused()) + { + this->SetState(STATE_CLICKED, t->chan); + } + } + } + } + } + } + + if(this->IsHoldable()) + { + bool held = false; + s32 wm_btns, wm_btns_h, wm_btns_trig, cc_btns, cc_btns_h, cc_btns_trig, wupc_btns, wupc_btns_h, wupc_btns_trig; + + for(int i=0; i<3; i++) + { + if(trigger[i] && (trigger[i]->chan == -1 || trigger[i]->chan == t->chan)) + { + // higher 16 bits only (wiimote) + wm_btns = t->wpad->btns_d << 16; + wm_btns_h = t->wpad->btns_h << 16; + wm_btns_trig = trigger[i]->wpad->btns_h << 16; + + // lower 16 bits only (classic controller) + cc_btns = t->wpad->btns_d >> 16; + cc_btns_h = t->wpad->btns_h >> 16; + cc_btns_trig = trigger[i]->wpad->btns_h >> 16; + + // lower 16 bits only (WiiU Pro controller) + wupc_btns = t->wpad->btns_d >> 16; + wupc_btns_h = t->wpad->btns_h >> 16; + wupc_btns_trig = trigger[i]->wpad->btns_h >> 16; + + if( + (t->wpad->btns_d > 0 && + (wm_btns == wm_btns_trig || + (cc_btns == cc_btns_trig && t->wpad->exp.type == EXP_CLASSIC))) || + (t->pad.btns_d == trigger[i]->pad.btns_h && t->pad.btns_d > 0) || + (wupc_btns == wupc_btns_trig && wupc_btns > 0)) + { + if(trigger[i]->type == TRIGGER_HELD && state == STATE_SELECTED && + (t->chan == stateChan || stateChan == -1)) + this->SetState(STATE_CLICKED, t->chan); + } + + if( + (t->wpad->btns_h > 0 && + (wm_btns_h == wm_btns_trig || + (cc_btns_h == cc_btns_trig && t->wpad->exp.type == EXP_CLASSIC))) || + (t->pad.btns_h == trigger[i]->pad.btns_h && t->pad.btns_h > 0) || + (wupc_btns_h == wupc_btns_trig && wupc_btns_h > 0)) + + { + if(trigger[i]->type == TRIGGER_HELD) + held = true; + } + + if(!held && state == STATE_HELD && stateChan == t->chan) + { + this->ResetState(); + } + else if(held && state == STATE_CLICKED && stateChan == t->chan) + { + this->SetState(STATE_HELD, t->chan); + } + } + } + } + + if(updateCB) + updateCB(this); +} diff --git a/plugins/snes9x_gx/source/gui/gui_element.cpp b/plugins/snes9x_gx/source/gui/gui_element.cpp new file mode 100644 index 00000000..9efb1c10 --- /dev/null +++ b/plugins/snes9x_gx/source/gui/gui_element.cpp @@ -0,0 +1,582 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_element.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" + +/** + * Constructor for the Object class. + */ +GuiElement::GuiElement() +{ + xoffset = 0; + yoffset = 0; + xmin = 0; + xmax = 0; + ymin = 0; + ymax = 0; + width = 0; + height = 0; + alpha = 255; + xscale = 1; + yscale = 1; + state = STATE_DEFAULT; + stateChan = -1; + trigger[0] = NULL; + trigger[1] = NULL; + trigger[2] = NULL; + parentElement = NULL; + rumble = true; + selectable = false; + clickable = false; + holdable = false; + visible = true; + focus = -1; // cannot be focused + updateCB = NULL; + yoffsetDyn = 0; + xoffsetDyn = 0; + alphaDyn = -1; + scaleDyn = 1; + effects = 0; + effectAmount = 0; + effectTarget = 0; + effectsOver = 0; + effectAmountOver = 0; + effectTargetOver = 0; + + // default alignment - align to top left + alignmentVert = ALIGN_TOP; + alignmentHor = ALIGN_LEFT; +} + +/** + * Destructor for the GuiElement class. + */ +GuiElement::~GuiElement() +{ +} + +void GuiElement::SetParent(GuiElement * e) +{ + parentElement = e; +} + +GuiElement * GuiElement::GetParent() +{ + return parentElement; +} + +int GuiElement::GetLeft() +{ + int x = 0; + int pWidth = 0; + int pLeft = 0; + + if(parentElement) + { + pWidth = parentElement->GetWidth(); + pLeft = parentElement->GetLeft(); + } + + if(effects & (EFFECT_SLIDE_IN | EFFECT_SLIDE_OUT)) + pLeft += xoffsetDyn; + + switch(alignmentHor) + { + case ALIGN_LEFT: + x = pLeft; + break; + case ALIGN_CENTRE: + x = pLeft + pWidth/2.0 - (width*xscale)/2.0; + break; + case ALIGN_RIGHT: + x = pLeft + pWidth - width*xscale; + break; + } + x += (width*(xscale - 1))/2.0; // correct offset for scaled images + return x + xoffset; +} + +int GuiElement::GetTop() +{ + int y = 0; + int pHeight = 0; + int pTop = 0; + + if(parentElement) + { + pHeight = parentElement->GetHeight(); + pTop = parentElement->GetTop(); + } + + if(effects & (EFFECT_SLIDE_IN | EFFECT_SLIDE_OUT)) + pTop += yoffsetDyn; + + switch(alignmentVert) + { + case ALIGN_TOP: + y = pTop; + break; + case ALIGN_MIDDLE: + y = pTop + pHeight/2.0 - (height*yscale)/2.0; + break; + case ALIGN_BOTTOM: + y = pTop + pHeight - height*yscale; + break; + } + y += (height*(yscale - 1))/2.0; // correct offset for scaled images + return y + yoffset; +} + +void GuiElement::SetMinX(int x) +{ + xmin = x; +} + +int GuiElement::GetMinX() +{ + return xmin; +} + +void GuiElement::SetMaxX(int x) +{ + xmax = x; +} + +int GuiElement::GetMaxX() +{ + return xmax; +} + +void GuiElement::SetMinY(int y) +{ + ymin = y; +} + +int GuiElement::GetMinY() +{ + return ymin; +} + +void GuiElement::SetMaxY(int y) +{ + ymax = y; +} + +int GuiElement::GetMaxY() +{ + return ymax; +} + +int GuiElement::GetWidth() +{ + return width; +} + +int GuiElement::GetHeight() +{ + return height; +} + +void GuiElement::SetSize(int w, int h) +{ + + width = w; + height = h; +} + +bool GuiElement::IsVisible() +{ + return visible; +} + +void GuiElement::SetVisible(bool v) +{ + visible = v; +} + +void GuiElement::SetAlpha(int a) +{ + alpha = a; +} + +int GuiElement::GetAlpha() +{ + int a = alpha; + + if(alphaDyn >= 0) + a = alphaDyn; + + if(parentElement) + a *= float(parentElement->GetAlpha())/255.0f; + + return a; +} + +void GuiElement::SetScale(float s) +{ + xscale = s; + yscale = s; +} + +void GuiElement::SetScaleX(float s) +{ + xscale = s; +} + +void GuiElement::SetScaleY(float s) +{ + yscale = s; +} + +void GuiElement::SetScale(int mw, int mh) +{ + xscale = 1.0f; + if(width > mw || height > mh) + { + if(width/(height*1.0) > mw/(mh*1.0)) + xscale = mw/(width*1.0); + else + xscale = mh/(height*1.0); + } + yscale = xscale; +} + +float GuiElement::GetScale() +{ + float s = xscale * scaleDyn; + + if(parentElement) + s *= parentElement->GetScale(); + + return s; +} + +float GuiElement::GetScaleX() +{ + float s = xscale * scaleDyn; + + if(parentElement) + s *= parentElement->GetScale(); + + return s; +} + +float GuiElement::GetScaleY() +{ + float s = yscale * scaleDyn; + + if(parentElement) + s *= parentElement->GetScaleY(); + + return s; +} + +int GuiElement::GetState() +{ + return state; +} + +int GuiElement::GetStateChan() +{ + return stateChan; +} + +void GuiElement::SetState(int s, int c) +{ + state = s; + stateChan = c; +} + +void GuiElement::ResetState() +{ + if(state != STATE_DISABLED) + { + state = STATE_DEFAULT; + stateChan = -1; + } +} + +void GuiElement::SetClickable(bool c) +{ + clickable = c; +} + +void GuiElement::SetSelectable(bool s) +{ + selectable = s; +} + +void GuiElement::SetHoldable(bool d) +{ + holdable = d; +} + +bool GuiElement::IsSelectable() +{ + if(state == STATE_DISABLED || state == STATE_CLICKED) + return false; + else + return selectable; +} + +bool GuiElement::IsClickable() +{ + if(state == STATE_DISABLED || + state == STATE_CLICKED || + state == STATE_HELD) + return false; + else + return clickable; +} + +bool GuiElement::IsHoldable() +{ + if(state == STATE_DISABLED) + return false; + else + return holdable; +} + +void GuiElement::SetFocus(int f) +{ + focus = f; +} + +int GuiElement::IsFocused() +{ + return focus; +} + +void GuiElement::SetTrigger(GuiTrigger * t) +{ + if(!trigger[0]) + trigger[0] = t; + else if(!trigger[1]) + trigger[1] = t; + else if(!trigger[2]) + trigger[2] = t; + else // all were assigned, so we'll just overwrite the first one + trigger[0] = t; +} + +void GuiElement::SetTrigger(u8 i, GuiTrigger * t) +{ + trigger[i] = t; +} + +bool GuiElement::Rumble() +{ + return rumble; +} + +void GuiElement::SetRumble(bool r) +{ + rumble = r; +} + +int GuiElement::GetEffect() +{ + return effects; +} + +void GuiElement::SetEffect(int eff, int amount, int target) +{ + if(eff & EFFECT_SLIDE_IN) + { + // these calculations overcompensate a little + if(eff & EFFECT_SLIDE_TOP) + yoffsetDyn = -screenheight; + else if(eff & EFFECT_SLIDE_LEFT) + xoffsetDyn = -screenwidth; + else if(eff & EFFECT_SLIDE_BOTTOM) + yoffsetDyn = screenheight; + else if(eff & EFFECT_SLIDE_RIGHT) + xoffsetDyn = screenwidth; + } + if(eff & EFFECT_FADE) + { + if(amount > 0) + alphaDyn = 0; + else if(amount < 0) + alphaDyn = alpha; + } + + effects |= eff; + effectAmount = amount; + effectTarget = target; +} + +void GuiElement::SetEffectOnOver(int eff, int amount, int target) +{ + effectsOver |= eff; + effectAmountOver = amount; + effectTargetOver = target; +} + +void GuiElement::SetEffectGrow() +{ + SetEffectOnOver(EFFECT_SCALE, 4, 110); +} + +void GuiElement::UpdateEffects() +{ + if(effects & (EFFECT_SLIDE_IN | EFFECT_SLIDE_OUT)) + { + if(effects & EFFECT_SLIDE_IN) + { + if(effects & EFFECT_SLIDE_LEFT) + { + xoffsetDyn += effectAmount; + + if(xoffsetDyn >= 0) + { + xoffsetDyn = 0; + effects = 0; + } + } + else if(effects & EFFECT_SLIDE_RIGHT) + { + xoffsetDyn -= effectAmount; + + if(xoffsetDyn <= 0) + { + xoffsetDyn = 0; + effects = 0; + } + } + else if(effects & EFFECT_SLIDE_TOP) + { + yoffsetDyn += effectAmount; + + if(yoffsetDyn >= 0) + { + yoffsetDyn = 0; + effects = 0; + } + } + else if(effects & EFFECT_SLIDE_BOTTOM) + { + yoffsetDyn -= effectAmount; + + if(yoffsetDyn <= 0) + { + yoffsetDyn = 0; + effects = 0; + } + } + } + else + { + if(effects & EFFECT_SLIDE_LEFT) + { + xoffsetDyn -= effectAmount; + + if(xoffsetDyn <= -screenwidth) + effects = 0; // shut off effect + } + else if(effects & EFFECT_SLIDE_RIGHT) + { + xoffsetDyn += effectAmount; + + if(xoffsetDyn >= screenwidth) + effects = 0; // shut off effect + } + else if(effects & EFFECT_SLIDE_TOP) + { + yoffsetDyn -= effectAmount; + + if(yoffsetDyn <= -screenheight) + effects = 0; // shut off effect + } + else if(effects & EFFECT_SLIDE_BOTTOM) + { + yoffsetDyn += effectAmount; + + if(yoffsetDyn >= screenheight) + effects = 0; // shut off effect + } + } + } + if(effects & EFFECT_FADE) + { + alphaDyn += effectAmount; + + if(effectAmount < 0 && alphaDyn <= 0) + { + alphaDyn = 0; + effects = 0; // shut off effect + } + else if(effectAmount > 0 && alphaDyn >= alpha) + { + alphaDyn = alpha; + effects = 0; // shut off effect + } + } + if(effects & EFFECT_SCALE) + { + scaleDyn += f32(effectAmount)*0.01f; + f32 effTar100 = f32(effectTarget)*0.01f; + + if((effectAmount < 0 && scaleDyn <= effTar100) + || (effectAmount > 0 && scaleDyn >= effTar100)) + { + scaleDyn = effTar100; + effects = 0; // shut off effect + } + } +} + +void GuiElement::Update(GuiTrigger * t) +{ + if(updateCB) + updateCB(this); +} + +void GuiElement::SetUpdateCallback(UpdateCallback u) +{ + updateCB = u; +} + +void GuiElement::SetPosition(int xoff, int yoff) +{ + xoffset = xoff; + yoffset = yoff; +} + +void GuiElement::SetAlignment(int hor, int vert) +{ + alignmentHor = hor; + alignmentVert = vert; +} + +int GuiElement::GetSelected() +{ + return -1; +} + +void GuiElement::ResetText() +{ +} + +void GuiElement::Draw() +{ +} + +void GuiElement::DrawTooltip() +{ +} + +bool GuiElement::IsInside(int x, int y) +{ + if(unsigned(x - this->GetLeft()) < unsigned(width) + && unsigned(y - this->GetTop()) < unsigned(height)) + return true; + return false; +} diff --git a/plugins/snes9x_gx/source/gui/gui_filebrowser.cpp b/plugins/snes9x_gx/source/gui/gui_filebrowser.cpp new file mode 100644 index 00000000..42edebd0 --- /dev/null +++ b/plugins/snes9x_gx/source/gui/gui_filebrowser.cpp @@ -0,0 +1,457 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_filebrowser.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" +#include "filebrowser.h" + +/** + * Constructor for the GuiFileBrowser class. + */ +GuiFileBrowser::GuiFileBrowser(int w, int h) +{ + width = w; + height = h; + numEntries = 0; + selectedItem = 0; + selectable = true; + listChanged = true; // trigger an initial list update + focus = 0; // allow focus + + trigA = new GuiTrigger; + trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + trig2 = new GuiTrigger; + trig2->SetSimpleTrigger(-1, WPAD_BUTTON_2, 0); + + trigHeldA = new GuiTrigger; + trigHeldA->SetHeldTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + btnSoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, SOUND_PCM); + btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM); + + bgFileSelection = new GuiImageData(bg_game_selection_png); + bgFileSelectionImg = new GuiImage(bgFileSelection); + bgFileSelectionImg->SetParent(this); + bgFileSelectionImg->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + + bgFileSelectionEntry = new GuiImageData(bg_game_selection_entry_png); + + iconFolder = new GuiImageData(icon_folder_png); + iconSD = new GuiImageData(icon_sd_png); + iconUSB = new GuiImageData(icon_usb_png); + iconDVD = new GuiImageData(icon_dvd_png); + iconSMB = new GuiImageData(icon_smb_png); + + scrollbar = new GuiImageData(scrollbar_png); + scrollbarImg = new GuiImage(scrollbar); + scrollbarImg->SetParent(this); + scrollbarImg->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + scrollbarImg->SetPosition(0, 30); + + arrowDown = new GuiImageData(scrollbar_arrowdown_png); + arrowDownImg = new GuiImage(arrowDown); + arrowDownOver = new GuiImageData(scrollbar_arrowdown_over_png); + arrowDownOverImg = new GuiImage(arrowDownOver); + arrowUp = new GuiImageData(scrollbar_arrowup_png); + arrowUpImg = new GuiImage(arrowUp); + arrowUpOver = new GuiImageData(scrollbar_arrowup_over_png); + arrowUpOverImg = new GuiImage(arrowUpOver); + scrollbarBox = new GuiImageData(scrollbar_box_png); + scrollbarBoxImg = new GuiImage(scrollbarBox); + scrollbarBoxOver = new GuiImageData(scrollbar_box_over_png); + scrollbarBoxOverImg = new GuiImage(scrollbarBoxOver); + + arrowUpBtn = new GuiButton(arrowUpImg->GetWidth(), arrowUpImg->GetHeight()); + arrowUpBtn->SetParent(this); + arrowUpBtn->SetImage(arrowUpImg); + arrowUpBtn->SetImageOver(arrowUpOverImg); + arrowUpBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + arrowUpBtn->SetSelectable(false); + arrowUpBtn->SetClickable(false); + arrowUpBtn->SetHoldable(true); + arrowUpBtn->SetTrigger(trigHeldA); + arrowUpBtn->SetSoundOver(btnSoundOver); + arrowUpBtn->SetSoundClick(btnSoundClick); + + arrowDownBtn = new GuiButton(arrowDownImg->GetWidth(), arrowDownImg->GetHeight()); + arrowDownBtn->SetParent(this); + arrowDownBtn->SetImage(arrowDownImg); + arrowDownBtn->SetImageOver(arrowDownOverImg); + arrowDownBtn->SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + arrowDownBtn->SetSelectable(false); + arrowDownBtn->SetClickable(false); + arrowDownBtn->SetHoldable(true); + arrowDownBtn->SetTrigger(trigHeldA); + arrowDownBtn->SetSoundOver(btnSoundOver); + arrowDownBtn->SetSoundClick(btnSoundClick); + + scrollbarBoxBtn = new GuiButton(scrollbarBoxImg->GetWidth(), scrollbarBoxImg->GetHeight()); + scrollbarBoxBtn->SetParent(this); + scrollbarBoxBtn->SetImage(scrollbarBoxImg); + scrollbarBoxBtn->SetImageOver(scrollbarBoxOverImg); + scrollbarBoxBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + scrollbarBoxBtn->SetMinY(0); + scrollbarBoxBtn->SetMaxY(156); + scrollbarBoxBtn->SetSelectable(false); + scrollbarBoxBtn->SetClickable(false); + scrollbarBoxBtn->SetHoldable(true); + scrollbarBoxBtn->SetTrigger(trigHeldA); + + for(int i=0; i<FILE_PAGESIZE; ++i) + { + fileListText[i] = new GuiText(NULL, 20, (GXColor){0, 0, 0, 0xff}); + fileListText[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + fileListText[i]->SetPosition(5,0); + fileListText[i]->SetMaxWidth(295); + + fileListBg[i] = new GuiImage(bgFileSelectionEntry); + fileListIcon[i] = NULL; + + fileList[i] = new GuiButton(295, 26); + fileList[i]->SetParent(this); + fileList[i]->SetLabel(fileListText[i]); + fileList[i]->SetImageOver(fileListBg[i]); + fileList[i]->SetPosition(2,26*i+3); + fileList[i]->SetTrigger(trigA); + fileList[i]->SetTrigger(trig2); + fileList[i]->SetSoundClick(btnSoundClick); + } +} + +/** + * Destructor for the GuiFileBrowser class. + */ +GuiFileBrowser::~GuiFileBrowser() +{ + delete arrowUpBtn; + delete arrowDownBtn; + delete scrollbarBoxBtn; + + delete bgFileSelectionImg; + delete scrollbarImg; + delete arrowDownImg; + delete arrowDownOverImg; + delete arrowUpImg; + delete arrowUpOverImg; + delete scrollbarBoxImg; + delete scrollbarBoxOverImg; + + delete bgFileSelection; + delete bgFileSelectionEntry; + delete iconFolder; + delete iconSD; + delete iconUSB; + delete iconDVD; + delete iconSMB; + delete scrollbar; + delete arrowDown; + delete arrowDownOver; + delete arrowUp; + delete arrowUpOver; + delete scrollbarBox; + delete scrollbarBoxOver; + + delete btnSoundOver; + delete btnSoundClick; + delete trigHeldA; + delete trigA; + delete trig2; + + for(int i=0; i<FILE_PAGESIZE; i++) + { + delete fileListText[i]; + delete fileList[i]; + delete fileListBg[i]; + + if(fileListIcon[i]) + delete fileListIcon[i]; + } +} + +void GuiFileBrowser::SetFocus(int f) +{ + focus = f; + + for(int i=0; i<FILE_PAGESIZE; i++) + fileList[i]->ResetState(); + + if(f == 1) + fileList[selectedItem]->SetState(STATE_SELECTED); +} + +void GuiFileBrowser::ResetState() +{ + state = STATE_DEFAULT; + stateChan = -1; + selectedItem = 0; + + for(int i=0; i<FILE_PAGESIZE; i++) + { + fileList[i]->ResetState(); + } +} + +void GuiFileBrowser::TriggerUpdate() +{ + int newIndex = browser.selIndex-browser.pageIndex; + + if(newIndex >= FILE_PAGESIZE) + newIndex = FILE_PAGESIZE-1; + else if(newIndex < 0) + newIndex = 0; + + selectedItem = newIndex; + listChanged = true; +} + +/** + * Draw the button on screen + */ +void GuiFileBrowser::Draw() +{ + if(!this->IsVisible()) + return; + + bgFileSelectionImg->Draw(); + + for(u32 i=0; i<FILE_PAGESIZE; ++i) + { + fileList[i]->Draw(); + } + + scrollbarImg->Draw(); + arrowUpBtn->Draw(); + arrowDownBtn->Draw(); + scrollbarBoxBtn->Draw(); + + this->UpdateEffects(); +} + +void GuiFileBrowser::DrawTooltip() +{ +} + +void GuiFileBrowser::Update(GuiTrigger * t) +{ + if(state == STATE_DISABLED || !t) + return; + + int position = 0; + int positionWiimote = 0; + + arrowUpBtn->Update(t); + arrowDownBtn->Update(t); + scrollbarBoxBtn->Update(t); + + // move the file listing to respond to wiimote cursor movement + if(scrollbarBoxBtn->GetState() == STATE_HELD && + scrollbarBoxBtn->GetStateChan() == t->chan && + t->wpad->ir.valid && + browser.numEntries > FILE_PAGESIZE + ) + { + scrollbarBoxBtn->SetPosition(0,0); + positionWiimote = t->wpad->ir.y - 60 - scrollbarBoxBtn->GetTop(); + + if(positionWiimote < scrollbarBoxBtn->GetMinY()) + positionWiimote = scrollbarBoxBtn->GetMinY(); + else if(positionWiimote > scrollbarBoxBtn->GetMaxY()) + positionWiimote = scrollbarBoxBtn->GetMaxY(); + + browser.pageIndex = (positionWiimote * browser.numEntries)/156.0f - selectedItem; + + if(browser.pageIndex <= 0) + { + browser.pageIndex = 0; + } + else if(browser.pageIndex+FILE_PAGESIZE >= browser.numEntries) + { + browser.pageIndex = browser.numEntries-FILE_PAGESIZE; + } + listChanged = true; + focus = false; + } + + if(arrowDownBtn->GetState() == STATE_HELD && arrowDownBtn->GetStateChan() == t->chan) + { + t->wpad->btns_d |= WPAD_BUTTON_DOWN; + if(!this->IsFocused()) + ((GuiWindow *)this->GetParent())->ChangeFocus(this); + } + else if(arrowUpBtn->GetState() == STATE_HELD && arrowUpBtn->GetStateChan() == t->chan) + { + t->wpad->btns_d |= WPAD_BUTTON_UP; + if(!this->IsFocused()) + ((GuiWindow *)this->GetParent())->ChangeFocus(this); + } + + // pad/joystick navigation + if(!focus) + { + goto endNavigation; // skip navigation + listChanged = false; + } + + if(t->Right()) + { + if(browser.pageIndex < browser.numEntries && browser.numEntries > FILE_PAGESIZE) + { + browser.pageIndex += FILE_PAGESIZE; + if(browser.pageIndex+FILE_PAGESIZE >= browser.numEntries) + browser.pageIndex = browser.numEntries-FILE_PAGESIZE; + listChanged = true; + } + } + else if(t->Left()) + { + if(browser.pageIndex > 0) + { + browser.pageIndex -= FILE_PAGESIZE; + if(browser.pageIndex < 0) + browser.pageIndex = 0; + listChanged = true; + } + } + else if(t->Down()) + { + if(browser.pageIndex + selectedItem + 1 < browser.numEntries) + { + if(selectedItem == FILE_PAGESIZE-1) + { + // move list down by 1 + ++browser.pageIndex; + listChanged = true; + } + else if(fileList[selectedItem+1]->IsVisible()) + { + fileList[selectedItem]->ResetState(); + fileList[++selectedItem]->SetState(STATE_SELECTED, t->chan); + } + } + } + else if(t->Up()) + { + if(selectedItem == 0 && browser.pageIndex + selectedItem > 0) + { + // move list up by 1 + --browser.pageIndex; + listChanged = true; + } + else if(selectedItem > 0) + { + fileList[selectedItem]->ResetState(); + fileList[--selectedItem]->SetState(STATE_SELECTED, t->chan); + } + } + + endNavigation: + + for(int i=0; i<FILE_PAGESIZE; ++i) + { + if(listChanged || numEntries != browser.numEntries) + { + if(browser.pageIndex+i < browser.numEntries) + { + if(fileList[i]->GetState() == STATE_DISABLED) + fileList[i]->SetState(STATE_DEFAULT); + + fileList[i]->SetVisible(true); + + fileListText[i]->SetText(browserList[browser.pageIndex+i].displayname); + + if(fileListIcon[i]) + { + delete fileListIcon[i]; + fileListIcon[i] = NULL; + fileListText[i]->SetPosition(5,0); + } + + switch(browserList[browser.pageIndex+i].icon) + { + case ICON_FOLDER: + fileListIcon[i] = new GuiImage(iconFolder); + break; + case ICON_SD: + fileListIcon[i] = new GuiImage(iconSD); + break; + case ICON_USB: + fileListIcon[i] = new GuiImage(iconUSB); + break; + case ICON_DVD: + fileListIcon[i] = new GuiImage(iconDVD); + break; + case ICON_SMB: + fileListIcon[i] = new GuiImage(iconSMB); + break; + } + fileList[i]->SetIcon(fileListIcon[i]); + if(fileListIcon[i] != NULL) + fileListText[i]->SetPosition(30,0); + } + else + { + fileList[i]->SetVisible(false); + fileList[i]->SetState(STATE_DISABLED); + } + } + + if(i != selectedItem && fileList[i]->GetState() == STATE_SELECTED) + fileList[i]->ResetState(); + else if(focus && i == selectedItem && fileList[i]->GetState() == STATE_DEFAULT) + fileList[selectedItem]->SetState(STATE_SELECTED, t->chan); + + int currChan = t->chan; + + if(t->wpad->ir.valid && !fileList[i]->IsInside(t->wpad->ir.x, t->wpad->ir.y)) + t->chan = -1; + + fileList[i]->Update(t); + t->chan = currChan; + + if(fileList[i]->GetState() == STATE_SELECTED) + { + selectedItem = i; + browser.selIndex = browser.pageIndex + i; + } + + if(selectedItem == i) + fileListText[i]->SetScroll(SCROLL_HORIZONTAL); + else + fileListText[i]->SetScroll(SCROLL_NONE); + } + + // update the location of the scroll box based on the position in the file list + if(positionWiimote > 0) + { + position = positionWiimote; // follow wiimote cursor + scrollbarBoxBtn->SetPosition(0,position+36); + } + else if(listChanged || numEntries != browser.numEntries) + { + if(float((browser.pageIndex<<1))/(float(FILE_PAGESIZE)) < 1.0) + { + position = 0; + } + else if(browser.pageIndex+FILE_PAGESIZE >= browser.numEntries) + { + position = 156; + } + else + { + position = 156 * (browser.pageIndex + FILE_PAGESIZE/2) / (float)browser.numEntries; + } + scrollbarBoxBtn->SetPosition(0,position+36); + } + + listChanged = false; + numEntries = browser.numEntries; + + if(updateCB) + updateCB(this); +} diff --git a/plugins/snes9x_gx/source/gui/gui_image.cpp b/plugins/snes9x_gx/source/gui/gui_image.cpp new file mode 100644 index 00000000..acf1b00c --- /dev/null +++ b/plugins/snes9x_gx/source/gui/gui_image.cpp @@ -0,0 +1,255 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_image.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" +/** + * Constructor for the GuiImage class. + */ +GuiImage::GuiImage() +{ + image = NULL; + width = 0; + height = 0; + imageangle = 0; + tile = -1; + stripe = 0; + imgType = IMAGE_DATA; +} + +GuiImage::GuiImage(GuiImageData * img) +{ + image = NULL; + width = 0; + height = 0; + if(img) + { + image = img->GetImage(); + width = img->GetWidth(); + height = img->GetHeight(); + } + imageangle = 0; + tile = -1; + stripe = 0; + imgType = IMAGE_DATA; +} + +GuiImage::GuiImage(u8 * img, int w, int h) +{ + image = img; + width = w; + height = h; + imageangle = 0; + tile = -1; + stripe = 0; + imgType = IMAGE_TEXTURE; +} + +GuiImage::GuiImage(int w, int h, GXColor c) +{ + image = (u8 *)memalign (32, w * h << 2); + width = w; + height = h; + imageangle = 0; + tile = -1; + stripe = 0; + imgType = IMAGE_COLOR; + + if(!image) + return; + + int x, y; + + for(y=0; y < h; ++y) + { + for(x=0; x < w; ++x) + { + this->SetPixel(x, y, c); + } + } + int len = w * h << 2; + if(len%32) len += (32-len%32); + DCFlushRange(image, len); +} + +/** + * Destructor for the GuiImage class. + */ +GuiImage::~GuiImage() +{ + if(imgType == IMAGE_COLOR && image) + free(image); +} + +u8 * GuiImage::GetImage() +{ + return image; +} + +void GuiImage::SetImage(GuiImageData * img) +{ + image = NULL; + width = 0; + height = 0; + if(img) + { + image = img->GetImage(); + width = img->GetWidth(); + height = img->GetHeight(); + } + imgType = IMAGE_DATA; +} + +void GuiImage::SetImage(u8 * img, int w, int h) +{ + image = img; + width = w; + height = h; + imgType = IMAGE_TEXTURE; +} + +void GuiImage::SetAngle(float a) +{ + imageangle = a; +} + +void GuiImage::SetTile(int t) +{ + tile = t; +} + +GXColor GuiImage::GetPixel(int x, int y) +{ + if(!image || this->GetWidth() <= 0 || x < 0 || y < 0) + return (GXColor){0, 0, 0, 0}; + + u32 offset = (((y >> 2)<<4)*this->GetWidth()) + ((x >> 2)<<6) + (((y%4 << 2) + x%4 ) << 1); + GXColor color; + color.a = *(image+offset); + color.r = *(image+offset+1); + color.g = *(image+offset+32); + color.b = *(image+offset+33); + return color; +} + +void GuiImage::SetPixel(int x, int y, GXColor color) +{ + if(!image || this->GetWidth() <= 0 || x < 0 || y < 0) + return; + + u32 offset = (((y >> 2)<<4)*this->GetWidth()) + ((x >> 2)<<6) + (((y%4 << 2) + x%4 ) << 1); + *(image+offset) = color.a; + *(image+offset+1) = color.r; + *(image+offset+32) = color.g; + *(image+offset+33) = color.b; +} + +void GuiImage::SetStripe(int s) +{ + stripe = s; +} + +void GuiImage::ColorStripe(int shift) +{ + GXColor color; + int x, y=0; + int alt = 0; + + int thisHeight = this->GetHeight(); + int thisWidth = this->GetWidth(); + + for(; y < thisHeight; ++y) + { + if(y % 3 == 0) + alt ^= 1; + + if(alt) + { + for(x=0; x < thisWidth; ++x) + { + color = GetPixel(x, y); + + if(color.r < 255-shift) + color.r += shift; + else + color.r = 255; + if(color.g < 255-shift) + color.g += shift; + else + color.g = 255; + if(color.b < 255-shift) + color.b += shift; + else + color.b = 255; + + color.a = 255; + SetPixel(x, y, color); + } + } + else + { + for(x=0; x < thisWidth; ++x) + { + color = GetPixel(x, y); + + if(color.r > shift) + color.r -= shift; + else + color.r = 0; + if(color.g > shift) + color.g -= shift; + else + color.g = 0; + if(color.b > shift) + color.b -= shift; + else + color.b = 0; + + color.a = 255; + SetPixel(x, y, color); + } + } + } +} + +/** + * Draw the button on screen + */ +void GuiImage::Draw() +{ + if(!image || !this->IsVisible() || tile == 0) + return; + + float currScaleX = this->GetScaleX(); + float currScaleY = this->GetScaleY(); + int currLeft = this->GetLeft(); + int thisTop = this->GetTop(); + + if(tile > 0) + { + int alpha = this->GetAlpha(); + for(int i=0; i<tile; ++i) + { + Menu_DrawImg(currLeft+width*i, thisTop, width, height, image, imageangle, currScaleX, currScaleY, alpha); + } + } + else + { + Menu_DrawImg(currLeft, thisTop, width, height, image, imageangle, currScaleX, currScaleY, this->GetAlpha()); + } + + if(stripe > 0) + { + int thisHeight = this->GetHeight(); + int thisWidth = this->GetWidth(); + for(int y=0; y < thisHeight; y+=6) + Menu_DrawRectangle(currLeft,thisTop+y,thisWidth,3,(GXColor){0, 0, 0, stripe},1); + } + this->UpdateEffects(); +} diff --git a/plugins/snes9x_gx/source/gui/gui_imagedata.cpp b/plugins/snes9x_gx/source/gui/gui_imagedata.cpp new file mode 100644 index 00000000..97e7513e --- /dev/null +++ b/plugins/snes9x_gx/source/gui/gui_imagedata.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_imagedata.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" + +/** + * Constructor for the GuiImageData class. + */ +GuiImageData::GuiImageData(const u8 * i, int maxw, int maxh) +{ + data = NULL; + width = 0; + height = 0; + + if(i) + data = DecodePNG(i, &width, &height, data, maxw, maxh); +} + +/** + * Destructor for the GuiImageData class. + */ +GuiImageData::~GuiImageData() +{ + if(data) + { + free(data); + data = NULL; + } +} + +u8 * GuiImageData::GetImage() +{ + return data; +} + +int GuiImageData::GetWidth() +{ + return width; +} + +int GuiImageData::GetHeight() +{ + return height; +} diff --git a/plugins/snes9x_gx/source/gui/gui_keyboard.cpp b/plugins/snes9x_gx/source/gui/gui_keyboard.cpp new file mode 100644 index 00000000..db4a9647 --- /dev/null +++ b/plugins/snes9x_gx/source/gui/gui_keyboard.cpp @@ -0,0 +1,372 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_keyboard.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" + +static char tmptxt[MAX_KEYBOARD_DISPLAY]; + +static char * GetDisplayText(char * t) +{ + if(!t) + return NULL; + + int len = strlen(t); + + if(len < MAX_KEYBOARD_DISPLAY) + return t; + + snprintf(tmptxt, MAX_KEYBOARD_DISPLAY, "%s", &t[len-MAX_KEYBOARD_DISPLAY]); + return &tmptxt[0]; +} + +/** + * Constructor for the GuiKeyboard class. + */ + +GuiKeyboard::GuiKeyboard(char * t, u32 max) +{ + width = 540; + height = 400; + shift = 0; + caps = 0; + selectable = true; + focus = 0; // allow focus + alignmentHor = ALIGN_CENTRE; + alignmentVert = ALIGN_MIDDLE; + snprintf(kbtextstr, 255, "%s", t); + kbtextmaxlen = max; + + Key thekeys[4][11] = { + { + {'1','!'}, + {'2','@'}, + {'3','#'}, + {'4','$'}, + {'5','%'}, + {'6','^'}, + {'7','&'}, + {'8','*'}, + {'9','('}, + {'0',')'}, + {'\0','\0'} + }, + { + {'q','Q'}, + {'w','W'}, + {'e','E'}, + {'r','R'}, + {'t','T'}, + {'y','Y'}, + {'u','U'}, + {'i','I'}, + {'o','O'}, + {'p','P'}, + {'-','_'} + }, + { + {'a','A'}, + {'s','S'}, + {'d','D'}, + {'f','F'}, + {'g','G'}, + {'h','H'}, + {'j','J'}, + {'k','K'}, + {'l','L'}, + {';',':'}, + {'\'','"'} + }, + + { + {'z','Z'}, + {'x','X'}, + {'c','C'}, + {'v','V'}, + {'b','B'}, + {'n','N'}, + {'m','M'}, + {',','<'}, + {'.','>'}, + {'/','?'}, + {'\0','\0'} + } + }; + memcpy(keys, thekeys, sizeof(thekeys)); + + keyTextbox = new GuiImageData(keyboard_textbox_png); + keyTextboxImg = new GuiImage(keyTextbox); + keyTextboxImg->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + keyTextboxImg->SetPosition(0, 0); + this->Append(keyTextboxImg); + + kbText = new GuiText(GetDisplayText(kbtextstr), 22, (GXColor){0, 0, 0, 0xff}); + kbText->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + kbText->SetPosition(0, 13); + this->Append(kbText); + + key = new GuiImageData(keyboard_key_png); + keyOver = new GuiImageData(keyboard_key_over_png); + keyMedium = new GuiImageData(keyboard_mediumkey_png); + keyMediumOver = new GuiImageData(keyboard_mediumkey_over_png); + keyLarge = new GuiImageData(keyboard_largekey_png); + keyLargeOver = new GuiImageData(keyboard_largekey_over_png); + + keySoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, SOUND_PCM); + keySoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM); + + trigA = new GuiTrigger; + trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + trig2 = new GuiTrigger; + trig2->SetSimpleTrigger(-1, WPAD_BUTTON_2, 0); + + keyBackImg = new GuiImage(keyMedium); + keyBackOverImg = new GuiImage(keyMediumOver); + keyBackText = new GuiText("Back", 22, (GXColor){0, 0, 0, 0xff}); + keyBack = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight()); + keyBack->SetImage(keyBackImg); + keyBack->SetImageOver(keyBackOverImg); + keyBack->SetLabel(keyBackText); + keyBack->SetSoundOver(keySoundOver); + keyBack->SetSoundClick(keySoundClick); + keyBack->SetTrigger(trigA); + keyBack->SetTrigger(trig2); + keyBack->SetPosition(10*42+40, 0*42+80); + keyBack->SetEffectGrow(); + this->Append(keyBack); + + keyCapsImg = new GuiImage(keyMedium); + keyCapsOverImg = new GuiImage(keyMediumOver); + keyCapsText = new GuiText("Caps", 22, (GXColor){0, 0, 0, 0xff}); + keyCaps = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight()); + keyCaps->SetImage(keyCapsImg); + keyCaps->SetImageOver(keyCapsOverImg); + keyCaps->SetLabel(keyCapsText); + keyCaps->SetSoundOver(keySoundOver); + keyCaps->SetSoundClick(keySoundClick); + keyCaps->SetTrigger(trigA); + keyCaps->SetTrigger(trig2); + keyCaps->SetPosition(0, 2*42+80); + keyCaps->SetEffectGrow(); + this->Append(keyCaps); + + keyShiftImg = new GuiImage(keyMedium); + keyShiftOverImg = new GuiImage(keyMediumOver); + keyShiftText = new GuiText("Shift", 22, (GXColor){0, 0, 0, 0xff}); + keyShift = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight()); + keyShift->SetImage(keyShiftImg); + keyShift->SetImageOver(keyShiftOverImg); + keyShift->SetLabel(keyShiftText); + keyShift->SetSoundOver(keySoundOver); + keyShift->SetSoundClick(keySoundClick); + keyShift->SetTrigger(trigA); + keyShift->SetTrigger(trig2); + keyShift->SetPosition(21, 3*42+80); + keyShift->SetEffectGrow(); + this->Append(keyShift); + + keySpaceImg = new GuiImage(keyLarge); + keySpaceOverImg = new GuiImage(keyLargeOver); + keySpace = new GuiButton(keyLarge->GetWidth(), keyLarge->GetHeight()); + keySpace->SetImage(keySpaceImg); + keySpace->SetImageOver(keySpaceOverImg); + keySpace->SetSoundOver(keySoundOver); + keySpace->SetSoundClick(keySoundClick); + keySpace->SetTrigger(trigA); + keySpace->SetTrigger(trig2); + keySpace->SetPosition(0, 4*42+80); + keySpace->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + keySpace->SetEffectGrow(); + this->Append(keySpace); + + char txt[2] = { 0, 0 }; + + for(int i=0; i<4; i++) + { + for(int j=0; j<11; j++) + { + if(keys[i][j].ch != '\0') + { + txt[0] = keys[i][j].ch; + keyImg[i][j] = new GuiImage(key); + keyImgOver[i][j] = new GuiImage(keyOver); + keyTxt[i][j] = new GuiText(txt, 22, (GXColor){0, 0, 0, 0xff}); + keyTxt[i][j]->SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + keyTxt[i][j]->SetPosition(0, -8); + keyBtn[i][j] = new GuiButton(key->GetWidth(), key->GetHeight()); + keyBtn[i][j]->SetImage(keyImg[i][j]); + keyBtn[i][j]->SetImageOver(keyImgOver[i][j]); + keyBtn[i][j]->SetSoundOver(keySoundOver); + keyBtn[i][j]->SetSoundClick(keySoundClick); + keyBtn[i][j]->SetTrigger(trigA); + keyBtn[i][j]->SetTrigger(trig2); + keyBtn[i][j]->SetLabel(keyTxt[i][j]); + keyBtn[i][j]->SetPosition(j*42+21*i+40, i*42+80); + keyBtn[i][j]->SetEffectGrow(); + this->Append(keyBtn[i][j]); + } + } + } +} + +/** + * Destructor for the GuiKeyboard class. + */ +GuiKeyboard::~GuiKeyboard() +{ + delete kbText; + delete keyTextbox; + delete keyTextboxImg; + delete keyCapsText; + delete keyCapsImg; + delete keyCapsOverImg; + delete keyCaps; + delete keyShiftText; + delete keyShiftImg; + delete keyShiftOverImg; + delete keyShift; + delete keyBackText; + delete keyBackImg; + delete keyBackOverImg; + delete keyBack; + delete keySpaceImg; + delete keySpaceOverImg; + delete keySpace; + delete key; + delete keyOver; + delete keyMedium; + delete keyMediumOver; + delete keyLarge; + delete keyLargeOver; + delete keySoundOver; + delete keySoundClick; + delete trigA; + delete trig2; + + for(int i=0; i<4; i++) + { + for(int j=0; j<11; j++) + { + if(keys[i][j].ch != '\0') + { + delete keyImg[i][j]; + delete keyImgOver[i][j]; + delete keyTxt[i][j]; + delete keyBtn[i][j]; + } + } + } +} + +void GuiKeyboard::Update(GuiTrigger * t) +{ + if(_elements.size() == 0 || (state == STATE_DISABLED && parentElement)) + return; + + for (u8 i = 0; i < _elements.size(); i++) + { + try { _elements.at(i)->Update(t); } + catch (const std::exception& e) { } + } + + bool update = false; + + if(keySpace->GetState() == STATE_CLICKED) + { + if(strlen(kbtextstr) < kbtextmaxlen) + { + kbtextstr[strlen(kbtextstr)] = ' '; + kbText->SetText(kbtextstr); + } + keySpace->SetState(STATE_SELECTED, t->chan); + } + else if(keyBack->GetState() == STATE_CLICKED) + { + if(strlen(kbtextstr) > 0) + { + kbtextstr[strlen(kbtextstr)-1] = 0; + kbText->SetText(GetDisplayText(kbtextstr)); + } + keyBack->SetState(STATE_SELECTED, t->chan); + } + else if(keyShift->GetState() == STATE_CLICKED) + { + shift ^= 1; + keyShift->SetState(STATE_SELECTED, t->chan); + update = true; + } + else if(keyCaps->GetState() == STATE_CLICKED) + { + caps ^= 1; + keyCaps->SetState(STATE_SELECTED, t->chan); + update = true; + } + + char txt[2] = { 0, 0 }; + + startloop: + + for(int i=0; i<4; i++) + { + for(int j=0; j<11; j++) + { + if(keys[i][j].ch != '\0') + { + if(update) + { + if(shift || caps) + txt[0] = keys[i][j].chShift; + else + txt[0] = keys[i][j].ch; + + keyTxt[i][j]->SetText(txt); + } + + if(keyBtn[i][j]->GetState() == STATE_CLICKED) + { + if(strlen(kbtextstr) < kbtextmaxlen) + { + if(shift || caps) + { + kbtextstr[strlen(kbtextstr)] = keys[i][j].chShift; + } + else + { + kbtextstr[strlen(kbtextstr)] = keys[i][j].ch; + } + } + kbText->SetText(GetDisplayText(kbtextstr)); + keyBtn[i][j]->SetState(STATE_SELECTED, t->chan); + + if(shift) + { + shift ^= 1; + update = true; + goto startloop; + } + } + } + } + } + + this->ToggleFocus(t); + + if(focus) // only send actions to this window if it's in focus + { + // pad/joystick navigation + if(t->Right()) + this->MoveSelectionHor(1); + else if(t->Left()) + this->MoveSelectionHor(-1); + else if(t->Down()) + this->MoveSelectionVert(1); + else if(t->Up()) + this->MoveSelectionVert(-1); + } +} diff --git a/plugins/snes9x_gx/source/gui/gui_optionbrowser.cpp b/plugins/snes9x_gx/source/gui/gui_optionbrowser.cpp new file mode 100644 index 00000000..027fbfb6 --- /dev/null +++ b/plugins/snes9x_gx/source/gui/gui_optionbrowser.cpp @@ -0,0 +1,366 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_optionbrowser.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" + +/** + * Constructor for the GuiOptionBrowser class. + */ +GuiOptionBrowser::GuiOptionBrowser(int w, int h, OptionList * l) +{ + width = w; + height = h; + options = l; + selectable = true; + listOffset = this->FindMenuItem(-1, 1); + listChanged = true; // trigger an initial list update + selectedItem = 0; + focus = 0; // allow focus + + trigA = new GuiTrigger; + trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + trig2 = new GuiTrigger; + trig2->SetSimpleTrigger(-1, WPAD_BUTTON_2, 0); + + btnSoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, SOUND_PCM); + btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM); + + bgOptions = new GuiImageData(bg_options_png); + bgOptionsImg = new GuiImage(bgOptions); + bgOptionsImg->SetParent(this); + bgOptionsImg->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + + bgOptionsEntry = new GuiImageData(bg_options_entry_png); + + scrollbar = new GuiImageData(scrollbar_png); + scrollbarImg = new GuiImage(scrollbar); + scrollbarImg->SetParent(this); + scrollbarImg->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + scrollbarImg->SetPosition(0, 30); + + arrowDown = new GuiImageData(scrollbar_arrowdown_png); + arrowDownImg = new GuiImage(arrowDown); + arrowDownOver = new GuiImageData(scrollbar_arrowdown_over_png); + arrowDownOverImg = new GuiImage(arrowDownOver); + arrowUp = new GuiImageData(scrollbar_arrowup_png); + arrowUpImg = new GuiImage(arrowUp); + arrowUpOver = new GuiImageData(scrollbar_arrowup_over_png); + arrowUpOverImg = new GuiImage(arrowUpOver); + + arrowUpBtn = new GuiButton(arrowUpImg->GetWidth(), arrowUpImg->GetHeight()); + arrowUpBtn->SetParent(this); + arrowUpBtn->SetImage(arrowUpImg); + arrowUpBtn->SetImageOver(arrowUpOverImg); + arrowUpBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + arrowUpBtn->SetSelectable(false); + arrowUpBtn->SetTrigger(trigA); + arrowUpBtn->SetSoundOver(btnSoundOver); + arrowUpBtn->SetSoundClick(btnSoundClick); + + arrowDownBtn = new GuiButton(arrowDownImg->GetWidth(), arrowDownImg->GetHeight()); + arrowDownBtn->SetParent(this); + arrowDownBtn->SetImage(arrowDownImg); + arrowDownBtn->SetImageOver(arrowDownOverImg); + arrowDownBtn->SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + arrowDownBtn->SetSelectable(false); + arrowDownBtn->SetTrigger(trigA); + arrowDownBtn->SetSoundOver(btnSoundOver); + arrowDownBtn->SetSoundClick(btnSoundClick); + + for(int i=0; i<PAGESIZE; i++) + { + optionTxt[i] = new GuiText(NULL, 20, (GXColor){0, 0, 0, 0xff}); + optionTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + optionTxt[i]->SetPosition(8,0); + + optionVal[i] = new GuiText(NULL, 20, (GXColor){0, 0, 0, 0xff}); + optionVal[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + optionVal[i]->SetPosition(250,0); + + optionBg[i] = new GuiImage(bgOptionsEntry); + + optionBtn[i] = new GuiButton(512,30); + optionBtn[i]->SetParent(this); + optionBtn[i]->SetLabel(optionTxt[i], 0); + optionBtn[i]->SetLabel(optionVal[i], 1); + optionBtn[i]->SetImageOver(optionBg[i]); + optionBtn[i]->SetPosition(0,30*i+3); + optionBtn[i]->SetTrigger(trigA); + optionBtn[i]->SetTrigger(trig2); + optionBtn[i]->SetSoundClick(btnSoundClick); + } +} + +/** + * Destructor for the GuiOptionBrowser class. + */ +GuiOptionBrowser::~GuiOptionBrowser() +{ + delete arrowUpBtn; + delete arrowDownBtn; + + delete bgOptionsImg; + delete scrollbarImg; + delete arrowDownImg; + delete arrowDownOverImg; + delete arrowUpImg; + delete arrowUpOverImg; + + delete bgOptions; + delete bgOptionsEntry; + delete scrollbar; + delete arrowDown; + delete arrowDownOver; + delete arrowUp; + delete arrowUpOver; + + delete trigA; + delete trig2; + delete btnSoundOver; + delete btnSoundClick; + + for(int i=0; i<PAGESIZE; i++) + { + delete optionTxt[i]; + delete optionVal[i]; + delete optionBg[i]; + delete optionBtn[i]; + } +} + +void GuiOptionBrowser::SetCol1Position(int x) +{ + for(int i=0; i<PAGESIZE; i++) + optionTxt[i]->SetPosition(x,0); +} + +void GuiOptionBrowser::SetCol2Position(int x) +{ + for(int i=0; i<PAGESIZE; i++) + optionVal[i]->SetPosition(x,0); +} + +void GuiOptionBrowser::SetFocus(int f) +{ + focus = f; + + for(int i=0; i<PAGESIZE; i++) + optionBtn[i]->ResetState(); + + if(f == 1) + optionBtn[selectedItem]->SetState(STATE_SELECTED); +} + +void GuiOptionBrowser::ResetState() +{ + if(state != STATE_DISABLED) + { + state = STATE_DEFAULT; + stateChan = -1; + } + + for(int i=0; i<PAGESIZE; i++) + { + optionBtn[i]->ResetState(); + } +} + +int GuiOptionBrowser::GetClickedOption() +{ + int found = -1; + for(int i=0; i<PAGESIZE; i++) + { + if(optionBtn[i]->GetState() == STATE_CLICKED) + { + optionBtn[i]->SetState(STATE_SELECTED); + found = optionIndex[i]; + break; + } + } + return found; +} + +/**************************************************************************** + * FindMenuItem + * + * Help function to find the next visible menu item on the list + ***************************************************************************/ + +int GuiOptionBrowser::FindMenuItem(int currentItem, int direction) +{ + int nextItem = currentItem + direction; + + if(nextItem < 0 || nextItem >= options->length) + return -1; + + if(strlen(options->name[nextItem]) > 0) + return nextItem; + else + return FindMenuItem(nextItem, direction); +} + +/** + * Draw the button on screen + */ +void GuiOptionBrowser::Draw() +{ + if(!this->IsVisible()) + return; + + bgOptionsImg->Draw(); + + int next = listOffset; + + for(int i=0; i<PAGESIZE; ++i) + { + if(next >= 0) + { + optionBtn[i]->Draw(); + next = this->FindMenuItem(next, 1); + } + else + break; + } + + scrollbarImg->Draw(); + arrowUpBtn->Draw(); + arrowDownBtn->Draw(); + + this->UpdateEffects(); +} + +void GuiOptionBrowser::TriggerUpdate() +{ + listChanged = true; +} + +void GuiOptionBrowser::ResetText() +{ + int next = listOffset; + + for(int i=0; i<PAGESIZE; i++) + { + if(next >= 0) + { + optionBtn[i]->ResetText(); + next = this->FindMenuItem(next, 1); + } + else + break; + } +} + +void GuiOptionBrowser::Update(GuiTrigger * t) +{ + if(state == STATE_DISABLED || !t) + return; + + int next, prev; + + arrowUpBtn->Update(t); + arrowDownBtn->Update(t); + + next = listOffset; + + if(listChanged) + { + listChanged = false; + for(int i=0; i<PAGESIZE; ++i) + { + if(next >= 0) + { + if(optionBtn[i]->GetState() == STATE_DISABLED) + { + optionBtn[i]->SetVisible(true); + optionBtn[i]->SetState(STATE_DEFAULT); + } + + optionTxt[i]->SetText(options->name[next]); + optionVal[i]->SetText(options->value[next]); + optionIndex[i] = next; + next = this->FindMenuItem(next, 1); + } + else + { + optionBtn[i]->SetVisible(false); + optionBtn[i]->SetState(STATE_DISABLED); + } + } + } + + for(int i=0; i<PAGESIZE; ++i) + { + if(i != selectedItem && optionBtn[i]->GetState() == STATE_SELECTED) + optionBtn[i]->ResetState(); + else if(focus && i == selectedItem && optionBtn[i]->GetState() == STATE_DEFAULT) + optionBtn[selectedItem]->SetState(STATE_SELECTED, t->chan); + + int currChan = t->chan; + + if(t->wpad->ir.valid && !optionBtn[i]->IsInside(t->wpad->ir.x, t->wpad->ir.y)) + t->chan = -1; + + optionBtn[i]->Update(t); + t->chan = currChan; + + if(optionBtn[i]->GetState() == STATE_SELECTED) + selectedItem = i; + } + + // pad/joystick navigation + if(!focus) + return; // skip navigation + + if(t->Down() || arrowDownBtn->GetState() == STATE_CLICKED) + { + next = this->FindMenuItem(optionIndex[selectedItem], 1); + + if(next >= 0) + { + if(selectedItem == PAGESIZE-1) + { + // move list down by 1 + listOffset = this->FindMenuItem(listOffset, 1); + listChanged = true; + } + else if(optionBtn[selectedItem+1]->IsVisible()) + { + optionBtn[selectedItem]->ResetState(); + optionBtn[selectedItem+1]->SetState(STATE_SELECTED, t->chan); + ++selectedItem; + } + } + arrowDownBtn->ResetState(); + } + else if(t->Up() || arrowUpBtn->GetState() == STATE_CLICKED) + { + prev = this->FindMenuItem(optionIndex[selectedItem], -1); + + if(prev >= 0) + { + if(selectedItem == 0) + { + // move list up by 1 + listOffset = prev; + listChanged = true; + } + else + { + optionBtn[selectedItem]->ResetState(); + optionBtn[selectedItem-1]->SetState(STATE_SELECTED, t->chan); + --selectedItem; + } + } + arrowUpBtn->ResetState(); + } + + if(updateCB) + updateCB(this); +} diff --git a/plugins/snes9x_gx/source/gui/gui_savebrowser.cpp b/plugins/snes9x_gx/source/gui/gui_savebrowser.cpp new file mode 100644 index 00000000..5e181773 --- /dev/null +++ b/plugins/snes9x_gx/source/gui/gui_savebrowser.cpp @@ -0,0 +1,398 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_savebrowser.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" +#include "filebrowser.h" + +/** + * Constructor for the GuiSaveBrowser class. + */ +GuiSaveBrowser::GuiSaveBrowser(int w, int h, SaveList * s, int a) +{ + width = w; + height = h; + saves = s; + action = a; + selectable = true; + + if(action == 0) // load + listOffset = 0; + else + listOffset = -2; // save - reserve -2 & -1 for new slots + + selectedItem = 0; + focus = 0; // allow focus + + trigA = new GuiTrigger; + trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + trig2 = new GuiTrigger; + trig2->SetSimpleTrigger(-1, WPAD_BUTTON_2, 0); + + btnSoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, SOUND_PCM); + btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM); + + gameSave = new GuiImageData(button_gamesave_png); + gameSaveOver = new GuiImageData(button_gamesave_over_png); + gameSaveBlank = new GuiImageData(button_gamesave_blank_png); + + scrollbar = new GuiImageData(scrollbar_png); + scrollbarImg = new GuiImage(scrollbar); + scrollbarImg->SetParent(this); + scrollbarImg->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + scrollbarImg->SetPosition(0, 30); + + arrowDown = new GuiImageData(scrollbar_arrowdown_png); + arrowDownImg = new GuiImage(arrowDown); + arrowDownOver = new GuiImageData(scrollbar_arrowdown_over_png); + arrowDownOverImg = new GuiImage(arrowDownOver); + arrowUp = new GuiImageData(scrollbar_arrowup_png); + arrowUpImg = new GuiImage(arrowUp); + arrowUpOver = new GuiImageData(scrollbar_arrowup_over_png); + arrowUpOverImg = new GuiImage(arrowUpOver); + + arrowUpBtn = new GuiButton(arrowUpImg->GetWidth(), arrowUpImg->GetHeight()); + arrowUpBtn->SetParent(this); + arrowUpBtn->SetImage(arrowUpImg); + arrowUpBtn->SetImageOver(arrowUpOverImg); + arrowUpBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + arrowUpBtn->SetSelectable(false); + arrowUpBtn->SetTrigger(trigA); + arrowUpBtn->SetSoundOver(btnSoundOver); + arrowUpBtn->SetSoundClick(btnSoundClick); + + arrowDownBtn = new GuiButton(arrowDownImg->GetWidth(), arrowDownImg->GetHeight()); + arrowDownBtn->SetParent(this); + arrowDownBtn->SetImage(arrowDownImg); + arrowDownBtn->SetImageOver(arrowDownOverImg); + arrowDownBtn->SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + arrowDownBtn->SetSelectable(false); + arrowDownBtn->SetTrigger(trigA); + arrowDownBtn->SetSoundOver(btnSoundOver); + arrowDownBtn->SetSoundClick(btnSoundClick); + + for(int i=0; i<SAVELISTSIZE; i++) + { + saveDate[i] = new GuiText(NULL, 18, (GXColor){0, 0, 0, 0xff}); + saveDate[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); + saveDate[i]->SetPosition(80,5); + saveTime[i] = new GuiText(NULL, 18, (GXColor){0, 0, 0, 0xff}); + saveTime[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); + saveTime[i]->SetPosition(80,27); + + saveType[i] = new GuiText(NULL, 18, (GXColor){0, 0, 0, 0xff}); + saveType[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); + saveType[i]->SetPosition(80,50); + + saveBgImg[i] = new GuiImage(gameSave); + saveBgOverImg[i] = new GuiImage(gameSaveOver); + savePreviewImg[i] = new GuiImage(gameSaveBlank); + savePreviewImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + savePreviewImg[i]->SetPosition(5,0); + + saveBtn[i] = new GuiButton(saveBgImg[i]->GetWidth(),saveBgImg[i]->GetHeight()); + saveBtn[i]->SetParent(this); + saveBtn[i]->SetLabel(saveDate[i], 0); + saveBtn[i]->SetLabel(saveTime[i], 1); + saveBtn[i]->SetLabel(saveType[i], 2); + saveBtn[i]->SetImage(saveBgImg[i]); + saveBtn[i]->SetImageOver(saveBgOverImg[i]); + saveBtn[i]->SetIcon(savePreviewImg[i]); + saveBtn[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); + saveBtn[i]->SetPosition(257*(i % 2),87*(i>>1)); + saveBtn[i]->SetTrigger(trigA); + saveBtn[i]->SetTrigger(trig2); + saveBtn[i]->SetState(STATE_DISABLED); + saveBtn[i]->SetEffectGrow(); + saveBtn[i]->SetVisible(false); + saveBtn[i]->SetSoundOver(btnSoundOver); + saveBtn[i]->SetSoundClick(btnSoundClick); + saveBtnLastOver[i] = false; + } + saveBtn[0]->SetState(STATE_SELECTED, -1); + saveBtn[0]->SetVisible(true); +} + +/** + * Destructor for the GuiSaveBrowser class. + */ +GuiSaveBrowser::~GuiSaveBrowser() +{ + delete arrowUpBtn; + delete arrowDownBtn; + + delete scrollbarImg; + delete arrowDownImg; + delete arrowDownOverImg; + delete arrowUpImg; + delete arrowUpOverImg; + + delete gameSave; + delete gameSaveOver; + delete gameSaveBlank; + delete scrollbar; + delete arrowDown; + delete arrowDownOver; + delete arrowUp; + delete arrowUpOver; + + delete btnSoundOver; + delete btnSoundClick; + delete trigA; + delete trig2; + + for(int i=0; i<SAVELISTSIZE; i++) + { + delete saveBtn[i]; + delete saveDate[i]; + delete saveTime[i]; + delete saveType[i]; + delete saveBgImg[i]; + delete saveBgOverImg[i]; + delete savePreviewImg[i]; + } +} + +void GuiSaveBrowser::SetFocus(int f) +{ + focus = f; + + for(int i=0; i<SAVELISTSIZE; i++) + saveBtn[i]->ResetState(); + + if(f == 1 && selectedItem >= 0) + saveBtn[selectedItem]->SetState(STATE_SELECTED); +} + +void GuiSaveBrowser::ResetState() +{ + if(state != STATE_DISABLED) + { + state = STATE_DEFAULT; + stateChan = -1; + } + + for(int i=0; i<SAVELISTSIZE; i++) + { + saveBtn[i]->ResetState(); + } +} + +int GuiSaveBrowser::GetClickedSave() +{ + int found = -3; + for(int i=0; i<SAVELISTSIZE; i++) + { + if(saveBtn[i]->GetState() == STATE_CLICKED) + { + saveBtn[i]->SetState(STATE_SELECTED); + found = listOffset+i; + break; + } + } + return found; +} + +/** + * Draw the button on screen + */ +void GuiSaveBrowser::Draw() +{ + if(!this->IsVisible()) + return; + + for(int i=0; i<SAVELISTSIZE; i++) + saveBtn[i]->Draw(); + + scrollbarImg->Draw(); + arrowUpBtn->Draw(); + arrowDownBtn->Draw(); + + this->UpdateEffects(); +} + +void GuiSaveBrowser::Update(GuiTrigger * t) +{ + if(state == STATE_DISABLED || !t) + return; + + int i, len; + char savetext[50]; + + arrowUpBtn->Update(t); + arrowDownBtn->Update(t); + + // pad/joystick navigation + if(!focus) + goto endNavigation; // skip navigation + + if(selectedItem < 0) selectedItem = 0; + + if(t->Right()) + { + if(selectedItem == SAVELISTSIZE-1) + { + if(listOffset + SAVELISTSIZE < saves->length) + { + // move list down by 1 row + listOffset += 2; + selectedItem -= 1; + } + } + else if(saveBtn[selectedItem+1]->IsVisible()) + { + saveBtn[selectedItem]->ResetState(); + saveBtn[selectedItem+1]->SetState(STATE_SELECTED, t->chan); + selectedItem += 1; + } + } + else if(t->Left()) + { + if(selectedItem == 0) + { + if((listOffset - 2 >= 0 && action == 0) || + (listOffset >= 0 && action == 1)) + { + // move list up by 1 + listOffset -= 2; + selectedItem = SAVELISTSIZE-1; + } + } + else + { + selectedItem -= 1; + } + } + else if(t->Down() || arrowDownBtn->GetState() == STATE_CLICKED) + { + if(selectedItem >= SAVELISTSIZE-2) + { + if(listOffset + SAVELISTSIZE + 1 < saves->length) + { + listOffset += 2; + } + else if(listOffset + SAVELISTSIZE < saves->length) + { + listOffset += 2; + + if(selectedItem == SAVELISTSIZE-1) + selectedItem -= 1; + } + } + else if(saveBtn[selectedItem+2]->IsVisible()) + { + selectedItem += 2; + } + } + else if(t->Up() || arrowUpBtn->GetState() == STATE_CLICKED) + { + if(selectedItem < 2) + { + if((listOffset - 2 >= 0 && action == 0) || + (listOffset >= 0 && action == 1)) + { + // move list up by 1 + listOffset -= 2; + } + } + else + { + selectedItem -= 2; + } + } + + endNavigation: + + if(arrowDownBtn->GetState() == STATE_CLICKED) + arrowDownBtn->ResetState(); + + if(arrowUpBtn->GetState() == STATE_CLICKED) + arrowUpBtn->ResetState(); + + for(i=0; i<SAVELISTSIZE; i++) + { + if(listOffset+i < 0 && action == 1) + { + saveDate[0]->SetText(NULL); + saveDate[1]->SetText(NULL); + saveTime[0]->SetText("New"); + saveTime[1]->SetText("New"); + saveType[0]->SetText("SRAM"); + saveType[1]->SetText("Snapshot"); + savePreviewImg[0]->SetImage(gameSaveBlank); + savePreviewImg[1]->SetImage(gameSaveBlank); + saveBtn[0]->SetVisible(true); + saveBtn[1]->SetVisible(true); + + if(saveBtn[0]->GetState() == STATE_DISABLED) + saveBtn[0]->SetState(STATE_DEFAULT); + if(saveBtn[1]->GetState() == STATE_DISABLED) + saveBtn[1]->SetState(STATE_DEFAULT); + } + else if(listOffset+i < saves->length) + { + if(saveBtn[i]->GetState() == STATE_DISABLED || !saveBtn[i]->IsVisible()) + { + saveBtn[i]->SetVisible(true); + saveBtn[i]->SetState(STATE_DEFAULT); + } + + saveDate[i]->SetText(saves->date[listOffset+i]); + saveTime[i]->SetText(saves->time[listOffset+i]); + + if(saves->type[listOffset+i] == FILE_SRAM) + sprintf(savetext, "SRAM"); + else + sprintf(savetext, "Snapshot"); + + len = strlen(saves->filename[listOffset+i]); + if(len > 10 && + ((saves->filename[listOffset+i][len-8] == 'A' && + saves->filename[listOffset+i][len-7] == 'u' && + saves->filename[listOffset+i][len-6] == 't' && + saves->filename[listOffset+i][len-5] == 'o') || + saves->filename[listOffset+i][len-5] == '0') + ) + { + strcat(savetext, " (Auto)"); + } + saveType[i]->SetText(savetext); + + if(saves->previewImg[listOffset+i] != NULL) + savePreviewImg[i]->SetImage(saves->previewImg[listOffset+i]); + else + savePreviewImg[i]->SetImage(gameSaveBlank); + } + else + { + saveBtn[i]->SetVisible(false); + saveBtn[i]->SetState(STATE_DISABLED); + } + + if(i != selectedItem && saveBtn[i]->GetState() == STATE_SELECTED) + saveBtn[i]->ResetState(); + else if(focus && i == selectedItem && saveBtn[i]->GetState() == STATE_DEFAULT) + saveBtn[selectedItem]->SetState(STATE_SELECTED, t->chan); + + if(t->wpad->ir.valid) + { + if(!saveBtnLastOver[i] && saveBtn[i]->IsInside(t->wpad->ir.x, t->wpad->ir.y)) + saveBtn[i]->ResetState(); + saveBtnLastOver[i] = saveBtn[i]->IsInside(t->wpad->ir.x, t->wpad->ir.y); + } + + saveBtn[i]->Update(t); + + if(saveBtn[i]->GetState() == STATE_SELECTED) + selectedItem = i; + } + + if(updateCB) + updateCB(this); +} diff --git a/plugins/snes9x_gx/source/gui/gui_sound.cpp b/plugins/snes9x_gx/source/gui/gui_sound.cpp new file mode 100644 index 00000000..4dcd5e25 --- /dev/null +++ b/plugins/snes9x_gx/source/gui/gui_sound.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_sound.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" + +/** + * Constructor for the GuiSound class. + */ +GuiSound::GuiSound(const u8 * s, s32 l, int t) +{ + sound = s; + length = l; + type = t; + voice = -1; + volume = 100; + loop = false; +} + +/** + * Destructor for the GuiSound class. + */ +GuiSound::~GuiSound() +{ + #ifndef NO_SOUND + if(type == SOUND_OGG) + StopOgg(); + #endif +} + +void GuiSound::Play() +{ + #ifndef NO_SOUND + int vol; + + switch(type) + { + case SOUND_PCM: + vol = 0.0255f*(volume*GCSettings.SFXVolume); + voice = ASND_GetFirstUnusedVoice(); + if(voice >= 0) + ASND_SetVoice(voice, VOICE_STEREO_16BIT, 48000, 0, + (u8 *)sound, length, vol, vol, NULL); + break; + + case SOUND_OGG: + voice = 0; + if(loop) + PlayOgg((char *)sound, length, 0, OGG_INFINITE_TIME); + else + PlayOgg((char *)sound, length, 0, OGG_ONE_TIME); + SetVolumeOgg(2.55f*(volume)); + break; + } + #endif +} + +void GuiSound::Stop() +{ + #ifndef NO_SOUND + if(voice < 0) + return; + + switch(type) + { + case SOUND_PCM: + ASND_StopVoice(voice); + break; + + case SOUND_OGG: + StopOgg(); + break; + } + #endif +} + +void GuiSound::Pause() +{ + #ifndef NO_SOUND + if(voice < 0) + return; + + switch(type) + { + case SOUND_PCM: + ASND_PauseVoice(voice, 1); + break; + + case SOUND_OGG: + PauseOgg(1); + break; + } + #endif +} + +void GuiSound::Resume() +{ + #ifndef NO_SOUND + if(voice < 0) + return; + + switch(type) + { + case SOUND_PCM: + ASND_PauseVoice(voice, 0); + break; + + case SOUND_OGG: + PauseOgg(0); + break; + } + #endif +} + +bool GuiSound::IsPlaying() +{ + if(ASND_StatusVoice(voice) == SND_WORKING || ASND_StatusVoice(voice) == SND_WAITING) + return true; + else + return false; +} + +void GuiSound::SetVolume(int vol) +{ + #ifndef NO_SOUND + volume = vol; + + if(voice < 0) + return; + + int newvol = 0.0255f*(volume*GCSettings.SFXVolume); + + switch(type) + { + case SOUND_PCM: + ASND_ChangeVolumeVoice(voice, newvol, newvol); + break; + + case SOUND_OGG: + SetVolumeOgg(2.55f*(volume)); + break; + } + #endif +} + +void GuiSound::SetLoop(bool l) +{ + loop = l; +} diff --git a/plugins/snes9x_gx/source/gui/gui_text.cpp b/plugins/snes9x_gx/source/gui/gui_text.cpp new file mode 100644 index 00000000..c2d3a093 --- /dev/null +++ b/plugins/snes9x_gx/source/gui/gui_text.cpp @@ -0,0 +1,480 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_text.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" +#include "../utils/gettext.h" + +static GXColor presetColor = (GXColor){255, 255, 255, 255}; +static int currentSize = 0; +static int presetSize = 0; +static int presetMaxWidth = 0; +static int presetAlignmentHor = 0; +static int presetAlignmentVert = 0; +static u16 presetStyle = 0; + +#define TEXT_SCROLL_DELAY 8 +#define TEXT_SCROLL_INITIAL_DELAY 6 + +/** + * Constructor for the GuiText class. + */ +GuiText::GuiText(const char * t, int s, GXColor c) +{ + origText = NULL; + text = NULL; + size = s; + color = c; + alpha = c.a; + style = FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE; + maxWidth = 0; + wrap = false; + textDynNum = 0; + textScroll = SCROLL_NONE; + textScrollPos = 0; + textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; + textScrollDelay = TEXT_SCROLL_DELAY; + + alignmentHor = ALIGN_CENTRE; + alignmentVert = ALIGN_MIDDLE; + + if(t) + { + origText = strdup(t); + text = charToWideChar(gettext(t)); + } + + for(int i=0; i < 20; i++) + textDyn[i] = NULL; +} + +/** + * Constructor for the GuiText class, uses presets + */ +GuiText::GuiText(const char * t) +{ + origText = NULL; + text = NULL; + size = presetSize; + color = presetColor; + alpha = presetColor.a; + style = presetStyle; + maxWidth = presetMaxWidth; + wrap = false; + textDynNum = 0; + textScroll = SCROLL_NONE; + textScrollPos = 0; + textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; + textScrollDelay = TEXT_SCROLL_DELAY; + + alignmentHor = presetAlignmentHor; + alignmentVert = presetAlignmentVert; + + if(t) + { + origText = strdup(t); + text = charToWideChar(gettext(t)); + } + + for(int i=0; i < 20; i++) + textDyn[i] = NULL; +} + +/** + * Destructor for the GuiText class. + */ +GuiText::~GuiText() +{ + if(origText) + free(origText); + if(text) + delete[] text; + + if(textDynNum > 0) + { + for(int i=0; i < textDynNum; i++) + if(textDyn[i]) + delete[] textDyn[i]; + } +} + +void GuiText::SetText(const char * t) +{ + if(origText) + free(origText); + if(text) + delete[] text; + + if(textDynNum > 0) + { + for(int i=0; i < textDynNum; i++) + if(textDyn[i]) + delete[] textDyn[i]; + } + + origText = NULL; + text = NULL; + textDynNum = 0; + textScrollPos = 0; + textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; + + if(t) + { + origText = strdup(t); + text = charToWideChar(gettext(t)); + } +} + +void GuiText::SetWText(wchar_t * t) +{ + if(origText) + free(origText); + if(text) + delete[] text; + + if(textDynNum > 0) + { + for(int i=0; i < textDynNum; i++) + if(textDyn[i]) + delete[] textDyn[i]; + } + + origText = NULL; + text = NULL; + textDynNum = 0; + textScrollPos = 0; + textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; + + if(t) + text = wcsdup(t); +} + +int GuiText::GetLength() +{ + if(!text) + return 0; + + return wcslen(text); +} + +void GuiText::SetPresets(int sz, GXColor c, int w, u16 s, int h, int v) +{ + presetSize = sz; + presetColor = c; + presetStyle = s; + presetMaxWidth = w; + presetAlignmentHor = h; + presetAlignmentVert = v; +} + +void GuiText::SetFontSize(int s) +{ + size = s; +} + +void GuiText::SetMaxWidth(int width) +{ + maxWidth = width; + + for(int i=0; i < textDynNum; i++) + { + if(textDyn[i]) + { + delete[] textDyn[i]; + textDyn[i] = NULL; + } + } + + textDynNum = 0; +} + +int GuiText::GetTextWidth() +{ + if(!text) + return 0; + + if(currentSize != size) + { + ChangeFontSize(size); + + if(!fontSystem[size]) + fontSystem[size] = new FreeTypeGX(size); + + currentSize = size; + } + return fontSystem[size]->getWidth(text); +} + +void GuiText::SetWrap(bool w, int width) +{ + wrap = w; + maxWidth = width; + + for(int i=0; i < textDynNum; i++) + { + if(textDyn[i]) + { + delete[] textDyn[i]; + textDyn[i] = NULL; + } + } + + textDynNum = 0; +} + +void GuiText::SetScroll(int s) +{ + if(textScroll == s) + return; + + for(int i=0; i < textDynNum; i++) + { + if(textDyn[i]) + { + delete[] textDyn[i]; + textDyn[i] = NULL; + } + } + + textDynNum = 0; + + textScroll = s; + textScrollPos = 0; + textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; + textScrollDelay = TEXT_SCROLL_DELAY; +} + +void GuiText::SetColor(GXColor c) +{ + color = c; + alpha = c.a; +} + +void GuiText::SetStyle(u16 s) +{ + style = s; +} + +void GuiText::SetAlignment(int hor, int vert) +{ + style = 0; + + switch(hor) + { + case ALIGN_LEFT: + style |= FTGX_JUSTIFY_LEFT; + break; + case ALIGN_RIGHT: + style |= FTGX_JUSTIFY_RIGHT; + break; + default: + style |= FTGX_JUSTIFY_CENTER; + break; + } + switch(vert) + { + case ALIGN_TOP: + style |= FTGX_ALIGN_TOP; + break; + case ALIGN_BOTTOM: + style |= FTGX_ALIGN_BOTTOM; + break; + default: + style |= FTGX_ALIGN_MIDDLE; + break; + } + + alignmentHor = hor; + alignmentVert = vert; +} + +void GuiText::ResetText() +{ + if(!origText) + return; + if(text) + delete[] text; + + text = charToWideChar(gettext(origText)); + + for(int i=0; i < textDynNum; i++) + { + if(textDyn[i]) + { + delete[] textDyn[i]; + textDyn[i] = NULL; + } + } + + textDynNum = 0; + currentSize = 0; +} + +/** + * Draw the text on screen + */ +void GuiText::Draw() +{ + if(!text) + return; + + if(!this->IsVisible()) + return; + + GXColor c = color; + c.a = this->GetAlpha(); + + int newSize = size*this->GetScale(); + + if(newSize > MAX_FONT_SIZE) + newSize = MAX_FONT_SIZE; + + if(newSize != currentSize) + { + ChangeFontSize(newSize); + if(!fontSystem[newSize]) + fontSystem[newSize] = new FreeTypeGX(newSize); + currentSize = newSize; + } + + if(maxWidth == 0) + { + fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), text, c, style); + this->UpdateEffects(); + return; + } + + u32 textlen = wcslen(text); + + if(wrap) + { + if(textDynNum == 0) + { + u32 n = 0, ch = 0; + int linenum = 0; + int lastSpace = -1; + int lastSpaceIndex = -1; + + while(ch < textlen && linenum < 20) + { + if(n == 0) + textDyn[linenum] = new wchar_t[textlen + 1]; + + textDyn[linenum][n] = text[ch]; + textDyn[linenum][n+1] = 0; + + if(text[ch] == ' ' || ch == textlen-1) + { + if(fontSystem[currentSize]->getWidth(textDyn[linenum]) > maxWidth) + { + if(lastSpace >= 0) + { + textDyn[linenum][lastSpaceIndex] = 0; // discard space, and everything after + ch = lastSpace; // go backwards to the last space + lastSpace = -1; // we have used this space + lastSpaceIndex = -1; + } + ++linenum; + n = -1; + } + else if(ch == textlen-1) + { + ++linenum; + } + } + if(text[ch] == ' ' && n >= 0) + { + lastSpace = ch; + lastSpaceIndex = n; + } + ++ch; + ++n; + } + textDynNum = linenum; + } + + int lineheight = newSize + 6; + int voffset = 0; + + if(alignmentVert == ALIGN_MIDDLE) + voffset = (lineheight >> 1) * (1-textDynNum); + + int left = this->GetLeft(); + int top = this->GetTop() + voffset; + + for(int i=0; i < textDynNum; ++i) + fontSystem[currentSize]->drawText(left, top+i*lineheight, textDyn[i], c, style); + } + else + { + if(textDynNum == 0) + { + textDynNum = 1; + textDyn[0] = wcsdup(text); + int len = wcslen(textDyn[0]); + + while(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth) + textDyn[0][--len] = 0; + } + + if(textScroll == SCROLL_HORIZONTAL) + { + if(fontSystem[currentSize]->getWidth(text) > maxWidth && (FrameTimer % textScrollDelay == 0)) + { + if(textScrollInitialDelay) + { + --textScrollInitialDelay; + } + else + { + ++textScrollPos; + if((u32)textScrollPos > textlen-1) + { + textScrollPos = 0; + textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; + } + + wcscpy(textDyn[0], &text[textScrollPos]); + u32 dynlen = wcslen(textDyn[0]); + + if(dynlen+2 < textlen) + { + textDyn[0][dynlen] = ' '; + textDyn[0][dynlen+1] = ' '; + textDyn[0][dynlen+2] = 0; + dynlen += 2; + } + + if(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth) + { + while(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth) + textDyn[0][--dynlen] = 0; + } + else + { + int i = 0; + + while(fontSystem[currentSize]->getWidth(textDyn[0]) < maxWidth && dynlen+1 < textlen) + { + textDyn[0][dynlen] = text[i++]; + textDyn[0][++dynlen] = 0; + } + + if(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth) + textDyn[0][dynlen-2] = 0; + else + textDyn[0][dynlen-1] = 0; + } + } + } + } + fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn[0], c, style); + } + this->UpdateEffects(); +} diff --git a/plugins/snes9x_gx/source/gui/gui_trigger.cpp b/plugins/snes9x_gx/source/gui/gui_trigger.cpp new file mode 100644 index 00000000..85f7d331 --- /dev/null +++ b/plugins/snes9x_gx/source/gui/gui_trigger.cpp @@ -0,0 +1,303 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_trigger.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" +#include <ogc/lwp_watchdog.h> +#include <gctypes.h> + +static u64 prev[4]; +static u64 now[4]; +static u32 delay[4]; + +/** + * Constructor for the GuiTrigger class. + */ +GuiTrigger::GuiTrigger() +{ + chan = -1; + memset(&wupcdata, 0, sizeof(WUPCFullData)); + memset(&wpaddata, 0, sizeof(WPADData)); + memset(&pad, 0, sizeof(PADData)); + wpad = &wpaddata; +} + +/** + * Destructor for the GuiTrigger class. + */ +GuiTrigger::~GuiTrigger() +{ +} + +/** + * Sets a simple trigger. Requires: + * - Element is selected + * - Trigger button is pressed + */ +void GuiTrigger::SetSimpleTrigger(s32 ch, u32 wiibtns, u16 gcbtns) +{ + type = TRIGGER_SIMPLE; + chan = ch; + wupcdata.btns_d = wiibtns; + wpaddata.btns_d = wiibtns; + pad.btns_d = gcbtns; +} + +/** + * Sets a held trigger. Requires: + * - Element is selected + * - Trigger button is pressed and held + */ +void GuiTrigger::SetHeldTrigger(s32 ch, u32 wiibtns, u16 gcbtns) +{ + type = TRIGGER_HELD; + chan = ch; + wupcdata.btns_h = wiibtns; + wpaddata.btns_h = wiibtns; + pad.btns_h = gcbtns; +} + +/** + * Sets a button trigger. Requires: + * - Trigger button is pressed + */ +void GuiTrigger::SetButtonOnlyTrigger(s32 ch, u32 wiibtns, u16 gcbtns) +{ + type = TRIGGER_BUTTON_ONLY; + chan = ch; + wupcdata.btns_d = wiibtns; + wpaddata.btns_d = wiibtns; + pad.btns_d = gcbtns; +} + +/** + * Sets a button trigger. Requires: + * - Trigger button is pressed + * - Parent window is in focus + */ +void GuiTrigger::SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns) +{ + type = TRIGGER_BUTTON_ONLY_IN_FOCUS; + chan = ch; + wupcdata.btns_d = wiibtns; + wpaddata.btns_d = wiibtns; + pad.btns_d = gcbtns; +} + +/**************************************************************************** + * WPAD_Stick + * + * Get X/Y value from Wii Joystick (classic, nunchuk) input + ***************************************************************************/ + +s8 GuiTrigger::WPAD_Stick(u8 stick, int axis) +{ + #ifdef HW_RVL + + float mag = 0.0; + float ang = 0.0; + + switch (wpad->exp.type) + { + case WPAD_EXP_NUNCHUK: + case WPAD_EXP_GUITARHERO3: + if (stick == 0) + { + mag = wpad->exp.nunchuk.js.mag; + ang = wpad->exp.nunchuk.js.ang; + } + break; + + case WPAD_EXP_CLASSIC: + if (stick == 0) + { + mag = wpad->exp.classic.ljs.mag; + ang = wpad->exp.classic.ljs.ang; + } + else + { + mag = wpad->exp.classic.rjs.mag; + ang = wpad->exp.classic.rjs.ang; + } + break; + + default: + break; + } + + /* calculate x/y value (angle need to be converted into radian) */ + if (mag > 1.0) mag = 1.0; + else if (mag < -1.0) mag = -1.0; + double val; + + if(axis == 0) // x-axis + val = mag * sin((PI * ang)/180.0f); + else // y-axis + val = mag * cos((PI * ang)/180.0f); + + return (s8)(val * 128.0f); + + #else + return 0; + #endif +} + +s8 GuiTrigger::WPAD_StickX(u8 stick) +{ + return WPAD_Stick(stick, 0); +} + +s8 GuiTrigger::WPAD_StickY(u8 stick) +{ + return WPAD_Stick(stick, 1); +} + +bool GuiTrigger::Left() +{ + u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_UP : WPAD_BUTTON_LEFT; + + if((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT) + || (wupcdata.btns_d | wupcdata.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT) + || (pad.btns_d | pad.btns_h) & PAD_BUTTON_LEFT + || pad.stickX < -PADCAL + || WPAD_StickX(0) < -PADCAL + || wupcdata.stickX < -WUPCCAL) + { + if((wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT)) + || (wupcdata.btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT)) + || pad.btns_d & PAD_BUTTON_LEFT) + { + prev[chan] = gettime(); + delay[chan] = SCROLL_DELAY_INITIAL; // reset scroll delay + return true; + } + + now[chan] = gettime(); + + if(diff_usec(prev[chan], now[chan]) > delay[chan]) + { + prev[chan] = now[chan]; + + if(delay[chan] == SCROLL_DELAY_INITIAL) + delay[chan] = SCROLL_DELAY_LOOP; + else if(delay[chan] > SCROLL_DELAY_DECREASE) + delay[chan] -= SCROLL_DELAY_DECREASE; + return true; + } + } + return false; +} + +bool GuiTrigger::Right() +{ + u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_DOWN : WPAD_BUTTON_RIGHT; + + if((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT) + || ((wupcdata.btns_d | wupcdata.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT)) + || (pad.btns_d | pad.btns_h) & PAD_BUTTON_RIGHT + || pad.stickX > PADCAL + || WPAD_StickX(0) > PADCAL + || wupcdata.stickX > WUPCCAL) + { + if((wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT)) + || (wupcdata.btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT)) + || pad.btns_d & PAD_BUTTON_RIGHT) + { + prev[chan] = gettime(); + delay[chan] = SCROLL_DELAY_INITIAL; // reset scroll delay + return true; + } + + now[chan] = gettime(); + + if(diff_usec(prev[chan], now[chan]) > delay[chan]) + { + prev[chan] = now[chan]; + + if(delay[chan] == SCROLL_DELAY_INITIAL) + delay[chan] = SCROLL_DELAY_LOOP; + else if(delay[chan] > SCROLL_DELAY_DECREASE) + delay[chan] -= SCROLL_DELAY_DECREASE; + return true; + } + } + return false; +} + +bool GuiTrigger::Up() +{ + u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_RIGHT : WPAD_BUTTON_UP; + + if(((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_UP)) + || ((wupcdata.btns_d | wupcdata.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_UP)) + || (pad.btns_d | pad.btns_h) & PAD_BUTTON_UP + || pad.stickY > PADCAL + || WPAD_StickY(0) > PADCAL + || wupcdata.stickY > WUPCCAL) + { + if((wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_UP)) + || (wupcdata.btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_UP)) + || pad.btns_d & PAD_BUTTON_UP) + { + prev[chan] = gettime(); + delay[chan] = SCROLL_DELAY_INITIAL; // reset scroll delay + return true; + } + + now[chan] = gettime(); + + if(diff_usec(prev[chan], now[chan]) > delay[chan]) + { + prev[chan] = now[chan]; + + if(delay[chan] == SCROLL_DELAY_INITIAL) + delay[chan] = SCROLL_DELAY_LOOP; + else if(delay[chan] > SCROLL_DELAY_DECREASE) + delay[chan] -= SCROLL_DELAY_DECREASE; + return true; + } + } + return false; +} + +bool GuiTrigger::Down() +{ + u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_LEFT : WPAD_BUTTON_DOWN; + + if(((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_DOWN)) + || ((wupcdata.btns_d | wupcdata.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_DOWN)) + || (pad.btns_d | pad.btns_h) & PAD_BUTTON_DOWN + || pad.stickY < -PADCAL + || WPAD_StickY(0) < -PADCAL + || wupcdata.stickY < -WUPCCAL) + { + if((wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_DOWN)) + || wupcdata.btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_DOWN) + || pad.btns_d & PAD_BUTTON_DOWN) + { + prev[chan] = gettime(); + delay[chan] = SCROLL_DELAY_INITIAL; // reset scroll delay + return true; + } + + now[chan] = gettime(); + + if(diff_usec(prev[chan], now[chan]) > delay[chan]) + { + prev[chan] = now[chan]; + + if(delay[chan] == SCROLL_DELAY_INITIAL) + delay[chan] = SCROLL_DELAY_LOOP; + else if(delay[chan] > SCROLL_DELAY_DECREASE) + delay[chan] -= SCROLL_DELAY_DECREASE; + return true; + } + } + return false; +} diff --git a/plugins/snes9x_gx/source/gui/gui_window.cpp b/plugins/snes9x_gx/source/gui/gui_window.cpp new file mode 100644 index 00000000..636d8ba3 --- /dev/null +++ b/plugins/snes9x_gx/source/gui/gui_window.cpp @@ -0,0 +1,451 @@ +/**************************************************************************** + * libwiigui + * + * Tantric 2009 + * + * gui_window.cpp + * + * GUI class definitions + ***************************************************************************/ + +#include "gui.h" + +GuiWindow::GuiWindow() +{ + width = 0; + height = 0; + focus = 0; // allow focus +} + +GuiWindow::GuiWindow(int w, int h) +{ + width = w; + height = h; + focus = 0; // allow focus +} + +GuiWindow::~GuiWindow() +{ +} + +void GuiWindow::Append(GuiElement* e) +{ + if (e == NULL) + return; + + Remove(e); + _elements.push_back(e); + e->SetParent(this); +} + +void GuiWindow::Insert(GuiElement* e, u32 index) +{ + if (e == NULL || index > (_elements.size() - 1)) + return; + + Remove(e); + _elements.insert(_elements.begin()+index, e); + e->SetParent(this); +} + +void GuiWindow::Remove(GuiElement* e) +{ + if (e == NULL) + return; + + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) + { + if(e == _elements.at(i)) + { + _elements.erase(_elements.begin()+i); + break; + } + } +} + +void GuiWindow::RemoveAll() +{ + _elements.clear(); +} + +bool GuiWindow::Find(GuiElement* e) +{ + if (e == NULL) + return false; + + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) + if(e == _elements.at(i)) + return true; + return false; +} + +GuiElement* GuiWindow::GetGuiElementAt(u32 index) const +{ + if (index >= _elements.size()) + return NULL; + return _elements.at(index); +} + +u32 GuiWindow::GetSize() +{ + return _elements.size(); +} + +void GuiWindow::Draw() +{ + if(_elements.size() == 0 || !this->IsVisible()) + return; + + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) + { + try { _elements.at(i)->Draw(); } + catch (const std::exception& e) { } + } + + this->UpdateEffects(); + + if(parentElement && state == STATE_DISABLED) + Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0xbe, 0xca, 0xd5, 0x70},1); +} + +void GuiWindow::DrawTooltip() +{ + if(_elements.size() == 0 || !this->IsVisible()) + return; + + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; i++) + { + try { _elements.at(i)->DrawTooltip(); } + catch (const std::exception& e) { } + } +} + +void GuiWindow::ResetState() +{ + if(state != STATE_DISABLED) + state = STATE_DEFAULT; + + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) + { + try { _elements.at(i)->ResetState(); } + catch (const std::exception& e) { } + } +} + +void GuiWindow::SetState(int s) +{ + state = s; + + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) + { + try { _elements.at(i)->SetState(s); } + catch (const std::exception& e) { } + } +} + +void GuiWindow::SetVisible(bool v) +{ + visible = v; + + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) + { + try { _elements.at(i)->SetVisible(v); } + catch (const std::exception& e) { } + } +} + +void GuiWindow::SetFocus(int f) +{ + focus = f; + + if(f == 1) + this->MoveSelectionVert(1); + else + this->ResetState(); +} + +void GuiWindow::ChangeFocus(GuiElement* e) +{ + if(parentElement) + return; // this is only intended for the main window + + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) + { + if(e == _elements.at(i)) + _elements.at(i)->SetFocus(1); + else if(_elements.at(i)->IsFocused() == 1) + _elements.at(i)->SetFocus(0); + } +} + +void GuiWindow::ToggleFocus(GuiTrigger * t) +{ + if(parentElement) + return; // this is only intended for the main window + + int found = -1; + int newfocus = -1; + int i; + + int elemSize = _elements.size(); + + // look for currently in focus element + for (i = 0; i < elemSize; ++i) + { + try + { + if(_elements.at(i)->IsFocused() == 1) + { + found = i; + break; + } + } + catch (const std::exception& e) { } + } + + // element with focus not found, try to give focus + if(found == -1) + { + for (i = 0; i < elemSize; ++i) + { + try + { + if(_elements.at(i)->IsFocused() == 0 && _elements.at(i)->GetState() != STATE_DISABLED) // focus is possible (but not set) + { + _elements.at(i)->SetFocus(1); // give this element focus + break; + } + } + catch (const std::exception& e) { } + } + } + // change focus + else if((t->wpad->btns_d & (WPAD_BUTTON_1 | WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B)) + || (t->pad.btns_d & PAD_BUTTON_B) || (t->wupcdata.btns_d & WPAD_CLASSIC_BUTTON_B)) + { + for (i = found; i < elemSize; ++i) + { + try + { + if(_elements.at(i)->IsFocused() == 0 && _elements.at(i)->GetState() != STATE_DISABLED) // focus is possible (but not set) + { + newfocus = i; + _elements.at(i)->SetFocus(1); // give this element focus + _elements.at(found)->SetFocus(0); // disable focus on other element + break; + } + } + catch (const std::exception& e) { } + } + + if(newfocus == -1) + { + for (i = 0; i < found; ++i) + { + try + { + if(_elements.at(i)->IsFocused() == 0 && _elements.at(i)->GetState() != STATE_DISABLED) // focus is possible (but not set) + { + _elements.at(i)->SetFocus(1); // give this element focus + _elements.at(found)->SetFocus(0); // disable focus on other element + break; + } + } + catch (const std::exception& e) { } + } + } + } +} + +int GuiWindow::GetSelected() +{ + // find selected element + int found = -1; + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) + { + try + { + if(_elements.at(i)->GetState() == STATE_SELECTED) + { + found = int(i); + break; + } + } + catch (const std::exception& e) { } + } + return found; +} + +// set element to left/right as selected +// there's probably a more clever way to do this, but this way works +void GuiWindow::MoveSelectionHor(int dir) +{ + int found = -1; + u16 left = 0; + u16 top = 0; + u32 i; + u32 elemSize = _elements.size(); + + int selected = this->GetSelected(); + + if(selected >= 0) + { + left = _elements.at(selected)->GetLeft(); + top = _elements.at(selected)->GetTop(); + } + + + // look for a button on the same row, to the left/right + for (i = 0; i < elemSize; ++i) + { + try + { + if(_elements.at(i)->IsSelectable()) + { + if(_elements.at(i)->GetLeft()*dir > left*dir && _elements.at(i)->GetTop() == top) + { + if(found == -1) + found = int(i); + else if(_elements.at(i)->GetLeft()*dir < _elements.at(found)->GetLeft()*dir) + found = int(i); // this is a better match + } + } + } + catch (const std::exception& e) { } + } + if(found >= 0) + goto matchfound; + + // match still not found, let's try the first button in the next row + for (i = 0; i < elemSize; ++i) + { + try + { + if(_elements.at(i)->IsSelectable()) + { + if(_elements.at(i)->GetTop()*dir > top*dir) + { + if(found == -1) + found = i; + else if(_elements.at(i)->GetTop()*dir < _elements.at(found)->GetTop()*dir) + found = i; // this is a better match + else if(_elements.at(i)->GetTop()*dir == _elements.at(found)->GetTop()*dir + && + _elements.at(i)->GetLeft()*dir < _elements.at(found)->GetLeft()*dir) + found = i; // this is a better match + } + } + } + catch (const std::exception& e) { } + } + + // match found + matchfound: + if(found >= 0) + { + _elements.at(found)->SetState(STATE_SELECTED); + if(selected >= 0) + _elements.at(selected)->ResetState(); + } +} + +void GuiWindow::MoveSelectionVert(int dir) +{ + int found = -1; + u16 left = 0; + u16 top = 0; + + int selected = this->GetSelected(); + + if(selected >= 0) + { + left = _elements.at(selected)->GetLeft(); + top = _elements.at(selected)->GetTop(); + } + + // look for a button above/below, with the least horizontal difference + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) + { + try + { + if(_elements.at(i)->IsSelectable()) + { + if(_elements.at(i)->GetTop()*dir > top*dir) + { + if(found == -1) + found = i; + else if(_elements.at(i)->GetTop()*dir < _elements.at(found)->GetTop()*dir) + found = i; // this is a better match + else if(_elements.at(i)->GetTop()*dir == _elements.at(found)->GetTop()*dir + && + abs(_elements.at(i)->GetLeft() - left) < + abs(_elements.at(found)->GetLeft() - left)) + found = i; + } + } + } + catch (const std::exception& e) { } + } + if(found >= 0) + goto matchfound; + + // match found + matchfound: + if(found >= 0) + { + _elements.at(found)->SetState(STATE_SELECTED); + if(selected >= 0) + _elements.at(selected)->ResetState(); + } +} + +void GuiWindow::ResetText() +{ + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; i++) + { + try { _elements.at(i)->ResetText(); } + catch (const std::exception& e) { } + } +} + +void GuiWindow::Update(GuiTrigger * t) +{ + if(_elements.size() == 0 || (state == STATE_DISABLED && parentElement)) + return; + + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) + { + try { _elements.at(i)->Update(t); } + catch (const std::exception& e) { } + } + + this->ToggleFocus(t); + + if(focus) // only send actions to this window if it's in focus + { + // pad/joystick navigation + if(t->Right()) + this->MoveSelectionHor(1); + else if(t->Left()) + this->MoveSelectionHor(-1); + else if(t->Down()) + this->MoveSelectionVert(1); + else if(t->Up()) + this->MoveSelectionVert(-1); + } + + if(updateCB) + updateCB(this); +} diff --git a/plugins/snes9x_gx/source/images/battery.png b/plugins/snes9x_gx/source/images/battery.png new file mode 100644 index 00000000..1733f41e Binary files /dev/null and b/plugins/snes9x_gx/source/images/battery.png differ diff --git a/plugins/snes9x_gx/source/images/battery_bar.png b/plugins/snes9x_gx/source/images/battery_bar.png new file mode 100644 index 00000000..474f24d6 Binary files /dev/null and b/plugins/snes9x_gx/source/images/battery_bar.png differ diff --git a/plugins/snes9x_gx/source/images/battery_red.png b/plugins/snes9x_gx/source/images/battery_red.png new file mode 100644 index 00000000..fd7d995c Binary files /dev/null and b/plugins/snes9x_gx/source/images/battery_red.png differ diff --git a/plugins/snes9x_gx/source/images/bg_bottom.png b/plugins/snes9x_gx/source/images/bg_bottom.png new file mode 100644 index 00000000..35cb2b85 Binary files /dev/null and b/plugins/snes9x_gx/source/images/bg_bottom.png differ diff --git a/plugins/snes9x_gx/source/images/bg_game_selection.png b/plugins/snes9x_gx/source/images/bg_game_selection.png new file mode 100644 index 00000000..7978d45e Binary files /dev/null and b/plugins/snes9x_gx/source/images/bg_game_selection.png differ diff --git a/plugins/snes9x_gx/source/images/bg_game_selection_entry.png b/plugins/snes9x_gx/source/images/bg_game_selection_entry.png new file mode 100644 index 00000000..47efdde6 Binary files /dev/null and b/plugins/snes9x_gx/source/images/bg_game_selection_entry.png differ diff --git a/plugins/snes9x_gx/source/images/bg_options.png b/plugins/snes9x_gx/source/images/bg_options.png new file mode 100644 index 00000000..5365f172 Binary files /dev/null and b/plugins/snes9x_gx/source/images/bg_options.png differ diff --git a/plugins/snes9x_gx/source/images/bg_options_entry.png b/plugins/snes9x_gx/source/images/bg_options_entry.png new file mode 100644 index 00000000..61b00c58 Binary files /dev/null and b/plugins/snes9x_gx/source/images/bg_options_entry.png differ diff --git a/plugins/snes9x_gx/source/images/bg_preview.png b/plugins/snes9x_gx/source/images/bg_preview.png new file mode 100644 index 00000000..19b28251 Binary files /dev/null and b/plugins/snes9x_gx/source/images/bg_preview.png differ diff --git a/plugins/snes9x_gx/source/images/bg_top.png b/plugins/snes9x_gx/source/images/bg_top.png new file mode 100644 index 00000000..dd6c1dd7 Binary files /dev/null and b/plugins/snes9x_gx/source/images/bg_top.png differ diff --git a/plugins/snes9x_gx/source/images/button.png b/plugins/snes9x_gx/source/images/button.png new file mode 100644 index 00000000..ed7d4e55 Binary files /dev/null and b/plugins/snes9x_gx/source/images/button.png differ diff --git a/plugins/snes9x_gx/source/images/button_arrow_down.png b/plugins/snes9x_gx/source/images/button_arrow_down.png new file mode 100644 index 00000000..bb0b639b Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_arrow_down.png differ diff --git a/plugins/snes9x_gx/source/images/button_arrow_down_over.png b/plugins/snes9x_gx/source/images/button_arrow_down_over.png new file mode 100644 index 00000000..96a4e7bb Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_arrow_down_over.png differ diff --git a/plugins/snes9x_gx/source/images/button_arrow_left.png b/plugins/snes9x_gx/source/images/button_arrow_left.png new file mode 100644 index 00000000..29898cff Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_arrow_left.png differ diff --git a/plugins/snes9x_gx/source/images/button_arrow_left_over.png b/plugins/snes9x_gx/source/images/button_arrow_left_over.png new file mode 100644 index 00000000..d37e2197 Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_arrow_left_over.png differ diff --git a/plugins/snes9x_gx/source/images/button_arrow_right.png b/plugins/snes9x_gx/source/images/button_arrow_right.png new file mode 100644 index 00000000..21a7b483 Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_arrow_right.png differ diff --git a/plugins/snes9x_gx/source/images/button_arrow_right_over.png b/plugins/snes9x_gx/source/images/button_arrow_right_over.png new file mode 100644 index 00000000..9a68beb6 Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_arrow_right_over.png differ diff --git a/plugins/snes9x_gx/source/images/button_arrow_up.png b/plugins/snes9x_gx/source/images/button_arrow_up.png new file mode 100644 index 00000000..2f676a3d Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_arrow_up.png differ diff --git a/plugins/snes9x_gx/source/images/button_arrow_up_over.png b/plugins/snes9x_gx/source/images/button_arrow_up_over.png new file mode 100644 index 00000000..9d3fd792 Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_arrow_up_over.png differ diff --git a/plugins/snes9x_gx/source/images/button_gamesave.png b/plugins/snes9x_gx/source/images/button_gamesave.png new file mode 100644 index 00000000..1e44a737 Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_gamesave.png differ diff --git a/plugins/snes9x_gx/source/images/button_gamesave_blank.png b/plugins/snes9x_gx/source/images/button_gamesave_blank.png new file mode 100644 index 00000000..056d8c98 Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_gamesave_blank.png differ diff --git a/plugins/snes9x_gx/source/images/button_gamesave_over.png b/plugins/snes9x_gx/source/images/button_gamesave_over.png new file mode 100644 index 00000000..0f44608a Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_gamesave_over.png differ diff --git a/plugins/snes9x_gx/source/images/button_large.png b/plugins/snes9x_gx/source/images/button_large.png new file mode 100644 index 00000000..49312d69 Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_large.png differ diff --git a/plugins/snes9x_gx/source/images/button_large_over.png b/plugins/snes9x_gx/source/images/button_large_over.png new file mode 100644 index 00000000..99f81971 Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_large_over.png differ diff --git a/plugins/snes9x_gx/source/images/button_long.png b/plugins/snes9x_gx/source/images/button_long.png new file mode 100644 index 00000000..82fa9a23 Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_long.png differ diff --git a/plugins/snes9x_gx/source/images/button_long_over.png b/plugins/snes9x_gx/source/images/button_long_over.png new file mode 100644 index 00000000..5674c943 Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_long_over.png differ diff --git a/plugins/snes9x_gx/source/images/button_over.png b/plugins/snes9x_gx/source/images/button_over.png new file mode 100644 index 00000000..605cfeb4 Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_over.png differ diff --git a/plugins/snes9x_gx/source/images/button_prompt.png b/plugins/snes9x_gx/source/images/button_prompt.png new file mode 100644 index 00000000..1bf942e7 Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_prompt.png differ diff --git a/plugins/snes9x_gx/source/images/button_prompt_over.png b/plugins/snes9x_gx/source/images/button_prompt_over.png new file mode 100644 index 00000000..2f244c25 Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_prompt_over.png differ diff --git a/plugins/snes9x_gx/source/images/button_short.png b/plugins/snes9x_gx/source/images/button_short.png new file mode 100644 index 00000000..487ee9ab Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_short.png differ diff --git a/plugins/snes9x_gx/source/images/button_short_over.png b/plugins/snes9x_gx/source/images/button_short_over.png new file mode 100644 index 00000000..9fc69f0f Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_short_over.png differ diff --git a/plugins/snes9x_gx/source/images/button_small.png b/plugins/snes9x_gx/source/images/button_small.png new file mode 100644 index 00000000..9ffde9ea Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_small.png differ diff --git a/plugins/snes9x_gx/source/images/button_small_over.png b/plugins/snes9x_gx/source/images/button_small_over.png new file mode 100644 index 00000000..983c3826 Binary files /dev/null and b/plugins/snes9x_gx/source/images/button_small_over.png differ diff --git a/plugins/snes9x_gx/source/images/credits_box.png b/plugins/snes9x_gx/source/images/credits_box.png new file mode 100644 index 00000000..d0404ba1 Binary files /dev/null and b/plugins/snes9x_gx/source/images/credits_box.png differ diff --git a/plugins/snes9x_gx/source/images/dialogue_box.png b/plugins/snes9x_gx/source/images/dialogue_box.png new file mode 100644 index 00000000..f479bf1e Binary files /dev/null and b/plugins/snes9x_gx/source/images/dialogue_box.png differ diff --git a/plugins/snes9x_gx/source/images/icon_dvd.png b/plugins/snes9x_gx/source/images/icon_dvd.png new file mode 100644 index 00000000..c8e73569 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_dvd.png differ diff --git a/plugins/snes9x_gx/source/images/icon_folder.png b/plugins/snes9x_gx/source/images/icon_folder.png new file mode 100644 index 00000000..14fab1d4 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_folder.png differ diff --git a/plugins/snes9x_gx/source/images/icon_game_cheats.png b/plugins/snes9x_gx/source/images/icon_game_cheats.png new file mode 100644 index 00000000..e45c70cb Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_game_cheats.png differ diff --git a/plugins/snes9x_gx/source/images/icon_game_controllers.png b/plugins/snes9x_gx/source/images/icon_game_controllers.png new file mode 100644 index 00000000..be2747ac Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_game_controllers.png differ diff --git a/plugins/snes9x_gx/source/images/icon_game_load.png b/plugins/snes9x_gx/source/images/icon_game_load.png new file mode 100644 index 00000000..19c11d35 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_game_load.png differ diff --git a/plugins/snes9x_gx/source/images/icon_game_reset.png b/plugins/snes9x_gx/source/images/icon_game_reset.png new file mode 100644 index 00000000..43663736 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_game_reset.png differ diff --git a/plugins/snes9x_gx/source/images/icon_game_save.png b/plugins/snes9x_gx/source/images/icon_game_save.png new file mode 100644 index 00000000..121c462e Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_game_save.png differ diff --git a/plugins/snes9x_gx/source/images/icon_game_settings.png b/plugins/snes9x_gx/source/images/icon_game_settings.png new file mode 100644 index 00000000..b47dabe0 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_game_settings.png differ diff --git a/plugins/snes9x_gx/source/images/icon_home.png b/plugins/snes9x_gx/source/images/icon_home.png new file mode 100644 index 00000000..b1fac47a Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_home.png differ diff --git a/plugins/snes9x_gx/source/images/icon_sd.png b/plugins/snes9x_gx/source/images/icon_sd.png new file mode 100644 index 00000000..7f12ae83 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_sd.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings.png b/plugins/snes9x_gx/source/images/icon_settings.png new file mode 100644 index 00000000..690763fd Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings_classic.png b/plugins/snes9x_gx/source/images/icon_settings_classic.png new file mode 100644 index 00000000..bce6d723 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings_classic.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings_file.png b/plugins/snes9x_gx/source/images/icon_settings_file.png new file mode 100644 index 00000000..41ab9940 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings_file.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings_gamecube.png b/plugins/snes9x_gx/source/images/icon_settings_gamecube.png new file mode 100644 index 00000000..1c113a1f Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings_gamecube.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings_justifier.png b/plugins/snes9x_gx/source/images/icon_settings_justifier.png new file mode 100644 index 00000000..b2bbfd82 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings_justifier.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings_mappings.png b/plugins/snes9x_gx/source/images/icon_settings_mappings.png new file mode 100644 index 00000000..36969b79 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings_mappings.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings_menu.png b/plugins/snes9x_gx/source/images/icon_settings_menu.png new file mode 100644 index 00000000..b0c86c29 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings_menu.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings_mouse.png b/plugins/snes9x_gx/source/images/icon_settings_mouse.png new file mode 100644 index 00000000..f836b124 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings_mouse.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings_network.png b/plugins/snes9x_gx/source/images/icon_settings_network.png new file mode 100644 index 00000000..fc53f512 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings_network.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings_nunchuk.png b/plugins/snes9x_gx/source/images/icon_settings_nunchuk.png new file mode 100644 index 00000000..55052a1d Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings_nunchuk.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings_screenshot.png b/plugins/snes9x_gx/source/images/icon_settings_screenshot.png new file mode 100644 index 00000000..6cc3a45a Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings_screenshot.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings_snescontroller.png b/plugins/snes9x_gx/source/images/icon_settings_snescontroller.png new file mode 100644 index 00000000..562c80eb Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings_snescontroller.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings_superscope.png b/plugins/snes9x_gx/source/images/icon_settings_superscope.png new file mode 100644 index 00000000..88fb5a17 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings_superscope.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings_video.png b/plugins/snes9x_gx/source/images/icon_settings_video.png new file mode 100644 index 00000000..19eab99d Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings_video.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings_wiimote.png b/plugins/snes9x_gx/source/images/icon_settings_wiimote.png new file mode 100644 index 00000000..d337aec5 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings_wiimote.png differ diff --git a/plugins/snes9x_gx/source/images/icon_settings_wiiupro.png b/plugins/snes9x_gx/source/images/icon_settings_wiiupro.png new file mode 100644 index 00000000..69eeeeda Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_settings_wiiupro.png differ diff --git a/plugins/snes9x_gx/source/images/icon_smb.png b/plugins/snes9x_gx/source/images/icon_smb.png new file mode 100644 index 00000000..5b62deb5 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_smb.png differ diff --git a/plugins/snes9x_gx/source/images/icon_usb.png b/plugins/snes9x_gx/source/images/icon_usb.png new file mode 100644 index 00000000..9b6c82a8 Binary files /dev/null and b/plugins/snes9x_gx/source/images/icon_usb.png differ diff --git a/plugins/snes9x_gx/source/images/keyboard_key.png b/plugins/snes9x_gx/source/images/keyboard_key.png new file mode 100644 index 00000000..07d82989 Binary files /dev/null and b/plugins/snes9x_gx/source/images/keyboard_key.png differ diff --git a/plugins/snes9x_gx/source/images/keyboard_key_over.png b/plugins/snes9x_gx/source/images/keyboard_key_over.png new file mode 100644 index 00000000..f8a55daf Binary files /dev/null and b/plugins/snes9x_gx/source/images/keyboard_key_over.png differ diff --git a/plugins/snes9x_gx/source/images/keyboard_largekey.png b/plugins/snes9x_gx/source/images/keyboard_largekey.png new file mode 100644 index 00000000..cbf15746 Binary files /dev/null and b/plugins/snes9x_gx/source/images/keyboard_largekey.png differ diff --git a/plugins/snes9x_gx/source/images/keyboard_largekey_over.png b/plugins/snes9x_gx/source/images/keyboard_largekey_over.png new file mode 100644 index 00000000..16d9ceb5 Binary files /dev/null and b/plugins/snes9x_gx/source/images/keyboard_largekey_over.png differ diff --git a/plugins/snes9x_gx/source/images/keyboard_mediumkey.png b/plugins/snes9x_gx/source/images/keyboard_mediumkey.png new file mode 100644 index 00000000..78930226 Binary files /dev/null and b/plugins/snes9x_gx/source/images/keyboard_mediumkey.png differ diff --git a/plugins/snes9x_gx/source/images/keyboard_mediumkey_over.png b/plugins/snes9x_gx/source/images/keyboard_mediumkey_over.png new file mode 100644 index 00000000..928e67d5 Binary files /dev/null and b/plugins/snes9x_gx/source/images/keyboard_mediumkey_over.png differ diff --git a/plugins/snes9x_gx/source/images/keyboard_textbox.png b/plugins/snes9x_gx/source/images/keyboard_textbox.png new file mode 100644 index 00000000..081a63c8 Binary files /dev/null and b/plugins/snes9x_gx/source/images/keyboard_textbox.png differ diff --git a/plugins/snes9x_gx/source/images/logo.png b/plugins/snes9x_gx/source/images/logo.png new file mode 100644 index 00000000..512a99b9 Binary files /dev/null and b/plugins/snes9x_gx/source/images/logo.png differ diff --git a/plugins/snes9x_gx/source/images/logo_over.png b/plugins/snes9x_gx/source/images/logo_over.png new file mode 100644 index 00000000..1b8c03c4 Binary files /dev/null and b/plugins/snes9x_gx/source/images/logo_over.png differ diff --git a/plugins/snes9x_gx/source/images/player1_grab.png b/plugins/snes9x_gx/source/images/player1_grab.png new file mode 100644 index 00000000..d95c2b35 Binary files /dev/null and b/plugins/snes9x_gx/source/images/player1_grab.png differ diff --git a/plugins/snes9x_gx/source/images/player1_point.png b/plugins/snes9x_gx/source/images/player1_point.png new file mode 100644 index 00000000..19f94e86 Binary files /dev/null and b/plugins/snes9x_gx/source/images/player1_point.png differ diff --git a/plugins/snes9x_gx/source/images/player2_grab.png b/plugins/snes9x_gx/source/images/player2_grab.png new file mode 100644 index 00000000..5f3f6abd Binary files /dev/null and b/plugins/snes9x_gx/source/images/player2_grab.png differ diff --git a/plugins/snes9x_gx/source/images/player2_point.png b/plugins/snes9x_gx/source/images/player2_point.png new file mode 100644 index 00000000..f4b12327 Binary files /dev/null and b/plugins/snes9x_gx/source/images/player2_point.png differ diff --git a/plugins/snes9x_gx/source/images/player3_grab.png b/plugins/snes9x_gx/source/images/player3_grab.png new file mode 100644 index 00000000..c0c3546b Binary files /dev/null and b/plugins/snes9x_gx/source/images/player3_grab.png differ diff --git a/plugins/snes9x_gx/source/images/player3_point.png b/plugins/snes9x_gx/source/images/player3_point.png new file mode 100644 index 00000000..e88b90f2 Binary files /dev/null and b/plugins/snes9x_gx/source/images/player3_point.png differ diff --git a/plugins/snes9x_gx/source/images/player4_grab.png b/plugins/snes9x_gx/source/images/player4_grab.png new file mode 100644 index 00000000..7e9a814e Binary files /dev/null and b/plugins/snes9x_gx/source/images/player4_grab.png differ diff --git a/plugins/snes9x_gx/source/images/player4_point.png b/plugins/snes9x_gx/source/images/player4_point.png new file mode 100644 index 00000000..68bb3aa4 Binary files /dev/null and b/plugins/snes9x_gx/source/images/player4_point.png differ diff --git a/plugins/snes9x_gx/source/images/progressbar.png b/plugins/snes9x_gx/source/images/progressbar.png new file mode 100644 index 00000000..87ec09d0 Binary files /dev/null and b/plugins/snes9x_gx/source/images/progressbar.png differ diff --git a/plugins/snes9x_gx/source/images/progressbar_empty.png b/plugins/snes9x_gx/source/images/progressbar_empty.png new file mode 100644 index 00000000..ddf53cdf Binary files /dev/null and b/plugins/snes9x_gx/source/images/progressbar_empty.png differ diff --git a/plugins/snes9x_gx/source/images/progressbar_outline.png b/plugins/snes9x_gx/source/images/progressbar_outline.png new file mode 100644 index 00000000..c4db0646 Binary files /dev/null and b/plugins/snes9x_gx/source/images/progressbar_outline.png differ diff --git a/plugins/snes9x_gx/source/images/screen_position.png b/plugins/snes9x_gx/source/images/screen_position.png new file mode 100644 index 00000000..edecaffe Binary files /dev/null and b/plugins/snes9x_gx/source/images/screen_position.png differ diff --git a/plugins/snes9x_gx/source/images/scrollbar.png b/plugins/snes9x_gx/source/images/scrollbar.png new file mode 100644 index 00000000..195ec168 Binary files /dev/null and b/plugins/snes9x_gx/source/images/scrollbar.png differ diff --git a/plugins/snes9x_gx/source/images/scrollbar_arrowdown.png b/plugins/snes9x_gx/source/images/scrollbar_arrowdown.png new file mode 100644 index 00000000..5616c301 Binary files /dev/null and b/plugins/snes9x_gx/source/images/scrollbar_arrowdown.png differ diff --git a/plugins/snes9x_gx/source/images/scrollbar_arrowdown_over.png b/plugins/snes9x_gx/source/images/scrollbar_arrowdown_over.png new file mode 100644 index 00000000..69dbb75d Binary files /dev/null and b/plugins/snes9x_gx/source/images/scrollbar_arrowdown_over.png differ diff --git a/plugins/snes9x_gx/source/images/scrollbar_arrowup.png b/plugins/snes9x_gx/source/images/scrollbar_arrowup.png new file mode 100644 index 00000000..7dd53341 Binary files /dev/null and b/plugins/snes9x_gx/source/images/scrollbar_arrowup.png differ diff --git a/plugins/snes9x_gx/source/images/scrollbar_arrowup_over.png b/plugins/snes9x_gx/source/images/scrollbar_arrowup_over.png new file mode 100644 index 00000000..6badbafa Binary files /dev/null and b/plugins/snes9x_gx/source/images/scrollbar_arrowup_over.png differ diff --git a/plugins/snes9x_gx/source/images/scrollbar_box.png b/plugins/snes9x_gx/source/images/scrollbar_box.png new file mode 100644 index 00000000..1dbfca7c Binary files /dev/null and b/plugins/snes9x_gx/source/images/scrollbar_box.png differ diff --git a/plugins/snes9x_gx/source/images/scrollbar_box_over.png b/plugins/snes9x_gx/source/images/scrollbar_box_over.png new file mode 100644 index 00000000..ceb9e01e Binary files /dev/null and b/plugins/snes9x_gx/source/images/scrollbar_box_over.png differ diff --git a/plugins/snes9x_gx/source/images/throbber.png b/plugins/snes9x_gx/source/images/throbber.png new file mode 100644 index 00000000..47bb5478 Binary files /dev/null and b/plugins/snes9x_gx/source/images/throbber.png differ diff --git a/plugins/snes9x_gx/source/input.cpp b/plugins/snes9x_gx/source/input.cpp new file mode 100644 index 00000000..a1a49935 --- /dev/null +++ b/plugins/snes9x_gx/source/input.cpp @@ -0,0 +1,791 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * crunchy2 May-June 2007 + * Michniewski 2008 + * Tantric 2008-2010 + * + * input.cpp + * + * Wii/Gamecube controller management + ***************************************************************************/ + +#include <gccore.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include <ogcsys.h> +#include <unistd.h> +#include <wiiuse/wpad.h> +#include <wupc/wupc.h> +#include <ogc/lwp_watchdog.h> + +#include "snes9xgx.h" +#include "button_mapping.h" +#include "menu.h" +#include "video.h" +#include "input.h" +#include "gui/gui.h" + +#include "snes9x/snes9x.h" +#include "snes9x/memmap.h" +#include "snes9x/controls.h" + +int rumbleRequest[4] = {0,0,0,0}; +GuiTrigger userInput[4]; + +#ifdef HW_RVL +static int rumbleCount[4] = {0,0,0,0}; +#endif + +// hold superscope/mouse/justifier cursor positions +static int cursor_x[5] = {0,0,0,0,0}; +static int cursor_y[5] = {0,0,0,0,0}; + +/**************************************************************************** + * Controller Functions + * + * The following map the Wii controls to the Snes9x controller system + ***************************************************************************/ +#define ASSIGN_BUTTON_TRUE( keycode, snescmd ) \ + S9xMapButton( keycode, cmd = S9xGetCommandT(snescmd), true) + +#define ASSIGN_BUTTON_FALSE( keycode, snescmd ) \ + S9xMapButton( keycode, cmd = S9xGetCommandT(snescmd), false) + +static int scopeTurbo = 0; // tracks whether superscope turbo is on or off +u32 btnmap[4][4][12]; // button mapping + +void ResetControls(int consoleCtrl, int wiiCtrl) +{ + int i; + /*** Gamecube controller Padmap ***/ + if(consoleCtrl == -1 || (consoleCtrl == CTRL_PAD && wiiCtrl == CTRLR_GCPAD)) + { + i=0; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_A; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_B; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_X; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_Y; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_TRIGGER_L; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_TRIGGER_R; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_START; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_TRIGGER_Z; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_UP; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_DOWN; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_LEFT; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_RIGHT; + } + + /*** Wiimote Padmap ***/ + if(consoleCtrl == -1 || (consoleCtrl == CTRL_PAD && wiiCtrl == CTRLR_WIIMOTE)) + { + i=0; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_B; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_2; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_1; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_A; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = 0x0000; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = 0x0000; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_PLUS; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_MINUS; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_RIGHT; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_LEFT; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_UP; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_DOWN; + } + + /*** Classic Controller Padmap ***/ + if(consoleCtrl == -1 || (consoleCtrl == CTRL_PAD && wiiCtrl == CTRLR_CLASSIC)) + { + i=0; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_A; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_B; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_X; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_Y; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_FULL_L; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_FULL_R; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_PLUS; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_MINUS; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_UP; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_DOWN; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_LEFT; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_RIGHT; + } + + /*** Nunchuk + wiimote Padmap ***/ + if(consoleCtrl == -1 || (consoleCtrl == CTRL_PAD && wiiCtrl == CTRLR_NUNCHUK)) + { + i=0; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_A; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_B; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_NUNCHUK_BUTTON_C; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_NUNCHUK_BUTTON_Z; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_2; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_1; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_PLUS; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_MINUS; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_UP; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_DOWN; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_LEFT; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_RIGHT; + } + + /*** Superscope : GC controller button mapping ***/ + if(consoleCtrl == -1 || (consoleCtrl == CTRL_SCOPE && wiiCtrl == CTRLR_GCPAD)) + { + i=0; + btnmap[CTRL_SCOPE][CTRLR_GCPAD][i++] = PAD_BUTTON_A; + btnmap[CTRL_SCOPE][CTRLR_GCPAD][i++] = PAD_BUTTON_B; + btnmap[CTRL_SCOPE][CTRLR_GCPAD][i++] = PAD_TRIGGER_Z; + btnmap[CTRL_SCOPE][CTRLR_GCPAD][i++] = PAD_BUTTON_Y; + btnmap[CTRL_SCOPE][CTRLR_GCPAD][i++] = PAD_BUTTON_X; + btnmap[CTRL_SCOPE][CTRLR_GCPAD][i++] = PAD_BUTTON_START; + } + + /*** Superscope : wiimote button mapping ***/ + if(consoleCtrl == -1 || (consoleCtrl == CTRL_SCOPE && wiiCtrl == CTRLR_WIIMOTE)) + { + i=0; + btnmap[CTRL_SCOPE][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_B; + btnmap[CTRL_SCOPE][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_A; + btnmap[CTRL_SCOPE][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_MINUS; + btnmap[CTRL_SCOPE][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_UP; + btnmap[CTRL_SCOPE][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_DOWN; + btnmap[CTRL_SCOPE][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_PLUS; + } + + /*** Mouse : GC controller button mapping ***/ + if(consoleCtrl == -1 || (consoleCtrl == CTRL_MOUSE && wiiCtrl == CTRLR_GCPAD)) + { + i=0; + btnmap[CTRL_MOUSE][CTRLR_GCPAD][i++] = PAD_BUTTON_A; + btnmap[CTRL_MOUSE][CTRLR_GCPAD][i++] = PAD_BUTTON_B; + } + + /*** Mouse : wiimote button mapping ***/ + if(consoleCtrl == -1 || (consoleCtrl == CTRL_MOUSE && wiiCtrl == CTRLR_WIIMOTE)) + { + i=0; + btnmap[CTRL_MOUSE][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_A; + btnmap[CTRL_MOUSE][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_B; + } + + /*** Justifier : GC controller button mapping ***/ + if(consoleCtrl == -1 || (consoleCtrl == CTRL_JUST && wiiCtrl == CTRLR_GCPAD)) + { + i=0; + btnmap[CTRL_JUST][CTRLR_GCPAD][i++] = PAD_BUTTON_B; + btnmap[CTRL_JUST][CTRLR_GCPAD][i++] = PAD_BUTTON_A; + btnmap[CTRL_JUST][CTRLR_GCPAD][i++] = PAD_BUTTON_START; + } + + /*** Justifier : wiimote button mapping ***/ + if(consoleCtrl == -1 || (consoleCtrl == CTRL_JUST && wiiCtrl == CTRLR_WIIMOTE)) + { + i=0; + btnmap[CTRL_JUST][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_B; + btnmap[CTRL_JUST][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_A; + btnmap[CTRL_JUST][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_PLUS; + } +} + +/**************************************************************************** + * UpdatePads + * + * Scans pad and wpad + ***************************************************************************/ + +void +UpdatePads() +{ + #ifdef HW_RVL + WUPC_UpdateButtonStats(); + WPAD_ScanPads(); + #endif + + PAD_ScanPads(); + + for(int i=3; i >= 0; i--) + { + userInput[i].pad.btns_d = PAD_ButtonsDown(i); + userInput[i].pad.btns_u = PAD_ButtonsUp(i); + userInput[i].pad.btns_h = PAD_ButtonsHeld(i); + userInput[i].pad.stickX = PAD_StickX(i); + userInput[i].pad.stickY = PAD_StickY(i); + userInput[i].pad.substickX = PAD_SubStickX(i); + userInput[i].pad.substickY = PAD_SubStickY(i); + userInput[i].pad.triggerL = PAD_TriggerL(i); + userInput[i].pad.triggerR = PAD_TriggerR(i); + #ifdef HW_RVL + userInput[i].wupcdata.btns_d = WUPC_ButtonsDown(i); + userInput[i].wupcdata.btns_u = WUPC_ButtonsUp(i); + userInput[i].wupcdata.btns_h = WUPC_ButtonsHeld(i); + userInput[i].wupcdata.stickX = WUPC_lStickX(i); + userInput[i].wupcdata.stickY = WUPC_lStickY(i); + userInput[i].wupcdata.substickX = WUPC_rStickX(i); + userInput[i].wupcdata.substickY = WUPC_rStickY(i); + #endif + } +} + +/**************************************************************************** + * SetupPads + * + * Sets up userInput triggers for use + ***************************************************************************/ +void +SetupPads() +{ + PAD_Init(); + + #ifdef HW_RVL + // read wiimote accelerometer and IR data + WPAD_SetDataFormat(WPAD_CHAN_ALL,WPAD_FMT_BTNS_ACC_IR); + WPAD_SetVRes(WPAD_CHAN_ALL, screenwidth, screenheight); + #endif + + for(int i=0; i < 4; i++) + { + userInput[i].chan = i; + #ifdef HW_RVL + userInput[i].wpad = WPAD_Data(i); + #endif + } +} + +#ifdef HW_RVL +/**************************************************************************** + * ShutoffRumble + ***************************************************************************/ +void ShutoffRumble() +{ + if(CONF_GetPadMotorMode() == 0) + return; + + for(int i=0;i<4;i++) + { + WPAD_Rumble(i, 0); + rumbleCount[i] = 0; + rumbleRequest[i] = 0; + } +} + +/**************************************************************************** + * DoRumble + ***************************************************************************/ +void DoRumble(int i) +{ + if(CONF_GetPadMotorMode() == 0 || !GCSettings.Rumble) return; + + if(rumbleRequest[i] && rumbleCount[i] < 3) + { + WPAD_Rumble(i, 1); // rumble on + rumbleCount[i]++; + } + else if(rumbleRequest[i]) + { + rumbleCount[i] = 12; + rumbleRequest[i] = 0; + } + else + { + if(rumbleCount[i]) + rumbleCount[i]--; + WPAD_Rumble(i, 0); // rumble off + } +} +#endif + +/**************************************************************************** + * UpdateCursorPosition + * + * Updates X/Y coordinates for Superscope/mouse/justifier position + ***************************************************************************/ +static void UpdateCursorPosition (int chan, int &pos_x, int &pos_y) +{ + #define SCOPEPADCAL 20 + + #define WUPCSCOPEPADCAL 160 + // gc left joystick + + if (userInput[chan].pad.stickX > SCOPEPADCAL) + { + pos_x += (userInput[chan].pad.stickX*1.0)/SCOPEPADCAL; + if (pos_x > 256) pos_x = 256; + } + if (userInput[chan].pad.stickX < -SCOPEPADCAL) + { + pos_x -= (userInput[chan].pad.stickX*-1.0)/SCOPEPADCAL; + if (pos_x < 0) pos_x = 0; + } + + if (userInput[chan].pad.stickY < -SCOPEPADCAL) + { + pos_y += (userInput[chan].pad.stickY*-1.0)/SCOPEPADCAL; + if (pos_y > 224) pos_y = 224; + } + if (userInput[chan].pad.stickY > SCOPEPADCAL) + { + pos_y -= (userInput[chan].pad.stickY*1.0)/SCOPEPADCAL; + if (pos_y < 0) pos_y = 0; + } + +#ifdef HW_RVL + if (userInput[chan].wpad->ir.valid) + { + pos_x = (userInput[chan].wpad->ir.x * 256) / 640; + pos_y = (userInput[chan].wpad->ir.y * 224) / 480; + } + else + { + s8 wm_ax = userInput[chan].WPAD_StickX(0); + s8 wm_ay = userInput[chan].WPAD_StickY(0); + + if (wm_ax > SCOPEPADCAL) + { + pos_x += (wm_ax*1.0)/SCOPEPADCAL; + if (pos_x > 256) pos_x = 256; + } + if (wm_ax < -SCOPEPADCAL) + { + pos_x -= (wm_ax*-1.0)/SCOPEPADCAL; + if (pos_x < 0) pos_x = 0; + } + + if (wm_ay < -SCOPEPADCAL) + { + pos_y += (wm_ay*-1.0)/SCOPEPADCAL; + if (pos_y > 224) pos_y = 224; + } + if (wm_ay > SCOPEPADCAL) + { + pos_y -= (wm_ay*1.0)/SCOPEPADCAL; + if (pos_y < 0) pos_y = 0; + } + + /* WiiU Pro Controller */ + s8 wupc_ax = userInput[chan].wupcdata.stickX; + s8 wupc_ay = userInput[chan].wupcdata.stickX; + + if (wupc_ax > WUPCSCOPEPADCAL) + { + pos_x += (wupc_ax*1.0)/WUPCSCOPEPADCAL; + if (pos_x > 256) pos_x = 256; + } + if (wupc_ax < -WUPCSCOPEPADCAL) + { + pos_x -= (wupc_ax*-1.0)/WUPCSCOPEPADCAL; + if (pos_x < 0) pos_x = 0; + } + + if (wupc_ay < -WUPCSCOPEPADCAL) + { + pos_y += (wupc_ay*-1.0)/WUPCSCOPEPADCAL; + if (pos_y > 224) pos_y = 224; + } + if (wupc_ay > WUPCSCOPEPADCAL) + { + pos_y -= (wupc_ay*1.0)/WUPCSCOPEPADCAL; + if (pos_y < 0) pos_y = 0; + } + } +#endif + +} + +/**************************************************************************** + * decodepad + * + * Reads the changes (buttons pressed, etc) from a controller and reports + * these changes to Snes9x + ***************************************************************************/ +static void decodepad (int chan) +{ + int i, offset; + double angle; + static const double THRES = 0.38268343236508984; // cos(67.5) + + s8 pad_x = userInput[chan].pad.stickX; + s8 pad_y = userInput[chan].pad.stickY; + u32 jp = userInput[chan].pad.btns_h; + +#ifdef HW_RVL + s8 wm_ax = userInput[chan].WPAD_StickX(0); + s8 wm_ay = userInput[chan].WPAD_StickY(0); + u32 wp = userInput[chan].wpad->btns_h; + + u32 exp_type; + if ( WPAD_Probe(chan, &exp_type) != 0 ) + exp_type = WPAD_EXP_NONE; + + s16 wupc_ax = userInput[chan].wupcdata.stickX; + s16 wupc_ay = userInput[chan].wupcdata.stickY; + u32 wupcp = userInput[chan].wupcdata.btns_h; +#endif + + /*** + Gamecube Joystick input + ***/ + // Is XY inside the "zone"? + if (pad_x * pad_x + pad_y * pad_y > PADCAL * PADCAL) + { + angle = atan2(pad_y, pad_x); + + if(cos(angle) > THRES) + jp |= PAD_BUTTON_RIGHT; + else if(cos(angle) < -THRES) + jp |= PAD_BUTTON_LEFT; + if(sin(angle) > THRES) + jp |= PAD_BUTTON_UP; + else if(sin(angle) < -THRES) + jp |= PAD_BUTTON_DOWN; + } + + // Count as pressed if down far enough (~50% down) + if (userInput[chan].pad.triggerL > 0x80) + jp |= PAD_TRIGGER_L; + if (userInput[chan].pad.triggerR > 0x80) + jp |= PAD_TRIGGER_R; + +#ifdef HW_RVL + /*** + Wii Joystick (classic, nunchuk) input + ***/ + // Is XY inside the "zone"? + if (wm_ax * wm_ax + wm_ay * wm_ay > PADCAL * PADCAL) + { + angle = atan2(wm_ay, wm_ax); + + if(cos(angle) > THRES) + wp |= (exp_type == WPAD_EXP_CLASSIC) ? WPAD_CLASSIC_BUTTON_RIGHT : WPAD_BUTTON_RIGHT; + else if(cos(angle) < -THRES) + wp |= (exp_type == WPAD_EXP_CLASSIC) ? WPAD_CLASSIC_BUTTON_LEFT : WPAD_BUTTON_LEFT; + if(sin(angle) > THRES) + wp |= (exp_type == WPAD_EXP_CLASSIC) ? WPAD_CLASSIC_BUTTON_UP : WPAD_BUTTON_UP; + else if(sin(angle) < -THRES) + wp |= (exp_type == WPAD_EXP_CLASSIC) ? WPAD_CLASSIC_BUTTON_DOWN : WPAD_BUTTON_DOWN; + } + + /* Pro Controller */ + if (wupc_ax * wupc_ax + wupc_ay * wupc_ay > WUPCCAL * WUPCCAL) + { + angle = atan2(wupc_ay, wupc_ax); + if(cos(angle) > THRES) + wupcp |= WPAD_CLASSIC_BUTTON_RIGHT; + else if(cos(angle) < -THRES) + wupcp |= WPAD_CLASSIC_BUTTON_LEFT; + if(sin(angle) > THRES) + wupcp |= WPAD_CLASSIC_BUTTON_UP; + else if(sin(angle) < -THRES) + wupcp |= WPAD_CLASSIC_BUTTON_DOWN; + } +#endif + + /*** Fix offset to pad ***/ + offset = ((chan + 1) << 4); + + /*** Report pressed buttons (gamepads) ***/ + for (i = 0; i < MAXJP; i++) + { + if ( (jp & btnmap[CTRL_PAD][CTRLR_GCPAD][i]) // gamecube controller +#ifdef HW_RVL + || ( (exp_type == WPAD_EXP_NONE) && (wp & btnmap[CTRL_PAD][CTRLR_WIIMOTE][i]) ) // wiimote + || ( (exp_type == WPAD_EXP_CLASSIC) && (wp & btnmap[CTRL_PAD][CTRLR_CLASSIC][i]) ) // classic controller + || ( (exp_type == WPAD_EXP_NUNCHUK) && (wp & btnmap[CTRL_PAD][CTRLR_NUNCHUK][i]) ) // nunchuk + wiimote + || ( (wupcp & btnmap[CTRL_PAD][CTRLR_CLASSIC][i]) ) // WiiU Pro Controller +#endif + ) + S9xReportButton (offset + i, true); + else + S9xReportButton (offset + i, false); + } + + /*** Superscope ***/ + if (Settings.SuperScopeMaster && chan == 0) // report only once + { + // buttons + offset = 0x50; + for (i = 0; i < 6; i++) + { + if (jp & btnmap[CTRL_SCOPE][CTRLR_GCPAD][i] +#ifdef HW_RVL + || wp & btnmap[CTRL_SCOPE][CTRLR_WIIMOTE][i] + || wupcp & btnmap[CTRL_SCOPE][CTRLR_WIIMOTE][i] +#endif + ) + { + if(i == 3 || i == 4) // turbo + { + if((i == 3 && scopeTurbo == 1) || // turbo ON already, don't change + (i == 4 && scopeTurbo == 0)) // turbo OFF already, don't change + { + S9xReportButton(offset + i, false); + } + else // turbo changed to ON or OFF + { + scopeTurbo = 4-i; + S9xReportButton(offset + i, true); + } + } + else + S9xReportButton(offset + i, true); + } + else + S9xReportButton(offset + i, false); + } + // pointer + offset = 0x80; + UpdateCursorPosition(chan, cursor_x[0], cursor_y[0]); + S9xReportPointer(offset, (u16) cursor_x[0], (u16) cursor_y[0]); + } + /*** Mouse ***/ + else if (Settings.MouseMaster && chan == 0) + { + // buttons + offset = 0x60 + (2 * chan); + for (i = 0; i < 2; i++) + { + if (jp & btnmap[CTRL_MOUSE][CTRLR_GCPAD][i] +#ifdef HW_RVL + || wp & btnmap[CTRL_MOUSE][CTRLR_WIIMOTE][i] + || wupcp & btnmap[CTRL_MOUSE][CTRLR_WIIMOTE][i] +#endif + ) + S9xReportButton(offset + i, true); + else + S9xReportButton(offset + i, false); + } + // pointer + offset = 0x81; + UpdateCursorPosition(chan, cursor_x[1 + chan], cursor_y[1 + chan]); + S9xReportPointer(offset + chan, (u16) cursor_x[1 + chan], + (u16) cursor_y[1 + chan]); + } + /*** Justifier ***/ + else if (Settings.JustifierMaster && chan < 2) + { + // buttons + offset = 0x70 + (3 * chan); + for (i = 0; i < 3; i++) + { + if (jp & btnmap[CTRL_JUST][CTRLR_GCPAD][i] +#ifdef HW_RVL + || wp & btnmap[CTRL_JUST][CTRLR_WIIMOTE][i] + || wupcp & btnmap[CTRL_JUST][CTRLR_WIIMOTE][i] +#endif + ) + S9xReportButton(offset + i, true); + else + S9xReportButton(offset + i, false); + } + // pointer + offset = 0x83; + UpdateCursorPosition(chan, cursor_x[3 + chan], cursor_y[3 + chan]); + S9xReportPointer(offset + chan, (u16) cursor_x[3 + chan], + (u16) cursor_y[3 + chan]); + } + +#ifdef HW_RVL + // screenshot (temp) + if (wp & CLASSIC_CTRL_BUTTON_ZR) + S9xReportButton(0x90, true); + else + S9xReportButton(0x90, false); +#endif +} + +bool MenuRequested() +{ + for(int i=0; i<4; i++) + { + if ( + (userInput[i].pad.substickX < -70) || + (userInput[i].pad.btns_h & PAD_TRIGGER_L && + userInput[i].pad.btns_h & PAD_TRIGGER_R && + userInput[i].pad.btns_h & PAD_BUTTON_X && + userInput[i].pad.btns_h & PAD_BUTTON_Y + ) + #ifdef HW_RVL + || (userInput[i].wpad->btns_h & WPAD_BUTTON_HOME) || + (userInput[i].wpad->btns_h & WPAD_CLASSIC_BUTTON_HOME) || + (userInput[i].wupcdata.btns_h & WPAD_CLASSIC_BUTTON_HOME) + #endif + ) + { + return true; + } + } + return false; +} + +/**************************************************************************** + * ReportButtons + * + * Called on each rendered frame + * Our way of putting controller input into Snes9x + ***************************************************************************/ +void ReportButtons () +{ + int i, j; + + UpdatePads(); + + Settings.TurboMode = ( + userInput[0].pad.substickX > 70 || + userInput[0].WPAD_StickX(1) > 70 || + userInput[0].wupcdata.substickX > 560 + ); // RIGHT on c-stick and on classic controller right joystick + + /* Check for menu: + * CStick left + * OR "L+R+X+Y" (eg. Homebrew/Adapted SNES controllers) + * OR "Home" on the wiimote or classic controller + * OR Left on classic right analog stick + */ + if(MenuRequested()) + ScreenshotRequested = 1; // go to the menu + + j = (Settings.MultiPlayer5Master == true ? 4 : 2); + + for (i = 0; i < j; i++) + decodepad (i); +} + +void SetControllers() +{ + if (Settings.MultiPlayer5Master == true) + { + S9xSetController (0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController (1, CTL_MP5, 1, 2, 3, -1); + } + else if (Settings.SuperScopeMaster == true) + { + S9xSetController (0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController (1, CTL_SUPERSCOPE, 0, 0, 0, 0); + } + else if (Settings.MouseMaster == true) + { + S9xSetController (0, CTL_MOUSE, 0, 0, 0, 0); + S9xSetController (1, CTL_JOYPAD, 1, 0, 0, 0); + } + else if (Settings.JustifierMaster == true) + { + S9xSetController (0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(1, CTL_JUSTIFIER, 1, 0, 0, 0); + } + else + { + // Plugin 2 Joypads by default + S9xSetController (0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController (1, CTL_JOYPAD, 1, 0, 0, 0); + } +} + +/**************************************************************************** + * Set the default mapping + ***************************************************************************/ +void SetDefaultButtonMap () +{ + int maxcode = 0x10; + s9xcommand_t cmd; + + /*** Joypad 1 ***/ + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 A"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 B"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 X"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 Y"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 L"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 R"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 Start"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 Select"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 Up"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 Down"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 Left"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 Right"); + + maxcode = 0x20; + /*** Joypad 2 ***/ + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 A"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 B"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 X"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 Y"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 L"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 R"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 Start"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 Select"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 Up"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 Down"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 Left"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 Right"); + + maxcode = 0x30; + /*** Joypad 3 ***/ + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 A"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 B"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 X"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 Y"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 L"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 R"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 Start"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 Select"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 Up"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 Down"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 Left"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 Right"); + + maxcode = 0x40; + /*** Joypad 4 ***/ + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 A"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 B"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 X"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 Y"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 L"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 R"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 Start"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 Select"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 Up"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 Down"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 Left"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 Right"); + + maxcode = 0x50; + /*** Superscope ***/ + ASSIGN_BUTTON_FALSE (maxcode++, "Superscope Fire"); + ASSIGN_BUTTON_FALSE (maxcode++, "Superscope AimOffscreen"); + ASSIGN_BUTTON_FALSE (maxcode++, "Superscope Cursor"); + ASSIGN_BUTTON_FALSE (maxcode++, "Superscope ToggleTurbo"); + ASSIGN_BUTTON_FALSE (maxcode++, "Superscope ToggleTurbo"); + ASSIGN_BUTTON_FALSE (maxcode++, "Superscope Pause"); + + maxcode = 0x60; + /*** Mouse ***/ + ASSIGN_BUTTON_FALSE (maxcode++, "Mouse1 L"); + ASSIGN_BUTTON_FALSE (maxcode++, "Mouse1 R"); + ASSIGN_BUTTON_FALSE (maxcode++, "Mouse2 L"); + ASSIGN_BUTTON_FALSE (maxcode++, "Mouse2 R"); + + maxcode = 0x70; + /*** Justifier ***/ + ASSIGN_BUTTON_FALSE (maxcode++, "Justifier1 Trigger"); + ASSIGN_BUTTON_FALSE (maxcode++, "Justifier1 AimOffscreen"); + ASSIGN_BUTTON_FALSE (maxcode++, "Justifier1 Start"); + ASSIGN_BUTTON_FALSE (maxcode++, "Justifier2 Trigger"); + ASSIGN_BUTTON_FALSE (maxcode++, "Justifier2 AimOffscreen"); + ASSIGN_BUTTON_FALSE (maxcode++, "Justifier2 Start"); + + maxcode = 0x80; + S9xMapPointer(maxcode++, S9xGetCommandT("Pointer Superscope"), false); + S9xMapPointer(maxcode++, S9xGetCommandT("Pointer Mouse1"), false); + S9xMapPointer(maxcode++, S9xGetCommandT("Pointer Mouse2"), false); + S9xMapPointer(maxcode++, S9xGetCommandT("Pointer Justifier1"), false); + S9xMapPointer(maxcode++, S9xGetCommandT("Pointer Justifier2"), false); + + maxcode = 0x90; + //ASSIGN_BUTTON_FALSE (maxcode++, "Screenshot"); + + SetControllers(); +} diff --git a/plugins/snes9x_gx/source/input.h b/plugins/snes9x_gx/source/input.h new file mode 100644 index 00000000..efcf6e1d --- /dev/null +++ b/plugins/snes9x_gx/source/input.h @@ -0,0 +1,38 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * crunchy2 May-June 2007 + * Michniewski 2008 + * Tantric 2008-2010 + * + * input.h + * + * Wii/Gamecube controller management + ***************************************************************************/ + +#ifndef _INPUT_H_ +#define _INPUT_H_ + +#include <gccore.h> +#include <wiiuse/wpad.h> + +#define PI 3.14159265f +#define PADCAL 50 +#define WUPCCAL 400 +#define MAXJP 12 // # of mappable controller buttons + +extern u32 btnmap[4][4][12]; +extern int rumbleRequest[4]; + +void ResetControls(int cc = -1, int wc = -1); +void ShutoffRumble(); +void DoRumble(int i); +void ReportButtons (); +void SetControllers (); +void SetDefaultButtonMap (); +bool MenuRequested(); +void SetupPads(); +void UpdatePads(); + +#endif diff --git a/plugins/snes9x_gx/source/lang/ca.lang b/plugins/snes9x_gx/source/lang/ca.lang new file mode 100644 index 00000000..522e21ae --- /dev/null +++ b/plugins/snes9x_gx/source/lang/ca.lang @@ -0,0 +1,854 @@ +msgid "&" +msgstr "&" + +msgid "16:9 Correction" +msgstr "Correcció 16:9" + +msgid "7z decompression failed: Archive contains too many files" +msgstr "Error descomprimint 7z: L'arxiu conté massa fitxers" + +msgid "7z decompression failed: Failed to read file data" +msgstr "Error descomprimint 7z: error llegint fitxer" + +msgid "7z decompression failed: File is corrupt" +msgstr "Error descomprimint 7z: Arxiu corrupte" + +msgid "7z decompression failed: File is corrupt (CRC mismatch)" +msgstr "Error descomprimint 7z: Arxiu corrupte (error de CRC)" + +msgid "7z decompression failed: File uses too high of compression settings (dictionary size is too large)" +msgstr "Error descomprimint 7z: Paràmetre de compressió massa alt (format de diccionari massa gran)" + +msgid "7z decompression failed: File uses unsupported compression settings" +msgstr "Error descomprimint 7z: El fitxer fa servir paràmetres incompatibles" + +msgid "A (Rapid)" +msgstr "A (Ràpid)" + +msgid "Additional coding" +msgstr "Programació addic." + +msgid "Aim Offscreen" +msgstr "Apunteu fora" + +msgid "An update is available!" +msgstr "Actualització disponible!" + +msgid "Are you sure that you want to reset this game? Any unsaved progress will be lost." +msgstr "Segur que voleu reiniciar aquest joc? Es perdrà qualsevol progrés no desat." + +msgid "Are you sure that you want to reset your mappings?" +msgstr "Segur que voleu reiniciar els controls?" + +msgid "Are you sure that you want to reset your settings?" +msgstr "Segur que voleu reiniciar la configuració?" + +msgid "Maintain Aspect Ratio" +msgstr "Conservar proporcions" + +msgid "Attempting to determine load device..." +msgstr "Detectant dispositiu de càrrega..." + +msgid "Attempting to determine save device..." +msgstr "Detectant el dispositiu d'enmagatzament" + +msgid "Auto" +msgstr "Auto" + +msgid "Auto Detect" +msgstr "Auto detectar" + +msgid "Auto Load" +msgstr "Auto carregar" + +msgid "Auto Save" +msgstr "Auto desar" + +msgid "Automatic (Recommended)" +msgstr "Automàtic (Recomenat)" + +msgid "B (Rapid)" +msgstr "B (Ràpid)" + +msgid "Back" +msgstr "Enrera" + +msgid "Both" +msgstr "Tots dos" + +msgid "Controles" +msgstr "Controls" + +msgid "Button Mappings" +msgstr "Redefinir botons" + +msgid "Cancel" +msgstr "Cancel.la" + +msgid "Caps" +msgstr "Maj." + +msgid "Cheats" +msgstr "Cheats" + +msgid "Cheats file not found!" +msgstr "No trobo fitxer cheats!" + +msgid "Cheats Folder" +msgstr "Carpeta Cheats" + +msgid "Choose Game" +msgstr "Escollir joc" + +msgid "Classic Controller" +msgstr "Comandament clàssic" + +msgid "Close" +msgstr "Tancar" + +msgid "Coding" +msgstr "Programació" + +msgid "Coding & menu design" +msgstr "Programació & disseny menú" + +msgid "Compressed GBA files are not supported!" +msgstr "Els fitxers GBA comprimits incompatibles!" + +msgid "Connecting to network share..." +msgstr "Connectant a xarxa compartida..." + +msgid "Controller" +msgstr "Comandament" + +msgid "Cover View" +msgstr "Veure cover" + +msgid "Covers Folder" +msgstr "Carpeta covers" + +msgid "Credits" +msgstr "Crèdits" + +msgid "Cropping" +msgstr "Retallar" + +msgid "Crosshair" +msgstr "Punter" + +msgid "Cursor" +msgstr "Cursor" + +msgid "Data DVD" +msgstr "Dades DVD" + +msgid "Default" +msgstr "Per defecte" + +msgid "Directory name is too long!" +msgstr "Nom de directori massa larg!" + +msgid "Disabled" +msgstr "Desactivat" + +msgid "DISABLED" +msgstr "DESACTIVAT" + +msgid "distributed, or modified under the terms of the" +msgstr "distribuït, o modificat sota els termes de" + +msgid "Don't Save" +msgstr "No desis" + +msgid "Down" +msgstr "Avall" + +msgid "DOWN" +msgstr "AVALL" + +msgid "Downloading..." +msgstr "Descarregant" + +msgid "Dutch" +msgstr "Holandès" + +msgid "Empty or invalid ZIP file!" +msgstr "Fitxer zip buit o invàlid!" + +msgid "Enabled" +msgstr "Activat" + +msgid "ENABLED" +msgstr "ACTIVAT" + +msgid "English" +msgstr "Anglès" + +msgid "Error" +msgstr "Error" + +msgid "Error - Invalid ZIP file!" +msgstr "Error - Fitxer ZIP invàlid!" + +msgid "Error creating file!" +msgstr "Error creant fitxer!" + +msgid "Error loading game!" +msgstr "Error carregant joc!" + +msgid "Error opening archive!" +msgstr "Error obrint l'arxiu!" + +msgid "Error opening directory!" +msgstr "Error obrint directori!" + +msgid "Error opening file!" +msgstr "Error obrint fitxer!" + +msgid "Error reading file!" +msgstr "Error llegint fitxer!" + +msgid "Error saving file!" +msgstr "Error desant fitxer!" + +msgid "Exit" +msgstr "Surt" + +msgid "Exit Action" +msgstr "Mode sortida" + +msgid "Failed to connect to network share." +msgstr "Error de connexió a xarxa compartida." + +msgid "FDS BIOS file is invalid!" +msgstr "Fitxer BIOS FDS invàlid!" + +msgid "FDS BIOS file not found!" +msgstr "Fitxer BIOS FDS no trobat!" + +msgid "Filtered" +msgstr "Filtrat" + +msgid "Filtering" +msgstr "Filtrar" + +msgid "Fire" +msgstr "Foc" + +msgid "French" +msgstr "Francès" + +msgid "GBA Screen Zoom" +msgstr "Zoom pantalla GBA" + +msgid "Game Genie ROM not found!" +msgstr "No es troba ROM GameGenie!" + +msgid "Game Settings" +msgstr "Configuració" + +msgid "Game Settings - Button Mappings" +msgstr "Configuració - Redefinir botons" +msgid "Game Settings - Cheats" +msgstr "Configuració - Cheats" + +msgid "Game Settings - Video" +msgstr "Configuració - Vídeo" + +msgid "Game Timing" +msgstr "Timing de joc" + +msgid "Game Genie DISABLED" +msgstr "GameGenie DESACTIVAT" + +msgid "Game Genie ENABLED" +msgstr "GameGenie ACTIVAT" + +msgid "GameCube Controller" +msgstr "Comandament Gamecube" + +msgid "German" +msgstr "Alemany" + +msgid "GNU General Public License (GPL) Version 2." +msgstr "GNU General Public License (GPL) Versió 2." + +msgid "Go Back" +msgstr "Tornar" + +msgid "Horizontal" +msgstr "Horitzontal" + +msgid "Information" +msgstr "Informació" + +msgid "Initializing network..." +msgstr "Iniciant la xarxa..." + + +msgid "Insert Coin" +msgstr "Ficar Moneda" + +msgid "Insert Coin / Switch Disk" +msgstr "Ficar Moneda / Canviar Disc" + +msgid "Invalid file size!" +msgstr "Format fitxer invàlid!" + +msgid "Invalid game file!" +msgstr "Fitxer de joc invàlid!" + +msgid "Invalid network settings - Check settings.xml." +msgstr "Error de xarxa - Comproveu fitxer settings.xml." + +msgid "Invalid network settings - Share IP is blank." +msgstr "Configuració de xarxa invàlida - IP en blanc." + +msgid "Invalid network settings - Share name is blank." +msgstr "Configuració de xarxa invàlida - Nom en blanc." + +msgid "Invalid save file" +msgstr "Fitxer de save invàlid" + +msgid "Invalid state file" +msgstr "Fitxer d'estat invàlid" + +msgid "Italian" +msgstr "Italià" + +msgid "Japanese" +msgstr "Japonès" + +msgid "Justifier" +msgstr "Justifier" + +msgid "Justifier - GameCube Controller" +msgstr "Justifier - Comandament GameCube" + +msgid "Justifier - Wiimote" +msgstr "Justifier - Wiimote" + +msgid "Korean" +msgstr "Coreà" + +msgid "L TRIG" +msgstr "L" + +msgid "Language" +msgstr "Llengua" + +msgid "Languages Folder" +msgstr "Carpeta d'idioma" + +msgid "Left" +msgstr "Esquerra" + +msgid "LEFT" +msgstr "ESQUERRA" + +msgid "Left Button" +msgstr "Botó esquerre" + +msgid "Load" +msgstr "Carregar" + +msgid "Load Device" +msgstr "Càrrega" + +msgid "Load Folder" +msgstr "Carpeta partides" + +msgid "Load Game" +msgstr "Carregar partida" + +msgid "Loading" +msgstr "Carregant" + +msgid "Loading DVD..." +msgstr "Carregant DVD..." + +msgid "Loading patch..." +msgstr "Carregant patch..." + +msgid "Loading..." +msgstr "Carregant..." + +msgid "Main Menu" +msgstr "Inici" + +msgid "Match GC Controls" +msgstr "Coincidir controls GC" + +msgid "Match Wii Controls" +msgstr "Coincidir controls Wii" + +msgid "Maximum filepath length reached!" +msgid "Llargada màxima de ruta!" + +msgid "Menu" +msgstr "Menú" + +msgid "Menu artwork" +msgstr "Artwork menú" + +msgid "Menu sound" +msgstr "So del menú" + +msgid "MINUS" +msgstr "MENYS" + +msgid "Music Volume" +msgstr "Volum música" + +msgid "Mute" +msgstr "Silenci" + +msgid "NES Controller" +msgstr "Comandament NES" + +msgid "NES Controllers (2)" +msgstr "Comandaments NES (2)" + +msgid "NES Controllers (4)" +msgstr "Comandaments NES (4)" + +msgid "NES Zapper" +msgstr "NES Zapper" + +msgid "Network" +msgstr "Xarxa" + +msgid "Network Share" +msgstr "Xarxa compartida" + +msgid "New" +msgstr "Nou" + +msgid "New Snapshot" +msgstr "Nova captura" + +msgid "New SRAM" +msgstr "Nova SRAM" + +msgid "No" +msgstr "No" + +msgid "No data to save!" +msgstr "cap dada per desar!" + +msgid "No disc inserted!" +msgstr "No hi ha cap disc!" + +msgid "No SRAM data to save!" +msgstr "Cap dada SRAM per desar!" + +msgid "No game saves found." +msgstr "No hi ha partides" + +msgid "None" +msgstr "Cap" + +msgid "NTSC (480i)" +msgstr "NTSC (480i)" + +msgid "Nunchuk" +msgstr "Nunchuk" + +msgid "Off" +msgstr "Off" + +msgid "Official Site: http://code.google.com/p/fceugc/" +msgstr "Lloc Oficial: http://code.google.com/p/fceugc/" + +msgid "Official Site: http://code.google.com/p/snes9x-gx/" +msgstr "Lloc Oficial: http://code.google.com/p/snes9x-gx/" + +msgid "Official Site: http://code.google.com/p/vba-wii/" +msgstr "Lloc Oficial: http://code.google.com/p/vba-wii/" + +msgid "OK" +msgstr "D'acord" + +msgid "On" +msgstr "Encès" + +msgid "Original" +msgstr "Original" + +msgid "Out of memory!" +msgstr "Fora de memòria!" + +msgid "Out of memory: too many files!" +msgstr "Memòria insuficient: massa fitxers!" + +msgid "P1" +msgstr "J1" + +msgid "P2" +msgstr "J2" + +msgid "P3" +msgstr "J3" + +msgid "P4" +msgstr "J4" + +msgid "PAL (50Hz)" +msgstr "PAL (50Hz)" + +msgid "PAL (60Hz)" +msgstr "PAL (60Hz)" + +msgid "Palette saved" +msgstr "Paleta desada" + +msgid "Partial Stretch" +msgstr "Ajustament parcial" + +msgid "Pause" +msgstr "Pausa" + +msgid "Please Wait" +msgstr "Espereu sisplau" + +msgid "PLUS" +msgstr "MÉS" + +msgid "Portuguese" +msgstr "Portugès" + +msgid "Power off Wii" +msgstr "Apagar la Wii" + +msgid "Preferences saved" +msgstr "Preferències desades" + +msgid "Press any button on the Classic Controller now. Press Home to clear the existing mapping." +msgstr "Premeu qualsevol botó al Comandament Clàssic. Premeu HOME per eliminar la configuració." + +msgid "Press any button on the GameCube Controller now. Press Home or the C-Stick in any direction to clear the existing mapping." +msgstr "Premeu qualsevol botó al comandament de GameCube. Premeu HOME o moveu el Stick-C per eliminar la configuració actual." + +msgid "Press any button on the GameCube Controller now. Press the C-Stick in any direction to clear the existing mapping." +msgstr "Premeu qualsevol botó al comandament de GameCube. Moveu el Stick-C per eliminar la configuració actual." + +msgid "Press any button on the Wiimote now. Press Home to clear the existing mapping." +msgstr "Premeu qualsevol botó al Wiimote. Premeu HOME per eliminar la configuració." + +msgid "Press any button on the Wiimote or Nunchuk now. Press Home to clear the existing mapping." +msgstr "Premeu qualsevol botó al Wiimote o al Nunchuk. Premeu HOME per eliminar la configuració" + +msgid "Progressive (480p)" +msgstr "Progressu (480p)" + +msgid "Quit Game" +msgstr "Treure joc" + +msgid "Quit this game? Any unsaved progress will be lost." +msgstr "Treure joc? Qualsevol progrés no desat serà perdut." + +msgid "R TRIG" +msgstr "R" + +msgid "RAM saving is not available for FDS games!" +msgstr "Desar RAM és incompatible per als jocs FDS!" + +msgid "Reboot" +msgstr "Reiniciar" + +msgid "Rendering" +msgstr "Renderitzat" + +msgid "Reset" +msgstr "Reset" + +msgid "Reset Game" +msgstr "Reiniciar" + +msgid "Reset this game? Any unsaved progress will be lost." +msgstr "Reiniciar joc? Es perdrà qualsevol progrés no desat." + +msgid "Reset Mappings" +msgstr "Reiniciar Config." + +msgid "Reset Settings" +msgstr "Reiniciar Config." + +msgid "Retry" +msgstr "Prova" + +msgid "Return to Loader" +msgstr "Tornar al Loader" + +msgid "Return to Wii Menu" +msgstr "Tornar al Menú Wii" + +msgid "Right" +msgstr "Dreta" + +msgid "RIGHT" +msgstr "DRETA" + +msgid "Right Button" +msgstr "Botó dret" + +msgid "Rumble" +msgstr "Vibració" + +msgid "Save" +msgstr "Desar" + +msgid "Save Device" +msgstr "Disp. desar" + +msgid "Save failed!" +msgstr "Error desant!" + +msgid "Save file not found" +msgstr "Fitxer save no trobat" + +msgid "Save Folder" +msgstr "Carpeta de save" + +msgid "Save Game" +msgstr "Desar Joc" + +msgid "Save RAM and State?" +msgstr "Desar RAM i estat?" + +msgid "Save Snapshot?" +msgstr "Desar imatge?" + +msgid "Save SRAM and Snapshot?" +msgstr "Desar SRAM i imatge?" + +msgid "Save State?" +msgstr "Desar estat?" + +msgid "Save successful" +msgstr "Partida desada" + +msgid "Saving" +msgstr "Desant" + +msgid "Saving preferences..." +msgstr "Desant preferències..." + +msgid "Saving..." +msgstr "Desant..." + +msgid "Scaling" +msgstr "Ajust" + +msgid "Screen Position" +msgstr "Posició pantalla" + +msgid "Screen Zoom" +msgstr "Zoom" + +msgid "Select" +msgstr "Select" + +msgid "Seek error!" +msgstr "Error seek!" + +msgid "Settings" +msgstr "Config." + +msgid "Settings - Menu" +msgstr "Config. - Menú" + +msgid "Settings - Network" +msgstr "Config. - Xarxa" + +msgid "Settings - Saving & Loading" +msgstr "Config. - Desar & Carregar" + +msgid "SD Card" +msgstr "Targeta SD" + +msgid "SD card not found!" +msgstr "No trobo targeta SD!" + +msgid "Shift" +msgstr "Maj." + +msgid "Simp_chinese" +msgstr "Xinès simpl." + +msgid "SMB Share IP" +msgstr "IP del SMB" + +msgid "SMB Share Name" +msgstr "Nom del SMB" + +msgid "SMB Share Password" +msgstr "Contrasenya del SMB" + +msgid "SMB Share Username" +msgstr "Usuari del SMB" + +msgid "Snapshot" +msgstr "Imatge" + +msgid "Snapshot (Auto)" +msgstr "Imatge (Auto)" + +msgid "SNES Controller" +msgstr "Comandament SNES" + +msgid "SNES Controllers (2)" +msgstr "Comandaments SNES (2)" + +msgid "SNES Controllers (4)" +msgstr "Comandaments SNES (4)" + +msgid "SNES Controller - Classic Controller" +msgstr "Comandament SNES - Comandament Clàssic" + +msgid "SNES Controller - GameCube Controller" +msgstr "Comandament SNES - Comandament GameCube" + +msgid "SNES Controller - Nunchuk + Wiimote" +msgstr "Comandament SNES - Nunchuk + Wiimote" + +msgid "SNES Controller - Wiimote" +msgstr "Comandament SNES - Wiimote" + +msgid "SNES Mouse" +msgstr "Ratolí SNES" + +msgid "SNES Mouse - GameCube Controller" +msgstr "Ratolí SNES - Comandament GameCube" + +msgid "SNES Mouse - Wiimote" +msgstr "Ratolí SNES - Wiimote" + +msgid "Snes9x - Copyright (c) Snes9x Team 1996 - 2006" +msgstr "Snes9x - Copyright (c) Snes9x Team 1996 - 2006" + +msgid "Sound Effects Volume" +msgstr "Volum d'efectes sonors" + +msgid "Spanish" +msgstr "Castellà" + +msgid "Sprite Limit" +msgstr "Límit sprites" + +msgid "SRAM file not found" +msgstr "No trobo fitxer SRAM" + +msgid "State" +msgstr "Estat" + +msgid "State (Auto)" +msgstr "Estat (Auto)" + +msgid "State file not found" +msgstr "No trobo fitxer d'estat" + +msgid "Stretch to Fit" +msgstr "Estirar a mida" + +msgid "Superscope" +msgstr "SuperScope" + +msgid "Superscope - GameCube Controller" +msgstr "SuperScope - Comandament GameCube" + +msgid "Superscope - Wiimote" +msgstr "SuperScope - Wiimote" + +msgid "This software is open source and may be copied," +msgstr "Aquest software és de codi obert i pot ser copiat," + +msgid "Trad_chinese" +msgstr "Xinès trad." + +msgid "Unable to initialize network!" +msgstr "Impossible iniciar la xarxa!" + +msgid "Unable to locate a load device!" +msgstr "No trobo dispositiu de càrrega!" + +msgid "Unable to locate a save device!" +msgstr "No trobo dispositiu per desar!" + +msgid "Unable to open snapshot!" +msgstr "Impossible obrir imatge!" + +msgid "Unfiltered" +msgstr "No filtrat" + +msgid "Unknown file type!" +msgstr "Fitxer desconegut!" + +msgid "Unrecognized DVD format." +msgstr "Format de DVD desconegut." + +msgid "Unrecognized file extension!" +msgstr "No reconec extensió fitxer!" + +msgid "Up" +msgstr "Amunt" + +msgid "UP" +msgstr "AMUNT" + +msgid "Up One Level" +msgstr "Pujar nivell" + +msgid "Update Available" +msgstr "Nova actualització" + +msgid "Update failed!" +msgstr "No actualitzat" + +msgid "Update later" +msgstr "Fer després" + +msgid "Update now" +msgstr "Actualitzar" + +msgid "Update successful!" +msgstr "Actualització feta!" + +msgid "USB drive not found!" +msgstr "No trobo dispositiu USB!" + +msgid "USB Mass Storage" +msgstr "Dispositiu USB" + +msgid "Vertical" +msgstr "Vertical" + +msgid "Video" +msgstr "Vídeo" + +msgid "Video Mode" +msgstr "Mode vídeo" + +msgid "VM8: Unknown page type!" +msgstr "VM8: Pàgina desconeguda!" + +msgid "VM16: Unknown page type!" +msgstr "VM16: Pàgina desconeguda!" + +msgid "VM32: Unknown page type!" +msgstr "VM32: Pàgina desconeguda!" + +msgid "Wiimote" +msgstr "Wiimote" + +msgid "Wiimote Orientation" +msgstr "Orientació Wiimote" + +msgid "Yes" +msgstr "Sí" + +msgid "Zapper" +msgstr "Nintendo Zapper" + +msgid "Zapper Crosshair" +msgstr "Punter Zapper" diff --git a/plugins/snes9x_gx/source/lang/de.lang b/plugins/snes9x_gx/source/lang/de.lang new file mode 100644 index 00000000..6c7321e1 --- /dev/null +++ b/plugins/snes9x_gx/source/lang/de.lang @@ -0,0 +1,854 @@ +msgid "&" +msgstr "" + +msgid "16:9 Correction" +msgstr "16:9" + +msgid "7z decompression failed: Archive contains too many files" +msgstr "7z Dekomprimierung fehlgeschlagen: Archiv enthält zu viele Dateien" + +msgid "7z decompression failed: Failed to read file data" +msgstr "7z Dekomprimierung fehlgeschlagen: Dateidaten konnten nicht gelesen werden" + +msgid "7z decompression failed: File is corrupt" +msgstr "7z Dekomprimierung fehlgeschlagen: Datei ist fehlerhaft" + +msgid "7z decompression failed: File is corrupt (CRC mismatch)" +msgstr "7z Dekomprimierung fehlgeschlagen: Datei ist fehlerhaft (CRC-Fehler)" + +msgid "7z decompression failed: File uses too high of compression settings (dictionary size is too large)" +msgstr "7z Dekomprimierung fehlgeschlagen: Datei benutzt zu hohe Komprimierungseinstellungen (Wörterbuch ist zu groß)" + +msgid "7z decompression failed: File uses unsupported compression settings" +msgstr "7z Dekomprimierung fehlgeschlagen: Datei benutzt nicht unterstüzte Komprimierungseinstellungen" + +msgid "A (Rapid)" +msgstr "A (Turbo)" + +msgid "Additional coding" +msgstr "Uusätzliche Programmierung" + +msgid "Aim Offscreen" +msgstr "Neben Bildsch. zielen" + +msgid "An update is available!" +msgstr "Ein Update ist verfügbar!" + +msgid "Are you sure that you want to reset this game? Any unsaved progress will be lost." +msgstr "Bist du sicher das du das Spiel zurücksetzen willst? Ungespeicherter Fortschritt geht verloren." + +msgid "Are you sure that you want to reset your mappings?" +msgstr "Bist du sicher das du deine Tastenbelegung zurücksetzten willst?" + +msgid "Are you sure that you want to reset your settings?" +msgstr "Bist du sicher das du die Einstellungen zurücksetzten willst?" + +msgid "Maintain Aspect Ratio" +msgstr "Bildschirmverhältnis" + +msgid "Attempting to determine load device..." +msgstr "Versuche Ladegerät zu ermitteln..." + +msgid "Attempting to determine save device..." +msgstr "Versuche Speichergerät zu ermitteln..." + +msgid "Auto" +msgstr "" + +msgid "Auto Detect" +msgstr "Auto. feststellen" + +msgid "Auto Load" +msgstr "Auto. laden" + +msgid "Auto Save" +msgstr "Auto. speichern" + +msgid "Automatic (Recommended)" +msgstr "Automatisch (Empfohlen)" + +msgid "B (Rapid)" +msgstr "B (Turbo)" + +msgid "Back" +msgstr "Zurück" + +msgid "Both" +msgstr "Beide" + +msgid "Button Mapping" +msgstr "Tastenbelegung" + +msgid "Button Mappings" +msgstr "Tasten Belegung" + +msgid "Cancel" +msgstr "Abbrechen" + +msgid "Caps" +msgstr "" + +msgid "Cheats" +msgstr "" + +msgid "Cheats file not found!" +msgstr "Cheatdatei nicht gefunden!" + +msgid "Cheats Folder" +msgstr "Ordner f. Cheats" + +msgid "Choose Game" +msgstr "Spiel auswählen" + +msgid "Classic Controller" +msgstr "" + +msgid "Close" +msgstr "Schließen" + +msgid "Coding" +msgstr "Programmierung" + +msgid "Coding & menu design" +msgstr "Programmierung & Menüdesign" + +msgid "Compressed GBA files are not supported!" +msgstr "Komprimierte GBA Dateien werden nicht unterstützt!" + +msgid "Connecting to network share..." +msgstr "Verbinde mit Netzwerk Share..." + +msgid "Controller" +msgstr "" + +msgid "Cover View" +msgstr "Cover anzeigen" + +msgid "Covers Folder" +msgstr "Ordner f. Cover" + +msgid "Credits" +msgstr "" + +msgid "Cropping" +msgstr "Pan & Scan" + +msgid "Crosshair" +msgstr "Fadenkreuz" + +msgid "Cursor" +msgstr "Eingabezeiger" + +msgid "Data DVD" +msgstr "Daten DVD" + +msgid "Default" +msgstr "Standard" + +msgid "Directory name is too long!" +msgstr "Verzeichnisname ist zu lang!" + +msgid "Disabled" +msgstr "Deaktiviert" + +msgid "DISABLED" +msgstr "DEAKTIVIERT" + +msgid "distributed, or modified under the terms of the" +msgstr "veröffentlich, oder verändert unter den Bedingungen der" + +msgid "Don't Save" +msgstr "Nicht speichern" + +msgid "Down" +msgstr "Unten" + +msgid "DOWN" +msgstr "UNTEN" + +msgid "Downloading..." +msgstr "Lade herunter..." + +msgid "Dutch" +msgstr "Niederländisch" + +msgid "Empty or invalid ZIP file!" +msgstr "Leere order ungültige ZIP Datei!" + +msgid "Enabled" +msgstr "Aktiviert" + +msgid "ENABLED" +msgstr "AKTIVIERT" + +msgid "English" +msgstr "Englisch" + +msgid "Error" +msgstr "Fehler" + +msgid "Error - Invalid ZIP file!" +msgstr "Fehler - Ungültige ZIP Datei!" + +msgid "Error creating file!" +msgstr "Fehler beim Erstellen der Datei!" + +msgid "Error loading game!" +msgstr "Fehler beim Laden des Spiels!" + +msgid "Error opening archive!" +msgstr "Fehler beim Öffnen des Archivs!" + +msgid "Error opening directory!" +msgstr "Fehler beim Öffnen des Verzeichnis'!" + +msgid "Error opening file!" +msgstr "Fehler beim Öffnen der Datei!" + +msgid "Error reading file!" +msgstr "Fehler beim Lesen der Datei!" + +msgid "Error saving file!" +msgstr "Fehler beim Speichern der Datei!" + +msgid "Exit" +msgstr "Beenden" + +msgid "Exit Action" +msgstr "Aktion beim Beenden" + +msgid "Failed to connect to network share." +msgstr "Verbinden mit Netzwerk Share ist fehlgeschlagen." + +msgid "FDS BIOS file is invalid!" +msgstr "FDS BIOS Datei ist ungültig!" + +msgid "FDS BIOS file not found!" +msgstr "FDS BIOS Datei nicht gefunden!" + +msgid "Filtered" +msgstr "Gefiltert" + +msgid "Filtering" +msgstr "Filter" + +msgid "Fire" +msgstr "Schießen" + +msgid "French" +msgstr "Französich" + +msgid "GBA Screen Zoom" +msgstr "GBA Bildschirm Zoom" + +msgid "Game Genie ROM not found!" +msgstr "Game Genie ROM nicht gefunden!" + +msgid "Game Settings" +msgstr "Spiel Einstellungen" + +msgid "Game Settings - Button Mappings" +msgstr "Spieleinstellungen - Tastenbelegung" + +msgid "Game Settings - Cheats" +msgstr "Spieleinstellungen - Cheats" + +msgid "Game Settings - Video" +msgstr "Spieleinstellungen - Video" + +msgid "Game Timing" +msgstr "Spiel Timing" + +msgid "Game Genie DISABLED" +msgstr "Game Genie DEAKTIVIERT" + +msgid "Game Genie ENABLED" +msgstr "Game Genie AKTIVIERT" + +msgid "GameCube Controller" +msgstr "" + +msgid "German" +msgstr "Deutsch" + +msgid "GNU General Public License (GPL) Version 2." +msgstr "" + +msgid "Go Back" +msgstr "Zurück" + +msgid "Horizontal" +msgstr "" + +msgid "Information" +msgstr "" + +msgid "Initializing network..." +msgstr "Initialisiere Netzwerk..." + +msgid "Insert Coin" +msgstr "Münze einwerfen" + +msgid "Insert Coin / Switch Disk" +msgstr "Münze einwerfen / Disc wechseln" + +msgid "Invalid file size!" +msgstr "Ungültige Dateigröße!" + +msgid "Invalid game file!" +msgstr "Ungültige Spieldatei!" + +msgid "Invalid network settings - Check settings.xml." +msgstr "Ungültige Netzwerkeinstellung - Prüfe die settings.xml." + +msgid "Invalid network settings - Share IP is blank." +msgstr "Ungültige Netzwerkeinstellung - Share IP ist leer." + +msgid "Invalid network settings - Share name is blank." +msgstr "Ungültige Netzwerkeinstellung - Share Name ist leer." + +msgid "Invalid save file" +msgstr "Ungültige Speicherdatei" + +msgid "Invalid state file" +msgstr "Ungültige Statusdatei" + +msgid "Italian" +msgstr "Italienisch" + +msgid "Japanese" +msgstr "Japanisch" + +msgid "Justifier" +msgstr "" + +msgid "Justifier - GameCube Controller" +msgstr "" + +msgid "Justifier - Wiimote" +msgstr "Justifier - Wii-FB" + +msgid "Korean" +msgstr "Koreanisch" + +msgid "L TRIG" +msgstr "" + +msgid "Language" +msgstr "Sprache" + +msgid "Languages Folder" +msgstr "Ordner f. Sprachen" + +msgid "Left" +msgstr "Links" + +msgid "LEFT" +msgstr "LINKS" + +msgid "Left Button" +msgstr "Linke Taste" + +msgid "Load" +msgstr "Laden" + +msgid "Load Device" +msgstr "Startgerät" + +msgid "Load Folder" +msgstr "Ordner f. ROMs" + +msgid "Load Game" +msgstr "Spiel laden" + +msgid "Loading" +msgstr "Laden" + +msgid "Loading DVD..." +msgstr "Lade DVD..." + +msgid "Loading patch..." +msgstr "Lade Patch..." + +msgid "Loading..." +msgstr "Lade..." + +msgid "Main Menu" +msgstr "Hauptmenü" + +msgid "Match GC Controls" +msgstr "GC Steuerung anpassen" + +msgid "Match Wii Controls" +msgstr "Wii Steuerung anpassen" + +msgid "Maximum filepath length reached!" +msgid "Maximale Länge für Dateipfade erreicht!" + +msgid "Menu" +msgstr "Menü" + +msgid "Menu artwork" +msgstr "Menü Artwork" + +msgid "Menu sound" +msgstr "Menü Sound" + +msgid "MINUS" +msgstr "" + +msgid "Music Volume" +msgstr "Musik Lautstärke" + +msgid "Mute" +msgstr "Stumm" + +msgid "NES Controller" +msgstr "" + +msgid "NES Controllers (2)" +msgstr "" + +msgid "NES Controllers (4)" +msgstr "" + +msgid "NES Zapper" +msgstr "" + +msgid "Network" +msgstr "Netzwerk" + +msgid "Network Share" +msgstr "Netzwerk Share" + +msgid "New" +msgstr "Neu" + +msgid "New Snapshot" +msgstr "Neuer Schnappschuss" + +msgid "New SRAM" +msgstr "Neuer SRAM" + +msgid "No" +msgstr "Nein" + +msgid "No data to save!" +msgstr "Keine Daten gespeichert!" + +msgid "No disc inserted!" +msgstr "Keine Disc eingelegt!" + +msgid "No SRAM data to save!" +msgstr "Keine SRAM Daten zum speichern!" + +msgid "No game saves found." +msgstr "Kein Spielstand gefunden." + +msgid "None" +msgstr "Nichts" + +msgid "NTSC (480i)" +msgstr "" + +msgid "Nunchuk" +msgstr "" + +msgid "Off" +msgstr "Aus" + +msgid "Official Site: http://code.google.com/p/fceugc/" +msgstr "Offizielle Seite: http://code.google.com/p/fceugc/" + +msgid "Official Site: http://code.google.com/p/snes9x-gx/" +msgstr "Offizielle Seite: http://code.google.com/p/snes9x-gx/" + +msgid "Official Site: http://code.google.com/p/vba-wii/" +msgstr "Offizielle Seite: http://code.google.com/p/vba-wii/" + +msgid "OK" +msgstr "" + +msgid "On" +msgstr "An" + +msgid "Original" +msgstr "" + +msgid "Out of memory!" +msgstr "Nicht genug Speicher!" + +msgid "Out of memory: too many files!" +msgstr "Nicht genug Speicher: Zu viele Dateien!" + +msgid "P1" +msgstr "S1" + +msgid "P2" +msgstr "S2" + +msgid "P3" +msgstr "S3" + +msgid "P4" +msgstr "S4" + +msgid "PAL (50Hz)" +msgstr "" + +msgid "PAL (60Hz)" +msgstr "" + +msgid "Palette saved" +msgstr "Palette gespeichert" + +msgid "Partial Stretch" +msgstr "Partiell gestreckt" + +msgid "Pause" +msgstr "" + +msgid "Please Wait" +msgstr "Bitte Warten" + +msgid "PLUS" +msgstr "" + +msgid "Portuguese" +msgstr "Portugiesisch" + +msgid "Power off Wii" +msgstr "Wii ausschalten" + +msgid "Preferences saved" +msgstr "Einstellungen gespeichert" + +msgid "Press any button on the Classic Controller now. Press Home to clear the existing mapping." +msgstr "Drücke jetzt eine Taste auf dem Classic Controller. Drücke HOME um die vorhandene Belegung zu löschen." + +msgid "Press any button on the GameCube Controller now. Press Home or the C-Stick in any direction to clear the existing mapping." +msgstr "Drücke jetzt eine Taste auf dem GameCube Controller. Drücke HOME oder den C-Stick in eine beliebige Richtung um die vorhandene Belegung zu löschen." + +msgid "Press any button on the GameCube Controller now. Press the C-Stick in any direction to clear the existing mapping." +msgstr "Drücke jetzt eine Taste auf dem GameCube Controller. Drücke den C-Stick in eine beliebige Richtung um die vorhandene Belegung zu löschen." + +msgid "Press any button on the Wiimote now. Press Home to clear the existing mapping." +msgstr "Drücke jetzt eine Taste auf der Wii-FB. Drücke HOME um die vorhandene Belegung zu löschen." + +msgid "Press any button on the Wiimote or Nunchuk now. Press Home to clear the existing mapping." +msgstr "Drücke jetzt eine Taste auf der Wii-FB oder dem Nunchuk. Drücke HOME um die vorhandene Belegung zu löschen." + +msgid "Progressive (480p)" +msgstr "" + +msgid "Quit Game" +msgstr "Spiel beenden" + +msgid "Quit this game? Any unsaved progress will be lost." +msgstr "Dieses Spiel beenden? Ungespeicherter Fortschritt geht verloren." + +msgid "R TRIG" +msgstr "" + +msgid "RAM saving is not available for FDS games!" +msgstr "RAM speichern ist für FDS Spiele nicht verfügbar!" + +msgid "Reboot" +msgstr "Neustart" + +msgid "Rendering" +msgstr "Darstellung" + +msgid "Reset" +msgstr "Zurücksetzen" + +msgid "Reset Game" +msgstr "Spiel zurücksetzen" + +msgid "Reset this game? Any unsaved progress will be lost." +msgstr "Spiel zurücksetzen? Nicht gespeicherte Fortschritte gehen verloren." + +msgid "Reset Mappings" +msgstr "Belegung zurücksetzen" + +msgid "Reset Settings" +msgstr "Zurücksetzen" + +msgid "Retry" +msgstr "Wiederholen" + +msgid "Return to Loader" +msgstr "Zum Loader zurückkehren" + +msgid "Return to Wii Menu" +msgstr "Zum Wii Menü zurückkehren" + +msgid "Right" +msgstr "Rechts" + +msgid "RIGHT" +msgstr "RECHTS" + +msgid "Right Button" +msgstr "Rechte Taste" + +msgid "Rumble" +msgstr "" + +msgid "Save" +msgstr "Speichern" + +msgid "Save Device" +msgstr "Speichergerät" + +msgid "Save failed!" +msgstr "Speichern fehlgeschlagen!" + +msgid "Save file not found" +msgstr "Speicherdatei nicht gefunden" + +msgid "Save Folder" +msgstr "Ordner f. Spielstände" + +msgid "Save Game" +msgstr "Spiel speichern" + +msgid "Save RAM and State?" +msgstr "RAM und Status speichern?" + +msgid "Save Snapshot?" +msgstr "Schnappschuss speichern?" + +msgid "Save SRAM and Snapshot?" +msgstr "SRAM und Schnappschuss speichern?" + +msgid "Save State?" +msgstr "Status speichern?" + +msgid "Save successful" +msgstr "Erfolgreich gespeichert" + +msgid "Saving" +msgstr "Speichern" + +msgid "Saving preferences..." +msgstr "Einstellungen werden gespeichert..." + +msgid "Saving..." +msgstr "Speichern..." + +msgid "Scaling" +msgstr "Auflösung" + +msgid "Screen Position" +msgstr "Bildschirm Position" + +msgid "Screen Zoom" +msgstr "Bildschirm Zoom" + +msgid "Select" +msgstr "" + +msgid "Seek error!" +msgstr "Seekfehler!" + +msgid "Settings" +msgstr "Einstellungen" + +msgid "Settings - Menu" +msgstr "Einstellungen - Menü" + +msgid "Settings - Network" +msgstr "Einstellungen - Netzwerk" + +msgid "Settings - Saving & Loading" +msgstr "Einstellungen - Speichern & Laden" + +msgid "SD Card" +msgstr "" + +msgid "SD card not found!" +msgstr "SD Card nicht gefunden!" + +msgid "Shift" +msgstr "" + +msgid "Simp_chinese" +msgstr "Vereinfachtes Chinesisch" + +msgid "SMB Share IP" +msgstr "" + +msgid "SMB Share Name" +msgstr "" + +msgid "SMB Share Password" +msgstr "SMB Share Passwort" + +msgid "SMB Share Username" +msgstr "SMB Share Benutzername" + +msgid "Snapshot" +msgstr "Schnappschuss" + +msgid "Snapshot (Auto)" +msgstr "Schnappschuss (Auto)" + +msgid "SNES Controller" +msgstr "" + +msgid "SNES Controllers (2)" +msgstr "" + +msgid "SNES Controllers (4)" +msgstr "" + +msgid "SNES Controller - Classic Controller" +msgstr "" + +msgid "SNES Controller - GameCube Controller" +msgstr "" + +msgid "SNES Controller - Nunchuk + Wiimote" +msgstr "SNES Controller - Nunchuk + Wii-FB" + +msgid "SNES Controller - Wiimote" +msgstr "SNES Controller - Wii-FB" + +msgid "SNES Mouse" +msgstr "SNES Maus" + +msgid "SNES Mouse - GameCube Controller" +msgstr "SNES Maus - GameCube Controller" + +msgid "SNES Mouse - Wiimote" +msgstr "SNES Maus - Wii-FB" + +msgid "Snes9x - Copyright (c) Snes9x Team 1996 - 2006" +msgstr "" + +msgid "Sound Effects Volume" +msgstr "SFX Lautstärke" + +msgid "Spanish" +msgstr "Spanisch" + +msgid "Sprite Limit" +msgstr "" + +msgid "SRAM file not found" +msgstr "SRAM Datei nicht gefunden" + +msgid "State" +msgstr "Status" + +msgid "State (Auto)" +msgstr "Status (Auto)" + +msgid "State file not found" +msgstr "Statusdatei nicht gefunden" + +msgid "Stretch to Fit" +msgstr "Strecken zum Einpassen" + +msgid "Superscope" +msgstr "" + +msgid "Superscope - GameCube Controller" +msgstr "" + +msgid "Superscope - Wiimote" +msgstr "Superscope - Wii-FB" + +msgid "This software is open source and may be copied," +msgstr "Diese Software ist Open Source und evtl. kopiert," + +msgid "Trad_chinese" +msgstr "Traditionelles Chinesisch" + +msgid "Unable to initialize network!" +msgstr "Netzwerk konnte nicht initialisiert werden!" + +msgid "Unable to locate a load device!" +msgstr "Ladegerät konnte nicht gefunden werden!" + +msgid "Unable to locate a save device!" +msgstr "Speichergerät konnte nicht gefunden werden!" + +msgid "Unable to open snapshot!" +msgstr "Schnappschuss konnte nicht geöffnet werden!" + +msgid "Unfiltered" +msgstr "Ungefiltert" + +msgid "Unknown file type!" +msgstr "Unbekannter Dateityp!" + +msgid "Unrecognized DVD format." +msgstr "Unbekanntes DVD Format." + +msgid "Unrecognized file extension!" +msgstr "Unbekannte Dateiendung!" + +msgid "Up" +msgstr "Oben" + +msgid "UP" +msgstr "OBEN" + +msgid "Up One Level" +msgstr "Eine Ebene nach oben" + +msgid "Update Available" +msgstr "Update verfügbar" + +msgid "Update failed!" +msgstr "Aktualisierung fehlgeschlagen!" + +msgid "Update later" +msgstr "Später updaten" + +msgid "Update now" +msgstr "Jetzt updaten" + +msgid "Update successful!" +msgstr "Aktualisierung erfolgreich!" + +msgid "USB drive not found!" +msgstr "USB Laufwerk nicht gefunden!" + +msgid "USB Mass Storage" +msgstr "USB Massenspeicher" + +msgid "Vertical" +msgstr "Vertikal" + +msgid "Video" +msgstr "Bild" + +msgid "Video Mode" +msgstr "Videomodus" + +msgid "VM8: Unknown page type!" +msgstr "VM8: Unbekannter Seitentyp!" + +msgid "VM16: Unknown page type!" +msgstr "VM16: Unbekannter Seitentyp!" + +msgid "VM32: Unknown page type!" +msgstr "VM32: Unbekannter Seitentyp!" + +msgid "Wiimote" +msgstr "Wii-FB" + +msgid "Wiimote Orientation" +msgstr "Wii-FB Ausrichtung" + +msgid "Yes" +msgstr "Ja" + +msgid "Zapper" +msgstr "" + +msgid "Zapper Crosshair" +msgstr "Zapper Fadenkreuz" diff --git a/plugins/snes9x_gx/source/lang/en.lang b/plugins/snes9x_gx/source/lang/en.lang new file mode 100644 index 00000000..85d83649 --- /dev/null +++ b/plugins/snes9x_gx/source/lang/en.lang @@ -0,0 +1,2 @@ +msgid " " +msgstr "" diff --git a/plugins/snes9x_gx/source/lang/es.lang b/plugins/snes9x_gx/source/lang/es.lang new file mode 100644 index 00000000..89f972ab --- /dev/null +++ b/plugins/snes9x_gx/source/lang/es.lang @@ -0,0 +1,446 @@ +msgid "&" +msgstr "" + +msgid "Up" +msgstr "Arriba" + +msgid "Down" +msgstr "Abajo" + +msgid "Left" +msgstr "Izquierda" + +msgid "Right" +msgstr "Derecha" + +msgid "PLUS" +msgstr "MAS" + +msgid "MINUS" +msgstr "MENOS" + +msgid "Aim Offscreen" +msgstr "Apuntar Fuera de Pantalla" + +msgid "Cursor" +msgstr "" + +msgid "Turbo On" +msgstr "Turbo Encendido" + +msgid "Turbo Off" +msgstr "Turbo Apagado" + +msgid "Pause" +msgstr "Pausa" + +msgid "START" +msgstr "Inicio" + +msgid "16:9 Correction" +msgstr "Corrección 16:9" + +msgid "An update is available!" +msgstr "¡Actualización disponible!" + +msgid "Are you sure that you want to reset this game? Any unsaved progress will be lost." +msgstr "¿Seguro que desea reiniciar este juego? Se perderá cualquier progreso no salvado." + +msgid "Are you sure that you want to reset your mappings?" +msgstr "¿Seguro que desea reinicializar los controles?" + +msgid "Are you sure that you want to reset your settings?" +msgstr "¿Seguro que desea reinicializar la configuración?" + +msgid "Auto" +msgstr "Auto" + +msgid "Auto Detect" +msgstr "Auto Detect." + +msgid "Auto Load" +msgstr "Auto Cargar" + +msgid "Auto Save" +msgstr "Auto Salvar" + +msgid "Automatic (Recommended)" +msgstr "Automático (Recomendado)" + +msgid "Back" +msgstr "Atrás" + +msgid "Both" +msgstr "Ambos" + +msgid "Button Mapping" +msgstr "Controles" + +msgid "Button Mappings" +msgstr "Redefinir Controles" + +msgid "Cancel" +msgstr "Cancelar" + +msgid "Caps" +msgstr "" + +msgid "Cheats" +msgstr "Cheats" + +msgid "Cheats file not found!" +msgstr "¡Cheats no encontrado!" + +msgid "Cheats Folder" +msgstr "Carpeta Cheats" + +msgid "Choose Game" +msgstr "Elegir Juego" + +msgid "Classic Controller" +msgstr "Mando Clásico" + +msgid "Close" +msgstr "Cerrar" + +msgid "Coding" +msgstr "Programación" + +msgid "Coding & menu design" +msgstr "Código & diseño de menú" + +msgid "Controller" +msgstr "Mando" + +msgid "Cover View" +msgstr "Vista Portada" + +msgid "Covers Folder" +msgstr "Carpeta Portadas" + +msgid "Wii U Pro Controller" +msgstr "Mando Wii U Pro" + +msgid "Screenshots Folder" +msgstr "Carpeta Img. Pantalla" + +msgid "Credits" +msgstr "Créditos" + +msgid "Default" +msgstr "Por defecto" + +msgid "Disabled" +msgstr "Deshabilitado" + +msgid "distributed, or modified under the terms of the" +msgstr "distribuido, o modificado bajo los términos de" + +msgid "Don't Save" +msgstr "No Salvar" + +msgid "Enabled" +msgstr "Habilitado" + +msgid "Error" +msgstr "Error" + +msgid "Exit" +msgstr "Salir" + +msgid "Exit Action" +msgstr "Acción de Salir" + +msgid "Filtered" +msgstr "Filtrado" + +msgid "Filtering" +msgstr "Filtrar" + +msgid "Game Settings" +msgstr "Configuración" + +msgid "Game Settings - Button Mappings" +msgstr "Configuración - Redefinir Controles" + +msgid "Game Settings - Cheats" +msgstr "Configuración - Cheats" + +msgid "Game Settings - Video" +msgstr "Configuración - Vídeo" + +msgid "GameCube Controller" +msgstr "Mando de GameCube" + +msgid "GNU General Public License (GPL) Version 2." +msgstr "GNU General Public License (GPL) Versión 2." + +msgid "Go Back" +msgstr "Volver" + +msgid "Horizontal" +msgstr "" + +msgid "Information" +msgstr "Información" + +msgid "Justifier" +msgstr "Justificado" + +msgid "Language" +msgstr "Idioma" + +msgid "Languages Folder" +msgstr "Carpeta Idiomas" + +msgid "Load" +msgstr "Cargar" + +msgid "Load Device" +msgstr "Cargar Dispositivo" + +msgid "Load Folder" +msgstr "Cargar Carpeta" + +msgid "Load Game" +msgstr "Cargar Juego" + +msgid "Loading" +msgstr "Cargando" + +msgid "Main Menu" +msgstr "Menú Principal" + +msgid "Menu" +msgstr "Menú" + +msgid "Menu artwork" +msgstr "Artwork del menú" + +msgid "Menu sound" +msgstr "Sonido del menú" + +msgid "Music Volume" +msgstr "Volumen Música" + +msgid "Mute" +msgstr "Silenciar" + +msgid "Network" +msgstr "Red" + +msgid "No" +msgstr "No" + +msgid "No game saves found." +msgstr "No hay partidas salvadas." + +msgid "NTSC (480i)" +msgstr "" + +msgid "Nunchuk" +msgstr "" + +msgid "Off" +msgstr "" + +msgid "Official Site: http://code.google.com/p/snes9x-gx/" +msgstr "Sitio Oficial: http://code.google.com/p/snes9x-gx/" + +msgid "OK" +msgstr "" + +msgid "On" +msgstr "" + +msgid "Original" +msgstr "" + +msgid "PAL (50Hz)" +msgstr "" + +msgid "PAL (60Hz)" +msgstr "" + +msgid "Please Wait" +msgstr "Espere, por favor" + +msgid "Power off Wii" +msgstr "Apagar Wii" + +msgid "Press any button on the Classic Controller now. Press Home to clear the existing mapping." +msgstr "Presione un botón en el Mando Clásico. Presione HOME para eliminar la configuración actual." + +msgid "Press any button on the GameCube Controller now. Press Home or the C-Stick in any direction to clear the existing mapping." +msgstr "Presione un botón en el Mando de GameCube. Presione HOME o mueva el el Stick-C para eliminar la configuración actual." + +msgid "Press any button on the GameCube Controller now. Press the C-Stick in any direction to clear the existing mapping." +msgstr "Presione un botón en el Mando de GameCube. Mueva el el Stick-C para eliminar la configuración actual." + +msgid "Press any button on the Wiimote now. Press Home to clear the existing mapping." +msgstr "Presione un botón en el Wiimote. Presione HOME para eliminar la configuración actual." + +msgid "Press any button on the Wiimote or Nunchuk now. Press Home to clear the existing mapping." +msgstr "Presione un botón en el Wiimote o Nunchuck. Presione HOME para eliminar la configuración actual." + +msgid "Press any button on the Wii U Pro Controller now. Press Home to clear the existing mapping." +msgstr "Presione un botón en el Mando Wii U Pro. Presione HOME para eliminar la configuración actual." + +msgid "ScreenShot" +msgstr "Pantalla" + +msgid "Preview Screenshot" +msgstr "Imagen de Pantalla" + +msgid "Save a new Preview Screenshot? Current Screenshot image will be overwritten." +msgstr "¿Grabar una nueva imagen de pantalla? La imagen actual será sobre-escrita." + +msgid "Progressive (480p)" +msgstr "Progresivo (480p)" + +msgid "Quit Game" +msgstr "Salir" + +msgid "Quit this game? Any unsaved progress will be lost." +msgstr "¿Salir? Se perderá cualquier progreso no salvado." + +msgid "Reboot" +msgstr "Reiniciar" + +msgid "Rendering" +msgstr "Renderizado" + +msgid "Reset" +msgstr "Reinicializar" + +msgid "Reset Game" +msgstr "Reinicializar" + +msgid "Reset Mappings" +msgstr "Reinicializar" + +msgid "Reset Settings" +msgstr "Reinicializar" + +msgid "Retry" +msgstr "Reintentar" + +msgid "Return to Loader" +msgstr "Volver al Loader" + +msgid "Return to Wii Menu" +msgstr "Volver al menú de Wii" + +msgid "Rumble" +msgstr "Vibración" + +msgid "Save" +msgstr "Salvar" + +msgid "Save Device" +msgstr "Salvar Dispositivo" + +msgid "Save Folder" +msgstr "Salvar Carpeta" + +msgid "Save Game" +msgstr "Salvar Juego" + +msgid "Save Snapshot?" +msgstr "Salvar Instantánea?" + +msgid "Save SRAM and Snapshot?" +msgstr "Salvar SRAM e Instantánea?" + +msgid "Saving" +msgstr "Grabando" + +msgid "Scaling" +msgstr "Scaling" + +msgid "Screen Position" +msgstr "Posición Pantalla" + +msgid "Screen Zoom" +msgstr "Zoom Pantalla" + +msgid "Settings" +msgstr "Configuración" + +msgid "Settings - Menu" +msgstr "Configuración - Menú" + +msgid "Settings - Network" +msgstr "Configuración - Red" + +msgid "Settings - Saving & Loading" +msgstr "Configuración - Grabar y Cargar" + +msgid "Shift" +msgstr "Mayús." + +msgid "SMB Share IP" +msgstr "IP del SMB" + +msgid "SMB Share Name" +msgstr "Nombre del SMB" + +msgid "SMB Share Password" +msgstr "Contraseña del SMB" + +msgid "SMB Share Username" +msgstr "Usuario del SMB" + +msgid "Snapshot" +msgstr "Instantánea" + +msgid "SNES Controller" +msgstr "Mando de SNES" + +msgid "SNES Mouse" +msgstr "Ratón de SNES" + +msgid "Snes9x - Copyright (c) Snes9x Team 1996 - 2006" +msgstr "" + +msgid "Sound Effects Volume" +msgstr "Volumen Efectos" + +msgid "Super Scope" +msgstr "" + +msgid "This software is open source and may be copied," +msgstr "Este software es de código abierto y puede ser copiado," + +msgid "Unfiltered" +msgstr "No filtrado" + +msgid "Up One Level" +msgstr "Subir Nivel" + +msgid "Update Available" +msgstr "Actualización disponible" + +msgid "Update later" +msgstr "Actualizar después" + +msgid "Update now" +msgstr "Actualizar ya" + +msgid "Vertical" +msgstr "" + +msgid "Video" +msgstr "Vídeo" + +msgid "Video Mode" +msgstr "Modo de Vídeo" + +msgid "Wiimote" +msgstr "" + +msgid "Wiimote Orientation" +msgstr "Orientación del Wiimote" + +msgid "Yes" +msgstr "Sí" \ No newline at end of file diff --git a/plugins/snes9x_gx/source/lang/fr.lang b/plugins/snes9x_gx/source/lang/fr.lang new file mode 100644 index 00000000..e69456e5 --- /dev/null +++ b/plugins/snes9x_gx/source/lang/fr.lang @@ -0,0 +1,866 @@ +msgid "&" +msgstr "&" + +msgid "16:9 Correction" +msgstr "Correction 16:9" + +msgid "7z decompression failed: Archive contains too many files" +msgstr "La décompression 7z a échoué : l'archive contient trop de fichiers" + +msgid "7z decompression failed: Failed to read file data" +msgstr "La décompression 7z a échoué : la lecture des données du fichier a échoué" + +msgid "7z decompression failed: File is corrupt" +msgstr "La décompression 7z a échoué : le fichier est corrompu" + +msgid "7z decompression failed: File is corrupt (CRC mismatch)" +msgstr "La décompression 7z a échoué : le fichier est corrompu (erreur de contrôle de redondance cyclique - CRC)" + +msgid "7z decompression failed: File uses too high of compression settings (dictionary size is too large)" +msgstr "La décompression 7z a échoué : le fichier utilise un paramètre de compression trop élevé (taille du dictionnaire trop haute)" + +msgid "7z decompression failed: File uses unsupported compression settings" +msgstr "La décompression 7z a échoué : le fichier utilise des paramètres de compression non supportés" + +msgid "A (Rapid)" +msgstr "A (Rapide)" + +msgid "Additional coding" +msgstr "Programmation additionnelle" + +msgid "Aim Offscreen" +msgstr "Visée hors champ" + +msgid "An update is available!" +msgstr "Une mise à jour est disponible !" + +msgid "Are you sure that you want to reset this game? Any unsaved progress will be lost." +msgstr "Êtes-vous sûr de vouloir redémarrer ce jeu ? Toute progression non sauvegardée sera perdue." + +msgid "Are you sure that you want to reset your mappings?" +msgstr "Êtes-vous sûr de vouloir réinitialiser les touches ?" + +msgid "Are you sure that you want to reset your settings?" +msgstr "Êtes-vous sûr de vouloir réinitialiser tout les paramètres ?" + +msgid "Maintain Aspect Ratio" +msgstr "Conserver les proportions" + +msgid "Attempting to determine load device..." +msgstr "Tentative de détection du périphérique d'entrée..." + +msgid "Attempting to determine save device..." +msgstr "Tentative de détection du périphérique de sauvegarde..." + +msgid "Auto" +msgstr "Auto" + +msgid "Auto Detect" +msgstr "Détection Auto" + +msgid "Auto Load" +msgstr "Chargement Auto" + +msgid "Auto Save" +msgstr "Sauvegarde Auto" + +msgid "Automatic (Recommended)" +msgstr "Automatique (Recommandé)" + +msgid "B (Rapid)" +msgstr "B (Rapide)" + +msgid "Back" +msgstr "Retour" + +msgid "Both" +msgstr "Les deux" + +msgid "Button Mapping" +msgstr "Contrôles" + +msgid "Button Mappings" +msgstr "Redéfinir les touches" + +msgid "Cancel" +msgstr "Annuler" + +msgid "Caps" +msgstr "Verr.Maj" + +msgid "Catalan" +msgstr "Catalan" + +msgid "Cheats" +msgstr "Cheats" + +msgid "Cheats file not found!" +msgstr "Fichier Cheats non trouvé !" + +msgid "Cheats Folder" +msgstr "Dossier Cheats" + +msgid "Choose Game" +msgstr "Choisir un jeu" + +msgid "Classic Controller" +msgstr "Manette Classique" + +msgid "Close" +msgstr "Fermer" + +msgid "Coding" +msgstr "Programmation" + +msgid "Coding & menu design" +msgstr "Programmation & design du menu" + +msgid "Compressed GBA files are not supported!" +msgstr "Les fichiers GBA compressés ne sont pas supportés !" + +msgid "Connecting to network share..." +msgstr "Connection au partage réseau en cours..." + +msgid "Controller" +msgstr "Contrôleur" + +msgid "Cover View" +msgstr "Vue Jaquette" + +msgid "Covers Folder" +msgstr "Dossier des jaquettes" + +msgid "Credits" +msgstr "Crédits" + +msgid "Cropping" +msgstr "Recadrage" + +msgid "Crosshair" +msgstr "Réticule de visée" + +msgid "Cursor" +msgstr "Curseur" + +msgid "Data DVD" +msgstr "Données DVD" + +msgid "Default" +msgstr "Par défaut" + +msgid "Directory name is too long!" +msgstr "Le nom du répertoire est trop long !" + +msgid "Disabled" +msgstr "Désactivé" + +msgid "DISABLED" +msgstr "DÉSACTIVÉ" + +msgid "distributed, or modified under the terms of the" +msgstr "distribuée, ou modifiée selon les termes de" + +msgid "Don't Save" +msgstr "Ne pas sauver" + +msgid "Down" +msgstr "Bas" + +msgid "DOWN" +msgstr "BAS" + +msgid "Downloading..." +msgstr "Téléchargement en cours..." + +msgid "Dutch" +msgstr "Néerlandais" + +msgid "Empty or invalid ZIP file!" +msgstr "Fichier ZIP vide ou invalide !" + +msgid "Enabled" +msgstr "Activé" + +msgid "ENABLED" +msgstr "ACTIVÉ" + +msgid "English" +msgstr "Anglais" + +msgid "Error" +msgstr "Erreur" + +msgid "Error - Invalid ZIP file!" +msgstr "Erreur - Fichier ZIP invalide !" + +msgid "Error creating file!" +msgstr "Une erreur est survenue à la création du fichier !" + +msgid "Error loading game!" +msgstr "Erreur de chargement du jeu !" + +msgid "Error opening archive!" +msgstr "Erreur lors de l'ouverture de l'archive !" + +msgid "Error opening directory!" +msgstr "Erreur lors de l'ouverture du répertoire !" + +msgid "Error opening file!" +msgstr "Erreur lors de l'ouverture du fichier !" + +msgid "Error reading file!" +msgstr "Une erreur est survenue à la lecture du fichier !" + +msgid "Error saving file!" +msgstr "Erreur lors de la sauvegarde du fichier !" + +msgid "Exit" +msgstr "Sortir" + +msgid "Exit Action" +msgstr "Sortie de l'émulateur" + +msgid "Failed to connect to network share." +msgstr "La connection au partage réseau a échoué." + +msgid "FDS BIOS file is invalid!" +msgstr "Le fichier du BIOS du FDS (Famicom Disk System) est invalide !" + +msgid "FDS BIOS file not found!" +msgstr "Le fichier du BIOS du FDS (Famicom Disk System) est introuvable !" + +msgid "Filtered" +msgstr "Filtré" + +msgid "Filtering" +msgstr "Filtrage" + +msgid "Fire" +msgstr "Tirer" + +msgid "French" +msgstr "Français" + +msgid "GBA Screen Zoom" +msgstr "Zoom écran GBA" + +msgid "Game Genie ROM not found!" +msgstr "La ROM Game Genie est introuvable !" + +msgid "Game Settings" +msgstr "Configuration" + +msgid "Game Settings - Button Mappings" +msgstr "Configuration - Redéfinir les touches" + +msgid "Game Settings - Cheats" +msgstr "Configuration - Cheats" + +msgid "Game Settings - Video" +msgstr "Configuration - Vidéo" + +msgid "Game Timing" +msgstr "Timing du jeu" + +msgid "Game Genie DISABLED" +msgstr "Game Genie Désactivé" + +msgid "Game Genie ENABLED" +msgstr "Game Genie Activé" + +msgid "GameCube Controller" +msgstr "Manette Gamecube" + +msgid "German" +msgstr "Allemand" + +msgid "GNU General Public License (GPL) Version 2." +msgstr "la Licence Publique Générale (GPL) GNU Version 2." + +msgid "Go Back" +msgstr "Retour" + +msgid "Horizontal" +msgstr "Horizontal" + +msgid "Information" +msgstr "Information" + +msgid "Initializing network..." +msgstr "Initialisation du réseau en cours..." + +msgid "Insert Coin" +msgstr "Insérer une pièce" + +msgid "Insert Coin / Switch Disk" +msgstr "Insér. une pièce/Chang. disqtte" + +msgid "Invalid file size!" +msgstr "Taille du fichier invalide" + +msgid "Invalid game file!" +msgstr "Taille du fichier du jeu invalide" + +msgid "Invalid network settings - Check settings.xml." +msgstr "Paramètres réseau invalides - Veuillez vérifier le fichier settings.xml." + +msgid "Invalid network settings - Share IP is blank." +msgstr "Paramètres réseau invalides - L'IP partagée n'est pas renseignée." + +msgid "Invalid network settings - Share name is blank." +msgstr "Paramètres réseau invalides - Le nom du partage n'est pas renseigné." + +msgid "Invalid save file" +msgstr "Fichier de sauvegarde invalide" + +msgid "Invalid state file" +msgstr "Fichier de sauvegarde d'état invalide" + +msgid "Italian" +msgstr "Italien" + +msgid "Japanese" +msgstr "Japonais" + +msgid "Justifier" +msgstr "Konami Justifier" + +msgid "Justifier - GameCube Controller" +msgstr "Konami Justifier - Manette GameCube" + +msgid "Justifier - Wiimote" +msgstr "Konami Justifier - Wiimote" + +msgid "Korean" +msgstr "Coréen" + +msgid "L TRIG" +msgstr "L" + +msgid "Language" +msgstr "Langage" + +msgid "Languages Folder" +msgstr "Dossier des Langues" + +msgid "Left" +msgstr "Gauche" + +msgid "LEFT" +msgstr "GAUCHE" + +msgid "Left Button" +msgstr "Clic gauche" + +msgid "Load" +msgstr "Charger" + +msgid "Load Device" +msgstr "Périphérique d'entrée" + +msgid "Load Folder" +msgstr "Dossier des Jeux" + +msgid "Load Game" +msgstr "Charger une partie" + +msgid "Loading" +msgstr "Chargement" + +msgid "Loading DVD..." +msgstr "Chargement du DVD en cours..." + +msgid "Loading patch..." +msgstr "Chargement du patch en cours..." + +msgid "Loading..." +msgstr "Chargement en cours..." + +msgid "Main Menu" +msgstr "Menu Principal" + +msgid "Match GC Controls" +msgstr "Jouabilité GC identique" + +msgid "Match Wii Controls" +msgstr "Jouabilité Wii identique" + +msgid "Maximum filepath length reached!" +msgid "La longueur maximale du chemin d'accés est atteinte !" + +msgid "Menu" +msgstr "Menu" + +msgid "Menu artwork" +msgstr "Menu artwork" + +msgid "Menu sound" +msgstr "Menu Son" + +msgid "MINUS" +msgstr "MOINS" + +msgid "Music Volume" +msgstr "Volume de la Musique" + +msgid "Mute" +msgstr "Muet" + +msgid "NES Controller" +msgstr "Manette NES" + +msgid "NES Controllers (2)" +msgstr "Manettes NES (2)" + +msgid "NES Controllers (4)" +msgstr "Manettes NES (4)" + +msgid "NES Zapper" +msgstr "Nintendo Zapper" + +msgid "Network" +msgstr "Réseau" + +msgid "Network Share" +msgstr "Partage réseau" + +msgid "New" +msgstr "Nouvelle" + +msgid "New Snapshot" +msgstr "Nouvelle sauvegarde d'état" + +msgid "New SRAM" +msgstr "Nouvelle sauvegarde SRAM" + +msgid "No" +msgstr "Non" + +msgid "No data to save!" +msgstr "Pas de données (RAM) à sauvegarder !" + +msgid "No disc inserted!" +msgstr "Aucun disque inséré !" + +msgid "No SRAM data to save!" +msgstr "Pas de données SRAM à sauvegarder !" + +msgid "No game saves found." +msgstr "Aucune sauvegarde trouvée." + +msgid "None" +msgstr "Aucun" + +msgid "NTSC (480i)" +msgstr "NTSC (480i)" + +msgid "Nunchuk" +msgstr "Nunchuk" + +msgid "Off" +msgstr "Off" + +msgid "Official Site: http://code.google.com/p/fceugc/" +msgstr "Site Officiel: http://code.google.com/p/fceugc/" + +msgid "Official Site: http://code.google.com/p/snes9x-gx/" +msgstr "Site Officiel: http://code.google.com/p/snes9x-gx/" + +msgid "Official Site: http://code.google.com/p/vba-wii/" +msgstr "Site Officiel: http://code.google.com/p/vba-wii/" + +msgid "OK" +msgstr "OK" + +msgid "On" +msgstr "On" + +msgid "Original" +msgstr "Original" + +msgid "Out of memory!" +msgstr "Mémoire insuffisante !" + +msgid "Out of memory: too many files!" +msgstr "Mémoire insuffisante : trop de fichiers !" + +msgid "P1" +msgstr "J1" + +msgid "P2" +msgstr "J2" + +msgid "P3" +msgstr "J3" + +msgid "P4" +msgstr "J4" + +msgid "PAL (50Hz)" +msgstr "PAL (50Hz)" + +msgid "PAL (60Hz)" +msgstr "PAL (60Hz)" + +msgid "Palette saved" +msgstr "La palette est sauvegardée" + +msgid "Partial Stretch" +msgstr "Étirer partiellement" + +msgid "Pause" +msgstr "Pause" + +msgid "Please Wait" +msgstr "Veuillez patienter" + +msgid "PLUS" +msgstr "PLUS" + +msgid "Portuguese" +msgstr "Portugais" + +msgid "Power off Wii" +msgstr "Éteindre la Wii" + +msgid "Preferences saved" +msgstr "Les préférences ont été sauvegardés" + +msgid "Press any button on the Classic Controller now. Press Home to clear the existing mapping." +msgstr "Appuyer sur un bouton de la manette Classique. Appuyer sur HOME pour effacer le paramètre actuel." + +msgid "Press any button on the GameCube Controller now. Press Home or the C-Stick in any direction to clear the existing mapping." +msgstr "Presser un bouton de la manette Gamecube. Presser HOME ou le stick C pour effacer le paramètre actuel." + +msgid "Press any button on the GameCube Controller now. Press the C-Stick in any direction to clear the existing mapping." +msgstr "Presser un bouton de la manette Gamecube. Presser une direction du stick C pour effacer le paramètre actuel." + +msgid "Press any button on the Wiimote now. Press Home to clear the existing mapping." +msgstr "Presser un bouton de la Wiimote. Presser HOME pour effacer le paramètre actuel." + +msgid "Press any button on the Wiimote or Nunchuk now. Press Home to clear the existing mapping." +msgstr "Presser un bouton de la Wiimote ou du Nunchuk. Presser HOME pour effacer le paramètre actuel." + +msgid "Progressive (480p)" +msgstr "Progressif (480p)" + +msgid "Quit Game" +msgstr "Quitter le Jeu" + +msgid "Quit this game? Any unsaved progress will be lost." +msgstr "Quitter ce jeu ? Toute progression non sauvegardée sera perdue." + +msgid "R TRIG" +msgstr "R" + +msgid "RAM saving is not available for FDS games!" +msgstr "La sauvegarde RAM n'est pas disponible pour les jeux sur disquette (Famicom Disk System) !" + +msgid "Reboot" +msgstr "Redémarrer" + +msgid "Rendering" +msgstr "Rendu" + +msgid "Reset" +msgstr "Réinitialiser" + +msgid "Reset Game" +msgstr "Réinitialiser le Jeu" + +msgid "Reset this game? Any unsaved progress will be lost." +msgstr "Redémarrer ce jeu ? Toute progression non sauvegardée sera perdue." + +msgid "Reset Mappings" +msgstr "Réinit. les touches" + +msgid "Reset Settings" +msgstr "Réinitialiser" + +msgid "Retry" +msgstr "Réessayer" + +msgid "Return to Loader" +msgstr "Retourner au Loader" + +msgid "Return to Wii Menu" +msgstr "Retourner au Menu Wii" + +msgid "Right" +msgstr "Droite" + +msgid "RIGHT" +msgstr "DROITE" + +msgid "Right Button" +msgstr "Clic droit" + +msgid "Rumble" +msgstr "Vibration" + +msgid "Save" +msgstr "Sauver" + +msgid "Save Device" +msgstr "Périph. de sauvegarde" + +msgid "Save failed!" +msgstr "La sauvegarde a échoué !" + +msgid "Save file not found" +msgstr "Pas de fichier de sauvegarde trouvé" + +msgid "Save Folder" +msgstr "Dossier des sauv." + +msgid "Save Game" +msgstr "Sauvegarder la partie" + +msgid "Save RAM and State?" +msgstr "Sauver la RAM et la position du jeu (sauvegarde d'état) ?" + +msgid "Save Snapshot?" +msgstr "Sauver la position du jeu (sauvegarde d'état) ?" + +msgid "Save SRAM and Snapshot?" +msgstr "Sauver la SRAM et la position du jeu (sauvegarde d'état) ?" + +msgid "Save State?" +msgstr "Sauver la position du jeu (sauvegarde d'état) ?" + +msgid "Save successful" +msgstr "Sauvegarde réussie" + +msgid "Saving" +msgstr "Sauvegarde" + +msgid "Saving preferences..." +msgstr "Sauvegarde des préférences en cours..." + +msgid "Saving..." +msgstr "Sauvegarde en cours..." + +msgid "Scaling" +msgstr "Format" + +msgid "Screen Position" +msgstr "Position de l'écran" + +msgid "Screen Zoom" +msgstr "Zoom écran" + +msgid "Select" +msgstr "Select" + +msgid "Seek error!" +msgstr "Erreur de positionnement ! (seek error)" + +msgid "Settings" +msgstr "Paramètres" + +msgid "Settings - Menu" +msgstr "Paramètres - Menu" + +msgid "Settings - Network" +msgstr "Paramètres - Réseau" + +msgid "Settings - Saving & Loading" +msgstr "Paramètres - Sauvegarde & Chargement" + +msgid "SD Card" +msgstr "Carte SD" + +msgid "SD card not found!" +msgstr "Carte SD introuvable !" + +msgid "Shift" +msgstr "Maj" + +msgid "Simp_chinese" +msgstr "Chinois simplifié" + +msgid "SMB Share IP" +msgstr "IP partagée SMB" + +msgid "SMB Share Name" +msgstr "Nom du Partage SMB" + +msgid "SMB Share Password" +msgstr "Mot de passe de partage SMB" + +msgid "SMB Share Username" +msgstr "Nom d'utilisateur de partage SMB" + +msgid "Snapshot" +msgstr "Sauvegarde d'état" + +msgid "Snapshot (Auto)" +msgstr "Sauv. d'état (Auto)" + +msgid "SNES Controller" +msgstr "Manette SNES" + +msgid "SNES Controllers (2)" +msgstr "Manettes SNES (2)" + +msgid "SNES Controllers (4)" +msgstr "Manettes SNES (4)" + +msgid "SNES Controller - Classic Controller" +msgstr "Manette SNES - Manette Classique" + +msgid "SNES Controller - GameCube Controller" +msgstr "Manette SNES - Manette GameCube" + +msgid "SNES Controller - Nunchuk + Wiimote" +msgstr "Manette SNES - Nunchuk + Wiimote" + +msgid "SNES Controller - Wiimote" +msgstr "Manette SNES - Wiimote" + +msgid "SNES Mouse" +msgstr "Souris SNES" + +msgid "SNES Mouse - GameCube Controller" +msgstr "Souris SNES - Manette GameCube" + +msgid "SNES Mouse - Wiimote" +msgstr "Souris SNES - Wiimote" + +msgid "Snes9x - Copyright (c) Snes9x Team 1996 - 2006" +msgstr "Snes9x - Copyright (c) Snes9x Team 1996 - 2006" + +msgid "Sound Effects Volume" +msgstr "Volume des effets sonores" + +msgid "Spanish" +msgstr "Espagnol" + +msgid "Sprite Limit" +msgstr "Limite de Sprites" + +msgid "SRAM file not found" +msgstr "Pas de sauvegarde SRAM trouvée" + +msgid "State" +msgstr "Sauvegarde d'état" + +msgid "State (Auto)" +msgstr "Sauv. d'état (Auto)" + +msgid "State file not found" +msgstr "Pas de sauvegarde d'état trouvée" + +msgid "Stretch to Fit" +msgstr "Étirer au ratio de l'écran" + +msgid "Superscope" +msgstr "Super Scope" + +msgid "Superscope - GameCube Controller" +msgstr "Super Scope - Manette GameCube" + +msgid "Superscope - Wiimote" +msgstr "Super Scope - Wiimote" + +msgid "The current IOS has been altered (fake-signed). Functionality and/or stability may be adversely affected." +msgstr "L'IOS utilisé est altéré (fausse signature, Bug Trucha). Les fonctionnalités et/ou la stabilité peuvent en être affectées." + +msgid "The current IOS is unsupported. Functionality and/or stability may be adversely affected." +msgstr "L'IOS utilisé n'est pas supporté. Les fonctionnalités et/ou la stabilité peuvent en être affectées." + +msgid "This software is open source and may be copied," +msgstr "Cette application est libre et peut être copiée," + +msgid "Trad_chinese" +msgstr "Chinois traditionnel" + +msgid "Unable to initialize network!" +msgstr "Impossible d'initialiser le réseau !" + +msgid "Unable to locate a load device!" +msgstr "Périphérique d'entrée introuvable !" + +msgid "Unable to locate a save device!" +msgstr "Périphérique de sauvegarde introuvable !" + +msgid "Unable to open snapshot!" +msgstr "Impossible d'ouvrir la sauvegarde d'état" + +msgid "Unfiltered" +msgstr "Non-filtré" + +msgid "Unknown file type!" +msgstr "Type de fichier inconnu !" + +msgid "Unrecognized DVD format." +msgstr "Format du DVD inconnu." + +msgid "Unrecognized file extension!" +msgstr "L'extension du fichier est inconnu !" + +msgid "Unzipping..." +msgstr "Extraction de l'archive en cours..." + +msgid "Up" +msgstr "Haut" + +msgid "UP" +msgstr "HAUT" + +msgid "Up One Level" +msgstr "Dossier Parent" + +msgid "Update Available" +msgstr "Une mise à jour est disponible" + +msgid "Update failed!" +msgstr "La mise à jour a échouée !" + +msgid "Update later" +msgstr "Mettre à jour plus tard" + +msgid "Update now" +msgstr "Mettre à jour maintenant" + +msgid "Update successful!" +msgstr "La mise à jour a réussie !" + +msgid "USB drive not found!" +msgstr "Aucun disque USB n'a été trouvé !" + +msgid "USB Mass Storage" +msgstr "Périphérique de stockage USB" + +msgid "Vertical" +msgstr "Vertical" + +msgid "Video" +msgstr "Vidéo" + +msgid "Video Mode" +msgstr "Mode Vidéo" + +msgid "VM8: Unknown page type!" +msgstr "VM8 : Type de page inconnu !" + +msgid "VM16: Unknown page type!" +msgstr "VM16 : Type de page inconnu !" + +msgid "VM32: Unknown page type!" +msgstr "VM32 : Type de page inconnu !" + +msgid "Wiimote" +msgstr "Wiimote" + +msgid "Wiimote Orientation" +msgstr "Orientation de la Wiimote" + +msgid "Yes" +msgstr "Oui" + +msgid "Zapper" +msgstr "Nintendo Zapper" + +msgid "Zapper Crosshair" +msgstr "Réticule du Zapper" diff --git a/plugins/snes9x_gx/source/lang/it.lang b/plugins/snes9x_gx/source/lang/it.lang new file mode 100644 index 00000000..897855b2 --- /dev/null +++ b/plugins/snes9x_gx/source/lang/it.lang @@ -0,0 +1,917 @@ +msgid "&" +msgstr "&" + +msgid "16:9 Correction" +msgstr "Correzione 16:9" + +msgid "7z decompression failed: Archive contains too many files" +msgstr "7z decompressione fallita: L'archivio contiene troppi file" + +msgid "7z decompression failed: Failed to read file data" +msgstr "7z decompressione fallita: Fallimento nella lettura del file" + +msgid "7z decompression failed: File is corrupt" +msgstr "7z decompressione fallita: File corrotto" + +msgid "7z decompression failed: File is corrupt (CRC mismatch)" +msgstr "7z decompressione fallita: File corrotto (il CRC non coincide)" + +msgid "7z decompression failed: File uses too high of compression settings (dictionary size is too large)" +msgstr "7z decompressione fallita: Il file utilizza una compressione troppo alta (dimensione del dizionario troppo grosso)" + +msgid "7z decompression failed: File uses unsupported compression settings" +msgstr "7z decompressione fallita: Il file utilizza un impostazione di compressione sconosciuta" + +msgid "A (Rapid)" +msgstr "A (Rapido)" + +msgid "Additional coding" +msgstr "Codice supplementare" + +msgid "Aim Offscreen" +msgstr "Obiettivo Fuoricampo" + +msgid "An update is available!" +msgstr "Aggiornamento disponibile!" + +msgid "Are you sure that you want to reset this game? Any unsaved progress will be lost." +msgstr "Sei sicuro di voler resettare il gioco? Tutti i progressi non salvati verranno perduti." + +msgid "Are you sure that you want to reset your mappings?" +msgstr "Sei sicuro di voler resettare le tue mappature?" + +msgid "Are you sure that you want to reset your settings?" +msgstr "Sei sicuro di voler resettare le tue impostazioni?" + +msgid "Maintain Aspect Ratio" +msgstr "Mantieni Ascpect Ratio (Rapporto)" + +msgid "Attempting to determine load device..." +msgstr "Cercando di determinare la periferica di caricamento..." + +msgid "Attempting to determine save device..." +msgstr "Cercando di determinare la periferica di salvataggio..." + +msgid "Auto" +msgstr "Automatico" + +msgid "Auto Detect" +msgstr "Individuazione Automatica" + +msgid "Auto Load" +msgstr "Caricamento Automatico" + +msgid "Auto Save" +msgstr "Salvataggio Automatico" + +msgid "Automatic (Recommended)" +msgstr "Automatico (Raccomandato)" + +msgid "B (Rapid)" +msgstr "B (Rapido)" + +msgid "Back" +msgstr "" + +msgid "Both" +msgstr "Entrambi" + +msgid "Controles" +msgstr "Controlli" + +msgid "Button Mapping" +msgstr "Mappatura Pulsanti" + +msgid "Button Mappings" +msgstr "Mappature Pulsanti" + +msgid "Cancel" +msgstr "Annulla" + +msgid "Caps" +msgstr "" + +msgid "Cheats" +msgstr "Cheat" + +msgid "Cheats file not found!" +msgstr "File Cheat non trovato!" + +msgid "Cheats Folder" +msgstr "Cartella Cheat" + +msgid "Choose Game" +msgstr "Scelta Gioco" + +msgid "Classic Controller" +msgstr "Controller Tradizionale" + +msgid "Close" +msgstr "Chiudi" + +msgid "Coding" +msgstr "Programmazione" + +msgid "Coding & menu design" +msgstr "Programmazione e design del menù" + +msgid "Compressed GBA files are not supported!" +msgstr "I file GBA compressi non sono supportati!" + +msgid "Connecting to network share..." +msgstr "Collegandosi alla rete.." + +msgid "Controller" +msgstr "" + +msgid "Cover View" +msgstr "Vista Cover" + +msgid "Covers Folder" +msgstr "Cartella Cover" + +msgid "Credits" +msgstr "Crediti" + +msgid "Cropping" +msgstr "Ritaglio" + +msgid "Crosshair" +msgstr "Mirino" + +msgid "Cursor" +msgstr "Cursore" + +msgid "Data DVD" +msgstr "DVD Dati" + +msgid "Default" +msgstr "Default" + +msgid "Directory name is too long!" +msgstr "Nome della Cartella troppo lungo!" + +msgid "Disabled" +msgstr "Disabilitato" + +msgid "DISABLED" +msgstr "DISABILITATO" + +msgid "distributed, or modified under the terms of the" +msgstr "distribuito o modificato nei termini de" + +msgid "Don't Save" +msgstr "Non Salvare" + +msgid "Down" +msgstr "Giù" + +msgid "DOWN" +msgstr "GIU'" + +msgid "Downloading..." +msgstr "Scaricando..." + +msgid "Dutch" +msgstr "Olandese" + +msgid "Empty or invalid ZIP file!" +msgstr "File ZIP vuoto o non valido!" + +msgid "Enabled" +msgstr "Abilitato" + +msgid "ENABLED" +msgstr "ABILITATO" + +msgid "English" +msgstr "Inglese" + +msgid "Error" +msgstr "Errore" + +msgid "Error - Invalid ZIP file!" +msgstr "Errore - File ZIP non valido!" + +msgid "Error creating file!" +msgstr "Errore nella creazione del file!" + +msgid "Error loading game!" +msgstr "Errore nel caricamento del gioco!" + +msgid "Error opening archive!" +msgstr "Errore nell'apertura dell'archivio!" + +msgid "Error opening directory!" +msgstr "Errore nell'apertura della cartella!" + +msgid "Error opening file!" +msgstr "Errore nell'apertura del file!" + +msgid "Error reading file!" +msgstr "Errore nella lettura del file!" + +msgid "Error saving file!" +msgstr "Errore nel salvataggio del file!" + +msgid "Exit" +msgstr "Esci" + +msgid "Exit Action" +msgstr "Uscita" + +msgid "Failed to connect to network share." +msgstr "Connessione alla rete fallita." + +msgid "FDS BIOS file is invalid!" +msgstr "File BIOS FDS non valido!" + +msgid "FDS BIOS file not found!" +msgstr "File BIOS FDS non trovato!" + +msgid "Filtered" +msgstr "Filtrato" + +msgid "Filtering" +msgstr "Filtrando" + +msgid "Fire" +msgstr "Fuoco" + +msgid "French" +msgstr "Francese" + +msgid "GBA Screen Zoom" +msgstr "GBA Zoom Schermo" + +msgid "Game Genie ROM not found!" +msgstr "ROM Game Genie non trovata!" + +msgid "Game Settings" +msgstr "Impostazioni di Gioco" + +msgid "Game Settings - Button Mappings" +msgstr "Impostazioni di Gioco - Mappature pulsanti" + +msgid "Game Settings - Cheats" +msgstr "Impostazioni di Gioco - Cheat" + +msgid "Game Settings - Video" +msgstr "Impostazioni di Gioco - Video" + +msgid "Game Timing" +msgstr "Sincranizzazione di Gioco" + +msgid "Game Genie DISABLED" +msgstr "Game Genie DISABILITATO" + +msgid "Game Genie ENABLED" +msgstr "Game Genie ABILITATO" + +msgid "GameCube Controller" +msgstr "" + +msgid "German" +msgstr "Tedesco" + +msgid "GNU General Public License (GPL) Version 2." +msgstr "GNU General Public License (GPL) Version 2." + +msgid "Go Back" +msgstr "Torna Indietro" + +msgid "Horizontal" +msgstr "Orizzontale" + +msgid "Information" +msgstr "Informazione" + +msgid "Initializing network..." +msgstr "Inizializzando la rete..." + +msgid "Insert Coin" +msgstr "" + +msgid "Insert Coin / Switch Disk" +msgstr "Insert Coin / Cambia Disco" + +msgid "Invalid file size!" +msgstr "Dimensione del file non valida!" + +msgid "Invalid game file!" +msgstr "File di gioco non valido!" + +msgid "Invalid network settings - Check settings.xml." +msgstr "Impostazioni di rete non valide - Verificare settings.xml." + +msgid "Invalid network settings - Share IP is blank." +msgstr "Impostazioni di rete non valide - Campo IP Condivisione vuoto." + +msgid "Invalid network settings - Share name is blank." +msgstr "Impostazioni di rete non valide - Campo Nome Condivisione vuoto." + +msgid "Invalid save file" +msgstr "File di salvataggio non valido" + +msgid "Invalid state file" +msgstr "FIle di stato non valido" + +msgid "Italian" +msgstr "Italiano" + +msgid "Japanese" +msgstr "Giapponese" + +msgid "Justifier" +msgstr "Giustificato" + +msgid "Justifier - GameCube Controller" +msgstr "Giustificato - GameCube Controller" + +msgid "Justifier - Wiimote" +msgstr "Giustificato - Wiimote" + +msgid "Korean" +msgstr "Coreano" + +msgid "L TRIG" +msgstr "TASTO L" + +msgid "Language" +msgstr "Lingua" + +msgid "Languages Folder" +msgstr "Cartella Lingue" + +msgid "Left" +msgstr "Sinistra" + +msgid "LEFT" +msgstr "SINISTRA" + +msgid "Left Button" +msgstr "Pulsante Sinistro" + +msgid "Load" +msgstr "Carica" + +msgid "Load Device" +msgstr "Periferica di Caricamento" + +msgid "Load Folder" +msgstr "Cartella di Caricamento" + +msgid "Load Game" +msgstr "Carica Gioco" + +msgid "Loading" +msgstr "Caricando" + +msgid "Loading DVD..." +msgstr "Caricando DVD..." + +msgid "Loading patch..." +msgstr "Caricando patch..." + +msgid "Loading..." +msgstr "Caricando..." + +msgid "Main Menu" +msgstr "Menù Principale" + +msgid "Match GC Controls" +msgstr "Identico Controlli GC" + +msgid "Match Wii Controls" +msgstr "Identico Controlli Wii" + +msgid "Menu" +msgstr "Menù" + +msgid "Menu artwork" +msgstr "Menù Artwork" + +msgid "Menu sound" +msgstr "Menù Audio" + +msgid "MINUS" +msgstr "MENO" + +msgid "Music Volume" +msgstr "Volume Musica" + +msgid "Mute" +msgstr "Muto" + +msgid "NES Controller" +msgstr "" + +msgid "NES Controllers (2)" +msgstr "NES Controller (2)" + +msgid "NES Controllers (4)" +msgstr "NES Controller (4)" + +msgid "NES Zapper" +msgstr "" + +msgid "Network" +msgstr "Rete" + +msgid "Network Share" +msgstr "Condivisione Rete" + +msgid "New" +msgstr "Nuovo" + +msgid "New Snapshot" +msgstr "Nuovo Snapshot" + +msgid "New SRAM" +msgstr "Nuova SRAM" + +msgid "No" +msgstr "No" + +msgid "No data to save!" +msgstr "Nessun dato da salvare!" + +msgid "No disc inserted!" +msgstr "Disco non inserito!" + +msgid "No SRAM data to save!" +msgstr "Nessuna SRAM dove salvare!" + +msgid "No game saves found." +msgstr "Nessun salvataggio trovato." + +msgid "None" +msgstr "Nessuno" + +msgid "NTSC (480i)" +msgstr "" + +msgid "Nunchuk" +msgstr "Nunchuk" + +msgid "Off" +msgstr "Off" + +msgid "Official Site: http://code.google.com/p/fceugc/" +msgstr "Sito Ufficiale: http://code.google.com/p/fceugc/" + +msgid "Official Site: http://code.google.com/p/snes9x-gx/" +msgstr "Sito Ufficiale: http://code.google.com/p/snes9x-gx/" + +msgid "Official Site: http://code.google.com/p/vba-wii/" +msgstr "Sito Ufficiale: http://code.google.com/p/vba-wii/" + +msgid "OK" +msgstr "" + +msgid "On" +msgstr "" + +msgid "Original" +msgstr "Originale" + +msgid "Out of memory!" +msgstr "Memoria esaurita!" + +msgid "Out of memory: too many files!" +msgstr "Memoria esaurita: troppo file!" + +msgid "P1" +msgstr "" + +msgid "P2" +msgstr "" + +msgid "P3" +msgstr "" + +msgid "P4" +msgstr "" + +msgid "PAL (50Hz)" +msgstr "" + +msgid "PAL (60Hz)" +msgstr "" + +msgid "Palette saved" +msgstr "Palette salvata" + +msgid "Partial Stretch" +msgstr "Stretch Parziale" + +msgid "Pause" +msgstr "Pausa" + +msgid "Please Wait" +msgstr "Attendere Prego" + +msgid "PLUS" +msgstr "PIU'" + +msgid "Portuguese" +msgstr "Portoghese" + +msgid "Power off Wii" +msgstr "Spegnimento Wii" + +msgid "Preferences saved" +msgstr "Preferenze salvate" + +msgid "Press any button on the Classic Controller now. Press Home to clear the existing mapping." +msgstr "Premi un pulsante del Controller Tradizionale ora. Premi Home per pulire la mappatura esistente." + +msgid "Press any button on the GameCube Controller now. Press Home or the C-Stick in any direction to clear the existing mapping." +msgstr "Premi un pulsante del GameCube Controller ora. Premi Home o sposta il C-Stick per pulire la mappatura esistente." + +msgid "Press any button on the GameCube Controller now. Press the C-Stick in any direction to clear the existing mapping." +msgstr "Premi un pulsante del GameCube Controller ora. Sposta il C-Stick per pulire la mappatura esistente." + +msgid "Press any button on the Wiimote now. Press Home to clear the existing mapping." +msgstr "Premi un pulsante del Wiimote ora. Premi Home per pulire la mappatura esistente." + +msgid "Press any button on the Wiimote or Nunchuk now. Press Home to clear the existing mapping." +msgstr "Premi un pulsante del Wiimote o del Nunchuk ora. Premi Home per pulire la mappatura esistente." + +msgid "Progressive (480p)" +msgstr "Progressiva (480p)" + +msgid "Quit Game" +msgstr "Termina" + +msgid "Quit this game? Any unsaved progress will be lost." +msgstr "Terminare il gioco? Tutti i progressi saranno perduti." + +msgid "R TRIG" +msgstr "TASTO R" + +msgid "RAM saving is not available for FDS games!" +msgstr "Il salvataggio della RAM non è disponibile per i giochi FDS!" + +msgid "Reboot" +msgstr "" + +msgid "Rendering" +msgstr "Rendering" + +msgid "Reset" +msgstr "Reset" + +msgid "Reset Game" +msgstr "Resetta" + +msgid "Reset this game? Any unsaved progress will be lost." +msgstr "Resettare il gioco? Tutti i progressi saranno perduti." + +msgid "Reset Mappings" +msgstr "Resetta Mappatura" + +msgid "Reset Settings" +msgstr "Resetta Impostazioni" + +msgid "Retry" +msgstr "Ritenta" + +msgid "Return to Loader" +msgstr "Ritorna al Loader" + +msgid "Return to Wii Menu" +msgstr "Ritorna al Menù Wii" + +msgid "Right" +msgstr "Destra" + +msgid "RIGHT" +msgstr "DESTRA" + +msgid "Right Button" +msgstr "Pulsante Destro" + +msgid "Rumble" +msgstr "Vibrazione" + +msgid "Save" +msgstr "Salva" + +msgid "Save Device" +msgstr "Periferica Salvataggio" + +msgid "Save failed!" +msgstr "Salvataggio fallito!" + +msgid "Save file not found" +msgstr "File di salvataggio non trovato" + +msgid "Save Folder" +msgstr "Cartella Salvataggio" + +msgid "Save Game" +msgstr "Salvataggio" + +msgid "Save RAM and State?" +msgstr "Salvare RAM e STATO?" + +msgid "Save Snapshot?" +msgstr "Salvare Snapshot?" + +msgid "Save SRAM and Snapshot?" +msgstr "Salvare SRAM e Snapshot?" + +msgid "Save State?" +msgstr "" + +msgid "Save successful" +msgstr "Salvato con successo" + +msgid "Saving" +msgstr "Salvando" + +msgid "Saving preferences..." +msgstr "Salvando le preferenze..." + +msgid "Saving..." +msgstr "Salvando..." + +msgid "Scaling" +msgstr "Scalettatura" + +msgid "Screen Position" +msgstr "Posizione Schermo" + +msgid "Screen Zoom" +msgstr "Zoom Schermo" + +msgid "Select" +msgstr "" + +msgid "Seek error!" +msgstr "Errore di ricerca!" + +msgid "Settings" +msgstr "Impostazioni" + +msgid "Settings - Menu" +msgstr "Impostazioni - Menu" + +msgid "Settings - Network" +msgstr "Impostazioni - Rete" + +msgid "Settings - Saving & Loading" +msgstr "Impostazioni - Salvataggio e Caricamento" + +msgid "SD Card" +msgstr "Scheda SD" + +msgid "SD card not found!" +msgstr "Scheda SD non trovata!" + +msgid "Shift" +msgstr "" + +msgid "Simp_chinese" +msgstr "Cinese Semplificato" + +msgid "SMB Share IP" +msgstr "SMB IP Condivisione" + +msgid "SMB Share Name" +msgstr "SMB Nome Condivisione" + +msgid "SMB Share Password" +msgstr "SMB Password Condivisione" + +msgid "SMB Share Username" +msgstr "SMB Username Condivisione" + +msgid "Snapshot" +msgstr "" + +msgid "Snapshot (Auto)" +msgstr "" + +msgid "SNES Controller" +msgstr "" + +msgid "SNES Controllers (2)" +msgstr "SNES Controller (4)" + +msgid "SNES Controllers (4)" +msgstr "SNES Controller (4)" + +msgid "SNES Controller - Classic Controller" +msgstr "SNES Controller - Controller Tradizionale" + +msgid "SNES Controller - GameCube Controller" +msgstr "" + +msgid "SNES Controller - Nunchuk + Wiimote" +msgstr "" + +msgid "SNES Controller - Wiimote" +msgstr "" + +msgid "SNES Mouse" +msgstr "" + +msgid "SNES Mouse - GameCube Controller" +msgstr "" + +msgid "SNES Mouse - Wiimote" +msgstr "" + +msgid "Snes9x - Copyright (c) Snes9x Team 1996 - 2006" +msgstr "" + +msgid "Sound Effects Volume" +msgstr "Volume Effetti Sonori" + +msgid "Spanish" +msgstr "Spagnolo" + +msgid "Sprite Limit" +msgstr "Limite Sprite" + +msgid "SRAM file not found" +msgstr "File SRAM non trovato" + +msgid "Start" +msgstr "" + +msgid "State" +msgstr "Stato" + +msgid "State (Auto)" +msgstr "Stato (Auto)" + +msgid "State file not found" +msgstr "File di stato non trovato" + +msgid "Stretch to Fit" +msgstr "Allunga per Adattare" + +msgid "Super Scope" +msgstr "" + +msgid "Superscope" +msgstr "" + +msgid "Superscope - GameCube Controller" +msgstr "" + +msgid "Superscope - Wiimote" +msgstr "" + +msgid "This software is open source and may be copied," +msgstr "Questo software è open source e può essere copiato," + +msgid "Trad_chinese" +msgstr "Cinese Tradotto" + +msgid "Unable to initialize network!" +msgstr "Impossibile inizializzare la rete!" + +msgid "Unable to locate a load device!" +msgstr "Impossibile localizzare una periferica di caricamento!" + +msgid "Unable to locate a save device!" +msgstr "Impossibile localizzare una periferica di salvataggio!" + +msgid "Unable to open snapshot!" +msgstr "Impossibile aprire lo snapshot!" + +msgid "Unfiltered" +msgstr "Non filtrato!" + +msgid "Unknown file type!" +msgstr "Tipo di file sconosciuto!" + +msgid "Unrecognized DVD format." +msgstr "Formato DVD non riconosciuto!" + +msgid "Unrecognized file extension!" +msgstr "Estensione file non riconosciuta!" + +msgid "Up" +msgstr "Su" + +msgid "UP" +msgstr "SU" + +msgid "Up One Level" +msgstr "Livello superiore" + +msgid "Update Available" +msgstr "Aggiornamento Disponibile" + +msgid "Update failed!" +msgstr "Aggiornamento fallito!" + +msgid "Update later" +msgstr "Aggiorna più tardi" + +msgid "Update now" +msgstr "Aggiorna ora" + +msgid "Update successful!" +msgstr "Aggiornamento effettuato!" + +msgid "USB drive not found!" +msgstr "Disco USB non trovato!" + +msgid "USB Mass Storage" +msgstr "Memoria di Massa USB" + +msgid "Vertical" +msgstr "Verticale" + +msgid "Video" +msgstr "" + +msgid "Video Mode" +msgstr "Modalità Video" + +msgid "VM8: Unknown page type!" +msgstr "VM8: Tipo di pagina sconosciuta!" + +msgid "VM16: Unknown page type!" +msgstr "VM16: Tipo di pagina sconosciuta!" + +msgid "VM32: Unknown page type!" +msgstr "VM32: Tipo di pagina sconosciuta!" + +msgid "Wiimote" +msgstr "" + +msgid "Wiimote Orientation" +msgstr "Orientamento Wiimote" + +msgid "Yes" +msgstr "Si" + +msgid "Zapper" +msgstr "" + +msgid "Zapper Crosshair" +msgstr "Mirino Zapper" + +msgid "Logo" +msgstr "" + +msgid "Turbo On" +msgstr "" + +msgid "Turbo Off" +msgstr "" + +msgid "Automatic" +msgstr "Automatico" + +msgid "Palette" +msgstr "Paletta" + +msgid "AspiringSquire's Real palette" +msgstr "" + +msgid "Loopy's palette" +msgstr "" + +msgid "Quor's palette" +msgstr "" + +msgid "Chris Covell's palette" +msgstr "" + +msgid "Matthew Conte's palette" +msgstr "" + +msgid "PasoFami/99 palette" +msgstr "" + +msgid "CrashMan's palette" +msgstr "" + +msgid "MESS palette" +msgstr "" + +msgid "Zaphod's VS Castlevania palette" +msgstr "" + +msgid "Zaphod's VS SMB palette" +msgstr "" + +msgid "VS Dr. Mario palette" +msgstr "" + +msgid "VS Castlevania palette" +msgstr "" + +msgid "VS SMB/VS Ice Climber palette" +msgstr "" + +msgid "And many others who have contributed over the years!" +msgstr "E tutti quelli che hanno contribuito negli anni!" diff --git a/plugins/snes9x_gx/source/lang/jp.lang b/plugins/snes9x_gx/source/lang/jp.lang new file mode 100644 index 00000000..7508395c --- /dev/null +++ b/plugins/snes9x_gx/source/lang/jp.lang @@ -0,0 +1,935 @@ +msgid "&" +msgstr "&" + +msgid "16:9 Correction" +msgstr "16:9補正" + +msgid "7z decompression failed: Archive contains too many files" +msgstr "書庫内ã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒå¤šã™ãŽã§ã™" + +msgid "7z decompression failed: Failed to read file data" +msgstr "読ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ" + +msgid "7z decompression failed: File is corrupt" +msgstr "ファイルãŒç ´æã—ã¦ã„ã¾ã™" + +msgid "7z decompression failed: File is corrupt (CRC mismatch)" +msgstr "ファイルãŒç ´æã—ã¦ã„ã¾ã™(CRCä¸ä¸€è‡´)" + +msgid "7z decompression failed: File uses too high of compression settings (dictionary size is too large)" +msgstr "書庫ã®ã‚µã‚¤ã‚ºãŒå¤šãã™ãŽã§ã™" + +msgid "7z decompression failed: File uses unsupported compression settings" +msgstr "未対応ã®åœ§ç¸®è¨­å®šãŒä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™" + +msgid "A (Rapid)" +msgstr "A (連打)" + +msgid "Additional coding" +msgstr "追加コーディング" + +msgid "Aim Offscreen" +msgstr "照準をéžè¡¨ç¤º" + +msgid "An update is available!" +msgstr "æ›´æ–°ãŒã‚ã‚Šã¾ã™" + +msgid "Are you sure that you want to reset this game? Any unsaved progress will be lost." +msgstr "未ä¿å­˜ã®ãƒ‡ãƒ¼ã‚¿ã¯å¤±ã‚ã‚Œã¾ã™" + +msgid "Are you sure that you want to reset your mappings?" +msgstr "設定をåˆæœŸåŒ–ã—ã¾ã™ã‹?" + +msgid "Are you sure that you want to reset your settings?" +msgstr "設定をåˆæœŸåŒ–ã—ã¾ã™ã‹?" + +msgid "Maintain Aspect Ratio" +msgstr "アスペクト比を維æŒ" + +msgid "Attempting to determine load device..." +msgstr "デãƒã‚¤ã‚¹ã‚’試ã—ã¦ã„ã¾ã™â€¦" + +msgid "Attempting to determine save device..." +msgstr "デãƒã‚¤ã‚¹ã‚’試ã—ã¦ã„ã¾ã™â€¦" + +msgid "Auto" +msgstr "自動" + +msgid "Auto Detect" +msgstr "自動検出" + +msgid "Auto Load" +msgstr "自動ロード" + +msgid "Auto Save" +msgstr "自動セーブ" + +msgid "Automatic" +msgstr "自動" + +msgid "Automatic (Recommended)" +msgstr "自動(ãŠã™ã™ã‚)" + +msgid "B (Rapid)" +msgstr "B (連打)" + +msgid "Back" +msgstr "" + +msgid "Both" +msgstr "両方" + +msgid "Controles" +msgstr "æ“作" + +msgid "Button Mapping" +msgstr "ボタン設定" + +msgid "Button Mappings" +msgstr "ボタン設定" + +msgid "Cancel" +msgstr "キャンセル" + +msgid "Caps" +msgstr "" + +msgid "Cheats" +msgstr "改造コード" + +msgid "Cheats file not found!" +msgstr "改造コードãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + +msgid "Cheats Folder" +msgstr "改造コードフォルダ" + +msgid "Choose Game" +msgstr "ゲームをé¸æŠžã—ã¦ãã ã•ã„" + +msgid "Classic Controller" +msgstr "クラコン" + +msgid "Close" +msgstr "ã¨ã˜ã‚‹" + +msgid "Coding" +msgstr "設計" + +msgid "Coding & menu design" +msgstr "設計ã¨ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã®ãƒ‡ã‚¶ã‚¤ãƒ³" + +msgid "Compressed GBA files are not supported!" +msgstr "圧縮ã•ã‚ŒãŸGBAファイルã¯æœªå¯¾å¿œã§ã™" + +msgid "Connecting to network share..." +msgstr "接続ã—ã¦ã„ã¾ã™" + +msgid "Controller" +msgstr "コントローラ" + +msgid "Cover View" +msgstr "ã‚«ãƒãƒ¼ã‚’表示" + +msgid "Covers Folder" +msgstr "ã‚«ãƒãƒ¼ãƒ•ã‚©ãƒ«ãƒ€" + +msgid "Credits" +msgstr "æ供・å”力" + +msgid "Cropping" +msgstr "トリミング" + +msgid "Crosshair" +msgstr "å字ボタン" + +msgid "Cursor" +msgstr "カーソル" + +msgid "Data DVD" +msgstr "データDVD" + +msgid "Default" +msgstr "åˆæœŸå€¤" + +msgid "Directory name is too long!" +msgstr "フォルダåãŒé•·ã™ãŽã§ã™" + +msgid "Disabled" +msgstr "無効" + +msgid "DISABLED" +msgstr "無効" + +msgid "distributed, or modified under the terms of the" +msgstr "以下ã®æ¡ä»¶ã®ä¸‹ã§é…布ã€å¤‰æ›´ã•ã‚Œã¦ã„ã¾ã™" + +msgid "Don't Save" +msgstr "セーブã—ãªã„" + +msgid "Down" +msgstr "下" + +msgid "DOWN" +msgstr "下" + +msgid "Downloading..." +msgstr "ダウンロード中…" + +msgid "Dutch" +msgstr "ドイツ語" + +msgid "Empty or invalid ZIP file!" +msgstr "ä¸æ­£ãªZIPファイルã§ã™" + +msgid "Enabled" +msgstr "有効" + +msgid "ENABLED" +msgstr "有効" + +msgid "English" +msgstr "英語" + +msgid "Error" +msgstr "エラー" + +msgid "Error - Invalid ZIP file!" +msgstr "ä¸æ­£ãªZIPã§ã™" + +msgid "Error creating file!" +msgstr "作æˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" + +msgid "Error loading game!" +msgstr "読ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" + +msgid "Error opening archive!" +msgstr "解å‡ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" + +msgid "Error opening directory!" +msgstr "é–‹ã途中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" + +msgid "Error opening file!" +msgstr "é–‹ã„ã¦ã„る途中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" + +msgid "Error reading file!" +msgstr "読ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" + +msgid "Error saving file!" +msgstr "セーブ中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" + +msgid "Exit" +msgstr "終了" + +msgid "Exit Action" +msgstr "終了動作" + +msgid "Failed to connect to network share." +msgstr "接続ã«å¤±æ•—ã—ã¾ã—ãŸ" + +msgid "FDS BIOS file is invalid!" +msgstr "disksys.romãŒä¸æ­£ã§ã™" + +msgid "FDS BIOS file not found!" +msgstr "disksys.romãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + +msgid "Filtered" +msgstr "フィルターã™ã‚‹" + +msgid "Filtering" +msgstr "フィルタ" + +msgid "Fire" +msgstr "ファイア" + +msgid "French" +msgstr "フランス語" + +msgid "GBA Screen Zoom" +msgstr "GBAç”»é¢ã‚’拡大" + +msgid "Game Genie ROM not found!" +msgstr "Game Genieã®ROMãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + +msgid "Game Settings" +msgstr "ゲーム設定" + +msgid "Game Settings - Button Mappings" +msgstr "ゲーム設定 - ボタン設定" + +msgid "Game Settings - Cheats" +msgstr "ゲーム設定 - 改造コード" + +msgid "Game Settings - Video" +msgstr "ゲーム設定 - 映åƒ" + +msgid "Game Timing" +msgstr "ゲームã®é€Ÿåº¦" + +msgid "Game Genie DISABLED" +msgstr "Game Genie無効" + +msgid "Game Genie ENABLED" +msgstr "Game Genie有効" + +msgid "GameCube Controller" +msgstr "GCコントローラ" + +msgid "German" +msgstr "ドイツ語" + +msgid "GNU General Public License (GPL) Version 2." +msgstr "GNU 一般公衆利用許諾契約書ãƒãƒ¼ã‚¸ãƒ§ãƒ³2" + +msgid "Go Back" +msgstr "戻る" + +msgid "Horizontal" +msgstr "横方å‘" + +msgid "Information" +msgstr "情報" + +msgid "Initializing network..." +msgstr "接続中…" + +msgid "Insert Coin" +msgstr "コインを入れる" + +msgid "Insert Coin / Switch Disk" +msgstr "コイン/ディスクをã„れる" + +msgid "Invalid file size!" +msgstr "ä¸æ­£ãªã‚µã‚¤ã‚ºã§ã™" + +msgid "Invalid game file!" +msgstr "ä¸æ­£ãªã‚µã‚¤ã‚ºã§ã™" + +msgid "Invalid network settings - Check settings.xml." +msgstr "エラー:settings.xmlを確èªã—ã¦ãã ã•ã„" + +msgid "Invalid network settings - Share IP is blank." +msgstr "共有IPãŒç©ºç™½ã§ã™" + +msgid "Invalid network settings - Share name is blank." +msgstr "共有åãŒç©ºç™½ã§ã™" + +msgid "Invalid save file" +msgstr "ä¸æ­£ãªã‚»ãƒ¼ãƒ–データã§ã™" + +msgid "Invalid state file" +msgstr "ä¸æ­£ãªä¸­æ–­ãƒ•ã‚¡ã‚¤ãƒ«ã§ã™" + +msgid "Italian" +msgstr "イタリア語" + +msgid "Japanese" +msgstr "日本語" + +msgid "Justifier" +msgstr "MODEL510" + +msgid "Justifier - GameCube Controller" +msgstr "MODEL510 - GCコントローラ" + +msgid "Justifier - Wiimote" +msgstr "MODEL510 - Wiiリモコン" + +msgid "Korean" +msgstr "韓国語" + +msgid "L TRIG" +msgstr "Lトリガー" + +msgid "Language" +msgstr "言語" + +msgid "Languages Folder" +msgstr "言語フォルダ" + +msgid "Left" +msgstr "å·¦" + +msgid "LEFT" +msgstr "å·¦" + +msgid "Left Button" +msgstr "左ボタン" + +msgid "Load" +msgstr "ロード" + +msgid "Load Device" +msgstr "読ã¿è¾¼ã‚€ãƒ‡ãƒã‚¤ã‚¹" + +msgid "Load Folder" +msgstr "ロムフォルダ" + +msgid "Load Game" +msgstr "ゲームを読ã¿è¾¼ã‚€" + +msgid "Loading" +msgstr "ロード" + +msgid "Loading DVD..." +msgstr "DVDを読ã¿è¾¼ã¿ä¸­â€¦" + +msgid "Loading patch..." +msgstr "パッãƒã‚’読ã¿è¾¼ã¿ä¸­â€¦" + +msgid "Loading..." +msgstr "読ã¿è¾¼ã¿ä¸­â€¦" + +msgid "Main Menu" +msgstr "メインメニュー" + +msgid "Match GC Controls" +msgstr "æ“作を最é©åŒ–" + +msgid "Match Wii Controls" +msgstr "æ“作を最é©åŒ–" + +msgid "Maximum filepath length reached!" +msgid "ファイルã®ãƒ‘スã®é™ç•Œã¾ã§è¡Œãã¾ã—ãŸ" + +msgid "Menu" +msgstr "メニュー" + +msgid "Menu artwork" +msgstr "メニュー画åƒ" + +msgid "Menu sound" +msgstr "メニュー音楽" + +msgid "MINUS" +msgstr "マイナス" + +msgid "Music Volume" +msgstr "音楽ã®éŸ³é‡" + +msgid "Mute" +msgstr "消音" + +msgid "NES Controller" +msgstr "コントローラ" + +msgid "NES Controllers (2)" +msgstr "コントローラ(2)" + +msgid "NES Controllers (4)" +msgstr "コントローラ(4)" + +msgid "NES Zapper" +msgstr "ファミコンザッパー" + +msgid "Network" +msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯" + +msgid "Network Share" +msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å…±æœ‰" + +msgid "New" +msgstr "æ–°ã—ã„" + +msgid "New Snapshot" +msgstr "æ–°ã—ã„中断データ" + +msgid "New SRAM" +msgstr "æ–°ã—ã„SRAM" + +msgid "No" +msgstr "ã„ã„ãˆ" + +msgid "No data to save!" +msgstr "セーブã™ã‚‹ãƒ‡ãƒ¼ã‚¿ãŒã‚ã‚Šã¾ã›ã‚“" + +msgid "No disc inserted!" +msgstr "ディスクãŒæŒ¿å…¥ã•ã‚Œã¦ã„ã¾ã›ã‚“" + +msgid "No SRAM data to save!" +msgstr "セーブã™ã‚‹SRAMデータãŒã‚ã‚Šã¾ã›ã‚“" + +msgid "No game saves found." +msgstr "セーブデータãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + +msgid "None" +msgstr "ç„¡ã—" + +msgid "NTSC (480i)" +msgstr "NTSC(480i)" + +msgid "Nunchuk" +msgstr "ヌンãƒãƒ£ã‚¯" + +msgid "Off" +msgstr "オフ" + +msgid "Official Site: http://code.google.com/p/fceugc/" +msgstr "å…¬å¼ã‚µã‚¤ãƒˆ:http://code.google.com/p/fceugc/" + +msgid "Official Site: http://code.google.com/p/snes9x-gx/" +msgstr "å…¬å¼ã‚µã‚¤ãƒˆ: http://code.google.com/p/snes9x-gx/" + +msgid "Official Site: http://code.google.com/p/vba-wii/" +msgstr "å…¬å¼ã‚µã‚¤ãƒˆ: http://code.google.com/p/vba-wii/" + +msgid "OK" +msgstr "OK" + +msgid "On" +msgstr "オン" + +msgid "Original" +msgstr "オリジナル" + +msgid "Out of memory!" +msgstr "メモリãŒè¶³ã‚Šã¾ã›ã‚“" + +msgid "Out of memory: too many files!" +msgstr "ファイルãŒå¤šã™ãŽã¦ãƒ¡ãƒ¢ãƒªãŒè¶³ã‚Šã¾ã›ã‚“" + +msgid "P1" +msgstr "" + +msgid "P2" +msgstr "" + +msgid "P3" +msgstr "" + +msgid "P4" +msgstr "" + +msgid "PAL (50Hz)" +msgstr "PAL(50Hz)" + +msgid "PAL (60Hz)" +msgstr "PAL(60Hz)" + +msgid "Palette saved" +msgstr "パレットをセーブã—ã¾ã—ãŸ" + +msgid "Partial Stretch" +msgstr "部分的ã«ä¼¸ç¸®" + +msgid "Pause" +msgstr "一時中断" + +msgid "Please Wait" +msgstr "ãŠå¾…ã¡ãã ã•ã„" + +msgid "PLUS" +msgstr "プラス" + +msgid "Portuguese" +msgstr "ãƒãƒ«ãƒˆã‚¬ãƒ«èªž" + +msgid "Brazilian Portuguese" +msgstr "ブラジルãƒãƒ«ãƒˆã‚¬ãƒ«èªž" + +msgid "Power off Wii" +msgstr "Wiiã®é›»æºã‚’切る" + +msgid "Preferences saved" +msgstr "設定をセーブã—ã¾ã—ãŸ" + +msgid "Press any button on the Classic Controller now. Press Home to clear the existing mapping." +msgstr "ボタンを押ã—ã¦ãã ã•ã„(HOME=ç„¡ã—)" + +msgid "Press any button on the GameCube Controller now. Press Home or the C-Stick in any direction to clear the existing mapping." +msgstr "ボタンを押ã—ã¦ãã ã•ã„(HOMEï½¥C=ç„¡ã—)" + +msgid "Press any button on the GameCube Controller now. Press the C-Stick in any direction to clear the existing mapping." +msgstr "ボタンを押ã—ã¦ãã ã•ã„(HOMEï½¥C=ç„¡ã—)" + +msgid "Press any button on the Wiimote now. Press Home to clear the existing mapping." +msgstr "ボタンを押ã—ã¦ãã ã•ã„(HOME=ç„¡ã—)" + +msgid "Press any button on the Wiimote or Nunchuk now. Press Home to clear the existing mapping." +msgstr "ボタンを押ã—ã¦ãã ã•ã„(HOME=ç„¡ã—)" + +msgid "Progressive (480p)" +msgstr "プログレッシブ(480p)" + +msgid "Quit Game" +msgstr "ゲームを終了" + +msgid "Quit this game? Any unsaved progress will be lost." +msgstr "未ä¿å­˜ã®ãƒ‡ãƒ¼ã‚¿ã¯å¤±ã‚ã‚Œã¾ã™" + +msgid "R TRIG" +msgstr "Rトリガー" + +msgid "RAM saving is not available for FDS games!" +msgstr "ディスクシステムã«ã¯RAMセーブã¯ã‚ã‚Šã¾ã›ã‚“" + +msgid "Reboot" +msgstr "å†èµ·å‹•" + +msgid "Rendering" +msgstr "æç”»" + +msgid "Reset" +msgstr "リセット" + +msgid "Reset Game" +msgstr "ゲームをリセット" + +msgid "Reset this game? Any unsaved progress will be lost." +msgstr "未ä¿å­˜ã®ãƒ‡ãƒ¼ã‚¿ã¯å¤±ã‚ã‚Œã¾ã™" + +msgid "Reset Mappings" +msgstr "ボタン設定をåˆæœŸåŒ–" + +msgid "Reset Settings" +msgstr "設定をåˆæœŸåŒ–" + +msgid "Retry" +msgstr "å†è©¦è¡Œ" + +msgid "Return to Loader" +msgstr "ローダーã«æˆ»ã‚‹" + +msgid "Return to Wii Menu" +msgstr "Wiiメニューã«æˆ»ã‚‹" + +msgid "Right" +msgstr "å³" + +msgid "RIGHT" +msgstr "å³" + +msgid "Right Button" +msgstr "å³ãƒœã‚¿ãƒ³" + +msgid "Rumble" +msgstr "振動" + +msgid "Save" +msgstr "セーブ" + +msgid "Save Device" +msgstr "セーブã™ã‚‹ãƒ‡ãƒã‚¤ã‚¹" + +msgid "Save failed!" +msgstr "セーブã«å¤±æ•—ã—ã¾ã—ãŸ" + +msgid "Save file not found" +msgstr "セーブデータãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + +msgid "Save Folder" +msgstr "セーブフォルダ" + +msgid "Save Game" +msgstr "セーブデータをセーブ" + +msgid "Save RAM and State?" +msgstr "RAMã¨çŠ¶æ…‹ã‚’セーブã—ã¾ã™ã‹?" + +msgid "Save Snapshot?" +msgstr "中断データをセーブã—ã¾ã™ã‹?" + +msgid "Save SRAM and Snapshot?" +msgstr "SRAMã¨ä¸­æ–­ãƒ‡ãƒ¼ã‚¿ã‚’セーブã—ã¾ã™ã‹?" + +msgid "Save State?" +msgstr "状態をセーブã—ã¾ã™ã‹?" + +msgid "Save successful" +msgstr "セーブã«æˆåŠŸã—ã¾ã—ãŸ" + +msgid "Saving" +msgstr "セーブ" + +msgid "Saving preferences..." +msgstr "優先的ã«ã‚»ãƒ¼ãƒ–中…" + +msgid "Saving..." +msgstr "セーブ中…" + +msgid "Scaling" +msgstr "縮尺" + +msgid "Screen Position" +msgstr "ç”»é¢ã®ä½ç½®" + +msgid "Screen Zoom" +msgstr "ç”»é¢ã®æ‹¡å¤§" + +msgid "Select" +msgstr "セレクト" + +msgid "Seek error!" +msgstr "シークエラーã§ã™" + +msgid "Settings" +msgstr "設定" + +msgid "Settings - Menu" +msgstr "設定 - メニュー" + +msgid "Settings - Network" +msgstr "設定 - ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯" + +msgid "Settings - Saving & Loading" +msgstr "設定 - セーブã¨èª­ã¿è¾¼ã¿" + +msgid "SD Card" +msgstr "SD" + +msgid "SD card not found!" +msgstr "SDãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + +msgid "Shift" +msgstr "" + +msgid "Simp_chinese" +msgstr "簡体字中国語" + +msgid "SMB Share IP" +msgstr "SMB共有IP" + +msgid "SMB Share Name" +msgstr "SMB共有å" + +msgid "SMB Share Password" +msgstr "SMB共有パスワード" + +msgid "SMB Share Username" +msgstr "SMB共有ユーザーå" + +msgid "Snapshot" +msgstr "中断データ" + +msgid "Snapshot (Auto)" +msgstr "中断データ(自動)" + +msgid "SNES Controller" +msgstr "コントローラ" + +msgid "SNES Controllers (2)" +msgstr "コントローラ(2)" + +msgid "SNES Controllers (4)" +msgstr "コントローラ(4)" + +msgid "SNES Controller - Classic Controller" +msgstr "コントローラ - クラコン" + +msgid "SNES Controller - GameCube Controller" +msgstr "コントローラ - GCコン" + +msgid "SNES Controller - Nunchuk + Wiimote" +msgstr "コントローラ - Wiiリモコン+ヌンãƒãƒ£ã‚¯" + +msgid "SNES Controller - Wiimote" +msgstr "コントローラ - Wiiリモコン" + +msgid "SNES Mouse" +msgstr "マウス" + +msgid "SNES Mouse - GameCube Controller" +msgstr "マウス - GCコン" + +msgid "SNES Mouse - Wiimote" +msgstr "マウス - Wiiリモコン" + +msgid "Snes9x - Copyright (c) Snes9x Team 1996 - 2006" +msgstr "Snes9x - 著作権(c) Snes9xãƒãƒ¼ãƒ 1996-2006" + +msgid "Sound Effects Volume" +msgstr "効果音ã®éŸ³é‡" + +msgid "Spanish" +msgstr "スペイン語" + +msgid "Sprite Limit" +msgstr "スプライト制é™" + +msgid "SRAM file not found" +msgstr "SRAMファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + +msgid "Start" +msgstr "スタート" + +msgid "State" +msgstr "状態" + +msgid "State (Auto)" +msgstr "状態(自動)" + +msgid "State file not found" +msgstr "状態ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + +msgid "Stretch to Fit" +msgstr "é©ã™ã‚‹ã‚ˆã†ä¼¸ç¸®" + +msgid "Super Scope" +msgstr "スーパースコープ" + +msgid "Superscope" +msgstr "スーパースコープ" + +msgid "Superscope - GameCube Controller" +msgstr "スーパースコープ - GCコン" + +msgid "Superscope - Wiimote" +msgstr "スーパースコープ - Wiiリモコン" + +msgid "This software is open source and may be copied," +msgstr "ã“ã‚Œã¯ã‚ªãƒ¼ãƒ—ンソースã§ã‚³ãƒ”ーã•ã‚Œã¾ã—ãŸ" + +msgid "Trad_chinese" +msgstr "ç¹ä½“字中国語" + +msgid "Unable to initialize network!" +msgstr "接続ã§ãã¾ã›ã‚“ã§ã—ãŸ" + +msgid "Unable to locate a load device!" +msgstr "デãƒã‚¤ã‚¹ã‚’見ã¤ã‘られã¾ã›ã‚“ã§ã—ãŸ" + +msgid "Unable to locate a save device!" +msgstr "デãƒã‚¤ã‚¹ã‚’見ã¤ã‘られã¾ã›ã‚“ã§ã—ãŸ" + +msgid "Unable to open snapshot!" +msgstr "中断データを開ã‘ã¾ã›ã‚“ã§ã—ãŸ" + +msgid "Unfiltered" +msgstr "フィルタ無ã—" + +msgid "Unknown file type!" +msgstr "ä¸æ˜Žãªãƒ•ã‚¡ã‚¤ãƒ«å½¢å¼ã§ã™" + +msgid "Unrecognized DVD format." +msgstr "èªè­˜ã§ããªã„DVDå½¢å¼ã§ã™" + +msgid "Unrecognized file extension!" +msgstr "èªè­˜ã§ããªã„æ‹¡å¼µå­ã§ã™" + +msgid "Up" +msgstr "上" + +msgid "UP" +msgstr "上" + +msgid "Up One Level" +msgstr "一階層上ã¸" + +msgid "Update Available" +msgstr "æ›´æ–°ãŒã‚ã‚Šã¾ã™" + +msgid "Update failed!" +msgstr "æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ" + +msgid "Update later" +msgstr "æ›´æ–°ã—ãªã„" + +msgid "Update now" +msgstr "æ›´æ–°ã™ã‚‹" + +msgid "Update successful!" +msgstr "æ›´æ–°ã«æˆåŠŸã—ã¾ã—ãŸ" + +msgid "USB drive not found!" +msgstr "USBドライブãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + +msgid "USB Mass Storage" +msgstr "USBデãƒã‚¤ã‚¹" + +msgid "Vertical" +msgstr "縦方å‘" + +msgid "Video" +msgstr "映åƒ" + +msgid "Video Mode" +msgstr "映åƒãƒ¢ãƒ¼ãƒ‰" + +msgid "VM8: Unknown page type!" +msgstr "VM8:ä¸æ˜Žãªãƒšãƒ¼ã‚¸å½¢å¼ã§ã™" + +msgid "VM16: Unknown page type!" +msgstr "VM16:ä¸æ˜Žãªãƒšãƒ¼ã‚¸å½¢å¼ã§ã™" + +msgid "VM32: Unknown page type!" +msgstr "VM32:ä¸æ˜Žãªãƒšãƒ¼ã‚¸å½¢å¼ã§ã™" + +msgid "Wiimote" +msgstr "Wiiリモコン" + +msgid "Wiimote Orientation" +msgstr "Wiiリモコンã®å‘ã" + +msgid "Yes" +msgstr "ã¯ã„" + +msgid "Zapper" +msgstr "ザッパー" + +msgid "Zapper Crosshair" +msgstr "ザッパーã®å字カーソル" + +msgid "Logo" +msgstr "ロゴ" + +msgid "Turbo On" +msgstr "連打オン" + +msgid "Turbo Off" +msgstr "連打オフ" + +msgid "Automatic" +msgstr "自動" + +msgid "Palette" +msgstr "使用パレット" + +msgid "AspiringSquire's Real palette" +msgstr "AspiringSquire" + +msgid "Loopy's palette" +msgstr "Loopy" + +msgid "Quor's palette" +msgstr "Quor" + +msgid "Chris Covell's palette" +msgstr "Chris Covell" + +msgid "Matthew Conte's palette" +msgstr "Matthew Conte" + +msgid "PasoFami/99 palette" +msgstr "パソファミ/99" + +msgid "CrashMan's palette" +msgstr "CrashMan" + +msgid "MESS palette" +msgstr "MESS" + +msgid "Zaphod's VS Castlevania palette" +msgstr "VSキャッスルãƒãƒ‹ã‚¢" + +msgid "Zaphod's VS SMB palette" +msgstr "VSスーパーï¾ï¾˜ï½µï¾Œï¾žï¾—ザーズ" + +msgid "VS Dr. Mario palette" +msgstr "VSDr.マリオ" + +msgid "VS Castlevania palette" +msgstr "VSキャッスルãƒãƒ‹ã‚¢" + +msgid "VS SMB/VS Ice Climber palette" +msgstr "VSスーï¾ï¾˜/アイスクライï¾ï½°" + +msgid "Catalan" +msgstr "カタロニア語" + +msgid "The current IOS has been altered (fake-signed). Functionality and/or stability may be adversely affected." +msgstr "ã“ã®IOSã§ã¯ä¸å®‰å®šã«ãªã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™" + +msgid "The current IOS is unsupported. Functionality and/or stability may be adversely affected." +msgstr "ã“ã®IOSã«ã¯å¯¾å¿œã—ã¦ã„ãªã„ã®ã§ä¸å®‰å®šã«ãªã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™" + +msgid "Turkish" +msgstr "トルコ語" diff --git a/plugins/snes9x_gx/source/lang/ko.lang b/plugins/snes9x_gx/source/lang/ko.lang new file mode 100644 index 00000000..85d83649 --- /dev/null +++ b/plugins/snes9x_gx/source/lang/ko.lang @@ -0,0 +1,2 @@ +msgid " " +msgstr "" diff --git a/plugins/snes9x_gx/source/lang/nl.lang b/plugins/snes9x_gx/source/lang/nl.lang new file mode 100644 index 00000000..a501c08d --- /dev/null +++ b/plugins/snes9x_gx/source/lang/nl.lang @@ -0,0 +1,840 @@ +msgid "&" +msgstr "&" + +msgid "16:9 Correction" +msgstr 16:9 Correctie" + +msgid "7z decompression failed: Archive contains too many files" +msgstr "7z decompressie mislukt: te veel bestanden in archief" + +msgid "7z decompression failed: Failed to read file data" +msgstr "7z decompressie mislukt: fout bij lezen van bestand" + +msgid "7z decompression failed: File is corrupt" +msgstr "7z decompressie mislukt: fout bij lezen van bestand" + +msgid "7z decompression failed: File is corrupt (CRC mismatch)" +msgstr "7z decompressie mislukt: fout bij lezen van bestand (CRC komt niet overeen)" + +msgid "7z decompression failed: File uses too high of compression settings (dictionary size is too large)" +msgstr "7z decompressie mislukt: bestand gebruikt een te hoge compressie (woordenboek is te groot)" + +msgid "7z decompression failed: File uses unsupported compression settings" +msgstr "7z decompressie mislukt: bestand gebruikt een niet ondersteunde compressie" + +msgid "A (Rapid)" +msgstr "A (Snel)" + +msgid "Additional coding" +msgstr "Overige programmering" + +msgid "Aim Offscreen" +msgstr "Richt buiten het scherm" + +msgid "An update is available!" +msgstr "Een update is beschikbaar!" + +msgid "Are you sure that you want to reset this game? Any unsaved progress will be lost." +msgstr "Weet je zeker dat je het spel wilt herstarten? Niet opgeslagen gegevens zullen verloren gaan." + +msgid "Are you sure that you want to reset your mappings?" +msgstr "Weet je zeker dat je de controller instellingen wilt wissen?" + +msgid "Are you sure that you want to reset your settings?" +msgstr "Weet je zeker dat je de instellingen wilt wissen?" + +msgid "Maintain Aspect Ratio" +msgstr "Behoud Beeldverhouding" + +msgid "Attempting to determine load device..." +msgstr "Poging om het laadapparaat te bepalen..." + +msgid "Attempting to determine save device..." +msgstr "Poging om het opslaanapparaat te bepalen..." + +msgid "Auto" +msgstr "Auto" + +msgid "Auto Detect" +msgstr "Detecteer Automatisch" + +msgid "Auto Load" +msgstr "Auto Openen" + +msgid "Auto Save" +msgstr "Auto Opslaan" + +msgid "Automatic (Recommended)" +msgstr "Automatisch (Aanbevolen)" + +msgid "B (Rapid)" +msgstr "B (Snel)" + +msgid "Back" +msgstr "Terug" + +msgid "Both" +msgstr "Beide" + +msgid "Button Mapping" +msgstr "Controller" + +msgid "Button Mappings" +msgstr "Controller Instellingen" + +msgid "Cancel" +msgstr "Annuleren" + +msgid "Caps" +msgstr "Caps" + +msgid "Cheats" +msgstr "Cheats" + +msgid "Cheats file not found!" +msgstr "Cheats bestand niet gevonden!" + +msgid "Cheats Folder" +msgstr "Cheats Map" + +msgid "Choose Game" +msgstr "Kies Spel" + +msgid "Classic Controller" +msgstr "Traditionele Controller" + +msgid "Close" +msgstr "Sluiten" + +msgid "Coding" +msgstr "Programmering" + +msgid "Coding & menu design" +msgstr "Programmering & menu ontwerp" + +msgid "Compressed GBA files are not supported!" +msgstr "Gecomprimeerde GBA bestanden zijn niet ondersteund!" + +msgid "Connecting to network share..." +msgstr "Verbinden met gedeelde map..." + +msgid "Controller" +msgstr "Controller" + +msgid "Cover View" +msgstr "Hoes Weergave" + +msgid "Covers Folder" +msgstr "Hoezen map" + +msgid "Credits" +msgstr "Credits" + +msgid "Cropping" +msgstr "Bijsnijden" + +msgid "Crosshair" +msgstr "Crosshair" + +msgid "Cursor" +msgstr "Cursor" + +msgid "Data DVD" +msgstr "DVD-ROM" + +msgid "Default" +msgstr "Standaard" + +msgid "Directory name is too long!" +msgstr "Mapnaam is te lang!" + +msgid "Disabled" +msgstr "Uitgeschakeld" + +msgid "DISABLED" +msgstr "UITGESCHAKELD" + +msgid "distributed, or modified under the terms of the" +msgstr "uitgegeven, of bewerkt onder regels van de" + +msgid "Don't Save" +msgstr "Niet Opslaan" + +msgid "Down" +msgstr "Omlaag" + +msgid "DOWN" +msgstr "OMLAAG" + +msgid "Downloading..." +msgstr "Bezig met downloaden..." + +msgid "Dutch" +msgstr "Nederlands" + +msgid "Empty or invalid ZIP file!" +msgstr "Leeg of beschadigd ZIP bestand!" + +msgid "Enabled" +msgstr "Ingeschakeld" + +msgid "ENABLED" +msgstr "INGESCHAKELD" + +msgid "English" +msgstr "Engels" + +msgid "Error" +msgstr "Fout" + +msgid "Error - Invalid ZIP file!" +msgstr "Fout - Verkeerd ZIP bestand!" + +msgid "Error creating file!" +msgstr "Fout bij het maken van het bestand!" + +msgid "Error loading game!" +msgstr "Fout bij het laden van het spel!" + +msgid "Error opening archive!" +msgstr "Fout bij het openen van het archief!" + +msgid "Error opening directory!" +msgstr "Fout bij het openen van de map!" + +msgid "Error opening file!" +msgstr "Fout bij het openen van het bestand!" + +msgid "Error reading file!" +msgstr "Fout bij het lezen van het bestand!" + +msgid "Error saving file!" +msgstr "Fout bij het opslaan van het bestand!" + +msgid "Exit" +msgstr "Afsluiten" + +msgid "Exit Action" +msgstr "Afsluitactie" + +msgid "Failed to connect to network share." +msgstr "Verbinden met gedeelde map is mislukt." + +msgid "FDS BIOS file is invalid!" +msgstr "FDS BIOS bestand is verkeerd!" + +msgid "FDS BIOS file not found!" +msgstr "FDS BIOS bestand kan niet gevonden worden!" + +msgid "Filtered" +msgstr "Gesorteerd" + +msgid "Filtering" +msgstr "Sortering" + +msgid "Fire" +msgstr "Vuren" + +msgid "French" +msgstr "Frans" + +msgid "GBA Screen Zoom" +msgstr "GBA Scherm Zomen" + +msgid "Game Genie ROM not found!" +msgstr "Game Genie ROM niet gevonden!" + +msgid "Game Settings" +msgstr "Spelinstellingen" + +msgid "Game Settings - Button Mappings" +msgstr "Spelinstellingen - Controller Configuratie" + +msgid "Game Settings - Cheats" +msgstr "Spelinstellingen - Cheats" + +msgid "Game Settings - Video" +msgstr "Spelinstellingen - Video" + +msgid "Game Timing" +msgstr "Spel Timen" + +msgid "Game Genie DISABLED" +msgstr "Game Genie UITGESCHAKELD" + +msgid "Game Genie ENABLED" +msgstr "Game Genie INGESCHAKELD" + +msgid "GameCube Controller" +msgstr "GameCube Controller" + +msgid "German" +msgstr "Duits" + +msgid "GNU General Public License (GPL) Version 2." +msgstr "GNU General Public License (GPL) Versie 2." + +msgid "Go Back" +msgstr "Ga Terug" + +msgid "Horizontal" +msgstr "Horizontaal" + +msgid "Information" +msgstr "Informatie" + +msgid "Initializing network..." +msgstr "Netwerk Initialiseren..." + +msgid "Insert Coin" +msgstr "Munt inwerpen" + +msgid "Insert Coin / Switch Disk" +msgstr "Munt inwerpen / Disk wisselen" + +msgid "Invalid file size!" +msgstr "Verkeerde bestandsgrootte!" + +msgid "Invalid game file!" +msgstr "Verkeerd spelbestand!" + +msgid "Invalid network settings - Check settings.xml." +msgstr "Verkeerde netwerk instellingen - Controleer settings.xml." + +msgid "Invalid network settings - Share IP is blank." +msgstr "Verkeerde netwerk instellingen - Gedeeld ip adres is niet opgegeven." + +msgid "Invalid network settings - Share name is blank." +msgstr "Verkeerde netwerk instellingen - Gedeelde map is niet opgegeven." + +msgid "Invalid save file" +msgstr "Invalide opgeslagen bestand" + +msgid "Invalid state file" +msgstr "Invalide status bestand" + +msgid "Italian" +msgstr "Italiaans" + +msgid "Japanese" +msgstr "Japans" + +msgid "Justifier" +msgstr "Konami Justifier" + +msgid "Justifier - GameCube Controller" +msgstr "Konami Justifier - GameCube Controller" + +msgid "Justifier - Wiimote" +msgstr "Konami Justifier - Wiimote" + +msgid "Korean" +msgstr "Koreaans" + +msgid "L TRIG" +msgstr "L" + +msgid "Language" +msgstr "Taal" + +msgid "Languages Folder" +msgstr "Talenmap" + +msgid "Left" +msgstr "Links" + +msgid "LEFT" +msgstr "LINKS" + +msgid "Left Button" +msgstr "Knop Links" + +msgid "Load" +msgstr "Openen" + +msgid "Load Device" +msgstr "Open Apparaat" + +msgid "Load Folder" +msgstr "Open Map" + +msgid "Load Game" +msgstr "Spel starten" + +msgid "Loading" +msgstr "Laden" + +msgid "Loading DVD..." +msgstr "Bezig met DVD laden..." + +msgid "Loading patch..." +msgstr "Bezig met patch laden..." + +msgid "Loading..." +msgstr "Bezig met laden..." + +msgid "Main Menu" +msgstr "Hoofdmenu" + +msgid "Match GC Controls" +msgstr "Gelijk aan GC besturing" + +msgid "Match Wii Controls" +msgstr "Gelijk aan Wii besturing" + +msgid "Maximum filepath length reached!" +msgid "Maximale bestandspad lengte berijkt!" + +msgid "Menu" +msgstr "Menu" + +msgid "Menu artwork" +msgstr "Menu artwork" + +msgid "Menu sound" +msgstr "Menu geluid" + +msgid "Music Volume" +msgstr "Muziek volume" + +msgid "MINUS" +msgstr "MIN" + +msgid "Mute" +msgstr "Stil" + +msgid "NES Controller" +msgstr "NES Controller" + +msgid "NES Controllers (2)" +msgstr "NES COntrollers (2)" + +msgid "NES Controllers (4)" +msgstr "NES Controllers (4)" + +msgid "NES Zapper" +msgstr "Nintendo Zapper" + +msgid "Network" +msgstr "Netwerk" + +msgid "Network Share" +msgstr "Gedeelde map" + +msgid "New" +msgstr "Nieuw" + +msgid "New Snapshot" +msgstr "Nieuw Snapshot" + +msgid "New SRAM" +msgstr "Nieuw SRAM" + +msgid "No" +msgstr "Nee" + +msgid "No data to save!" +msgstr "Geen data om op te slaan!" + +msgid "No disc inserted!" +msgstr "Geen schijf ingevoerd!" + +msgid "No SRAM data to save!" +msgstr "Geen SRAM om op te slaan!" + +msgid "No game saves found." +msgstr "Geen opgeslagen spellen gevonden." + +msgid "None" + +msgstr "Geen" + +msgid "NTSC (480i)" +msgstr "NTSC (480i)" + +msgid "Nunchuk" +msgstr "Nunchuk" + +msgid "Off" +msgstr "Uit" + +msgid "Official Site: http://code.google.com/p/fceugc/" +msgstr "Officiële Website: http://code.google.com/p/fceugc/" + +msgid "Official Site: http://code.google.com/p/snes9x-gx/" +msgstr "Officiële Website: http://code.google.com/p/snes9x-gx/" + +msgid "Official Site: http://code.google.com/p/vba-wii/" +msgstr "Officiële Website: http://code.google.com/p/vba-wii/" + +msgid "OK" +msgstr "OK" + +msgid "On" +msgstr "Aan" + +msgid "Original" +msgstr "Origineel" + +msgid "Out of memory!" +msgstr "Te weinig geheugen!" + +msgid "Out of memory: too many files!" +msgstr "Te weinig geheugen: te veel bestanden!" + +msgid "P1" +msgstr "P1" + +msgid "P2" +msgstr "P2" + +msgid "P3" +msgstr "P3" + +msgid "P4" +msgstr "P4" + +msgid "PAL (50Hz)" +msgstr "PAL (50Hz)" + +msgid "PAL (60Hz)" +msgstr "PAL (60Hz)" + +msgid "Palette saved" +msgstr "Kleurenpalet opgeslagen" + +msgid "Partial Stretch" +msgstr "Gedeeltelijk Uitgerekt" + +msgid "Pause" +msgstr "Pauze" + +msgid "Please Wait" +msgstr "Even geduld" + +msgid "PLUS" +msgstr "PLUS" + +msgid "Portuguese" +msgstr "Portugees" + +msgid "Power off Wii" +msgstr "Wii uitschakelen" + +msgid "Preferences saved" +msgstr "Instellingen opgeslagen" + +msgid "Press any button on the Classic Controller now. Press Home to clear the existing mapping." +msgstr "Druk op een knop op de Tradionele Controller. Druk op Home om de instelling te wissen." + +msgid "Press any button on the GameCube Controller now. Press Home or the C-Stick in any direction to clear the existing mapping." +msgstr "Druk op een knop op de GameCube Controller. Druk op Home of beweeg de C-stick om de instelling te wissen." + +msgid "Press any button on the GameCube Controller now. Press the C-Stick in any direction to clear the existing mapping." +msgstr "Druk op een knop op de GameCube Controller. Beweeg de C-stick om de instelling te wissen." + +msgid "Press any button on the Wiimote now. Press Home to clear the existing mapping." +msgstr "Druk op een knop op de Wiimote. Druk op Home om de instelling te wissen." + +msgid "Press any button on the Wiimote or Nunchuk now. Press Home to clear the existing mapping." +msgstr "Druk op een knop op de Wiimote of Nunchuck. Druk op Home om de instelling te wissen." + +msgid "Progressive (480p)" +msgstr "Progressief (480p)" + +msgid "Quit Game" +msgstr "Spel Afsluiten" + +msgid "Quit this game? Any unsaved progress will be lost." +msgstr "Sluit dit spel af? Niet opgeslagen gegevens zullen verloren gaan." + +msgid "R TRIG" +msgstr "R" + +msgid "RAM saving is not available for FDS games!" +msgstr "RAM opslaan is niet beschikbaar voor FDS spellen!" + +msgid "Reboot" +msgstr "Herstart" + +msgid "Rendering" +msgstr "Rendering" + +msgid "Reset" +msgstr "Reset" + +msgid "Reset Game" +msgstr "Herstart Spel" + +msgid "Reset this game? Any unsaved progress will be lost." +msgstr "Herstart dit spel? Niet opgeslagen gegevens zullen verloren gaan." + +msgid "Reset Mappings" +msgstr "Reset Controllers" + +msgid "Reset Settings" +msgstr "Reset Instellingen" + +msgid "Retry" +msgstr "Opnieuw" + +msgid "Return to Loader" +msgstr "Terug naar de Lader" + +msgid "Return to Wii Menu" +msgstr "Terug naar het Wii Menu" + +msgid "Right" +msgstr "Rechts" + +msgid "RIGHT" +msgstr "RECHTS" + +msgid "Right Button" +msgstr "Knop Rechts" + +msgid "Rumble" +msgstr "Tril" + +msgid "Save" +msgstr "Opslaan" + +msgid "Save Device" +msgstr "Opslaan Apparaat" + +msgid "Save failed!" +msgstr "Opslaan is mislukt!" + +msgid "Save file not found" +msgstr "Opgeslagen bestand is niet gevonden" + +msgid "Save Folder" +msgstr "Opslaan Map" + +msgid "Save Game" +msgstr "Spel Opslaan" + +msgid "Save RAM and State?" +msgstr "Geheugen en status opslaan?" + +msgid "Save Snapshot?" +msgstr "Snapshot Opslaan?" + +msgid "Save SRAM and Snapshot?" +msgstr "SRAM en Snapshot opslaan?" + +msgid "Save State?" +msgstr "Status Opslaan?" + +msgid "Save successful" +msgstr "Succesvol opgeslagen" + +msgid "Saving" +msgstr "Opslaan" + +msgid "Saving preferences..." +msgstr "Instellingen opslaan..." + +msgid "Saving..." +msgstr "Bezig met opslaan..." + +msgid "Scaling" +msgstr "Schaal" + +msgid "Screen Position" +msgstr "Schermpositie" + +msgid "Screen Zoom" +msgstr "Zomen" + +msgid "Select" +msgstr "Selecteer" + +msgid "Seek error!" +msgstr "Zoekfout!" + +msgid "Settings" +msgstr "Instellingen" + +msgid "Settings - Menu" +msgstr "Instellingen - Menu" + +msgid "Settings - Network" +msgstr "Instellingen - Netwerk" + +msgid "Settings - Saving & Loading" +msgstr "Instellingen - Laden & Opslaan" + +msgid "SD Card" +msgstr "SD Kaart" + +msgid "SD card not found!" +msgstr "Geen SD kaart gevonden!" + +msgid "Shift" +msgstr "Shift" + +msgid "Simp_chinese" +msgstr "Vereenvoudigd Chinees" + +msgid "SMB Share IP" +msgstr "IP SMB Share" + +msgid "SMB Share Name" +msgstr "SMB Share Naam" + +msgid "SMB Share Password" +msgstr "SMB Share Wachtwoord" + +msgid "SMB Share Username" +msgstr "SMB Share Gebruiker" + +msgid "Snapshot" +msgstr "Snapshot" + +msgid "Snapshot (Auto)" +msgstr "Snapshot (Auto)" + +msgid "SNES Controller" +msgstr "SNES Controller" + +msgid "SNES Controllers (2)" +msgstr "SNES Controllers (2)" + +msgid "SNES Controllers (4)" +msgstr "SNES Controllers (4)" + +msgid "SNES Controller - Classic Controller" +msgstr "SNES Controller - Classic Controller" + +msgid "SNES Controller - GameCube Controller" +msgstr "SNES Controller - GameCube Controller" + +msgid "SNES Controller - Nunchuk + Wiimote" +msgstr "SNES Controller - Nunchuk + Wiimote" + +msgid "SNES Controller - Wiimote" +msgstr "SNES Controller - Wiimote" + +msgid "SNES Mouse" +msgstr "SNES Muis" + +msgid "SNES Mouse - GameCube Controller" +msgstr "SNES Muis - GameCube Controller" + +msgid "SNES Mouse - Wiimote" +msgstr "SNES Muis - Wiimote" + +msgid "Snes9x - Copyright (c) Snes9x Team 1996 - 2006" +msgstr "Snes9x - Copyright (c) Snes9x Team 1996 - 2006" + +msgid "Sound Effects Volume" +msgstr "Volume Geluidseffecten" + +msgid "Spanish" +msgstr "Spaans" + +msgid "Sprite Limit" +msgstr "Sprite Limiet" + +msgid "SRAM file not found" +msgstr "SRAM bestand niet gevonden" + +msgid "State" +msgstr "Status" + +msgid "State (Auto)" +msgstr "Status (Auto)" + +msgid "State file not found" +msgstr "Status bestand niet gevonden" + +msgid "Stretch to Fit" +msgstr "Uitrekken tot passend" + +msgid "Superscope" +msgstr "Superscope" + +msgid "Superscope - GameCube Controller" +msgstr "Superscope - GameCube Controller" + +msgid "Superscope - Wiimote" +msgstr "Superscope - Wiimote" + +msgid "This software is open source and may be copied," +msgstr "Deze software is Open Source en mag gekopieerd worden," + +msgid "Trad_chinese" +msgstr "Traditioneel Chinees" + +msgid "Unable to initialize network!" +msgstr "Kan netwerk niet initialiseren!" + +msgid "Unable to locate a load device!" +msgstr "Kan laad apparaat niet vinden!" + +msgid "Unable to locate a save device!" +msgstr "Kan opslaan apparaat niet vinden!" + +msgid "Unable to open snapshot!" +msgstr "Kan snapshot niet openen!" + +msgid "Unfiltered" +msgstr "Ongefiltered" + +msgid "Unknown file type!" +msgstr "Onbekend bestandstype!" + +msgid "Unrecognized DVD format." +msgstr "Onbekend DVD formaat." + +msgid "Unrecognized file extension!" +msgstr "Onbekende bestandsextentie!" + +msgid "Up" +msgstr "Omhoog" + +msgid "UP" +msgstr "OMHOOG" + +msgid "Up One Level" +msgstr "Eén Omhoog" + +msgid "Update Available" +msgstr "Update beschikbaar" + +msgid "Update failed!" +msgstr "Update mislukt!" + +msgid "Update later" +msgstr "Later updaten" + +msgid "Update now" +msgstr "Nu updaten" + +msgid "Update successful!" +msgstr "Update succesvol!" + +msgid "USB drive not found!" +msgstr "USB disk niet gevonden!" + +msgid "USB Mass Storage" +msgstr "USB Mass Storage" + +msgid "Vertical" +msgstr "Vertikaal" + +msgid "Video" +msgstr "Video" + +msgid "Video Mode" +msgstr "Video Modus" + +msgid "VM8: Unknown page type!" +msgstr "VM8: Onbekend pagina type!" + +msgid "VM16: Unknown page type!" +msgstr "VM16: Onbekend pagina type!" + +msgid "VM32: Unknown page type!" +msgstr "VM32: Onbekend pagina type!" \ No newline at end of file diff --git a/plugins/snes9x_gx/source/lang/pt.lang b/plugins/snes9x_gx/source/lang/pt.lang new file mode 100644 index 00000000..a4905ebc --- /dev/null +++ b/plugins/snes9x_gx/source/lang/pt.lang @@ -0,0 +1,872 @@ +msgid "&" +msgstr "&" + +msgid "16:9 Correction" +msgstr "Correcção 16:9" + +msgid "7z decompression failed: Archive contains too many files" +msgstr "Extracção 7z falhou: o ficheiro 7z contém demasiados ficheiros" + +msgid "7z decompression failed: Failed to read file data" +msgstr "Extracção 7z falhou: erro na leitura do ficheiro" + +msgid "7z decompression failed: File is corrupt" +msgstr "Extracção 7z falhou: ficheiro corrupto" + +msgid "7z decompression failed: File is corrupt (CRC mismatch)" +msgstr "Extracção 7z falhou: ficheiro corrupto (erro de CRC)" + +msgid "7z decompression failed: File uses too high of compression settings (dictionary size is too large)" +msgstr "Extracção 7z falhou: O ficheiro usa parâmetros de compressão muito altos (o tamanho de dicionário é muito grande)" + +msgid "7z decompression failed: File uses unsupported compression settings" +msgstr "Extracção 7z falhou: O ficheiro usa parâmetros não suportados" + +msgid "A (Rapid)" +msgstr "A (Rápido)" + +msgid "Additional coding" +msgstr "Programação adicional" + +msgid "Aim Offscreen" +msgstr "Mira fora do ecrã" + +msgid "An update is available!" +msgstr "Actualização disponível!" + +msgid "Are you sure that you want to reset this game? Any unsaved progress will be lost." +msgstr "Quer mesmo reiniciar este jogo? Qualquer progresso não gravado será perdido." + +msgid "Are you sure that you want to reset your mappings?" +msgstr "Quer mesmo repor os controlos mapeados?" + +msgid "Are you sure that you want to reset your settings?" +msgstr "Quer mesmo repor as configurações?" + +msgid "Maintain Aspect Ratio" +msgstr "Manter Proporções" + +msgid "Attempting to determine load device..." +msgstr "A determinar dispositivo de carregamento..." + +msgid "Attempting to determine save device..." +msgstr "A determinar dispositivo de gravação..." + +msgid "Auto" +msgstr "Automático" + +msgid "Auto Detect" +msgstr "Auto detectar" + +msgid "Auto Load" +msgstr "Auto carregar" + +msgid "Auto Save" +msgstr "Auto gravar" + +msgid "Automatic" +msgstr "Automático" + +msgid "Automatic (Recommended)" +msgstr "Automático (Recomendado)" + +msgid "B (Rapid)" +msgstr "B (Rápido)" + +msgid "Back" +msgstr "Voltar" + +msgid "Both" +msgstr "Ambos" + +msgid "Controles" +msgstr "Controlos" + +msgid "Button Mappings" +msgstr "Mapear Botões" + +msgid "Cancel" +msgstr "Cancelar" + +msgid "Caps" +msgstr "Maiúsc." + +msgid "Cheats" +msgstr "Truques" + +msgid "Cheats file not found!" +msgstr "Ficheiro de truques não encontrado!" + +msgid "Cheats Folder" +msgstr "Pasta de Truques" + +msgid "Choose Game" +msgstr "Escolher Jogo" + +msgid "Classic Controller" +msgstr "Comando Clássico" + +msgid "Close" +msgstr "Fechar" + +msgid "Coding" +msgstr "Programação" + +msgid "Coding & menu design" +msgstr "Programação & desenho do menu" + +msgid "Compressed GBA files are not supported!" +msgstr "Ficheiros GBA comprimidos não são suportados!" + +msgid "Connecting to network share..." +msgstr "A ligar à partilha de rede..." + +msgid "Controller" +msgstr "Controlo" + +msgid "Cover View" +msgstr "Visualização de Capas" + +msgid "Covers Folder" +msgstr "Pasta de Capas" + +msgid "Credits" +msgstr "Créditos" + +msgid "Cropping" +msgstr "Cropping" + +msgid "Crosshair" +msgstr "Mira" + +msgid "Cursor" +msgstr "Cursor" + +msgid "Data DVD" +msgstr "DVD de Dados" + +msgid "Default" +msgstr "Padrão" + +msgid "Directory name is too long!" +msgstr "O nome da directoria é muito grande!" + +msgid "Disabled" +msgstr "Desactivado" + +msgid "DISABLED" +msgstr "DESACTIVADO" + +msgid "distributed, or modified under the terms of the" +msgstr "distribuído, ou modificado sob os termos de" + +msgid "Don't Save" +msgstr "Não gravar" + +msgid "Down" +msgstr "Baixo" + +msgid "DOWN" +msgstr "BAIXO" + +msgid "Downloading..." +msgstr "A transferir..." + +msgid "Dutch" +msgstr "Holandês" + +msgid "Empty or invalid ZIP file!" +msgstr "Ficheiro ZIP vazio ou inválido" + +msgid "Enabled" +msgstr "Activado" + +msgid "ENABLED" +msgstr "ACTIVADO" + +msgid "English" +msgstr "Inglês" + +msgid "Error" +msgstr "Erro" + +msgid "Error - Invalid ZIP file!" +msgstr "Erro - Ficheiro ZIP inválido!" + +msgid "Error creating file!" +msgstr "Erro ao criar ficheiro!" + +msgid "Error loading game!" +msgstr "Erro ao carregar jogo!" + +msgid "Error opening archive!" +msgstr "Erro ao abrir arquivo!" + +msgid "Error opening directory!" +msgstr "Erro ao abrir diretoria!" + +msgid "Error opening file!" +msgstr "Erro ao abrir ficheiro!" + +msgid "Error reading file!" +msgstr "Erro ao ler ficheiro!" + +msgid "Error saving file!" +msgstr "Erro ao gravar ficheiro!" + +msgid "Exit" +msgstr "Sair" + +msgid "Exit Action" +msgstr "Acção ao Sair" + +msgid "Failed to connect to network share." +msgstr "Falha ao ligar-se à partilha de rede." + +msgid "FDS BIOS file is invalid!" +msgstr "Ficheiro de BIOS do FDS (Famicom Disk System) inválido!" + +msgid "FDS BIOS file not found!" +msgstr "Ficheiro de BIOS de FDS (Famicom Disk System) não encontrado!" + +msgid "Filtered" +msgstr "Filtrado" + +msgid "Filtering" +msgstr "Filtragem" + +msgid "Fire" +msgstr "Fogo" + +msgid "French" +msgstr "Francês" + +msgid "GBA Screen Zoom" +msgstr "Zoom do ecrã GBA" + +msgid "Game Genie ROM not found!" +msgstr "Não foi encontrada a ROM do Game Genie!" + +msgid "Game Settings" +msgstr "Configurações" + +msgid "Game Settings - Button Mappings" +msgstr "Configurações - Mapear Botões" + +msgid "Game Settings - Cheats" +msgstr "Configurações - Truques" + +msgid "Game Settings - Video" +msgstr "Configurações - Vídeo" + +msgid "Game Timing" +msgstr "Tempo de jogo" + +msgid "Game Genie DISABLED" +msgstr "Game Genie DESACTIVADO" + +msgid "Game Genie ENABLED" +msgstr "Game Genie ACTIVADO" + +msgid "GameCube Controller" +msgstr "Comando GameCube" + +msgid "German" +msgstr "Alemão" + +msgid "GNU General Public License (GPL) Version 2." +msgstr "GNU Licença Pública Geral (GPL) Versão 2." + +msgid "Go Back" +msgstr "Voltar" + +msgid "Horizontal" +msgstr "Horizontal" + +msgid "Information" +msgstr "Informação" + +msgid "Initializing network..." +msgstr "A iniciar ligação de rede..." + +msgid "Insert Coin" +msgstr "Inserir Moeda" + +msgid "Insert Coin / Switch Disk" +msgstr "Inserir Moeda / Trocar Disco" + +msgid "Invalid file size!" +msgstr "Tamanho de ficheiro inválido!" + +msgid "Invalid game file!" +msgstr "Ficheiro de jogo inválido!" + +msgid "Invalid network settings - Check settings.xml." +msgstr "Configuração de rede inválida - Verifique o ficheiro settings.xml." + +msgid "Invalid network settings - Share IP is blank." +msgstr "Configuração de rede inválida - IP vazio." + +msgid "Invalid network settings - Share name is blank." +msgstr "Configuração de rede inválida - Nome vazio." + +msgid "Invalid save file" +msgstr "Ficheiro gravado inválido" + +msgid "Invalid state file" +msgstr "Ficheiro de estado inválido" + +msgid "Italian" +msgstr "Italiano" + +msgid "Japanese" +msgstr "Japonês" + +msgid "Justifier" +msgstr "Justifier" + +msgid "Justifier - GameCube Controller" +msgstr "Justifier - Comando GameCube" + +msgid "Justifier - Wiimote" +msgstr "Justifier - Wii Remote" + +msgid "Korean" +msgstr "Coreano" + +msgid "L TRIG" +msgstr "L" + +msgid "Language" +msgstr "Idioma" + +msgid "Languages Folder" +msgstr "Pasta de Idiomas" + +msgid "Left" +msgstr "Esquerda" + +msgid "LEFT" +msgstr "ESQUERDA" + +msgid "Left Button" +msgstr "Botão Esquerdo" + +msgid "Load" +msgstr "Carregar" + +msgid "Load Device" +msgstr "Carregar do Dispositivo" + +msgid "Load Folder" +msgstr "Pasta de Jogos" + +msgid "Load Game" +msgstr "Carregar Jogo" + +msgid "Loading" +msgstr "A Carregar" + +msgid "Loading DVD..." +msgstr "A Carregar DVD..." + +msgid "Loading patch..." +msgstr "A Carregar patch..." + +msgid "Loading..." +msgstr "A carregar..." + +msgid "Main Menu" +msgstr "Menu Principal" + +msgid "Match GC Controls" +msgstr "Coincidir Controlos GC" + +msgid "Match Wii Controls" +msgstr "Coincidir Controlos Wii" + +msgid "Maximum filepath length reached!" +msgid "Tamanho máximo do caminho do ficheiro alcançado!" + +msgid "Menu" +msgstr "Menu" + +msgid "Menu artwork" +msgstr "Arte do Menu" + +msgid "Menu sound" +msgstr "Som do Menu" + +msgid "MINUS" +msgstr "MENOS" + +msgid "Music Volume" +msgstr "Volume da Música" + +msgid "Mute" +msgstr "Mudo" + +msgid "NES Controller" +msgstr "Comando NES" + +msgid "NES Controllers (2)" +msgstr "Comando NES (2)" + +msgid "NES Controllers (4)" +msgstr "Comando NES (4)" + +msgid "NES Zapper" +msgstr "Nintendo Zapper" + +msgid "Network" +msgstr "Rede" + +msgid "Network Share" +msgstr "Partilha de Rede" + +msgid "New" +msgstr "Novo" + +msgid "New Snapshot" +msgstr "Novo Snapshot" + +msgid "New SRAM" +msgstr "Nova SRAM" + +msgid "No" +msgstr "Não" + +msgid "No data to save!" +msgstr "Não há dados para gravar!" + +msgid "No disc inserted!" +msgstr "Nenhum disco inserido!" + +msgid "No SRAM data to save!" +msgstr "Não há dados de SRAM para gravar!" + +msgid "No game saves found." +msgstr "Nenhum jogo gravado encontrado." + +msgid "None" +msgstr "Nenhum" + +msgid "NTSC (480i)" +msgstr "NTSC (480i)" + +msgid "Nunchuk" +msgstr "Nunchuk" + +msgid "Off" +msgstr "Desligado" + +msgid "Official Site: http://code.google.com/p/fceugc/" +msgstr "Site Oficial: http://code.google.com/p/fceugc/" + +msgid "Official Site: http://code.google.com/p/snes9x-gx/" +msgstr "Site Oficial: http://code.google.com/p/snes9x-gx/" + +msgid "Official Site: http://code.google.com/p/vba-wii/" +msgstr "Site Oficial: http://code.google.com/p/vba-wii/" + +msgid "OK" +msgstr "OK" + +msgid "On" +msgstr "Ligado" + +msgid "Original" +msgstr "Original" + +msgid "Out of memory!" +msgstr "Memória insuficiente!" + +msgid "Out of memory: too many files!" +msgstr "Memória insuficiente: demasiados ficheiros!" + +msgid "P1" +msgstr "J1" + +msgid "P2" +msgstr "J2" + +msgid "P3" +msgstr "J3" + +msgid "P4" +msgstr "J4" + +msgid "PAL (50Hz)" +msgstr "PAL (50Hz)" + +msgid "PAL (60Hz)" +msgstr "PAL (60Hz)" + +msgid "Palette saved" +msgstr "Paleta gravada" + +msgid "Partial Stretch" +msgstr "Esticar Parcial" + +msgid "Pause" +msgstr "Pausa" + +msgid "Please Wait" +msgstr "Espere por favor" + +msgid "PLUS" +msgstr "MAIS" + +msgid "Portuguese" +msgstr "Português" + +msgid "Brazilian Portuguese" +msgstr "Português (BR)" + +msgid "Power off Wii" +msgstr "Desligar Wii" + +msgid "Preferences saved" +msgstr "Preferências gravadas" + +msgid "Press any button on the Classic Controller now. Press Home to clear the existing mapping." +msgstr "Pressione um botão no Comando Clássico. Pressione HOME para eliminar a configuração actual." + +msgid "Press any button on the GameCube Controller now. Press Home or the C-Stick in any direction to clear the existing mapping." +msgstr "Pressione um botão no Comando GameCube. Pressione HOME ou mova o Stick-C para eliminar a configuração actual." + +msgid "Press any button on the GameCube Controller now. Press the C-Stick in any direction to clear the existing mapping." +msgstr "Pressione um botão no Comando GameCube. Mova o Stick-C para eliminar a configuração actual." + +msgid "Press any button on the Wiimote now. Press Home to clear the existing mapping." +msgstr "Pressione um botão no Wii Remote. Pressione HOME para eliminar a configuração actual." + +msgid "Press any button on the Wiimote or Nunchuk now. Press Home to clear the existing mapping." +msgstr "Pressione um botão no Wii Remote ou no Nunchuk. Pressione HOME para eliminar a configuração actual." + +msgid "Progressive (480p)" +msgstr "Progressivo (480p)" + +msgid "Quit Game" +msgstr "Sair do Jogo" + +msgid "Quit this game? Any unsaved progress will be lost." +msgstr "Sair do Jogo? Qualquer progresso não gravado será perdido." + +msgid "R TRIG" +msgstr "R" + +msgid "RAM saving is not available for FDS games!" +msgstr "Gravar RAM não está disponível para jogos do FDS (Famicom Disk System)!" + +msgid "Reboot" +msgstr "Reiniciar" + +msgid "Rendering" +msgstr "Renderização" + +msgid "Reset" +msgstr "Reiniciar" + +msgid "Reset Game" +msgstr "Reiniciar Jogo" + +msgid "Reset this game? Any unsaved progress will be lost." +msgstr "Reiniciar Jogo? Qualquer progresso não gravado será perdido." + +msgid "Reset Mappings" +msgstr "Repor mapeamentos" + +msgid "Reset Settings" +msgstr "Repor configurações" + +msgid "Retry" +msgstr "Repetir" + +msgid "Return to Loader" +msgstr "Voltar ao Loader" + +msgid "Return to Wii Menu" +msgstr "Voltar ao Menu Wii" + +msgid "Right" +msgstr "Direita" + +msgid "RIGHT" +msgstr "DIREITA" + +msgid "Right Button" +msgstr "Botão direito" + +msgid "Rumble" +msgstr "Vibração" + +msgid "Save" +msgstr "Gravar" + +msgid "Save Device" +msgstr "Gravar no dispositivo" + +msgid "Save failed!" +msgstr "Falha ao gravar!" + +msgid "Save file not found" +msgstr "Ficheiro gravado não encontrado" + +msgid "Save Folder" +msgstr "Pasta de gravar" + +msgid "Save Game" +msgstr "Gravar Jogo" + +msgid "Save RAM and State?" +msgstr "Gravar RAM e o estado?" + +msgid "Save Snapshot?" +msgstr "Gravar Snapshot?" + +msgid "Save SRAM and Snapshot?" +msgstr "Gravar SRAM e Snapshot?" + +msgid "Save State?" +msgstr "Gravar estado?" + +msgid "Save successful" +msgstr "Gravado com sucesso" + +msgid "Saving" +msgstr "A gravar" + +msgid "Saving preferences..." +msgstr "A gravar preferências..." + +msgid "Saving..." +msgstr "A gravar..." + +msgid "Scaling" +msgstr "Escala" + +msgid "Screen Position" +msgstr "Posição do ecrã" + +msgid "Screen Zoom" +msgstr "Zoom do ecrã" + +msgid "Select" +msgstr "Seleccionar" + +msgid "Seek error!" +msgstr "Erro de posicionamento!" + +msgid "Settings" +msgstr "Configurações" + +msgid "Settings - Menu" +msgstr "Configurações - Menu" + +msgid "Settings - Network" +msgstr "Configurações - Rede" + +msgid "Settings - Saving & Loading" +msgstr "Configurações - Gravar & Carregar" + +msgid "SD Card" +msgstr "Cartão SD" + +msgid "SD card not found!" +msgstr "Cartão SD não encontrado!" + +msgid "Shift" +msgstr "Shift" + +msgid "Simp_chinese" +msgstr "Chinês Simp." + +msgid "SMB Share IP" +msgstr "IP do SMB" + +msgid "SMB Share Name" +msgstr "Nome do SMB" + +msgid "SMB Share Password" +msgstr "Palavra-passe do SMB" + +msgid "SMB Share Username" +msgstr "Nome de utilizador do SMB" + +msgid "Snapshot" +msgstr "Snapshot" + +msgid "Snapshot (Auto)" +msgstr "Snapshot (Auto)" + +msgid "SNES Controller" +msgstr "Comando SNES" + +msgid "SNES Controllers (2)" +msgstr "Comando SNES (2)" + +msgid "SNES Controllers (4)" +msgstr "Comando SNES (4)" + +msgid "SNES Controller - Classic Controller" +msgstr "Comando SNES - Comando Clássico" + +msgid "SNES Controller - GameCube Controller" +msgstr "Comando SNES - Comando GameCube" + +msgid "SNES Controller - Nunchuk + Wiimote" +msgstr "Comando SNES - Nunchuk + Wii Remote" + +msgid "SNES Controller - Wiimote" +msgstr "Comando SNES - Wii Remote" + +msgid "SNES Mouse" +msgstr "Rato SNES" + +msgid "SNES Mouse - GameCube Controller" +msgstr "Rato SNES - Comando GameCube" + +msgid "SNES Mouse - Wiimote" +msgstr "Rato SNES - Wii Remote" + +msgid "Snes9x - Copyright (c) Snes9x Team 1996 - 2006" +msgstr "Snes9x - Direitos de autor (c) Equipa Snes9x 1996 - 2006" + +msgid "Sound Effects Volume" +msgstr "Volume de Efeitos Sonoros" + +msgid "Spanish" +msgstr "Espanhol" + +msgid "Sprite Limit" +msgstr "Limite de Sprites" + +msgid "SRAM file not found" +msgstr "Ficheiro SRAM não encontrado" + +msgid "State" +msgstr "Estado" + +msgid "State (Auto)" +msgstr "Estado (Auto)" + +msgid "State file not found" +msgstr "Ficheiro de estado não encontrado" + +msgid "Stretch to Fit" +msgstr "Esticar para Caber" + +msgid "Superscope" +msgstr "SuperScope" + +msgid "Superscope - GameCube Controller" +msgstr "SuperScope - Comando GameCube" + +msgid "Superscope - Wiimote" +msgstr "SuperScope - Wii Remote" + +msgid "This software is open source and may be copied," +msgstr "Este software é de código aberto e pode ser copiado," + +msgid "Trad_chinese" +msgstr "Chinês Trad." + +msgid "Unable to initialize network!" +msgstr "Não foi possível iniciar ligação!" + +msgid "Unable to locate a load device!" +msgstr "Dispositivo de carregamento não encontrado!" + +msgid "Unable to locate a save device!" +msgstr "Dispositivo de gravar não encontrado!" + +msgid "Unable to open snapshot!" +msgstr "Não foi possível abrir snapshot!" + +msgid "Unfiltered" +msgstr "Sem filtro" + +msgid "Unknown file type!" +msgstr "Tipo de ficheiro desconhecido!" + +msgid "Unrecognized DVD format." +msgstr "Formato de DVD desconhecido." + +msgid "Unrecognized file extension!" +msgstr "Extensão de ficheiro desconhecida!" + +msgid "Up" +msgstr "Cima" + +msgid "UP" +msgstr "CIMA" + +msgid "Up One Level" +msgstr ".." + +msgid "Update Available" +msgstr "Actualização Disponível" + +msgid "Update failed!" +msgstr "A actualização falhou!" + +msgid "Update later" +msgstr "Actualizar depois" + +msgid "Update now" +msgstr "Actualizar agora" + +msgid "Update successful!" +msgstr "Actualização bem sucedida!" + +msgid "USB drive not found!" +msgstr "Drive USB não encontrado!" + +msgid "USB Mass Storage" +msgstr "Dispositivo USB" + +msgid "Vertical" +msgstr "Vertical" + +msgid "Video" +msgstr "Vídeo" + +msgid "Video Mode" +msgstr "Modo de Vídeo" + +msgid "VM8: Unknown page type!" +msgstr "VM8: Tipo de página desconhecida!" + +msgid "VM16: Unknown page type!" +msgstr "VM16: Tipo de página desconhecida!" + +msgid "VM32: Unknown page type!" +msgstr "VM32: Tipo de página desconhecida!" + +msgid "Wiimote" +msgstr "Wii Remote" + +msgid "Wiimote Orientation" +msgstr "Orientação do Wii Remote" + +msgid "Yes" +msgstr "Sim" + +msgid "Zapper" +msgstr "Zapper" + +msgid "Zapper Crosshair" +msgstr "Mira do Zapper" + +msgid "Catalan" +msgstr "Catalão" + +msgid "The current IOS has been altered (fake-signed). Functionality and/or stability may be adversely affected." +msgstr "O IOS actual foi alterado (fake-signed). A funcionalidade e/ou estabilidade podem ser adversamente afectadas." + +msgid "The current IOS is unsupported. Functionality and/or stability may be adversely affected." +msgstr "O IOS actual não é suportado. A funcionalidade e/ou estabilidade podem ser adversamente afectadas." + +msgid "Turkish" +msgstr "Turco" diff --git a/plugins/snes9x_gx/source/lang/pt_br.lang b/plugins/snes9x_gx/source/lang/pt_br.lang new file mode 100644 index 00000000..c81ba64e --- /dev/null +++ b/plugins/snes9x_gx/source/lang/pt_br.lang @@ -0,0 +1,857 @@ +msgid "&" +msgstr "&" + +msgid "16:9 Correction" +msgstr "Correção 16:9" + +msgid "7z decompression failed: Archive contains too many files" +msgstr "Decompressão 7z falhou: o arquivo contém arquivos demais" + +msgid "7z decompression failed: Failed to read file data" +msgstr "Decompressão 7z falhou: erro na leitura do arquivo" + +msgid "7z decompression failed: File is corrupt" +msgstr "Decompressão 7z falhou: arquivo corrompido" + +msgid "7z decompression failed: File is corrupt (CRC mismatch)" +msgstr "Decompressão 7z falhou: arquivo corrompido (erro de CRC)" + +msgid "7z decompression failed: File uses too high of compression settings (dictionary size is too large)" +msgstr "Decompressão 7z falhou: O arquivo usa parâmetros de compressão muito altos (o tamanho de dicionário é muito grande)" + +msgid "7z decompression failed: File uses unsupported compression settings" +msgstr "Decompressão 7z falhou: O arquivo usa parâmetros não-suportados" + +msgid "A (Rapid)" +msgstr "A (Rápido)" + +msgid "Additional coding" +msgstr "Programação adicional" + +msgid "Aim Offscreen" +msgstr "Mirar fora da tela" + +msgid "An update is available!" +msgstr "Atualização disponível!" + +msgid "Are you sure that you want to reset this game? Any unsaved progress will be lost." +msgstr "Quer mesmo resetar este jogo? Qualquer progresso não-salvo será perdido." + +msgid "Are you sure that you want to reset your mappings?" +msgstr "Quer mesmo resetar os controles?" + +msgid "Are you sure that you want to reset your settings?" +msgstr "Quer mesmo resetar as configurações?" + +msgid "Maintain Aspect Ratio" +msgstr "Manter Proporções" + +msgid "Attempting to determine load device..." +msgstr "Determinando dispositivo de carregamento..." + +msgid "Attempting to determine save device..." +msgstr "Determinando dispositivo de saves..." + +msgid "Auto" +msgstr "Auto" + +msgid "Auto Detect" +msgstr "Auto Detectar" + +msgid "Auto Load" +msgstr "Auto Carregar" + +msgid "Auto Save" +msgstr "Auto Salvar" + +msgid "Automatic (Recommended)" +msgstr "Automático (Recomendado)" + +msgid "B (Rapid)" +msgstr "B (Rápido)" + +msgid "Back" +msgstr "Voltar" + +msgid "Both" +msgstr "Ambos" + +msgid "Controles" +msgstr "Controles" + +msgid "Button Mappings" +msgstr "Redefinir Botões" + +msgid "Cancel" +msgstr "Cancelar" + +msgid "Caps" +msgstr "Maiusc." + +msgid "Cheats" +msgstr "Cheats" + +msgid "Cheats file not found!" +msgstr "Arquivo de Cheats não encontrado!" + +msgid "Cheats Folder" +msgstr "Pasta de Cheats" + +msgid "Choose Game" +msgstr "Escolher Jogo" + +msgid "Classic Controller" +msgstr "Controle Clássico" + +msgid "Close" +msgstr "Fechar" + +msgid "Coding" +msgstr "Programação" + +msgid "Coding & menu design" +msgstr "Programação & desing do menu" + +msgid "Compressed GBA files are not supported!" +msgstr "Arquivos comprimidos do GBA não são suportados!" + +msgid "Connecting to network share..." +msgstr "Conectando ao compartilhamento de rede..." + +msgid "Controller" +msgstr "Controle" + +msgid "Cover View" +msgstr "Visualização de Capas" + +msgid "Covers Folder" +msgstr "Pasta de Capas" + +msgid "Credits" +msgstr "Créditos" + +msgid "Cropping" +msgstr "Recorte" + +msgid "Crosshair" +msgstr "Alvo" + +msgid "Cursor" +msgstr "Cursor" + +msgid "Data DVD" +msgstr "DVD de Dados" + +msgid "Default" +msgstr "Padrão" + +msgid "Directory name is too long!" +msgstr "O nome de diretório é muito grande!" + +msgid "Disabled" +msgstr "Desativado" + +msgid "DISABLED" +msgstr "DESATIVADO" + +msgid "distributed, or modified under the terms of the" +msgstr "distribuído, ou modificado sob os termos de" + +msgid "Don't Save" +msgstr "Não Salvar" + +msgid "Down" +msgstr "Abaixo" + +msgid "DOWN" +msgstr "ABAIXO" + +msgid "Downloading..." +msgstr "Baixando..." + +msgid "Dutch" +msgstr "Holandês" + +msgid "Empty or invalid ZIP file!" +msgstr "Arquivo ZIP vazio ou inválido" + +msgid "Enabled" +msgstr "Ativado" + +msgid "ENABLED" +msgstr "ATIVADO" + +msgid "English" +msgstr "Inglês" + +msgid "Erro" +msgstr "Erro" + +msgid "Error - Invalid ZIP file!" +msgstr "Erro - Arquivo ZIP inválido!" + +msgid "Error creating file!" +msgstr "Erro ao criar o arquivo!" + +msgid "Error loading game!" +msgstr "Erro ao carregar o jogo!" + +msgid "Error opening archive!" +msgstr "Erro ao abrir o arquivo!" + +msgid "Error opening directory!" +msgstr "Erro ao abrir o diretório!" + +msgid "Error opening file!" +msgstr "Erro ao abrir o arquivo!" + +msgid "Error reading file!" +msgstr "Erro ao ler o arquivo!" + +msgid "Error saving file!" +msgstr "Erro ao salvar o arquivo!" + +msgid "Exit" +msgstr "Sair" + +msgid "Exit Action" +msgstr "Ação de Saída" + +msgid "Failed to connect to network share." +msgstr "Falha ao conectar-se ao compartilhamento de rede." + +msgid "FDS BIOS file is invalid!" +msgstr "Arquivo de BIOS do FDS (Famicom Disk System) inválido!" + +msgid "FDS BIOS file not found!" +msgstr "Arquivo de BIOS de FDS (Famicom Disk System) não encontrado!" + +msgid "Filtered" +msgstr "Filtrado" + +msgid "Filtering" +msgstr "Filtragem" + +msgid "Fire" +msgstr "Fogo" + +msgid "French" +msgstr "Francês" + +msgid "GBA Screen Zoom" +msgstr "Zoom da tela do GBA" + +msgid "Game Genie ROM not found!" +msgstr "Não foi encontrada a ROM do Game Genie!" + +msgid "Game Settings" +msgstr "Configuração" + +msgid "Game Settings - Button Mappings" +msgstr "Configuração - Redefinir Botões" + +msgid "Game Settings - Cheats" +msgstr "Configuração - Cheats" + +msgid "Game Settings - Video" +msgstr "Configuração - Vídeo" + +msgid "Game Timing" +msgstr "Timing de jogo" + +msgid "Game Genie DISABLED" +msgstr "Game Genie DESATIVADO" + +msgid "Game Genie ENABLED" +msgstr "Game Genie ATIVADO" + +msgid "GameCube Controller" +msgstr "Controle de GameCube" + +msgid "German" +msgstr "Alemão" + +msgid "GNU General Public License (GPL) Version 2." +msgstr "GNU General Public License (GPL) Versão 2." + +msgid "Go Back" +msgstr "Voltar" + +msgid "Horizontal" +msgstr "Horizontal" + +msgid "Information" +msgstr "Informação" + +msgid "Initializing network..." +msgstr "Inicializando rede..." + +msgid "Insert Coin" +msgstr "Inserir Moeda" + +msgid "Insert Coin / Switch Disk" +msgstr "Inserir Moeda / Trocar Disco" + +msgid "Invalid file size!" +msgstr "Tamanho de arquivo inválido!" + +msgid "Invalid game file!" +msgstr "Arquivo de jogo inválido!" + +msgid "Invalid network settings - Check settings.xml." +msgstr "Configuração de rede inválida - Verifique o arquivo settings.xml." + +msgid "Invalid network settings - Share IP is blank." +msgstr "Configuração de rede inválida - IP em branco." + +msgid "Invalid network settings - Share name is blank." +msgstr "Configuração de rede inválida - Nome em branco." + +msgid "Invalid save file" +msgstr "Arquivo de save inválido" + +msgid "Invalid state file" +msgstr "Arquivo de state inválido" + +msgid "Italian" +msgstr "Italiano" + +msgid "Japanese" +msgstr "Japonês" + +msgid "Justifier" +msgstr "Konami Justifier" + +msgid "Justifier - GameCube Controller" +msgstr "Konami Justifier - Controle de GameCube" + +msgid "Justifier - Wiimote" +msgstr "Konami Justifier - Wiimote" + +msgid "Korean" +msgstr "Coreano" + +msgid "L TRIG" +msgstr "L" + +msgid "Language" +msgstr "Idioma" + +msgid "Languages Folder" +msgstr "Pasta de Idiomas" + +msgid "Left" +msgstr "Esquerda" + +msgid "LEFT" +msgstr "ESQUERDA" + +msgid "Left Button" +msgstr "Botão Esquerdo" + +msgid "Load" +msgstr "Carregar" + +msgid "Load Device" +msgstr "Dispositivo de Carregamento" + +msgid "Load Folder" +msgstr "Pasta dos Jogos" + +msgid "Load Game" +msgstr "Carregar Jogo" + +msgid "Loading" +msgstr "Carregando" + +msgid "Loading DVD..." +msgstr "Carregando DVD..." + +msgid "Loading patch..." +msgstr "Carregando patch..." + +msgid "Loading..." +msgstr "Carregando..." + +msgid "Main Menu" +msgstr "Menu Principal" + +msgid "Match GC Controls" +msgstr "Coincidir Controles do GC" + +msgid "Match Wii Controls" +msgstr "Coincidir Controles do Wii" + +msgid "Maximum filepath length reached!" +msgid "Tamanho máximo de caminho de arquivo alcançado!" + +msgid "Menu" +msgstr "Menu" + +msgid "Menu artwork" +msgstr "Desenho do Menu" + +msgid "Menu sound" +msgstr "Som do Menu" + +msgid "MINUS" +msgstr "MENOS" + +msgid "Music Volume" +msgstr "Volume da Música" + +msgid "Mute" +msgstr "Silenciar" + +msgid "NES Controller" +msgstr "Controle de NES" + +msgid "NES Controllers (2)" +msgstr "Controles de NES (2)" + +msgid "NES Controllers (4)" +msgstr "Controles de NES (4)" + +msgid "NES Zapper" +msgstr "Nintendo Zapper" + +msgid "Network" +msgstr "Rede" + +msgid "Network Share" +msgstr "Compartilhamento de Rede" + +msgid "New" +msgstr "Novo" + +msgid "New Snapshot" +msgstr "Novo State" + +msgid "New SRAM" +msgstr "Nova SRAM" + +msgid "No" +msgstr "Não" + + +msgid "No data to save!" +msgstr "Nenhum dado a salvar!" + +msgid "No disc inserted!" +msgstr "Nenhum disco inserido!" + +msgid "No SRAM data to save!" +msgstr "Nenhum dado de SRAM a salvar!" + + +msgid "No game saves found." +msgstr "Nenhum save foi encontrado." + +msgid "None" + +msgstr "Nenhum" + +msgid "NTSC (480i)" +msgstr "NTSC (480i)" + +msgid "Nunchuk" +msgstr "Nunchuk" + +msgid "Off" +msgstr "Off" + +msgid "Official Site: http://code.google.com/p/fceugc/" +msgstr "Site Oficial: http://code.google.com/p/fceugc/" + +msgid "Official Site: http://code.google.com/p/snes9x-gx/" +msgstr "Site Oficial: http://code.google.com/p/snes9x-gx/" + +msgid "Official Site: http://code.google.com/p/vba-wii/" +msgstr "Site Oficial: http://code.google.com/p/vba-wii/" + +msgid "OK" +msgstr "OK" + +msgid "On" +msgstr "On" + +msgid "Original" +msgstr "Original" + +msgid "Out of memory!" +msgstr "Memória insuficiente!" + +msgid "Out of memory: too many files!" +msgstr "Memória insuficiente: arquivos demais!" + +msgid "P1" +msgstr "P1" + +msgid "P2" +msgstr "P2" + +msgid "P3" +msgstr "P3" + +msgid "P4" +msgstr "P4" + +msgid "PAL (50Hz)" +msgstr "PAL (50Hz)" + +msgid "PAL (60Hz)" +msgstr "PAL (60Hz)" + +msgid "Palette saved" +msgstr "Paleta salva" + +msgid "Partial Stretch" +msgstr "Esticamento Parcial" + +msgid "Pause" +msgstr "Pausa" + +msgid "Please Wait" +msgstr "Espere por favor" + +msgid "PLUS" +msgstr "MAIS" + +msgid "Portuguese" +msgstr "Português" + +msgid "Power off Wii" +msgstr "Desligar Wii" + +msgid "Preferences saved" +msgstr "Preferências salvas" + +msgid "Press any button on the Classic Controller now. Press Home to clear the existing mapping." +msgstr "Pressione um botão no Controle Clássico. Pressione HOME para eliminar a configuração atual." + +msgid "Press any button on the GameCube Controller now. Press Home or the C-Stick in any direction to clear the existing mapping." +msgstr "Pressione um botão no Controle de GameCube. Pressione HOME ou mova o Stick-C para eliminar a configuração atual." + +msgid "Press any button on the GameCube Controller now. Press the C-Stick in any direction to clear the existing mapping." +msgstr "Pressione um botão no Controle de GameCube. Mova o Stick-C para eliminar a configuração atual." + +msgid "Press any button on the Wiimote now. Press Home to clear the existing mapping." +msgstr "Pressione um botão no Wiimote. Pressione HOME para eliminar a configuração atual." + +msgid "Press any button on the Wiimote or Nunchuk now. Press Home to clear the existing mapping." +msgstr "Pressione um botão no Wiimote ou no Nunchuk. Pressione HOME para eliminar a configuração atual." + +msgid "Progressive (480p)" +msgstr "Progressive (480p)" + +msgid "Quit Game" +msgstr "Sair do Jogo" + +msgid "Quit this game? Any unsaved progress will be lost." +msgstr "Sair do Jogo? Qualquer progresso não-salvo será perdido." + +msgid "R TRIG" +msgstr "R" + +msgid "RAM saving is not available for FDS games!" +msgstr "Salvamento de RAM não está disponível para jogos do FDS (Famicom Disk System)!" + +msgid "Reboot" +msgstr "Reiniciar" + +msgid "Rendering" +msgstr "Renderização" + +msgid "Reset" +msgstr "Resetar" + +msgid "Reset Game" +msgstr "Resetar Jogo" + +msgid "Reset this game? Any unsaved progress will be lost." +msgstr "Resetar Jogo? Qualquer progresso não-salvo será perdido." + +msgid "Reset Mappings" +msgstr "Resetar Configuração" + +msgid "Reset Settings" +msgstr "Resetar" + +msgid "Retry" +msgstr "Tentar de novo" + +msgid "Return to Loader" +msgstr "Voltar ao Loader" + +msgid "Return to Wii Menu" +msgstr "Voltar ao Wii Menu" + +msgid "Right" +msgstr "Direita" + +msgid "RIGHT" +msgstr "Direita" + +msgid "Right Button" +msgstr "Botão direito" + +msgid "Rumble" +msgstr "Vibração" + +msgid "Save" +msgstr "Salvar" + +msgid "Save Device" +msgstr "Dispositivo de save" + +msgid "Save failed!" +msgstr "Falha ao salvar!" + +msgid "Save file not found" +msgstr "Arquivo de save não encontrado" + +msgid "Save Folder" +msgstr "Pasta de Saves" + +msgid "Save Game" +msgstr "Salvar Jogo" + +msgid "Save RAM and State?" +msgstr "Salvar a RAM e o State?" + +msgid "Save Snapshot?" +msgstr "Salvar State?" + +msgid "Save SRAM and Snapshot?" +msgstr "Salvar SRAM e State?" + +msgid "Save State?" +msgstr "Salvar State?" + +msgid "Save successful" +msgstr "Salvo com sucesso" + +msgid "Saving" +msgstr "Salvando" + +msgid "Saving preferences..." +msgstr "Salvando preferências..." + +msgid "Saving..." +msgstr "Salvando..." + +msgid "Scaling" +msgstr "Ajuste de Tela" + +msgid "Screen Position" +msgstr "Posição da Tela" + +msgid "Screen Zoom" +msgstr "Zoom da Tela" + +msgid "Select" +msgstr "Select" + +msgid "Seek error!" +msgstr "Erro de posicionamento!" + +msgid "Settings" +msgstr "Configuração" + +msgid "Settings - Menu" +msgstr "Configuração - Menu" + +msgid "Settings - Network" +msgstr "Configuração - Rede" + +msgid "Settings - Saving & Loading" +msgstr "Configuração - Salvar & Carregar" + +msgid "SD Card" +msgstr "Cartão SD" + +msgid "SD card not found!" +msgstr "Cartão SD não encontrado!" + +msgid "Shift" +msgstr "Maius." + +msgid "Simp_chinese" +msgstr "Chines Simp." + +msgid "SMB Share IP" +msgstr "IP do SMB" + +msgid "SMB Share Name" +msgstr "Nome do SMB" + +msgid "SMB Share Password" +msgstr "Senha do SMB" + +msgid "SMB Share Username" +msgstr "Nome de Usuário do SMB" + +msgid "Snapshot" +msgstr "State" + +msgid "Snapshot (Auto)" +msgstr "State (Auto)" + +msgid "SNES Controller" +msgstr "Controle SNES" + +msgid "SNES Controllers (2)" +msgstr "Controle SNES (2)" + +msgid "SNES Controllers (4)" +msgstr "Controle SNES (4)" + +msgid "SNES Controller - Classic Controller" +msgstr "Controle SNES - Controle Clássico" + +msgid "SNES Controller - GameCube Controller" +msgstr "Controle SNES - Controle de GameCube" + +msgid "SNES Controller - Nunchuk + Wiimote" +msgstr "Controle SNES - Nunchuk + Wiimote" + +msgid "SNES Controller - Wiimote" +msgstr "Controle SNES - Wiimote" + +msgid "SNES Mouse" +msgstr "Mouse SNES" + +msgid "SNES Mouse - GameCube Controller" +msgstr "Mouse SNES - Controle de GameCube" + +msgid "SNES Mouse - Wiimote" +msgstr "Mouse SNES - Wiimote" + +msgid "Snes9x - Copyright (c) Snes9x Team 1996 - 2006" +msgstr "Snes9x - Copyright (c) Snes9x Team 1996 - 2006" + +msgid "Sound Effects Volume" +msgstr "Volume dos Efeitos Sonoros" + +msgid "Spanish" +msgstr "Espanhol" + +msgid "Sprite Limit" +msgstr "Limite de Sprites" + +msgid "SRAM file not found" +msgstr "Arquivo de SRAM não encontrado" + +msgid "State" +msgstr "Salvar state" + +msgid "State (Auto)" +msgstr "State (Auto)" + +msgid "State file not found" +msgstr "Arquivo de State não encontrado" + +msgid "Stretch to Fit" +msgstr "Esticar para Caber" + +msgid "Superscope" +msgstr "Super Scope" + +msgid "Superscope - GameCube Controller" +msgstr "Super Scope - Controle de GameCube" + +msgid "Superscope - Wiimote" +msgstr "Super Scope - Wiimote" + +msgid "This software is open source and may be copied," +msgstr "Este software é de código aberto e pode ser copiado," + +msgid "Trad_chinese" +msgstr "Chinês Trad." + +msgid "Unable to initialize network!" +msgstr "Não foi possível inicializar a rede!" + +msgid "Unable to locate a load device!" +msgstr "Dispositivo de carregamento não encontrado!" + +msgid "Unable to locate a save device!" +msgstr "Dispositivo de saves não encontrado!" + +msgid "Unable to open snapshot!" +msgstr "Não foi possível carregar o state!" + +msgid "Unfiltered" +msgstr "Sem filtro" + +msgid "Unknown file type!" +msgstr "Tipo de arquivo desconhecido!" + +msgid "Unrecognized DVD format." +msgstr "Formato de DVD desconhecido." + +msgid "Unrecognized file extension!" +msgstr "Extensão de arquivo desconhecida!" + +msgid "Up" +msgstr "Acima" + +msgid "UP" +msgstr "Acima" + +msgid "Up One Level" +msgstr "Um Nível Acima" + +msgid "Update Available" +msgstr "Atualização Disponível" + +msgid "Update failed!" +msgstr "Atualização falhou!" + +msgid "Update later" +msgstr "Atualizar depois" + +msgid "Update now" +msgstr "Atualizar agora" + +msgid "Update successful!" +msgstr "Atualização concluída!" + +msgid "USB drive not found!" +msgstr "Drive USB não encontrado!" + +msgid "USB Mass Storage" +msgstr "Dispositivo USB Flash" + +msgid "Vertical" +msgstr "Vertical" + +msgid "Video" +msgstr "Vídeo" + +msgid "Video Mode" +msgstr "Modo de Vídeo" + +msgid "VM8: Unknown page type!" +msgstr "VM8: Tipo de página desconhecida!" + +msgid "VM16: Unknown page type!" +msgstr "VM16: Tipo de página desconhecida!" + +msgid "VM32: Unknown page type!" +msgstr "VM32: Tipo de página desconhecida!" + +msgid "Wiimote" +msgstr "Wiimote" + +msgid "Wiimote Orientation" +msgstr "Orientação do Wiimote" + +msgid "Yes" +msgstr "Sim" + +msgid "Zapper" +msgstr "Nintendo Zapper" + +msgid "Zapper Crosshair" +msgstr "Alvo do Zapper" diff --git a/plugins/snes9x_gx/source/lang/tr.lang b/plugins/snes9x_gx/source/lang/tr.lang new file mode 100644 index 00000000..e2e5adcb --- /dev/null +++ b/plugins/snes9x_gx/source/lang/tr.lang @@ -0,0 +1,935 @@ +msgid "&" +msgstr "&" + +msgid "16:9 Correction" +msgstr "16:9 Düzeltmesi" + +msgid "7z decompression failed: Archive contains too many files" +msgstr "7z dosya çıkarma baÅŸarısız: ArÅŸiv çok fazla dosya içeriyor" + +msgid "7z decompression failed: Failed to read file data" +msgstr "7z dosya çıkarma baÅŸarısız: Dosya verisi okunamadı" + +msgid "7z decompression failed: File is corrupt" +msgstr "7z dosya çıkarma baÅŸarısız: Dosya bozuk" + +msgid "7z decompression failed: File is corrupt (CRC mismatch)" +msgstr "7z dosya çıkarma baÅŸarısız: Dosya bozuk (CRC uyumsuz)" + +msgid "7z decompression failed: File uses too high of compression settings (dictionary size is too large)" +msgstr "7z dosya çıkarma baÅŸarısız: Dosya çok yüksek sıkıştırma ayarları kullanıyor (sözlük boyutu çok büyük)" + +msgid "7z decompression failed: File uses unsupported compression settings" +msgstr "7z dosya çıkarma baÅŸarısız: Dosya desteklenmeyen sıkıştırma ayarları kullanıyor" + +msgid "A (Rapid)" +msgstr "A (Seri)" + +msgid "Additional coding" +msgstr "Ä°lave kod" + +msgid "Aim Offscreen" +msgstr "Ekran Dışına Hedefleme" + +msgid "An update is available!" +msgstr "Güncelleme mevcut!" + +msgid "Are you sure that you want to reset this game? Any unsaved progress will be lost." +msgstr "Oyunu tekrar baÅŸlatmak istediÄŸinizden emin misiniz? KaydedilmemiÅŸ tüm veriler kaybolacak." + +msgid "Are you sure that you want to reset your mappings?" +msgstr "Buton ayarlarını sıfırlamak istediÄŸinizden emin misiniz?" + +msgid "Are you sure that you want to reset your settings?" +msgstr "Ayarları sıfırlamak istediÄŸinizden emin misiniz?" + +msgid "Maintain Aspect Ratio" +msgstr "En-Boy Oranını Koru" + +msgid "Attempting to determine load device..." +msgstr "Yükleme aygıtı belirlenmeye çalışılıyor..." + +msgid "Attempting to determine save device..." +msgstr "Kayıt aygıtı belirlenmeye çalışılıyor..." + +msgid "Auto" +msgstr "Otomatik" + +msgid "Auto Detect" +msgstr "Otomatik Algıla" + +msgid "Auto Load" +msgstr "Otomatik Yükleme" + +msgid "Auto Save" +msgstr "Otomatik Kayıt" + +msgid "Automatic" +msgstr "Otomatik" + +msgid "Automatic (Recommended)" +msgstr "Otomatik (Önerilen)" + +msgid "B (Rapid)" +msgstr "B (Seri)" + +msgid "Back" +msgstr "Sil" + +msgid "Both" +msgstr "Her Ä°kisi" + +msgid "Controles" +msgstr "Oyun Kumandaları" + +msgid "Button Mapping" +msgstr "Buton Ayarı" + +msgid "Button Mappings" +msgstr "Buton Ayarları" + +msgid "Cancel" +msgstr "Ä°ptal" + +msgid "Caps" +msgstr "Caps" + +msgid "Cheats" +msgstr "Hile" + +msgid "Cheats file not found!" +msgstr "Hile dosyası bulunamadı!" + +msgid "Cheats Folder" +msgstr "Hile Dizini" + +msgid "Choose Game" +msgstr "Oyun Seç" + +msgid "Classic Controller" +msgstr "Klasik Oyun Kumandası" + +msgid "Close" +msgstr "Kapat" + +msgid "Coding" +msgstr "Kod" + +msgid "Coding & menu design" +msgstr "Kod & Menü Tasarımı" + +msgid "Compressed GBA files are not supported!" +msgstr "Sıkıştırılmış GBA dosyaları desteklenmiyor!" + +msgid "Connecting to network share..." +msgstr "AÄŸ paylaşımına baÄŸlanıyor..." + +msgid "Controller" +msgstr "Oyun Kumandası" + +msgid "Cover View" +msgstr "Kapak" + +msgid "Covers Folder" +msgstr "Kapak Dizini" + +msgid "Credits" +msgstr "Hakkında" + +msgid "Cropping" +msgstr "Kırpma" + +msgid "Crosshair" +msgstr "Artı Ä°mleci" + +msgid "Cursor" +msgstr "Ä°mleç" + +msgid "Data DVD" +msgstr "Veri DVD'si" + +msgid "Default" +msgstr "Varsayılan" + +msgid "Directory name is too long!" +msgstr "Dizin adı çok uzun!" + +msgid "Disabled" +msgstr "Kapalı" + +msgid "DISABLED" +msgstr "KAPALI" + +msgid "distributed, or modified under the terms of the" +msgstr "GNU Genel Kamu Lisansı (GPL) Sürüm 2'nin koÅŸulları altında" + +msgid "Don't Save" +msgstr "Kaydetme" + +msgid "Down" +msgstr "AÅŸağı" + +msgid "DOWN" +msgstr "AÅžAÄžI" + +msgid "Downloading..." +msgstr "Ä°ndiriliyor..." + +msgid "Dutch" +msgstr "Flemenkçe" + +msgid "Empty or invalid ZIP file!" +msgstr "BoÅŸ veya geçersiz ZIP dosyası!" + +msgid "Enabled" +msgstr "Açık" + +msgid "ENABLED" +msgstr "AÇIK" + +msgid "English" +msgstr "Ä°ngilizce" + +msgid "Error" +msgstr "Hata" + +msgid "Error - Invalid ZIP file!" +msgstr "Hata - Geçersiz ZIP dosyası!" + +msgid "Error creating file!" +msgstr "Dosya oluÅŸturulamadı!" + +msgid "Error loading game!" +msgstr "Oyun yüklenemedi!" + +msgid "Error opening archive!" +msgstr "ArÅŸiv açılamadı!" + +msgid "Error opening directory!" +msgstr "Dizin açılamadı!" + +msgid "Error opening file!" +msgstr "Dosya açılamadı!" + +msgid "Error reading file!" +msgstr "Dosya okunamadı!" + +msgid "Error saving file!" +msgstr "Dosya kaydedilemedi!" + +msgid "Exit" +msgstr "Çıkış" + +msgid "Exit Action" +msgstr "Çıkış Eylemi" + +msgid "Failed to connect to network share." +msgstr "AÄŸ paylaşımına baÄŸlanılamadı." + +msgid "FDS BIOS file is invalid!" +msgstr "Geçersiz FDS BIOS dosyası!" + +msgid "FDS BIOS file not found!" +msgstr "FDS BIOS dosyası bulunamadı!" + +msgid "Filtered" +msgstr "Filtre Var" + +msgid "Filtering" +msgstr "Filtreleme" + +msgid "Fire" +msgstr "AteÅŸ" + +msgid "French" +msgstr "Fransızca" + +msgid "GBA Screen Zoom" +msgstr "GBA Ekran YakınlaÅŸtırması" + +msgid "Game Genie ROM not found!" +msgstr "Game Genie ROM'u bulunamadı!" + +msgid "Game Settings" +msgstr "Oyun Ayarları" + +msgid "Game Settings - Button Mappings" +msgstr "Oyun Ayarları - Buton Ayarları" + +msgid "Game Settings - Cheats" +msgstr "Oyun Ayarları - Hileler" + +msgid "Game Settings - Video" +msgstr "Oyun Ayarları - Ekran" + +msgid "Game Timing" +msgstr "Oyun Zamanlaması" + +msgid "Game Genie DISABLED" +msgstr "Game Genie KAPALI" + +msgid "Game Genie ENABLED" +msgstr "Game Genie AÇIK" + +msgid "GameCube Controller" +msgstr "GameCube Oyun Kumandası" + +msgid "German" +msgstr "Almanca" + +msgid "GNU General Public License (GPL) Version 2." +msgstr "kopyalanabilir, dağıtılabilir ve deÄŸiÅŸtirilebilir." + +msgid "Go Back" +msgstr "Geri Dön" + +msgid "Horizontal" +msgstr "Yatay" + +msgid "Information" +msgstr "Bilgi" + +msgid "Initializing network..." +msgstr "AÄŸ baÄŸlantısı baÅŸlatılıyor..." + +msgid "Insert Coin" +msgstr "Jeton Atın" + +msgid "Insert Coin / Switch Disk" +msgstr "Jeton Atın / Diski DeÄŸiÅŸtirin" + +msgid "Invalid file size!" +msgstr "Geçersiz dosya boyutu!" + +msgid "Invalid game file!" +msgstr "Geçersiz oyun dosyası!" + +msgid "Invalid network settings - Check settings.xml." +msgstr "Geçersiz aÄŸ baÄŸlantısı ayarları - settings.xml dosyasını kontrol ediniz." + +msgid "Invalid network settings - Share IP is blank." +msgstr "Geçersiz aÄŸ baÄŸlantısı ayarları - IP paylaşımı boÅŸ." + +msgid "Invalid network settings - Share name is blank." +msgstr "Geçersiz aÄŸ baÄŸlantısı ayarları - Paylaşım adı boÅŸ." + +msgid "Invalid save file" +msgstr "Geçersiz kayıt dosyası" + +msgid "Invalid state file" +msgstr "Geçersiz durum dosyası" + +msgid "Italian" +msgstr "Ä°talyanca" + +msgid "Japanese" +msgstr "Japonca" + +msgid "Justifier" +msgstr "Justifier Tabanca" + +msgid "Justifier - GameCube Controller" +msgstr "Justifier Tabanca - GameCube Oyun Kumandası" + +msgid "Justifier - Wiimote" +msgstr "Justifier Tabanca - Wii Kumanda" + +msgid "Korean" +msgstr "Korece" + +msgid "L TRIG" +msgstr "L Mandalı" + +msgid "Language" +msgstr "Dil" + +msgid "Languages Folder" +msgstr "Dil Dizini" + +msgid "Left" +msgstr "Sol" + +msgid "LEFT" +msgstr "SOL" + +msgid "Left Button" +msgstr "Sol Buton" + +msgid "Load" +msgstr "Yükle" + +msgid "Load Device" +msgstr "Yükleme Aygıtı" + +msgid "Load Folder" +msgstr "Yükleme Dizini" + +msgid "Load Game" +msgstr "Oyun Yükle" + +msgid "Loading" +msgstr "Yükleme" + +msgid "Loading DVD..." +msgstr "DVD yükleniyor..." + +msgid "Loading patch..." +msgstr "Yama dosyası yükleniyor..." + +msgid "Loading..." +msgstr "Yükleniyor..." + +msgid "Main Menu" +msgstr "Ana Menü" + +msgid "Match GC Controls" +msgstr "GC Kumandalarına EÅŸleÅŸtir" + +msgid "Match Wii Controls" +msgstr "Wii Kumandalarına EÅŸleÅŸtir" + +msgid "Maximum filepath length reached!" +msgid "Maksimum dizin yolu uzunluÄŸuna ulaşıldı!" + +msgid "Menu" +msgstr "Menü" + +msgid "Menu artwork" +msgstr "Menü Görselleri" + +msgid "Menu sound" +msgstr "Menü Sesleri" + +msgid "MINUS" +msgstr "EKSÄ°" + +msgid "Music Volume" +msgstr "Müzik Sesleri" + +msgid "Mute" +msgstr "Sessiz" + +msgid "NES Controller" +msgstr "NES Oyun Kumandası" + +msgid "NES Controllers (2)" +msgstr "NES Oyun Kumandası (2)" + +msgid "NES Controllers (4)" +msgstr "NES Oyun Kumandası (4)" + +msgid "NES Zapper" +msgstr "NES Zapper Tabanca" + +msgid "Network" +msgstr "AÄŸ" + +msgid "Network Share" +msgstr "AÄŸ Paylaşımı" + +msgid "New" +msgstr "Yeni" + +msgid "New Snapshot" +msgstr "Yeni Enstantane" + +msgid "New SRAM" +msgstr "Yeni SRAM" + +msgid "No" +msgstr "Hayır" + +msgid "No data to save!" +msgstr "Kaydedilecek veri yok!" + +msgid "No disc inserted!" +msgstr "Disk takılmamış!" + +msgid "No SRAM data to save!" +msgstr "Kaydedilecek SRAM verisi yok!" + +msgid "No game saves found." +msgstr "Hiç bir oyun kaydı bulunamadı." + +msgid "None" +msgstr "Yok" + +msgid "NTSC (480i)" +msgstr "NTSC (480i)" + +msgid "Nunchuk" +msgstr "Nunchuk" + +msgid "Off" +msgstr "Kapalı" + +msgid "Official Site: http://code.google.com/p/fceugc/" +msgstr "Resmi Site: http://code.google.com/p/fceugc/" + +msgid "Official Site: http://code.google.com/p/snes9x-gx/" +msgstr "Resmi Site: http://code.google.com/p/snes9x-gx/" + +msgid "Official Site: http://code.google.com/p/vba-wii/" +msgstr "Resmi Site: http://code.google.com/p/vba-wii/" + +msgid "OK" +msgstr "Tamam" + +msgid "On" +msgstr "Açık" + +msgid "Original" +msgstr "Orijinal" + +msgid "Out of memory!" +msgstr "Bellek yetersiz!" + +msgid "Out of memory: too many files!" +msgstr "Bellek yetersiz: çok fazla dosya!" + +msgid "P1" +msgstr "P1" + +msgid "P2" +msgstr "P2" + +msgid "P3" +msgstr "P3" + +msgid "P4" +msgstr "P4" + +msgid "PAL (50Hz)" +msgstr "PAL (50Hz)" + +msgid "PAL (60Hz)" +msgstr "PAL (60Hz)" + +msgid "Palette saved" +msgstr "Renk paleti kaydedildi" + +msgid "Partial Stretch" +msgstr "Kısmı Uzatma" + +msgid "Pause" +msgstr "Duraklatma" + +msgid "Please Wait" +msgstr "Lütfen Bekleyiniz" + +msgid "PLUS" +msgstr "ARTI" + +msgid "Portuguese" +msgstr "Portekizce" + +msgid "Brazilian Portuguese" +msgstr "Brezilya Portekizcesi" + +msgid "Power off Wii" +msgstr "Wii'yi kapat" + +msgid "Preferences saved" +msgstr "Ayarlar kaydedildi" + +msgid "Press any button on the Classic Controller now. Press Home to clear the existing mapping." +msgstr "Åžimdi Klasik Oyun Kumandasında herhangi bir butona basın. Mevcut buton ayarını sıfırlamak için Home butonuna basın." + +msgid "Press any button on the GameCube Controller now. Press Home or the C-Stick in any direction to clear the existing mapping." +msgstr "Åžimdi GameCube Oyun Kumandasında herhangi bir butona basın. Mevcut buton ayarını sıfırlamak için Home butonuna basın veya C-Stickini herhangi bir yöne itin." + +msgid "Press any button on the GameCube Controller now. Press the C-Stick in any direction to clear the existing mapping." +msgstr "Åžimdi GameCube Oyun Kumandasında herhangi bir butona basın. Mevcut buton ayarını sıfırlamak için C-Stickini herhangi bir yöne itin." + +msgid "Press any button on the Wiimote now. Press Home to clear the existing mapping." +msgstr "Åžimdi Wii Uzaktan Kumandasında herhangi bir butona basın. Mevcut buton ayarını sıfırlamak için Home butonuna basın." + +msgid "Press any button on the Wiimote or Nunchuk now. Press Home to clear the existing mapping." +msgstr "Åžimdi Wii Uzaktan Kumandasında veya Nunchuk'ta herhangi bir butona basın. Mevcut buton ayarını sıfırlamak için Home butonuna basın." + +msgid "Progressive (480p)" +msgstr "Progresif (480p)" + +msgid "Quit Game" +msgstr "Oyundan Çık" + +msgid "Quit this game? Any unsaved progress will be lost." +msgstr "Oyundan çıkılsın mı? KaydedilmemiÅŸ tüm veriler kaybolacak." + +msgid "R TRIG" +msgstr "R Mandalı" + +msgid "RAM saving is not available for FDS games!" +msgstr "RAM kaydetme FDS oyunları için mevcut deÄŸil!" + +msgid "Reboot" +msgstr "Yeniden BaÅŸlat" + +msgid "Rendering" +msgstr "Rendering" + +msgid "Reset" +msgstr "Tekrar BaÅŸlat" + +msgid "Reset Game" +msgstr "Oyunu Tekrar BaÅŸlat" + +msgid "Reset this game? Any unsaved progress will be lost." +msgstr "Oyun sıfırlansın mı? KaydedilmemiÅŸ tüm veriler kaybolacak." + +msgid "Reset Mappings" +msgstr "Buton Ayarlarını Sıfırla" + +msgid "Reset Settings" +msgstr "Ayarları Sıfırla" + +msgid "Retry" +msgstr "Yeniden dene" + +msgid "Return to Loader" +msgstr "Loader Ekranına Dön" + +msgid "Return to Wii Menu" +msgstr "Wii Menüsüne Dön" + +msgid "Right" +msgstr "SaÄŸ" + +msgid "RIGHT" +msgstr "SAÄž" + +msgid "Right Button" +msgstr "SaÄŸ Buton" + +msgid "Rumble" +msgstr "TitreÅŸim" + +msgid "Save" +msgstr "Kaydet" + +msgid "Save Device" +msgstr "Kayıt Aygıtı" + +msgid "Save failed!" +msgstr "Kaydetme baÅŸarısız!" + +msgid "Save file not found" +msgstr "Kayıt dosyası bulunamadı" + +msgid "Save Folder" +msgstr "Kayıt Dizini" + +msgid "Save Game" +msgstr "Oyunu Kaydet" + +msgid "Save RAM and State?" +msgstr "RAM ve Durum Kaydedilsin mi?" + +msgid "Save Snapshot?" +msgstr "Enstantane Kaydedilsin mi?" + +msgid "Save SRAM and Snapshot?" +msgstr "SRAM ve Enstantane Kaydedilsin mi?" + +msgid "Save State?" +msgstr "Durum kaydedilsin mi?" + +msgid "Save successful" +msgstr "Kayıt baÅŸarılı" + +msgid "Saving" +msgstr "Kayıt" + +msgid "Saving preferences..." +msgstr "Ayarlar kaydediliyor..." + +msgid "Saving..." +msgstr "Kaydediliyor..." + +msgid "Scaling" +msgstr "Ölçekleme" + +msgid "Screen Position" +msgstr "Ekran Konumu" + +msgid "Screen Zoom" +msgstr "Ekran YakınlaÅŸtırması" + +msgid "Select" +msgstr "Select" + +msgid "Seek error!" +msgstr "Tarama hatası!" + +msgid "Settings" +msgstr "Ayarlar" + +msgid "Settings - Menu" +msgstr "Ayarlar - Menü" + +msgid "Settings - Network" +msgstr "Ayarlar - AÄŸ" + +msgid "Settings - Saving & Loading" +msgstr "Ayarlar - Kayıt & Yükleme" + +msgid "SD Card" +msgstr "SD Kartı" + +msgid "SD card not found!" +msgstr "SD kartı bulunamadı!" + +msgid "Shift" +msgstr "Shift" + +msgid "Simp_chinese" +msgstr "BasitleÅŸtirilmiÅŸ Çince" + +msgid "SMB Share IP" +msgstr "SMB Paylaşım IP'si" + +msgid "SMB Share Name" +msgstr "SMB Paylaşım Adı" + +msgid "SMB Share Password" +msgstr "SMB Paylaşım Åžifresi" + +msgid "SMB Share Username" +msgstr "SMB Paylaşım Kullanıcı Adı" + +msgid "Snapshot" +msgstr "Enstantane" + +msgid "Snapshot (Auto)" +msgstr "Enstantane (Otomatik)" + +msgid "SNES Controller" +msgstr "SNES Oyun Kumandası" + +msgid "SNES Controllers (2)" +msgstr "SNES Oyun Kumandası (2)" + +msgid "SNES Controllers (4)" +msgstr "SNES Oyun Kumandası (4)" + +msgid "SNES Controller - Classic Controller" +msgstr "SNES Oyun Kumandası - Klasik Oyun Kumandası" + +msgid "SNES Controller - GameCube Controller" +msgstr "SNES Oyun Kumandası - GameCube Oyun Kumandası" + +msgid "SNES Controller - Nunchuk + Wiimote" +msgstr "SNES Oyun Kumandası - Nunchuck + Wii Kumanda" + +msgid "SNES Controller - Wiimote" +msgstr "SNES Oyun Kumandası - Wii Kumanda" + +msgid "SNES Mouse" +msgstr "SNES Faresi" + +msgid "SNES Mouse - GameCube Controller" +msgstr "SNES Faresi - GameCube Oyun Kumandası" + +msgid "SNES Mouse - Wiimote" +msgstr "SNES Faresi - Wii Kumanda" + +msgid "Snes9x - Copyright (c) Snes9x Team 1996 - 2006" +msgstr "Snes9x - Telif Hakkı (c) Snes9x Team 1996-2006" + +msgid "Sound Effects Volume" +msgstr "Efekt Sesleri" + +msgid "Spanish" +msgstr "Ä°spanyolca" + +msgid "Sprite Limit" +msgstr "Sprite Sınırı" + +msgid "SRAM file not found" +msgstr "SRAM dosyası bulunamadı" + +msgid "Start" +msgstr "Start" + +msgid "State" +msgstr "Durum" + +msgid "State (Auto)" +msgstr "Durum (Otomatik)" + +msgid "State file not found" +msgstr "Durum dosyası bulunamadı" + +msgid "Stretch to Fit" +msgstr "Uzat" + +msgid "Super Scope" +msgstr "Super Scope" + +msgid "Superscope" +msgstr "Superscope" + +msgid "Superscope - GameCube Controller" +msgstr "Superscope - GameCube Oyun Kumandası" + +msgid "Superscope - Wiimote" +msgstr "Superscope - Wii Kumanda" + +msgid "This software is open source and may be copied," +msgstr "Bu yazılım açık kaynak kodlu olup," + +msgid "Trad_chinese" +msgstr "Geleneksel Çince" + +msgid "Unable to initialize network!" +msgstr "AÄŸ baÅŸlatılamıyor!" + +msgid "Unable to locate a load device!" +msgstr "Yükleme aygıtı bulunamıyor!" + +msgid "Unable to locate a save device!" +msgstr "Kayıt aygıtı bulunamıyor!" + +msgid "Unable to open snapshot!" +msgstr "Enstantane açılamıyor!" + +msgid "Unfiltered" +msgstr "Filtre Yok" + +msgid "Unknown file type!" +msgstr "Tanınmayan dosya türü!" + +msgid "Unrecognized DVD format." +msgstr "Desteklenmeyen DVD formatı." + +msgid "Unrecognized file extension!" +msgstr "Desteklenmeyen dosya uzantısı!" + +msgid "Up" +msgstr "Yukarı" + +msgid "UP" +msgstr "YUKARI" + +msgid "Up One Level" +msgstr "Ãœst Dizin" + +msgid "Update Available" +msgstr "Güncelleme Mevcut" + +msgid "Update failed!" +msgstr "Güncelleme baÅŸarısız!" + +msgid "Update later" +msgstr "Sonra güncelle" + +msgid "Update now" +msgstr "Åžimdi güncelle" + +msgid "Update successful!" +msgstr "Güncelleme baÅŸarılı!" + +msgid "USB drive not found!" +msgstr "USB aygıtı bulunamadı!" + +msgid "USB Mass Storage" +msgstr "USB Yığın Depolama Aygıtı" + +msgid "Vertical" +msgstr "Dikey" + +msgid "Video" +msgstr "Ekran" + +msgid "Video Mode" +msgstr "Ekran Modu" + +msgid "VM8: Unknown page type!" +msgstr "VM8: Tanınmayan sayfa türü!" + +msgid "VM16: Unknown page type!" +msgstr "VM16: Tanınmayan sayfa türü!" + +msgid "VM32: Unknown page type!" +msgstr "VM32: Tanınmayan sayfa türü!" + +msgid "Wiimote" +msgstr "Wii Kumanda" + +msgid "Wiimote Orientation" +msgstr "Wii Kumanda Yönelimi" + +msgid "Yes" +msgstr "Evet" + +msgid "Zapper" +msgstr "Zapper Tabanca" + +msgid "Zapper Crosshair" +msgstr "Zapper Tabanca Artı Ä°mleci" + +msgid "Logo" +msgstr "Logo" + +msgid "Turbo On" +msgstr "Turbo Açık" + +msgid "Turbo Off" +msgstr "Turbo Kapalı" + +msgid "Automatic" +msgstr "Otomatik" + +msgid "Palette" +msgstr "Renk Paleti" + +msgid "AspiringSquire's Real palette" +msgstr "AspiringSquire Gerçek renk paleti" + +msgid "Loopy's palette" +msgstr "Loopy renk paleti" + +msgid "Quor's palette" +msgstr "Quor renk paleti" + +msgid "Chris Covell's palette" +msgstr "Chris Covell renk paleti" + +msgid "Matthew Conte's palette" +msgstr "Matthew Conte renk paleti" + +msgid "PasoFami/99 palette" +msgstr "PasoFami/99 renk paleti" + +msgid "CrashMan's palette" +msgstr "CrashMan renk paleti" + +msgid "MESS palette" +msgstr "MESS renk paleti" + +msgid "Zaphod's VS Castlevania palette" +msgstr "Zaphod'un VS Castlevania renk paleti" + +msgid "Zaphod's VS SMB palette" +msgstr "Zaphod'un VS SMB renk paleti" + +msgid "VS Dr. Mario palette" +msgstr "VS Dr. Mario renk paleti" + +msgid "VS Castlevania palette" +msgstr "VS Castlevania renk paleti" + +msgid "VS SMB/VS Ice Climber palette" +msgstr "VS SMB/VS Ice Climber renk paleti" + +msgid "Catalan" +msgstr "Katalonca" + +msgid "The current IOS has been altered (fake-signed). Functionality and/or stability may be adversely affected." +msgstr "Geçerli IOS deÄŸiÅŸtirilmiÅŸ (sahte-imzalı). IÅŸlevsellik ve/veya stabilite olumsuz etkilenebilir." + +msgid "The current IOS is unsupported. Functionality and/or stability may be adversely affected." +msgstr "Geçerli IOS desteklenmiyor. IÅŸlevsellik ve/veya stabilite olumsuz etkilenebilir." + +msgid "Turkish" +msgstr "Türkçe" diff --git a/plugins/snes9x_gx/source/lang/zh.lang b/plugins/snes9x_gx/source/lang/zh.lang new file mode 100644 index 00000000..85d83649 --- /dev/null +++ b/plugins/snes9x_gx/source/lang/zh.lang @@ -0,0 +1,2 @@ +msgid " " +msgstr "" diff --git a/plugins/snes9x_gx/source/mem2.cpp b/plugins/snes9x_gx/source/mem2.cpp new file mode 100644 index 00000000..08be67d0 --- /dev/null +++ b/plugins/snes9x_gx/source/mem2.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * Tantric 2010 + * + * mem2.cpp + * + * MEM2 memory allocator + ***************************************************************************/ + +#ifdef HW_RVL + +#include <ogc/machine/asm.h> +#include <ogc/lwp_heap.h> +#include <ogc/system.h> +#include <ogc/machine/processor.h> + +static heap_cntrl mem2_heap; + +u32 InitMem2Manager () +{ + int size = (12*1024*1024); + u32 level; + _CPU_ISR_Disable(level); + size &= ~0x1f; // round down, because otherwise we may exceed the area + void *mem2_heap_ptr = (void *)((u32)SYS_GetArena2Hi()-size); + SYS_SetArena2Hi(mem2_heap_ptr); + _CPU_ISR_Restore(level); + size = __lwp_heap_init(&mem2_heap, mem2_heap_ptr, size, 32); + return size; +} + +void* mem2_malloc(u32 size) +{ + return __lwp_heap_allocate(&mem2_heap, size); +} + +bool mem2_free(void *ptr) +{ + return __lwp_heap_free(&mem2_heap, ptr); +} + +#endif diff --git a/plugins/snes9x_gx/source/mem2.h b/plugins/snes9x_gx/source/mem2.h new file mode 100644 index 00000000..539b038e --- /dev/null +++ b/plugins/snes9x_gx/source/mem2.h @@ -0,0 +1,22 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * Tantric 2010 + * + * mem2.h + * + * MEM2 memory allocator + ***************************************************************************/ + +#ifdef HW_RVL + +#ifndef _MEM2MANAGER_H_ +#define _MEM2MANAGER_H_ + +u32 InitMem2Manager (); +void* mem2_malloc(u32 size); +bool mem2_free(void *ptr); + +#endif + +#endif diff --git a/plugins/snes9x_gx/source/menu.cpp b/plugins/snes9x_gx/source/menu.cpp new file mode 100644 index 00000000..cd936168 --- /dev/null +++ b/plugins/snes9x_gx/source/menu.cpp @@ -0,0 +1,4091 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * Tantric 2008-2010 + * + * menu.cpp + * + * Menu flow routines - handles all menu logic + ***************************************************************************/ + +#include <gccore.h> +#include <ogcsys.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wiiuse/wpad.h> +#include <wupc/wupc.h> +#include <sys/stat.h> + +#ifdef HW_RVL +#include <di/di.h> +#endif + +#include "snes9xgx.h" +#include "video.h" +#include "filebrowser.h" +#include "gcunzip.h" +#include "networkop.h" +#include "fileop.h" +#include "sram.h" +#include "freeze.h" +#include "preferences.h" +#include "button_mapping.h" +#include "input.h" +#include "filter.h" +#include "filelist.h" +#include "gui/gui.h" +#include "menu.h" +#include "utils/gettext.h" + +#include "snes9x/snes9x.h" +#include "snes9x/memmap.h" +#include "snes9x/cheats.h" + +extern SCheatData Cheat; + +#define THREAD_SLEEP 100 + +#ifdef HW_RVL +static GuiImageData * pointer[4]; +#endif + +#ifdef HW_RVL + #include "mem2.h" + + #define MEM_ALLOC(A) (u8*)mem2_malloc(A) + #define MEM_DEALLOC(A) mem2_free(A) +#else + #define MEM_ALLOC(A) (u8*)memalign(32, A) + #define MEM_DEALLOC(A) free(A) +#endif + +static GuiTrigger * trigA = NULL; +static GuiTrigger * trig2 = NULL; + +static GuiButton * btnLogo = NULL; +static GuiImageData * gameScreen = NULL; +static GuiImage * gameScreenImg = NULL; +static GuiImage * bgTopImg = NULL; +static GuiImage * bgBottomImg = NULL; +static GuiSound * bgMusic = NULL; +static GuiSound * enterSound = NULL; +static GuiSound * exitSound = NULL; +static GuiWindow * mainWindow = NULL; +static GuiText * settingText = NULL; +static GuiText * settingText2 = NULL; +static int lastMenu = MENU_NONE; +static int wiiuproCtrl = 0; +static int mapMenuCtrl = 0; +static int mapMenuCtrlSNES = 0; + +static lwp_t guithread = LWP_THREAD_NULL; +static lwp_t progressthread = LWP_THREAD_NULL; +#ifdef HW_RVL +static lwp_t updatethread = LWP_THREAD_NULL; +#endif +static bool guiHalt = true; +static int showProgress = 0; + +static char progressTitle[101]; +static char progressMsg[201]; +static int progressDone = 0; +static int progressTotal = 0; + +/**************************************************************************** + * ResumeGui + * + * Signals the GUI thread to start, and resumes the thread. This is called + * after finishing the removal/insertion of new elements, and after initial + * GUI setup. + ***************************************************************************/ +static void +ResumeGui() +{ + guiHalt = false; + LWP_ResumeThread (guithread); +} + +/**************************************************************************** + * HaltGui + * + * Signals the GUI thread to stop, and waits for GUI thread to stop + * This is necessary whenever removing/inserting new elements into the GUI. + * This eliminates the possibility that the GUI is in the middle of accessing + * an element that is being changed. + ***************************************************************************/ +static void +HaltGui() +{ + guiHalt = true; + + // wait for thread to finish + while(!LWP_ThreadIsSuspended(guithread)) + usleep(THREAD_SLEEP); +} + +void ResetText() +{ + LoadLanguage(); + + if(mainWindow) + mainWindow->ResetText(); +} + +/**************************************************************************** + * WindowPrompt + * + * Displays a prompt window to user, with information, an error message, or + * presenting a user with a choice + ***************************************************************************/ +int +WindowPrompt(const char *title, const char *msg, const char *btn1Label, const char *btn2Label) +{ + if(!mainWindow || ExitRequested || ShutdownRequested) + return 0; + + int choice = -1; + + GuiWindow promptWindow(448,288); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_prompt_png); + GuiImageData btnOutlineOver(button_prompt_over_png); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText titleTxt(title, 26, (GXColor){70, 70, 10, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,14); + GuiText msgTxt(msg, 26, (GXColor){0, 0, 0, 255}); + msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + msgTxt.SetPosition(0,-20); + msgTxt.SetWrap(true, 430); + + GuiText btn1Txt(btn1Label, 22, (GXColor){0, 0, 0, 255}); + GuiImage btn1Img(&btnOutline); + GuiImage btn1ImgOver(&btnOutlineOver); + GuiButton btn1(btnOutline.GetWidth(), btnOutline.GetHeight()); + + if(btn2Label) + { + btn1.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + btn1.SetPosition(20, -25); + } + else + { + btn1.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + btn1.SetPosition(0, -25); + } + + btn1.SetLabel(&btn1Txt); + btn1.SetImage(&btn1Img); + btn1.SetImageOver(&btn1ImgOver); + btn1.SetSoundOver(&btnSoundOver); + btn1.SetSoundClick(&btnSoundClick); + btn1.SetTrigger(trigA); + btn1.SetTrigger(trig2); + btn1.SetState(STATE_SELECTED); + btn1.SetEffectGrow(); + + GuiText btn2Txt(btn2Label, 22, (GXColor){0, 0, 0, 255}); + GuiImage btn2Img(&btnOutline); + GuiImage btn2ImgOver(&btnOutlineOver); + GuiButton btn2(btnOutline.GetWidth(), btnOutline.GetHeight()); + btn2.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + btn2.SetPosition(-20, -25); + btn2.SetLabel(&btn2Txt); + btn2.SetImage(&btn2Img); + btn2.SetImageOver(&btn2ImgOver); + btn2.SetSoundOver(&btnSoundOver); + btn2.SetSoundClick(&btnSoundClick); + btn2.SetTrigger(trigA); + btn2.SetTrigger(trig2); + btn2.SetEffectGrow(); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&msgTxt); + promptWindow.Append(&btn1); + + if(btn2Label) + promptWindow.Append(&btn2); + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50); + CancelAction(); + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + if(btn2Label) + { + btn1.ResetState(); + btn2.SetState(STATE_SELECTED); + } + ResumeGui(); + + while(choice == -1) + { + usleep(THREAD_SLEEP); + + if(btn1.GetState() == STATE_CLICKED) + choice = 1; + else if(btn2.GetState() == STATE_CLICKED) + choice = 0; + } + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); + while(promptWindow.GetEffect() > 0) usleep(THREAD_SLEEP); + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + return choice; +} + +#ifdef HW_RVL +/**************************************************************************** + * EmulatorUpdate + * + * Prompts for confirmation, and downloads/installs updates + ***************************************************************************/ +static void * +EmulatorUpdate (void *arg) +{ + bool installUpdate = WindowPrompt( + "Update Available", + "An update is available!", + "Update now", + "Update later"); + if(installUpdate) + if(DownloadUpdate()) + ExitRequested = 1; + return NULL; +} +#endif + +/**************************************************************************** + * UpdateGUI + * + * Primary thread to allow GUI to respond to state changes, and draws GUI + ***************************************************************************/ + +static void * +UpdateGUI (void *arg) +{ + int i; + + while(1) + { + if(guiHalt) + LWP_SuspendThread(guithread); + + UpdatePads(); + mainWindow->Draw(); + + if (mainWindow->GetState() != STATE_DISABLED) + mainWindow->DrawTooltip(); + + #ifdef HW_RVL + i = 3; + do + { + if(userInput[i].wpad->ir.valid) + Menu_DrawImg(userInput[i].wpad->ir.x-48, userInput[i].wpad->ir.y-48, + 96, 96, pointer[i]->GetImage(), userInput[i].wpad->ir.angle, 1, 1, 255); + DoRumble(i); + --i; + } while(i>=0); + #endif + + Menu_Render(); + + mainWindow->Update(&userInput[3]); + mainWindow->Update(&userInput[2]); + mainWindow->Update(&userInput[1]); + mainWindow->Update(&userInput[0]); + + #ifdef HW_RVL + if(updateFound) + { + updateFound = false; + + if(!loadingFile) + LWP_CreateThread (&updatethread, EmulatorUpdate, NULL, NULL, 0, 70); + } + #endif + + if(ExitRequested || ShutdownRequested) + { + for(i = 0; i <= 255; i += 15) + { + mainWindow->Draw(); + Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0, 0, 0, (u8)i},1); + Menu_Render(); + } + ExitApp(); + } + usleep(THREAD_SLEEP); + } + return NULL; +} + +/**************************************************************************** + * ProgressWindow + * + * Opens a window, which displays progress to the user. Can either display a + * progress bar showing % completion, or a throbber that only shows that an + * action is in progress. + ***************************************************************************/ +static int progsleep = 0; + +static void +ProgressWindow(char *title, char *msg) +{ + GuiWindow promptWindow(448,288); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiImageData progressbarOutline(progressbar_outline_png); + GuiImage progressbarOutlineImg(&progressbarOutline); + progressbarOutlineImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + progressbarOutlineImg.SetPosition(25, 40); + + GuiImageData progressbarEmpty(progressbar_empty_png); + GuiImage progressbarEmptyImg(&progressbarEmpty); + progressbarEmptyImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + progressbarEmptyImg.SetPosition(25, 40); + progressbarEmptyImg.SetTile(100); + + GuiImageData progressbar(progressbar_png); + GuiImage progressbarImg(&progressbar); + progressbarImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + progressbarImg.SetPosition(25, 40); + + GuiImageData throbber(throbber_png); + GuiImage throbberImg(&throbber); + throbberImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + throbberImg.SetPosition(0, 40); + + GuiText titleTxt(title, 26, (GXColor){70, 70, 10, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,14); + GuiText msgTxt(msg, 26, (GXColor){0, 0, 0, 255}); + msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + msgTxt.SetPosition(0,80); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&msgTxt); + + if(showProgress == 1) + { + promptWindow.Append(&progressbarEmptyImg); + promptWindow.Append(&progressbarImg); + promptWindow.Append(&progressbarOutlineImg); + } + else + { + promptWindow.Append(&throbberImg); + } + + // wait to see if progress flag changes soon + progsleep = 400000; + + while(progsleep > 0) + { + if(!showProgress) + break; + usleep(THREAD_SLEEP); + progsleep -= THREAD_SLEEP; + } + + if(!showProgress) + return; + + HaltGui(); + int oldState = mainWindow->GetState(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + float angle = 0; + u32 count = 0; + + while(showProgress) + { + progsleep = 20000; + + while(progsleep > 0) + { + if(!showProgress) + break; + usleep(THREAD_SLEEP); + progsleep -= THREAD_SLEEP; + } + + if(showProgress == 1) + { + progressbarImg.SetTile(100*progressDone/progressTotal); + } + else if(showProgress == 2) + { + if(count % 5 == 0) + { + angle+=45.0f; + if(angle >= 360.0f) + angle = 0; + throbberImg.SetAngle(angle); + } + ++count; + } + } + + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(oldState); + ResumeGui(); +} + +static void * ProgressThread (void *arg) +{ + while(1) + { + if(!showProgress) + LWP_SuspendThread (progressthread); + + ProgressWindow(progressTitle, progressMsg); + usleep(THREAD_SLEEP); + } + return NULL; +} + +/**************************************************************************** + * InitGUIThread + * + * Startup GUI threads + ***************************************************************************/ +void +InitGUIThreads() +{ + LWP_CreateThread (&guithread, UpdateGUI, NULL, NULL, 0, 70); + LWP_CreateThread (&progressthread, ProgressThread, NULL, NULL, 0, 40); +} + +/**************************************************************************** + * CancelAction + * + * Signals the GUI progress window thread to halt, and waits for it to + * finish. Prevents multiple progress window events from interfering / + * overriding each other. + ***************************************************************************/ +void +CancelAction() +{ + showProgress = 0; + + // wait for thread to finish + while(!LWP_ThreadIsSuspended(progressthread)) + usleep(THREAD_SLEEP); +} + +/**************************************************************************** + * ShowProgress + * + * Updates the variables used by the progress window for drawing a progress + * bar. Also resumes the progress window thread if it is suspended. + ***************************************************************************/ +void +ShowProgress (const char *msg, int done, int total) +{ + if(!mainWindow || ExitRequested || ShutdownRequested) + return; + + if(total < (256*1024)) + return; + else if(done > total) // this shouldn't happen + done = total; + + if(done/total > 0.99) + done = total; + + if(showProgress != 1) + CancelAction(); // wait for previous progress window to finish + + snprintf(progressMsg, 200, "%s", msg); + sprintf(progressTitle, "Please Wait"); + showProgress = 1; + progressTotal = total; + progressDone = done; + LWP_ResumeThread (progressthread); +} + +/**************************************************************************** + * ShowAction + * + * Shows that an action is underway. Also resumes the progress window thread + * if it is suspended. + ***************************************************************************/ +void +ShowAction (const char *msg) +{ + if(!mainWindow || ExitRequested || ShutdownRequested) + return; + + if(showProgress != 0) + CancelAction(); // wait for previous progress window to finish + + snprintf(progressMsg, 200, "%s", msg); + sprintf(progressTitle, "Please Wait"); + showProgress = 2; + progressDone = 0; + progressTotal = 0; + LWP_ResumeThread (progressthread); +} + +void ErrorPrompt(const char *msg) +{ + WindowPrompt("Error", msg, "OK", NULL); +} + +int ErrorPromptRetry(const char *msg) +{ + return WindowPrompt("Error", msg, "Retry", "Cancel"); +} + +void InfoPrompt(const char *msg) +{ + WindowPrompt("Information", msg, "OK", NULL); +} + +/**************************************************************************** + * AutoSave + * + * Automatically saves SRAM/snapshot when returning from in-game to the menu + ***************************************************************************/ +void AutoSave() +{ + if (GCSettings.AutoSave == 1) + { + SaveSRAMAuto(SILENT); + } + else if (GCSettings.AutoSave == 2) + { + if (WindowPrompt("Save", "Save Snapshot?", "Save", "Don't Save") ) + SaveSnapshotAuto(NOTSILENT); + } + else if (GCSettings.AutoSave == 3) + { + if (WindowPrompt("Save", "Save SRAM and Snapshot?", "Save", "Don't Save") ) + { + SaveSRAMAuto(NOTSILENT); + SaveSnapshotAuto(NOTSILENT); + } + } +} + +/**************************************************************************** + * OnScreenKeyboard + * + * Opens an on-screen keyboard window, with the data entered being stored + * into the specified variable. + ***************************************************************************/ +static void OnScreenKeyboard(char * var, u32 maxlen) +{ + int save = -1; + + GuiKeyboard keyboard(var, maxlen); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiText okBtnTxt("OK", 22, (GXColor){0, 0, 0, 255}); + GuiImage okBtnImg(&btnOutline); + GuiImage okBtnImgOver(&btnOutlineOver); + GuiButton okBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + + okBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + okBtn.SetPosition(25, -25); + + okBtn.SetLabel(&okBtnTxt); + okBtn.SetImage(&okBtnImg); + okBtn.SetImageOver(&okBtnImgOver); + okBtn.SetSoundOver(&btnSoundOver); + okBtn.SetSoundClick(&btnSoundClick); + okBtn.SetTrigger(trigA); + okBtn.SetTrigger(trig2); + okBtn.SetEffectGrow(); + + GuiText cancelBtnTxt("Cancel", 22, (GXColor){0, 0, 0, 255}); + GuiImage cancelBtnImg(&btnOutline); + GuiImage cancelBtnImgOver(&btnOutlineOver); + GuiButton cancelBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + cancelBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + cancelBtn.SetPosition(-25, -25); + cancelBtn.SetLabel(&cancelBtnTxt); + cancelBtn.SetImage(&cancelBtnImg); + cancelBtn.SetImageOver(&cancelBtnImgOver); + cancelBtn.SetSoundOver(&btnSoundOver); + cancelBtn.SetSoundClick(&btnSoundClick); + cancelBtn.SetTrigger(trigA); + cancelBtn.SetTrigger(trig2); + cancelBtn.SetEffectGrow(); + + keyboard.Append(&okBtn); + keyboard.Append(&cancelBtn); + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&keyboard); + mainWindow->ChangeFocus(&keyboard); + ResumeGui(); + + while(save == -1) + { + usleep(THREAD_SLEEP); + + if(okBtn.GetState() == STATE_CLICKED) + save = 1; + else if(cancelBtn.GetState() == STATE_CLICKED) + save = 0; + } + + if(save) + { + snprintf(var, maxlen, "%s", keyboard.kbtextstr); + } + + HaltGui(); + mainWindow->Remove(&keyboard); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); +} + +/**************************************************************************** + * SettingWindow + * + * Opens a new window, with the specified window element appended. Allows + * for a customizable prompted setting. + ***************************************************************************/ +static int +SettingWindow(const char * title, GuiWindow * w) +{ + int save = -1; + + GuiWindow promptWindow(448,288); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText titleTxt(title, 26, (GXColor){70, 70, 10, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,14); + + GuiText okBtnTxt("OK", 22, (GXColor){0, 0, 0, 255}); + GuiImage okBtnImg(&btnOutline); + GuiImage okBtnImgOver(&btnOutlineOver); + GuiButton okBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + + okBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + okBtn.SetPosition(20, -25); + + okBtn.SetLabel(&okBtnTxt); + okBtn.SetImage(&okBtnImg); + okBtn.SetImageOver(&okBtnImgOver); + okBtn.SetSoundOver(&btnSoundOver); + okBtn.SetSoundClick(&btnSoundClick); + okBtn.SetTrigger(trigA); + okBtn.SetTrigger(trig2); + okBtn.SetEffectGrow(); + + GuiText cancelBtnTxt("Cancel", 22, (GXColor){0, 0, 0, 255}); + GuiImage cancelBtnImg(&btnOutline); + GuiImage cancelBtnImgOver(&btnOutlineOver); + GuiButton cancelBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + cancelBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + cancelBtn.SetPosition(-20, -25); + cancelBtn.SetLabel(&cancelBtnTxt); + cancelBtn.SetImage(&cancelBtnImg); + cancelBtn.SetImageOver(&cancelBtnImgOver); + cancelBtn.SetSoundOver(&btnSoundOver); + cancelBtn.SetSoundClick(&btnSoundClick); + cancelBtn.SetTrigger(trigA); + cancelBtn.SetTrigger(trig2); + cancelBtn.SetEffectGrow(); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&okBtn); + promptWindow.Append(&cancelBtn); + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->Append(w); + mainWindow->ChangeFocus(w); + ResumeGui(); + + while(save == -1) + { + usleep(THREAD_SLEEP); + + if(okBtn.GetState() == STATE_CLICKED) + save = 1; + else if(cancelBtn.GetState() == STATE_CLICKED) + save = 0; + } + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->Remove(w); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + return save; +} + +/**************************************************************************** + * WindowCredits + * Display credits, legal copyright and licence + * + * THIS MUST NOT BE REMOVED OR DISABLED IN ANY DERIVATIVE WORK + ***************************************************************************/ +static void WindowCredits(void * ptr) +{ + if(btnLogo->GetState() != STATE_CLICKED) + return; + + btnLogo->ResetState(); + + bool exit = false; + int i = 0; + int y = 20; + + GuiWindow creditsWindow(screenwidth,screenheight); + GuiWindow creditsWindowBox(580,448); + creditsWindowBox.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + + GuiImageData creditsBox(credits_box_png); + GuiImage creditsBoxImg(&creditsBox); + creditsBoxImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + creditsWindowBox.Append(&creditsBoxImg); + + int numEntries = 24; + GuiText * txt[numEntries]; + + txt[i] = new GuiText("Credits", 30, (GXColor){0, 0, 0, 255}); + txt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); txt[i]->SetPosition(0,y); i++; y+=32; + + txt[i] = new GuiText("Official Site: http://code.google.com/p/snes9x-gx/", 20, (GXColor){0, 0, 0, 255}); + txt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); txt[i]->SetPosition(0,y); i++; y+=40; + + txt[i]->SetPresets(20, (GXColor){0, 0, 0, 255}, 0, + FTGX_JUSTIFY_LEFT | FTGX_ALIGN_TOP, ALIGN_LEFT, ALIGN_TOP); + + txt[i] = new GuiText("Coding & menu design"); + txt[i]->SetPosition(60,y); i++; + txt[i] = new GuiText("Tantric"); + txt[i]->SetPosition(350,y); i++; y+=24; + txt[i] = new GuiText("Coding"); + txt[i]->SetPosition(60,y); i++; + txt[i] = new GuiText("michniewski"); + txt[i]->SetPosition(350,y); i++; y+=24; + txt[i] = new GuiText("Menu artwork"); + txt[i]->SetPosition(60,y); i++; + txt[i] = new GuiText("the3seashells"); + txt[i]->SetPosition(350,y); i++; y+=24; + txt[i] = new GuiText("Menu sound"); + txt[i]->SetPosition(60,y); i++; + txt[i] = new GuiText("Peter de Man"); + txt[i]->SetPosition(350,y); i++; y+=48; + + txt[i] = new GuiText("Snes9x GX GameCube"); + txt[i]->SetPosition(60,y); i++; + txt[i] = new GuiText("SoftDev, crunchy2,"); + txt[i]->SetPosition(350,y); i++; y+=24; + txt[i] = new GuiText("eke-eke, others"); + txt[i]->SetPosition(350,y); i++; y+=24; + txt[i] = new GuiText("Snes9x"); + txt[i]->SetPosition(60,y); i++; + txt[i] = new GuiText("Snes9x Team"); + txt[i]->SetPosition(350,y); i++; y+=24; + + txt[i] = new GuiText("libogc / devkitPPC"); + txt[i]->SetPosition(60,y); i++; + txt[i] = new GuiText("shagkur & wintermute"); + txt[i]->SetPosition(350,y); i++; y+=24; + txt[i] = new GuiText("FreeTypeGX"); + txt[i]->SetPosition(60,y); i++; + txt[i] = new GuiText("Armin Tamzarian"); + txt[i]->SetPosition(350,y); i++; y+=48; + + txt[i]->SetPresets(18, (GXColor){0, 0, 0, 255}, 0, + FTGX_JUSTIFY_CENTER | FTGX_ALIGN_TOP, ALIGN_CENTRE, ALIGN_TOP); + + txt[i] = new GuiText("Snes9x - Copyright (c) Snes9x Team 1996 - 2006"); + txt[i]->SetPosition(0,y); i++; y+=20; + txt[i] = new GuiText("This software is open source and may be copied,"); + txt[i]->SetPosition(0,y); i++; y+=20; + txt[i] = new GuiText("distributed, or modified under the terms of the"); + txt[i]->SetPosition(0,y); i++; y+=20; + txt[i] = new GuiText("GNU General Public License (GPL) Version 2."); + txt[i]->SetPosition(0,y); i++; y+=20; + + char iosVersion[20]; + +#ifdef HW_RVL + sprintf(iosVersion, "IOS: %d", IOS_GetVersion()); +#endif + + txt[i] = new GuiText(iosVersion, 18, (GXColor){0, 0, 0, 255}); + txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + txt[i]->SetPosition(20,-20); + + for(i=0; i < numEntries; i++) + creditsWindowBox.Append(txt[i]); + + creditsWindow.Append(&creditsWindowBox); + + while(!exit) + { + UpdatePads(); + + gameScreenImg->Draw(); + bgBottomImg->Draw(); + bgTopImg->Draw(); + creditsWindow.Draw(); + + #ifdef HW_RVL + i = 3; + do { + if(userInput[i].wpad->ir.valid) + Menu_DrawImg(userInput[i].wpad->ir.x-48, userInput[i].wpad->ir.y-48, + 96, 96, pointer[i]->GetImage(), userInput[i].wpad->ir.angle, 1, 1, 255); + DoRumble(i); + --i; + } while(i >= 0); + #endif + + Menu_Render(); + + if((userInput[0].wpad->btns_d || userInput[0].pad.btns_d || userInput[0].wupcdata.btns_d) || + (userInput[1].wpad->btns_d || userInput[1].pad.btns_d || userInput[1].wupcdata.btns_d) || + (userInput[2].wpad->btns_d || userInput[2].pad.btns_d || userInput[2].wupcdata.btns_d) || + (userInput[3].wpad->btns_d || userInput[3].pad.btns_d || userInput[3].wupcdata.btns_d)) + { + exit = true; + } + usleep(THREAD_SLEEP); + } + + // clear buttons pressed + for(i=0; i < 4; i++) + { + userInput[i].wupcdata.btns_d = 0; + userInput[i].wpad->btns_d = 0; + userInput[i].pad.btns_d = 0; + } + + for(i=0; i < numEntries; i++) + delete txt[i]; +} + +/**************************************************************************** + * MenuGameSelection + * + * Displays a list of games on the specified load device, and allows the user + * to browse and select from this list. + ***************************************************************************/ +static int MenuGameSelection() +{ + int menu = MENU_NONE; + bool res; + int i; + + GuiText titleTxt("Choose Game", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData iconHome(icon_home_png); + GuiImageData iconSettings(icon_settings_png); + GuiImageData btnOutline(button_long_png); + GuiImageData btnOutlineOver(button_long_over_png); + GuiImageData bgPreviewImg(bg_preview_png); + + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + + GuiText settingsBtnTxt("Settings", 22, (GXColor){0, 0, 0, 255}); + GuiImage settingsBtnIcon(&iconSettings); + settingsBtnIcon.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + settingsBtnIcon.SetPosition(14,0); + GuiImage settingsBtnImg(&btnOutline); + GuiImage settingsBtnImgOver(&btnOutlineOver); + GuiButton settingsBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + settingsBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + settingsBtn.SetPosition(90, -35); + settingsBtn.SetLabel(&settingsBtnTxt); + settingsBtn.SetIcon(&settingsBtnIcon); + settingsBtn.SetImage(&settingsBtnImg); + settingsBtn.SetImageOver(&settingsBtnImgOver); + settingsBtn.SetSoundOver(&btnSoundOver); + settingsBtn.SetSoundClick(&btnSoundClick); + settingsBtn.SetTrigger(trigA); + settingsBtn.SetTrigger(trig2); + settingsBtn.SetEffectGrow(); + + GuiText exitBtnTxt("Exit", 22, (GXColor){0, 0, 0, 255}); + GuiImage exitBtnIcon(&iconHome); + exitBtnIcon.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + exitBtnIcon.SetPosition(14,0); + GuiImage exitBtnImg(&btnOutline); + GuiImage exitBtnImgOver(&btnOutlineOver); + GuiButton exitBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + exitBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + exitBtn.SetPosition(-90, -35); + exitBtn.SetLabel(&exitBtnTxt); + exitBtn.SetIcon(&exitBtnIcon); + exitBtn.SetImage(&exitBtnImg); + exitBtn.SetImageOver(&exitBtnImgOver); + exitBtn.SetSoundOver(&btnSoundOver); + exitBtn.SetSoundClick(&btnSoundClick); + exitBtn.SetTrigger(trigA); + exitBtn.SetTrigger(trig2); + exitBtn.SetTrigger(&trigHome); + exitBtn.SetEffectGrow(); + + GuiWindow buttonWindow(screenwidth, screenheight); + buttonWindow.Append(&settingsBtn); + buttonWindow.Append(&exitBtn); + + GuiFileBrowser gameBrowser(330, 268); + gameBrowser.SetPosition(20, 98); + ResetBrowser(); + + GuiImage bgPreview(&bgPreviewImg); + bgPreview.SetPosition(365, 98); + + GuiImage preview; + preview.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + preview.SetPosition(174, -8); + u8* imgBuffer = MEM_ALLOC(512 * 512 * 4); + int previousBrowserIndex = -1; + char screenshotPath[MAXJOLIET + 1]; + + HaltGui(); + btnLogo->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + btnLogo->SetPosition(-50, 24); + mainWindow->Append(&titleTxt); + mainWindow->Append(&gameBrowser); + mainWindow->Append(&buttonWindow); + mainWindow->Append(&bgPreview); + mainWindow->Append(&preview); + ResumeGui(); + + #ifdef HW_RVL + ShutoffRumble(); + #endif + + // populate initial directory listing + selectLoadedFile = 1; + OpenGameList(); + + gameBrowser.ResetState(); + gameBrowser.fileList[0]->SetState(STATE_SELECTED); + gameBrowser.TriggerUpdate(); + titleTxt.SetText(inSz ? szname : "Choose Game"); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + if(selectLoadedFile == 2) + { + selectLoadedFile = 0; + mainWindow->ChangeFocus(&gameBrowser); + gameBrowser.TriggerUpdate(); + } + + // update gameWindow based on arrow buttons + // set MENU_EXIT if A button pressed on a game + for(i=0; i < FILE_PAGESIZE; i++) + { + if(gameBrowser.fileList[i]->GetState() == STATE_CLICKED) + { + gameBrowser.fileList[i]->ResetState(); + + // check corresponding browser entry + if(browserList[browser.selIndex].isdir || IsSz()) + { + HaltGui(); + res = BrowserChangeFolder(); + if(res) + { + gameBrowser.ResetState(); + gameBrowser.fileList[0]->SetState(STATE_SELECTED); + gameBrowser.TriggerUpdate(); + previousBrowserIndex = -1; + } + else + { + menu = MENU_GAMESELECTION; + break; + } + + + titleTxt.SetText(inSz ? szname : "Choose Game"); + + ResumeGui(); + } + else + { + #ifdef HW_RVL + ShutoffRumble(); + #endif + mainWindow->SetState(STATE_DISABLED); + SavePrefs(SILENT); + if(BrowserLoadFile()) + menu = MENU_EXIT; + else + mainWindow->SetState(STATE_DEFAULT); + } + } + } + + //update game screenshot + if(previousBrowserIndex != browser.selIndex) + { + previousBrowserIndex = browser.selIndex; + snprintf(screenshotPath, MAXJOLIET, "%s%s/%s.png", pathPrefix[GCSettings.LoadMethod], GCSettings.ScreenshotsFolder, browserList[browser.selIndex].displayname); + + AllocSaveBuffer(); + int width, height; + if(LoadFile(screenshotPath, SILENT)) + { + if(DecodePNG(savebuffer, &width, &height, imgBuffer, 512, 512)) + { + preview.SetImage(imgBuffer, width, height); + //preview.SetScale(225.0f / width); + preview.SetScale( MIN(225.0f / width, 235.0f / height) ); + } + else + { + preview.SetImage(NULL, 0, 0); + } + } + else + { + preview.SetImage(NULL, 0, 0); + } + FreeSaveBuffer(); + } + + if(settingsBtn.GetState() == STATE_CLICKED) + menu = MENU_SETTINGS; + else if(exitBtn.GetState() == STATE_CLICKED) + ExitRequested = 1; + } + + HaltParseThread(); // halt parsing + HaltGui(); + ResetBrowser(); + mainWindow->Remove(&titleTxt); + mainWindow->Remove(&buttonWindow); + mainWindow->Remove(&gameBrowser); + mainWindow->Remove(&bgPreview); + mainWindow->Remove(&preview); + MEM_DEALLOC(imgBuffer); + return menu; +} + +/**************************************************************************** + * ControllerWindowUpdate + * + * Callback for controller window. Responds to clicks on window elements. + ***************************************************************************/ +static void ControllerWindowUpdate(void * ptr, int dir) +{ + GuiButton * b = (GuiButton *)ptr; + if(b->GetState() == STATE_CLICKED) + { + GCSettings.Controller += dir; + + if(GCSettings.Controller > CTRL_PAD4) + GCSettings.Controller = CTRL_MOUSE; + if(GCSettings.Controller < CTRL_MOUSE) + GCSettings.Controller = CTRL_PAD4; + + settingText->SetText(ctrlName[GCSettings.Controller]); + b->ResetState(); + } +} + +/**************************************************************************** + * ControllerWindowLeftClick / ControllerWindowRightsClick + * + * Callbacks for controller window arrows. Responds arrow clicks. + ***************************************************************************/ +static void ControllerWindowLeftClick(void * ptr) { ControllerWindowUpdate(ptr, -1); } +static void ControllerWindowRightClick(void * ptr) { ControllerWindowUpdate(ptr, +1); } + +/**************************************************************************** + * ControllerWindow + * + * Opens a window to allow the user to select the controller to be used. + ***************************************************************************/ +static void ControllerWindow() +{ + GuiWindow * w = new GuiWindow(300,250); + w->SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + + GuiTrigger trigLeft; + trigLeft.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT, PAD_BUTTON_LEFT); + + GuiTrigger trigRight; + trigRight.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT, PAD_BUTTON_RIGHT); + + GuiImageData arrowLeft(button_arrow_left_png); + GuiImage arrowLeftImg(&arrowLeft); + GuiImageData arrowLeftOver(button_arrow_left_over_png); + GuiImage arrowLeftOverImg(&arrowLeftOver); + GuiButton arrowLeftBtn(arrowLeft.GetWidth(), arrowLeft.GetHeight()); + arrowLeftBtn.SetImage(&arrowLeftImg); + arrowLeftBtn.SetImageOver(&arrowLeftOverImg); + arrowLeftBtn.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + arrowLeftBtn.SetTrigger(trigA); + arrowLeftBtn.SetTrigger(trig2); + arrowLeftBtn.SetTrigger(&trigLeft); + arrowLeftBtn.SetSelectable(false); + arrowLeftBtn.SetUpdateCallback(ControllerWindowLeftClick); + + GuiImageData arrowRight(button_arrow_right_png); + GuiImage arrowRightImg(&arrowRight); + GuiImageData arrowRightOver(button_arrow_right_over_png); + GuiImage arrowRightOverImg(&arrowRightOver); + GuiButton arrowRightBtn(arrowRight.GetWidth(), arrowRight.GetHeight()); + arrowRightBtn.SetImage(&arrowRightImg); + arrowRightBtn.SetImageOver(&arrowRightOverImg); + arrowRightBtn.SetAlignment(ALIGN_RIGHT, ALIGN_MIDDLE); + arrowRightBtn.SetTrigger(trigA); + arrowRightBtn.SetTrigger(trig2); + arrowRightBtn.SetTrigger(&trigRight); + arrowRightBtn.SetSelectable(false); + arrowRightBtn.SetUpdateCallback(ControllerWindowRightClick); + + settingText = new GuiText(ctrlName[GCSettings.Controller], 22, (GXColor){0, 0, 0, 255}); + + int currentController = GCSettings.Controller; + + w->Append(&arrowLeftBtn); + w->Append(&arrowRightBtn); + w->Append(settingText); + + if(!SettingWindow("Controller",w)) + GCSettings.Controller = currentController; // undo changes + + delete(w); + delete(settingText); +} + +/**************************************************************************** + * MenuGame + * + * Menu displayed when returning to the menu from in-game. + ***************************************************************************/ +static int MenuGame() +{ + int menu = MENU_NONE; + + GuiText titleTxt((char *)Memory.ROMFilename, 22, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnCloseOutline(button_small_png); + GuiImageData btnCloseOutlineOver(button_small_over_png); + GuiImageData btnLargeOutline(button_large_png); + GuiImageData btnLargeOutlineOver(button_large_over_png); + GuiImageData iconGameSettings(icon_game_settings_png); + GuiImageData iconLoad(icon_game_load_png); + GuiImageData iconSave(icon_game_save_png); + GuiImageData iconReset(icon_game_reset_png); + + GuiImageData battery(battery_png); + GuiImageData batteryRed(battery_red_png); + GuiImageData batteryBar(battery_bar_png); + + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + + GuiText saveBtnTxt("Save", 22, (GXColor){0, 0, 0, 255}); + GuiImage saveBtnImg(&btnLargeOutline); + GuiImage saveBtnImgOver(&btnLargeOutlineOver); + GuiImage saveBtnIcon(&iconSave); + GuiButton saveBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + saveBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + saveBtn.SetPosition(-125, 120); + saveBtn.SetLabel(&saveBtnTxt); + saveBtn.SetImage(&saveBtnImg); + saveBtn.SetImageOver(&saveBtnImgOver); + saveBtn.SetIcon(&saveBtnIcon); + saveBtn.SetSoundOver(&btnSoundOver); + saveBtn.SetSoundClick(&btnSoundClick); + saveBtn.SetTrigger(trigA); + saveBtn.SetTrigger(trig2); + saveBtn.SetEffectGrow(); + + GuiText loadBtnTxt("Load", 22, (GXColor){0, 0, 0, 255}); + GuiImage loadBtnImg(&btnLargeOutline); + GuiImage loadBtnImgOver(&btnLargeOutlineOver); + GuiImage loadBtnIcon(&iconLoad); + GuiButton loadBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + loadBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + loadBtn.SetPosition(125, 120); + loadBtn.SetLabel(&loadBtnTxt); + loadBtn.SetImage(&loadBtnImg); + loadBtn.SetImageOver(&loadBtnImgOver); + loadBtn.SetIcon(&loadBtnIcon); + loadBtn.SetSoundOver(&btnSoundOver); + loadBtn.SetSoundClick(&btnSoundClick); + loadBtn.SetTrigger(trigA); + loadBtn.SetTrigger(trig2); + loadBtn.SetEffectGrow(); + + GuiText resetBtnTxt("Reset", 22, (GXColor){0, 0, 0, 255}); + GuiImage resetBtnImg(&btnLargeOutline); + GuiImage resetBtnImgOver(&btnLargeOutlineOver); + GuiImage resetBtnIcon(&iconReset); + GuiButton resetBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + resetBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + resetBtn.SetPosition(125, 250); + resetBtn.SetLabel(&resetBtnTxt); + resetBtn.SetImage(&resetBtnImg); + resetBtn.SetImageOver(&resetBtnImgOver); + resetBtn.SetIcon(&resetBtnIcon); + resetBtn.SetSoundOver(&btnSoundOver); + resetBtn.SetSoundClick(&btnSoundClick); + resetBtn.SetTrigger(trigA); + resetBtn.SetTrigger(trig2); + resetBtn.SetEffectGrow(); + + GuiText gameSettingsBtnTxt("Game Settings", 22, (GXColor){0, 0, 0, 255}); + gameSettingsBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-20); + GuiImage gameSettingsBtnImg(&btnLargeOutline); + GuiImage gameSettingsBtnImgOver(&btnLargeOutlineOver); + GuiImage gameSettingsBtnIcon(&iconGameSettings); + GuiButton gameSettingsBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + gameSettingsBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + gameSettingsBtn.SetPosition(-125, 250); + gameSettingsBtn.SetLabel(&gameSettingsBtnTxt); + gameSettingsBtn.SetImage(&gameSettingsBtnImg); + gameSettingsBtn.SetImageOver(&gameSettingsBtnImgOver); + gameSettingsBtn.SetIcon(&gameSettingsBtnIcon); + gameSettingsBtn.SetSoundOver(&btnSoundOver); + gameSettingsBtn.SetSoundClick(&btnSoundClick); + gameSettingsBtn.SetTrigger(trigA); + gameSettingsBtn.SetTrigger(trig2); + gameSettingsBtn.SetEffectGrow(); + + char Lable[28]; + snprintf(Lable, sizeof(Lable), "Back to %s", GCSettings.LoaderName); + GuiText mainmenuBtnTxt(Lable, 22, (GXColor){0, 0, 0, 255}); + GuiImage mainmenuBtnImg(&btnOutline); + GuiImage mainmenuBtnImgOver(&btnOutlineOver); + GuiButton mainmenuBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + mainmenuBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + mainmenuBtn.SetPosition(0, -35); + mainmenuBtn.SetLabel(&mainmenuBtnTxt); + mainmenuBtn.SetImage(&mainmenuBtnImg); + mainmenuBtn.SetImageOver(&mainmenuBtnImgOver); + mainmenuBtn.SetSoundOver(&btnSoundOver); + mainmenuBtn.SetSoundClick(&btnSoundClick); + mainmenuBtn.SetTrigger(trigA); + mainmenuBtn.SetTrigger(trig2); + mainmenuBtn.SetEffectGrow(); + + GuiText closeBtnTxt("Close", 20, (GXColor){0, 0, 0, 255}); + GuiImage closeBtnImg(&btnCloseOutline); + GuiImage closeBtnImgOver(&btnCloseOutlineOver); + GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + closeBtn.SetPosition(-50, 35); + closeBtn.SetLabel(&closeBtnTxt); + closeBtn.SetImage(&closeBtnImg); + closeBtn.SetImageOver(&closeBtnImgOver); + closeBtn.SetSoundOver(&btnSoundOver); + closeBtn.SetSoundClick(&btnSoundClick); + closeBtn.SetTrigger(trigA); + closeBtn.SetTrigger(trig2); + closeBtn.SetTrigger(&trigHome); + closeBtn.SetEffectGrow(); + + #ifdef HW_RVL + int i; + char txt[3]; + bool status[4] = { false, false, false, false }; + int level[4] = { 0, 0, 0, 0 }; + bool newStatus; + int newLevel; + GuiText * batteryTxt[4]; + GuiImage * batteryImg[4]; + GuiImage * batteryBarImg[4]; + GuiButton * batteryBtn[4]; + + for(i=0; i < 4; i++) + { + sprintf(txt, "P%d", i+1); + + batteryTxt[i] = new GuiText(txt, 20, (GXColor){255, 255, 255, 255}); + batteryTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryImg[i] = new GuiImage(&battery); + batteryImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryImg[i]->SetPosition(30, 0); + batteryBarImg[i] = new GuiImage(&batteryBar); + batteryBarImg[i]->SetTile(0); + batteryBarImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryBarImg[i]->SetPosition(34, 0); + + batteryBtn[i] = new GuiButton(70, 20); + batteryBtn[i]->SetLabel(batteryTxt[i]); + batteryBtn[i]->SetImage(batteryImg[i]); + batteryBtn[i]->SetIcon(batteryBarImg[i]); + batteryBtn[i]->SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + batteryBtn[i]->SetRumble(false); + batteryBtn[i]->SetSelectable(false); + batteryBtn[i]->SetAlpha(150); + } + + batteryBtn[0]->SetPosition(45, -65); + batteryBtn[1]->SetPosition(135, -65); + batteryBtn[2]->SetPosition(45, -40); + batteryBtn[3]->SetPosition(135, -40); + #endif + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&titleTxt); + w.Append(&saveBtn); + w.Append(&loadBtn); + w.Append(&resetBtn); + w.Append(&gameSettingsBtn); + + #ifdef HW_RVL + w.Append(batteryBtn[0]); + w.Append(batteryBtn[1]); + w.Append(batteryBtn[2]); + w.Append(batteryBtn[3]); + #endif + + w.Append(&mainmenuBtn); + w.Append(&closeBtn); + + btnLogo->SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + btnLogo->SetPosition(-50, -40); + mainWindow->Append(&w); + + if(lastMenu == MENU_NONE) + { + enterSound->Play(); + bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 35); + closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 35); + titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 35); + mainmenuBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + #ifdef HW_RVL + batteryBtn[0]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + batteryBtn[1]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + batteryBtn[2]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + batteryBtn[3]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + #endif + + w.SetEffect(EFFECT_FADE, 15); + } + + ResumeGui(); + + if(lastMenu == MENU_NONE) + AutoSave(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + #ifdef HW_RVL + for(i=0; i < 4; i++) + { + if(WPAD_Probe(i, NULL) == WPAD_ERR_NONE) + { + newStatus = true; + newLevel = (userInput[i].wpad->battery_level / 100.0) * 4; + if(newLevel > 4) newLevel = 4; + } + else + { + newStatus = false; + newLevel = 0; + } + + if(status[i] != newStatus || level[i] != newLevel) + { + if(newStatus == true) // controller connected + { + batteryBtn[i]->SetAlpha(255); + batteryBarImg[i]->SetTile(newLevel); + + if(newLevel == 0) + batteryImg[i]->SetImage(&batteryRed); + else + batteryImg[i]->SetImage(&battery); + } + else // controller not connected + { + batteryBtn[i]->SetAlpha(150); + batteryBarImg[i]->SetTile(0); + batteryImg[i]->SetImage(&battery); + } + status[i] = newStatus; + level[i] = newLevel; + } + } + #endif + + if(saveBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAME_SAVE; + } + else if(loadBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAME_LOAD; + } + else if(resetBtn.GetState() == STATE_CLICKED) + { + if (WindowPrompt("Reset Game", "Are you sure that you want to reset this game? Any unsaved progress will be lost.", "OK", "Cancel")) + { + S9xSoftReset (); + menu = MENU_EXIT; + } + } + else if(gameSettingsBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS; + } + else if(mainmenuBtn.GetState() == STATE_CLICKED) + { + if (WindowPrompt("Quit Game", "Quit this game? Any unsaved progress will be lost.", "OK", "Cancel")) + { + HaltGui(); + mainWindow->Remove(gameScreenImg); + delete gameScreenImg; + delete gameScreen; + gameScreen = NULL; + free(gameScreenPng); + gameScreenPng = NULL; + ExitToWiiflow(); + } + } + else if(closeBtn.GetState() == STATE_CLICKED) + { + menu = MENU_EXIT; + + exitSound->Play(); + bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + mainmenuBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + #ifdef HW_RVL + batteryBtn[0]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + batteryBtn[1]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + batteryBtn[2]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + batteryBtn[3]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + #endif + + w.SetEffect(EFFECT_FADE, -15); + usleep(350000); // wait for effects to finish + } + } + + HaltGui(); + + #ifdef HW_RVL + for(i=0; i < 4; i++) + { + delete batteryTxt[i]; + delete batteryImg[i]; + delete batteryBarImg[i]; + delete batteryBtn[i]; + } + #endif + + mainWindow->Remove(&w); + return menu; +} + +/**************************************************************************** + * FindGameSaveNum + * + * Determines the save file number of the given file name + * Returns -1 if none is found + ***************************************************************************/ +static int FindGameSaveNum(char * savefile, int device) +{ + int n = -1; + int romlen = strlen(Memory.ROMFilename); + int savelen = strlen(savefile); + + int diff = savelen-romlen; + + if(strncmp(savefile, Memory.ROMFilename, romlen) != 0) + return -1; + + if(savefile[romlen] == ' ') + { + if(diff == 5 && strncmp(&savefile[romlen+1], "Auto", 4) == 0) + n = 0; // found Auto save + else if(diff == 2 || diff == 3) + n = atoi(&savefile[romlen+1]); + } + + if(n >= 0 && n < MAX_SAVES) + return n; + else + return -1; +} + +/**************************************************************************** + * MenuGameSaves + * + * Allows the user to load or save progress. + ***************************************************************************/ +static int MenuGameSaves(int action) +{ + int menu = MENU_NONE; + int ret; + int i, n, type, len, len2; + int j = 0; + SaveList saves; + char filepath[1024]; + char scrfile[1024]; + char tmp[MAXJOLIET+1]; + struct stat filestat; + struct tm * timeinfo; + int device = GCSettings.SaveMethod; + + if(device == DEVICE_AUTO) + autoSaveMethod(NOTSILENT); + + if(!ChangeInterface(device, NOTSILENT)) + return MENU_GAME; + + GuiText titleTxt(NULL, 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + if(action == 0) + titleTxt.SetText("Load Game"); + else + titleTxt.SetText("Save Game"); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnCloseOutline(button_small_png); + GuiImageData btnCloseOutlineOver(button_small_over_png); + + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(50, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + GuiText closeBtnTxt("Close", 20, (GXColor){0, 0, 0, 255}); + GuiImage closeBtnImg(&btnCloseOutline); + GuiImage closeBtnImgOver(&btnCloseOutlineOver); + GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + closeBtn.SetPosition(-50, 35); + closeBtn.SetLabel(&closeBtnTxt); + closeBtn.SetImage(&closeBtnImg); + closeBtn.SetImageOver(&closeBtnImgOver); + closeBtn.SetSoundOver(&btnSoundOver); + closeBtn.SetSoundClick(&btnSoundClick); + closeBtn.SetTrigger(trigA); + closeBtn.SetTrigger(trig2); + closeBtn.SetTrigger(&trigHome); + closeBtn.SetEffectGrow(); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + w.Append(&closeBtn); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + memset(&saves, 0, sizeof(saves)); + + sprintf(browser.dir, "%s%s", pathPrefix[GCSettings.SaveMethod], GCSettings.SaveFolder); + ParseDirectory(true, false); + + len = strlen(Memory.ROMFilename); + + // find matching files + AllocSaveBuffer(); + + for(i=0; i < browser.numEntries; i++) + { + len2 = strlen(browserList[i].filename); + + if(len2 < 6 || len2-len < 5) + continue; + + if(strncmp(&browserList[i].filename[len2-4], ".srm", 4) == 0) + type = FILE_SRAM; + else if(strncmp(&browserList[i].filename[len2-4], ".frz", 4) == 0) + type = FILE_SNAPSHOT; + else + continue; + + strcpy(tmp, browserList[i].filename); + tmp[len2-4] = 0; + n = FindGameSaveNum(tmp, device); + + if(n >= 0) + { + saves.type[j] = type; + saves.files[saves.type[j]][n] = 1; + strcpy(saves.filename[j], browserList[i].filename); + + if(saves.type[j] == FILE_SNAPSHOT) + { + sprintf(scrfile, "%s%s/%s.png", pathPrefix[GCSettings.SaveMethod], GCSettings.SaveFolder, tmp); + + memset(savebuffer, 0, SAVEBUFFERSIZE); + if(LoadFile(scrfile, SILENT)) + saves.previewImg[j] = new GuiImageData(savebuffer, 64, 48); + } + snprintf(filepath, 1024, "%s%s/%s", pathPrefix[GCSettings.SaveMethod], GCSettings.SaveFolder, saves.filename[j]); + if (stat(filepath, &filestat) == 0) + { + timeinfo = localtime(&filestat.st_mtime); + strftime(saves.date[j], 20, "%a %b %d", timeinfo); + strftime(saves.time[j], 10, "%I:%M %p", timeinfo); + } + j++; + } + } + + FreeSaveBuffer(); + saves.length = j; + + if(saves.length == 0 && action == 0) + { + InfoPrompt("No game saves found."); + menu = MENU_GAME; + } + + GuiSaveBrowser saveBrowser(552, 248, &saves, action); + saveBrowser.SetPosition(0, 108); + saveBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + + HaltGui(); + mainWindow->Append(&saveBrowser); + mainWindow->ChangeFocus(&saveBrowser); + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + ret = saveBrowser.GetClickedSave(); + + // load or save game + if(ret > -3) + { + int result = 0; + + if(action == 0) // load + { + MakeFilePath(filepath, saves.type[ret], saves.filename[ret]); + switch(saves.type[ret]) + { + case FILE_SRAM: + result = LoadSRAM(filepath, NOTSILENT); + break; + case FILE_SNAPSHOT: + result = LoadSnapshot (filepath, NOTSILENT); + break; + } + if(result) + menu = MENU_EXIT; + } + else // save + { + if(ret == -2) // new SRAM + { + for(i=1; i < 100; i++) + if(saves.files[FILE_SRAM][i] == 0) + break; + + if(i < 100) + { + MakeFilePath(filepath, FILE_SRAM, Memory.ROMFilename, i); + SaveSRAM(filepath, NOTSILENT); + menu = MENU_GAME_SAVE; + } + } + else if(ret == -1) // new Snapshot + { + for(i=1; i < 100; i++) + if(saves.files[FILE_SNAPSHOT][i] == 0) + break; + + if(i < 100) + { + MakeFilePath(filepath, FILE_SNAPSHOT, Memory.ROMFilename, i); + SaveSnapshot (filepath, NOTSILENT); + menu = MENU_GAME_SAVE; + } + } + else // overwrite SRAM/Snapshot + { + MakeFilePath(filepath, saves.type[ret], saves.filename[ret]); + switch(saves.type[ret]) + { + case FILE_SRAM: + SaveSRAM(filepath, NOTSILENT); + break; + case FILE_SNAPSHOT: + SaveSnapshot (filepath, NOTSILENT); + break; + } + menu = MENU_GAME_SAVE; + } + } + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAME; + } + else if(closeBtn.GetState() == STATE_CLICKED) + { + menu = MENU_EXIT; + + exitSound->Play(); + bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + backBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + + w.SetEffect(EFFECT_FADE, -15); + + usleep(350000); // wait for effects to finish + } + } + + HaltGui(); + + for(i=0; i < saves.length; i++) + if(saves.previewImg[i]) + delete saves.previewImg[i]; + + mainWindow->Remove(&saveBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + ResetBrowser(); + return menu; +} + +/**************************************************************************** + * MenuGameSettings + ***************************************************************************/ +static int MenuGameSettings() +{ + int menu = MENU_NONE; + char filepath[1024]; + + GuiText titleTxt("Game Settings", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnLargeOutline(button_large_png); + GuiImageData btnLargeOutlineOver(button_large_over_png); + GuiImageData iconMappings(icon_settings_mappings_png); + GuiImageData iconVideo(icon_settings_video_png); + GuiImageData iconController(icon_game_controllers_png); + GuiImageData iconCheats(icon_game_cheats_png); + GuiImageData iconScreenshot(icon_settings_screenshot_png); + GuiImageData btnCloseOutline(button_small_png); + GuiImageData btnCloseOutlineOver(button_small_over_png); + + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + + GuiText mappingBtnTxt("Button Mappings", 22, (GXColor){0, 0, 0, 255}); + mappingBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30); + GuiImage mappingBtnImg(&btnLargeOutline); + GuiImage mappingBtnImgOver(&btnLargeOutlineOver); + GuiImage mappingBtnIcon(&iconMappings); + GuiButton mappingBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + mappingBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + mappingBtn.SetPosition(-125, 120); + mappingBtn.SetLabel(&mappingBtnTxt); + mappingBtn.SetImage(&mappingBtnImg); + mappingBtn.SetImageOver(&mappingBtnImgOver); + mappingBtn.SetIcon(&mappingBtnIcon); + mappingBtn.SetSoundOver(&btnSoundOver); + mappingBtn.SetSoundClick(&btnSoundClick); + mappingBtn.SetTrigger(trigA); + mappingBtn.SetTrigger(trig2); + mappingBtn.SetEffectGrow(); + + GuiText videoBtnTxt("Video", 22, (GXColor){0, 0, 0, 255}); + videoBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-20); + GuiImage videoBtnImg(&btnLargeOutline); + GuiImage videoBtnImgOver(&btnLargeOutlineOver); + GuiImage videoBtnIcon(&iconVideo); + GuiButton videoBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + videoBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + videoBtn.SetPosition(125, 120); + videoBtn.SetLabel(&videoBtnTxt); + videoBtn.SetImage(&videoBtnImg); + videoBtn.SetImageOver(&videoBtnImgOver); + videoBtn.SetIcon(&videoBtnIcon); + videoBtn.SetSoundOver(&btnSoundOver); + videoBtn.SetSoundClick(&btnSoundClick); + videoBtn.SetTrigger(trigA); + videoBtn.SetTrigger(trig2); + videoBtn.SetEffectGrow(); + + GuiText controllerBtnTxt("Controller", 22, (GXColor){0, 0, 0, 255}); + GuiImage controllerBtnImg(&btnLargeOutline); + GuiImage controllerBtnImgOver(&btnLargeOutlineOver); + GuiImage controllerBtnIcon(&iconController); + GuiButton controllerBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + controllerBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + controllerBtn.SetPosition(-200, 250); + controllerBtn.SetLabel(&controllerBtnTxt); + controllerBtn.SetImage(&controllerBtnImg); + controllerBtn.SetImageOver(&controllerBtnImgOver); + controllerBtn.SetIcon(&controllerBtnIcon); + controllerBtn.SetSoundOver(&btnSoundOver); + controllerBtn.SetSoundClick(&btnSoundClick); + controllerBtn.SetTrigger(trigA); + controllerBtn.SetTrigger(trig2); + controllerBtn.SetEffectGrow(); + + GuiText screenshotBtnTxt("ScreenShot", 22, (GXColor){0, 0, 0, 255}); + GuiImage screenshotBtnImg(&btnLargeOutline); + GuiImage screenshotBtnImgOver(&btnLargeOutlineOver); + GuiImage screenshotBtnIcon(&iconScreenshot); + GuiButton screenshotBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + screenshotBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + screenshotBtn.SetPosition(0, 250); + screenshotBtn.SetLabel(&screenshotBtnTxt); + screenshotBtn.SetImage(&screenshotBtnImg); + screenshotBtn.SetImageOver(&screenshotBtnImgOver); + screenshotBtn.SetIcon(&screenshotBtnIcon); + screenshotBtn.SetSoundOver(&btnSoundOver); + screenshotBtn.SetSoundClick(&btnSoundClick); + screenshotBtn.SetTrigger(trigA); + screenshotBtn.SetTrigger(trig2); + screenshotBtn.SetEffectGrow(); + + GuiText cheatsBtnTxt("Cheats", 22, (GXColor){0, 0, 0, 255}); + GuiImage cheatsBtnImg(&btnLargeOutline); + GuiImage cheatsBtnImgOver(&btnLargeOutlineOver); + GuiImage cheatsBtnIcon(&iconCheats); + GuiButton cheatsBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + cheatsBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + cheatsBtn.SetPosition(200, 250); + cheatsBtn.SetLabel(&cheatsBtnTxt); + cheatsBtn.SetImage(&cheatsBtnImg); + cheatsBtn.SetImageOver(&cheatsBtnImgOver); + cheatsBtn.SetIcon(&cheatsBtnIcon); + cheatsBtn.SetSoundOver(&btnSoundOver); + cheatsBtn.SetSoundClick(&btnSoundClick); + cheatsBtn.SetTrigger(trigA); + cheatsBtn.SetTrigger(trig2); + cheatsBtn.SetEffectGrow(); + + GuiText closeBtnTxt("Close", 20, (GXColor){0, 0, 0, 255}); + GuiImage closeBtnImg(&btnCloseOutline); + GuiImage closeBtnImgOver(&btnCloseOutlineOver); + GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + closeBtn.SetPosition(-50, 35); + closeBtn.SetLabel(&closeBtnTxt); + closeBtn.SetImage(&closeBtnImg); + closeBtn.SetImageOver(&closeBtnImgOver); + closeBtn.SetSoundOver(&btnSoundOver); + closeBtn.SetSoundClick(&btnSoundClick); + closeBtn.SetTrigger(trigA); + closeBtn.SetTrigger(trig2); + closeBtn.SetTrigger(&trigHome); + closeBtn.SetEffectGrow(); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(50, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&titleTxt); + w.Append(&mappingBtn); + w.Append(&videoBtn); + w.Append(&controllerBtn); + w.Append(&screenshotBtn); + w.Append(&cheatsBtn); + w.Append(&closeBtn); + w.Append(&backBtn); + + mainWindow->Append(&w); + + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + if(mappingBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_MAPPINGS; + } + else if(videoBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_VIDEO; + } + else if(controllerBtn.GetState() == STATE_CLICKED) + { + ControllerWindow(); + } + else if(cheatsBtn.GetState() == STATE_CLICKED) + { + cheatsBtn.ResetState(); + if(Cheat.num_cheats > 0) + menu = MENU_GAMESETTINGS_CHEATS; + else + InfoPrompt("Cheats file not found!"); + } + else if(screenshotBtn.GetState() == STATE_CLICKED) + { + if (WindowPrompt("Preview Screenshot", "Save a new Preview Screenshot? Current Screenshot image will be overwritten.", "OK", "Cancel")) + { + snprintf(filepath, 1024, "%s%s/%s", pathPrefix[GCSettings.SaveMethod], GCSettings.ScreenshotsFolder, Memory.ROMFilename); + SavePreviewImg(filepath, NOTSILENT); + } + } + else if(closeBtn.GetState() == STATE_CLICKED) + { + menu = MENU_EXIT; + + exitSound->Play(); + bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + backBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + + w.SetEffect(EFFECT_FADE, -15); + + usleep(350000); // wait for effects to finish + } + else if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAME; + } + } + + HaltGui(); + mainWindow->Remove(&w); + return menu; +} + +/**************************************************************************** + * MenuGameCheats + * + * Displays a list of cheats available, and allows the user to enable/disable + * them. + ***************************************************************************/ +static int MenuGameCheats() +{ + int menu = MENU_NONE; + int ret; + u16 i = 0; + OptionList options; + + for(i=0; i < Cheat.num_cheats; i++) + { + sprintf (options.name[i], "%s", Cheat.c[i].name); + sprintf (options.value[i], "%s", Cheat.c[i].enabled == true ? "On" : "Off"); + } + + options.length = i; + + GuiText titleTxt("Game Settings - Cheats", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(50, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + ret = optionBrowser.GetClickedOption(); + + if(ret >= 0) + { + if(Cheat.c[ret].enabled) + S9xDisableCheat(ret); + else + S9xEnableCheat(ret); + sprintf (options.value[ret], "%s", Cheat.c[ret].enabled == true ? "On" : "Off"); + optionBrowser.TriggerUpdate(); + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS; + } + } + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + return menu; +} + +/**************************************************************************** + * MenuSettingsMappings + ***************************************************************************/ +static int MenuSettingsMappings() +{ + int menu = MENU_NONE; + + GuiText titleTxt("Game Settings - Button Mappings", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnLargeOutline(button_large_png); + GuiImageData btnLargeOutlineOver(button_large_over_png); + GuiImageData iconSNESController(icon_settings_snescontroller_png); + GuiImageData iconSuperscope(icon_settings_superscope_png); + GuiImageData iconJustifier(icon_settings_justifier_png); + GuiImageData iconMouse(icon_settings_mouse_png); + + GuiText snesBtnTxt("SNES Controller", 22, (GXColor){0, 0, 0, 255}); + snesBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-40); + GuiImage snesBtnImg(&btnLargeOutline); + GuiImage snesBtnImgOver(&btnLargeOutlineOver); + GuiImage snesBtnIcon(&iconSNESController); + GuiButton snesBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + snesBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + snesBtn.SetPosition(-125, 120); + snesBtn.SetLabel(&snesBtnTxt); + snesBtn.SetImage(&snesBtnImg); + snesBtn.SetImageOver(&snesBtnImgOver); + snesBtn.SetIcon(&snesBtnIcon); + snesBtn.SetSoundOver(&btnSoundOver); + snesBtn.SetSoundClick(&btnSoundClick); + snesBtn.SetTrigger(trigA); + snesBtn.SetTrigger(trig2); + snesBtn.SetEffectGrow(); + + GuiText superscopeBtnTxt("Super Scope", 22, (GXColor){0, 0, 0, 255}); + superscopeBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-20); + GuiImage superscopeBtnImg(&btnLargeOutline); + GuiImage superscopeBtnImgOver(&btnLargeOutlineOver); + GuiImage superscopeBtnIcon(&iconSuperscope); + GuiButton superscopeBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + superscopeBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + superscopeBtn.SetPosition(125, 120); + superscopeBtn.SetLabel(&superscopeBtnTxt); + superscopeBtn.SetImage(&superscopeBtnImg); + superscopeBtn.SetImageOver(&superscopeBtnImgOver); + superscopeBtn.SetIcon(&superscopeBtnIcon); + superscopeBtn.SetSoundOver(&btnSoundOver); + superscopeBtn.SetSoundClick(&btnSoundClick); + superscopeBtn.SetTrigger(trigA); + superscopeBtn.SetTrigger(trig2); + superscopeBtn.SetEffectGrow(); + + GuiText mouseBtnTxt("SNES Mouse", 22, (GXColor){0, 0, 0, 255}); + mouseBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-55); + GuiImage mouseBtnImg(&btnLargeOutline); + GuiImage mouseBtnImgOver(&btnLargeOutlineOver); + GuiImage mouseBtnIcon(&iconMouse); + GuiButton mouseBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + mouseBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + mouseBtn.SetPosition(-125, 250); + mouseBtn.SetLabel(&mouseBtnTxt); + mouseBtn.SetImage(&mouseBtnImg); + mouseBtn.SetImageOver(&mouseBtnImgOver); + mouseBtn.SetIcon(&mouseBtnIcon); + mouseBtn.SetSoundOver(&btnSoundOver); + mouseBtn.SetSoundClick(&btnSoundClick); + mouseBtn.SetTrigger(trigA); + mouseBtn.SetTrigger(trig2); + mouseBtn.SetEffectGrow(); + + GuiText justifierBtnTxt("Justifier", 22, (GXColor){0, 0, 0, 255}); + GuiImage justifierBtnImg(&btnLargeOutline); + GuiImage justifierBtnImgOver(&btnLargeOutlineOver); + GuiImage justifierBtnIcon(&iconJustifier); + GuiButton justifierBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + justifierBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + justifierBtn.SetPosition(125, 250); + justifierBtn.SetLabel(&justifierBtnTxt); + justifierBtn.SetImage(&justifierBtnImg); + justifierBtn.SetImageOver(&justifierBtnImgOver); + justifierBtn.SetIcon(&justifierBtnIcon); + justifierBtn.SetSoundOver(&btnSoundOver); + justifierBtn.SetSoundClick(&btnSoundClick); + justifierBtn.SetTrigger(trigA); + justifierBtn.SetTrigger(trig2); + justifierBtn.SetEffectGrow(); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(50, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&titleTxt); + w.Append(&snesBtn); + w.Append(&superscopeBtn); + w.Append(&mouseBtn); + w.Append(&justifierBtn); + + w.Append(&backBtn); + + mainWindow->Append(&w); + + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + if(snesBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_MAPPINGS_CTRL; + mapMenuCtrlSNES = CTRL_PAD; + } + else if(superscopeBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_MAPPINGS_CTRL; + mapMenuCtrlSNES = CTRL_SCOPE; + } + else if(mouseBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_MAPPINGS_CTRL; + mapMenuCtrlSNES = CTRL_MOUSE; + } + else if(justifierBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_MAPPINGS_CTRL; + mapMenuCtrlSNES = CTRL_JUST; + } + else if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS; + } + } + HaltGui(); + mainWindow->Remove(&w); + return menu; +} + +static int MenuSettingsMappingsController() +{ + int menu = MENU_NONE; + char menuTitle[100]; + char menuSubtitle[100]; + + sprintf(menuTitle, "Game Settings - Button Mappings"); + GuiText titleTxt(menuTitle, 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,30); + + sprintf(menuSubtitle, "%s", ctrlName[mapMenuCtrlSNES]); + GuiText subtitleTxt(menuSubtitle, 20, (GXColor){255, 255, 255, 255}); + subtitleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + subtitleTxt.SetPosition(50,60); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnLargeOutline(button_large_png); + GuiImageData btnLargeOutlineOver(button_large_over_png); + GuiImageData iconWiimote(icon_settings_wiimote_png); + GuiImageData iconClassic(icon_settings_classic_png); + GuiImageData iconGamecube(icon_settings_gamecube_png); + GuiImageData iconNunchuk(icon_settings_nunchuk_png); + GuiImageData iconWiiupro(icon_settings_wiiupro_png); + + GuiText gamecubeBtnTxt("GameCube Controller", 22, (GXColor){0, 0, 0, 255}); + gamecubeBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-20); + GuiImage gamecubeBtnImg(&btnLargeOutline); + GuiImage gamecubeBtnImgOver(&btnLargeOutlineOver); + GuiImage gamecubeBtnIcon(&iconGamecube); + GuiButton gamecubeBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + gamecubeBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + gamecubeBtn.SetPosition(-125, 120); + gamecubeBtn.SetLabel(&gamecubeBtnTxt); + gamecubeBtn.SetImage(&gamecubeBtnImg); + gamecubeBtn.SetImageOver(&gamecubeBtnImgOver); + gamecubeBtn.SetIcon(&gamecubeBtnIcon); + gamecubeBtn.SetSoundOver(&btnSoundOver); + gamecubeBtn.SetSoundClick(&btnSoundClick); + gamecubeBtn.SetTrigger(trigA); + gamecubeBtn.SetTrigger(trig2); + gamecubeBtn.SetEffectGrow(); + + GuiText wiimoteBtnTxt("Wiimote", 22, (GXColor){0, 0, 0, 255}); + GuiImage wiimoteBtnImg(&btnLargeOutline); + GuiImage wiimoteBtnImgOver(&btnLargeOutlineOver); + GuiImage wiimoteBtnIcon(&iconWiimote); + GuiButton wiimoteBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + wiimoteBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + wiimoteBtn.SetPosition(125, 120); + wiimoteBtn.SetLabel(&wiimoteBtnTxt); + wiimoteBtn.SetImage(&wiimoteBtnImg); + wiimoteBtn.SetImageOver(&wiimoteBtnImgOver); + wiimoteBtn.SetIcon(&wiimoteBtnIcon); + wiimoteBtn.SetSoundOver(&btnSoundOver); + wiimoteBtn.SetSoundClick(&btnSoundClick); + wiimoteBtn.SetTrigger(trigA); + wiimoteBtn.SetTrigger(trig2); + wiimoteBtn.SetEffectGrow(); + + GuiText classicBtnTxt("Classic Controller", 22, (GXColor){0, 0, 0, 255}); + classicBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-20); + GuiImage classicBtnImg(&btnLargeOutline); + GuiImage classicBtnImgOver(&btnLargeOutlineOver); + GuiImage classicBtnIcon(&iconClassic); + GuiButton classicBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + classicBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + classicBtn.SetPosition(-200, 250); + classicBtn.SetLabel(&classicBtnTxt); + classicBtn.SetImage(&classicBtnImg); + classicBtn.SetImageOver(&classicBtnImgOver); + classicBtn.SetIcon(&classicBtnIcon); + classicBtn.SetSoundOver(&btnSoundOver); + classicBtn.SetSoundClick(&btnSoundClick); + classicBtn.SetTrigger(trigA); + classicBtn.SetTrigger(trig2); + classicBtn.SetEffectGrow(); + + GuiText wiiuproBtnTxt("Wii U Pro Controller", 22, (GXColor){0, 0, 0, 255}); + wiiuproBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-20); + GuiImage wiiuproBtnImg(&btnLargeOutline); + GuiImage wiiuproBtnImgOver(&btnLargeOutlineOver); + GuiImage wiiuproBtnIcon(&iconWiiupro); + GuiButton wiiuproBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + wiiuproBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + wiiuproBtn.SetPosition(0, 250); + wiiuproBtn.SetLabel(&wiiuproBtnTxt); + wiiuproBtn.SetImage(&wiiuproBtnImg); + wiiuproBtn.SetImageOver(&wiiuproBtnImgOver); + wiiuproBtn.SetIcon(&wiiuproBtnIcon); + wiiuproBtn.SetSoundOver(&btnSoundOver); + wiiuproBtn.SetSoundClick(&btnSoundClick); + wiiuproBtn.SetTrigger(trigA); + wiiuproBtn.SetTrigger(trig2); + wiiuproBtn.SetEffectGrow(); + + GuiText nunchukBtnTxt1("Wiimote", 22, (GXColor){0, 0, 0, 255}); + GuiText nunchukBtnTxt2("&", 18, (GXColor){0, 0, 0, 255}); + GuiText nunchukBtnTxt3("Nunchuk", 22, (GXColor){0, 0, 0, 255}); + nunchukBtnTxt1.SetPosition(0, -20); + nunchukBtnTxt3.SetPosition(0, +20); + GuiImage nunchukBtnImg(&btnLargeOutline); + GuiImage nunchukBtnImgOver(&btnLargeOutlineOver); + GuiImage nunchukBtnIcon(&iconNunchuk); + GuiButton nunchukBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + nunchukBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + nunchukBtn.SetPosition(200, 250); + nunchukBtn.SetLabel(&nunchukBtnTxt1, 0); + nunchukBtn.SetLabel(&nunchukBtnTxt2, 1); + nunchukBtn.SetLabel(&nunchukBtnTxt3, 2); + nunchukBtn.SetImage(&nunchukBtnImg); + nunchukBtn.SetImageOver(&nunchukBtnImgOver); + nunchukBtn.SetIcon(&nunchukBtnIcon); + nunchukBtn.SetSoundOver(&btnSoundOver); + nunchukBtn.SetSoundClick(&btnSoundClick); + nunchukBtn.SetTrigger(trigA); + nunchukBtn.SetTrigger(trig2); + nunchukBtn.SetEffectGrow(); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(50, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&titleTxt); + w.Append(&subtitleTxt); + + w.Append(&gamecubeBtn); +#ifdef HW_RVL + w.Append(&wiimoteBtn); + + if(mapMenuCtrlSNES == CTRL_PAD) + { + w.Append(&nunchukBtn); + w.Append(&classicBtn); + w.Append(&wiiuproBtn); + } +#endif + w.Append(&backBtn); + + mainWindow->Append(&w); + + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + if(wiimoteBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_MAPPINGS_MAP; + mapMenuCtrl = CTRLR_WIIMOTE; + } + else if(nunchukBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_MAPPINGS_MAP; + mapMenuCtrl = CTRLR_NUNCHUK; + } + else if(classicBtn.GetState() == STATE_CLICKED) + { + wiiuproCtrl = 0; + menu = MENU_GAMESETTINGS_MAPPINGS_MAP; + mapMenuCtrl = CTRLR_CLASSIC; + } + else if(wiiuproBtn.GetState() == STATE_CLICKED) + { + wiiuproCtrl = 1; + menu = MENU_GAMESETTINGS_MAPPINGS_MAP; + mapMenuCtrl = CTRLR_CLASSIC; + } + else if(gamecubeBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_MAPPINGS_MAP; + mapMenuCtrl = CTRLR_GCPAD; + } + else if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_MAPPINGS; + } + } + HaltGui(); + mainWindow->Remove(&w); + return menu; +} + +/**************************************************************************** + * ButtonMappingWindow + ***************************************************************************/ + +static u32 +ButtonMappingWindow() +{ + GuiWindow promptWindow(448,288); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText titleTxt("Button Mapping", 26, (GXColor){70, 70, 10, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,14); + + char msg[200]; + + switch(mapMenuCtrl) + { + case CTRLR_GCPAD: + #ifdef HW_RVL + sprintf(msg, "Press any button on the GameCube Controller now. Press Home or the C-Stick in any direction to clear the existing mapping."); + #else + sprintf(msg, "Press any button on the GameCube Controller now. Press the C-Stick in any direction to clear the existing mapping."); + #endif + break; + case CTRLR_WIIMOTE: + sprintf(msg, "Press any button on the Wiimote now. Press Home to clear the existing mapping."); + break; + case CTRLR_CLASSIC: + if(wiiuproCtrl == 1) + { + sprintf(msg, "Press any button on the Wii U Pro Controller now. Press Home to clear the existing mapping."); + } + else + { + sprintf(msg, "Press any button on the Classic Controller now. Press Home to clear the existing mapping."); + } + break; + case CTRLR_NUNCHUK: + sprintf(msg, "Press any button on the Wiimote or Nunchuk now. Press Home to clear the existing mapping."); + break; + } + + GuiText msgTxt(msg, 26, (GXColor){0, 0, 0, 255}); + msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + msgTxt.SetPosition(0,-20); + msgTxt.SetWrap(true, 430); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&msgTxt); + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + u32 pressed = 0; + + while(pressed == 0) + { + usleep(THREAD_SLEEP); + + if(mapMenuCtrl == CTRLR_GCPAD) + { + pressed = userInput[0].pad.btns_d; + + if(userInput[0].pad.substickX < -70 || + userInput[0].pad.substickX > 70 || + userInput[0].pad.substickY < -70 || + userInput[0].pad.substickY > 70) + pressed = WPAD_BUTTON_HOME; + + if(userInput[0].wpad->btns_d == WPAD_BUTTON_HOME) + pressed = WPAD_BUTTON_HOME; + } + else + { + pressed = userInput[0].wpad->btns_d; + + // always allow Home button to be pressed to clear the existing mapping + if(pressed != WPAD_BUTTON_HOME) + { + switch(mapMenuCtrl) + { + case CTRLR_WIIMOTE: + if(pressed > 0x1000) + pressed = 0; // not a valid input + break; + + case CTRLR_CLASSIC: + if(userInput[0].wpad->exp.type != WPAD_EXP_CLASSIC) + pressed = 0; // not a valid input + else if(pressed <= 0x1000) + pressed = 0; // not a valid input + break; + + case CTRLR_NUNCHUK: + if(userInput[0].wpad->exp.type != WPAD_EXP_NUNCHUK) + pressed = 0; // not a valid input + break; + } + } + if(pressed == 0) + pressed = userInput[0].wupcdata.btns_d; + } + } + + if(pressed == WPAD_BUTTON_HOME + || pressed == WPAD_CLASSIC_BUTTON_HOME) + pressed = 0; + + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + + return pressed; +} + +static int MenuSettingsMappingsMap() +{ + int menu = MENU_NONE; + int ret,i,j; + bool firstRun = true; + OptionList options; + + char menuTitle[100]; + char menuSubtitle[100]; + sprintf(menuTitle, "Game Settings - Button Mappings"); + + GuiText titleTxt(menuTitle, 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,30); + + if(wiiuproCtrl == 1) + { + sprintf(menuSubtitle, "%s - %s", gettext(ctrlName[mapMenuCtrlSNES]),"Wii U Pro Controller"); + } + else + { + sprintf(menuSubtitle, "%s - %s", gettext(ctrlName[mapMenuCtrlSNES]), gettext(ctrlrName[mapMenuCtrl])); + } + + GuiText subtitleTxt(menuSubtitle, 20, (GXColor){255, 255, 255, 255}); + subtitleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + subtitleTxt.SetPosition(50,60); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnShortOutline(button_short_png); + GuiImageData btnShortOutlineOver(button_short_over_png); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(50, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + GuiText resetBtnTxt("Reset", 22, (GXColor){0, 0, 0, 255}); + GuiImage resetBtnImg(&btnShortOutline); + GuiImage resetBtnImgOver(&btnShortOutlineOver); + GuiButton resetBtn(btnShortOutline.GetWidth(), btnShortOutline.GetHeight()); + resetBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + resetBtn.SetPosition(260, -35); + resetBtn.SetLabel(&resetBtnTxt); + resetBtn.SetImage(&resetBtnImg); + resetBtn.SetImageOver(&resetBtnImgOver); + resetBtn.SetSoundOver(&btnSoundOver); + resetBtn.SetSoundClick(&btnSoundClick); + resetBtn.SetTrigger(trigA); + resetBtn.SetTrigger(trig2); + resetBtn.SetEffectGrow(); + + i=0; + + switch(mapMenuCtrlSNES) + { + case CTRL_PAD: + sprintf(options.name[i++], "A"); + sprintf(options.name[i++], "B"); + sprintf(options.name[i++], "X"); + sprintf(options.name[i++], "Y"); + sprintf(options.name[i++], "L"); + sprintf(options.name[i++], "R"); + sprintf(options.name[i++], "Start"); + sprintf(options.name[i++], "Select"); + sprintf(options.name[i++], "Up"); + sprintf(options.name[i++], "Down"); + sprintf(options.name[i++], "Left"); + sprintf(options.name[i++], "Right"); + options.length = i; + break; + case CTRL_SCOPE: + sprintf(options.name[i++], "Fire"); + sprintf(options.name[i++], "Aim Offscreen"); + sprintf(options.name[i++], "Cursor"); + sprintf(options.name[i++], "Turbo On"); + sprintf(options.name[i++], "Turbo Off"); + sprintf(options.name[i++], "Pause"); + options.length = i; + break; + case CTRL_MOUSE: + sprintf(options.name[i++], "Left Button"); + sprintf(options.name[i++], "Right Button"); + options.length = i; + break; + case CTRL_JUST: + sprintf(options.name[i++], "Fire"); + sprintf(options.name[i++], "Aim Offscreen"); + sprintf(options.name[i++], "Start"); + options.length = i; + break; + }; + + for(i=0; i < options.length; i++) + options.value[i][0] = 0; + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + optionBrowser.SetCol2Position(215); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + w.Append(&resetBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + mainWindow->Append(&subtitleTxt); + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_MAPPINGS_CTRL; + } + else if(resetBtn.GetState() == STATE_CLICKED) + { + resetBtn.ResetState(); + + int choice = WindowPrompt( + "Reset Mappings", + "Are you sure that you want to reset your mappings?", + "Yes", + "No"); + + if(choice == 1) + { + ResetControls(mapMenuCtrlSNES, mapMenuCtrl); + firstRun = true; + } + } + + ret = optionBrowser.GetClickedOption(); + + if(ret >= 0) + { + // get a button selection from user + btnmap[mapMenuCtrlSNES][mapMenuCtrl][ret] = ButtonMappingWindow(); + } + + if(ret >= 0 || firstRun) + { + firstRun = false; + + for(i=0; i < options.length; i++) + { + for(j=0; j < ctrlr_def[mapMenuCtrl].num_btns; j++) + { + if(btnmap[mapMenuCtrlSNES][mapMenuCtrl][i] == 0) + { + options.value[i][0] = 0; + } + else if(btnmap[mapMenuCtrlSNES][mapMenuCtrl][i] == + ctrlr_def[mapMenuCtrl].map[j].btn) + { + if(strcmp(options.value[i], ctrlr_def[mapMenuCtrl].map[j].name) != 0) + sprintf(options.value[i], ctrlr_def[mapMenuCtrl].map[j].name); + break; + } + } + } + optionBrowser.TriggerUpdate(); + } + } + wiiuproCtrl = 0; + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + mainWindow->Remove(&subtitleTxt); + return menu; +} + +/**************************************************************************** + * MenuSettingsVideo + ***************************************************************************/ + +static void ScreenZoomWindowUpdate(void * ptr, float h, float v) +{ + GuiButton * b = (GuiButton *)ptr; + if(b->GetState() == STATE_CLICKED) + { + GCSettings.zoomHor += h; + GCSettings.zoomVert += v; + + char zoom[10]; + sprintf(zoom, "%.2f%%", GCSettings.zoomHor*100); + settingText->SetText(zoom); + sprintf(zoom, "%.2f%%", GCSettings.zoomVert*100); + settingText2->SetText(zoom); + b->ResetState(); + } +} + +static void ScreenZoomWindowLeftClick(void * ptr) { ScreenZoomWindowUpdate(ptr, -0.01, 0); } +static void ScreenZoomWindowRightClick(void * ptr) { ScreenZoomWindowUpdate(ptr, +0.01, 0); } +static void ScreenZoomWindowUpClick(void * ptr) { ScreenZoomWindowUpdate(ptr, 0, +0.01); } +static void ScreenZoomWindowDownClick(void * ptr) { ScreenZoomWindowUpdate(ptr, 0, -0.01); } + +static void ScreenZoomWindow() +{ + GuiWindow * w = new GuiWindow(200,200); + w->SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + + GuiTrigger trigLeft; + trigLeft.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT, PAD_BUTTON_LEFT); + + GuiTrigger trigRight; + trigRight.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT, PAD_BUTTON_RIGHT); + + GuiTrigger trigUp; + trigUp.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_UP | WPAD_CLASSIC_BUTTON_UP, PAD_BUTTON_UP); + + GuiTrigger trigDown; + trigDown.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_DOWN, PAD_BUTTON_DOWN); + + GuiImageData arrowLeft(button_arrow_left_png); + GuiImage arrowLeftImg(&arrowLeft); + GuiImageData arrowLeftOver(button_arrow_left_over_png); + GuiImage arrowLeftOverImg(&arrowLeftOver); + GuiButton arrowLeftBtn(arrowLeft.GetWidth(), arrowLeft.GetHeight()); + arrowLeftBtn.SetImage(&arrowLeftImg); + arrowLeftBtn.SetImageOver(&arrowLeftOverImg); + arrowLeftBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + arrowLeftBtn.SetPosition(50, 0); + arrowLeftBtn.SetTrigger(trigA); + arrowLeftBtn.SetTrigger(trig2); + arrowLeftBtn.SetTrigger(&trigLeft); + arrowLeftBtn.SetSelectable(false); + arrowLeftBtn.SetUpdateCallback(ScreenZoomWindowLeftClick); + + GuiImageData arrowRight(button_arrow_right_png); + GuiImage arrowRightImg(&arrowRight); + GuiImageData arrowRightOver(button_arrow_right_over_png); + GuiImage arrowRightOverImg(&arrowRightOver); + GuiButton arrowRightBtn(arrowRight.GetWidth(), arrowRight.GetHeight()); + arrowRightBtn.SetImage(&arrowRightImg); + arrowRightBtn.SetImageOver(&arrowRightOverImg); + arrowRightBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + arrowRightBtn.SetPosition(164, 0); + arrowRightBtn.SetTrigger(trigA); + arrowRightBtn.SetTrigger(trig2); + arrowRightBtn.SetTrigger(&trigRight); + arrowRightBtn.SetSelectable(false); + arrowRightBtn.SetUpdateCallback(ScreenZoomWindowRightClick); + + GuiImageData arrowUp(button_arrow_up_png); + GuiImage arrowUpImg(&arrowUp); + GuiImageData arrowUpOver(button_arrow_up_over_png); + GuiImage arrowUpOverImg(&arrowUpOver); + GuiButton arrowUpBtn(arrowUp.GetWidth(), arrowUp.GetHeight()); + arrowUpBtn.SetImage(&arrowUpImg); + arrowUpBtn.SetImageOver(&arrowUpOverImg); + arrowUpBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + arrowUpBtn.SetPosition(-76, -27); + arrowUpBtn.SetTrigger(trigA); + arrowUpBtn.SetTrigger(trig2); + arrowUpBtn.SetTrigger(&trigUp); + arrowUpBtn.SetSelectable(false); + arrowUpBtn.SetUpdateCallback(ScreenZoomWindowUpClick); + + GuiImageData arrowDown(button_arrow_down_png); + GuiImage arrowDownImg(&arrowDown); + GuiImageData arrowDownOver(button_arrow_down_over_png); + GuiImage arrowDownOverImg(&arrowDownOver); + GuiButton arrowDownBtn(arrowDown.GetWidth(), arrowDown.GetHeight()); + arrowDownBtn.SetImage(&arrowDownImg); + arrowDownBtn.SetImageOver(&arrowDownOverImg); + arrowDownBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + arrowDownBtn.SetPosition(-76, 27); + arrowDownBtn.SetTrigger(trigA); + arrowDownBtn.SetTrigger(trig2); + arrowDownBtn.SetTrigger(&trigDown); + arrowDownBtn.SetSelectable(false); + arrowDownBtn.SetUpdateCallback(ScreenZoomWindowDownClick); + + GuiImageData screenPosition(screen_position_png); + GuiImage screenPositionImg(&screenPosition); + screenPositionImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + screenPositionImg.SetPosition(0, 0); + + settingText = new GuiText(NULL, 20, (GXColor){0, 0, 0, 255}); + settingText2 = new GuiText(NULL, 20, (GXColor){0, 0, 0, 255}); + char zoom[10]; + sprintf(zoom, "%.2f%%", GCSettings.zoomHor*100); + settingText->SetText(zoom); + settingText->SetPosition(108, 0); + sprintf(zoom, "%.2f%%", GCSettings.zoomVert*100); + settingText2->SetText(zoom); + settingText2->SetPosition(-76, 0); + + float currentZoomHor = GCSettings.zoomHor; + float currentZoomVert = GCSettings.zoomVert; + + w->Append(&arrowLeftBtn); + w->Append(&arrowRightBtn); + w->Append(&arrowUpBtn); + w->Append(&arrowDownBtn); + w->Append(&screenPositionImg); + w->Append(settingText); + w->Append(settingText2); + + if(!SettingWindow("Screen Zoom",w)) + { + // undo changes + GCSettings.zoomHor = currentZoomHor; + GCSettings.zoomVert = currentZoomVert; + } + + delete(w); + delete(settingText); + delete(settingText2); +} + +static void ScreenPositionWindowUpdate(void * ptr, int x, int y) +{ + GuiButton * b = (GuiButton *)ptr; + if(b->GetState() == STATE_CLICKED) + { + GCSettings.xshift += x; + GCSettings.yshift += y; + + char shift[10]; + sprintf(shift, "%i, %i", GCSettings.xshift, GCSettings.yshift); + settingText->SetText(shift); + b->ResetState(); + } +} + +static void ScreenPositionWindowLeftClick(void * ptr) { ScreenPositionWindowUpdate(ptr, -1, 0); } +static void ScreenPositionWindowRightClick(void * ptr) { ScreenPositionWindowUpdate(ptr, +1, 0); } +static void ScreenPositionWindowUpClick(void * ptr) { ScreenPositionWindowUpdate(ptr, 0, -1); } +static void ScreenPositionWindowDownClick(void * ptr) { ScreenPositionWindowUpdate(ptr, 0, +1); } + +static void ScreenPositionWindow() +{ + GuiWindow * w = new GuiWindow(150,150); + w->SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + w->SetPosition(0, -10); + + GuiTrigger trigLeft; + trigLeft.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT, PAD_BUTTON_LEFT); + + GuiTrigger trigRight; + trigRight.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT, PAD_BUTTON_RIGHT); + + GuiTrigger trigUp; + trigUp.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_UP | WPAD_CLASSIC_BUTTON_UP, PAD_BUTTON_UP); + + GuiTrigger trigDown; + trigDown.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_DOWN, PAD_BUTTON_DOWN); + + GuiImageData arrowLeft(button_arrow_left_png); + GuiImage arrowLeftImg(&arrowLeft); + GuiImageData arrowLeftOver(button_arrow_left_over_png); + GuiImage arrowLeftOverImg(&arrowLeftOver); + GuiButton arrowLeftBtn(arrowLeft.GetWidth(), arrowLeft.GetHeight()); + arrowLeftBtn.SetImage(&arrowLeftImg); + arrowLeftBtn.SetImageOver(&arrowLeftOverImg); + arrowLeftBtn.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + arrowLeftBtn.SetTrigger(trigA); + arrowLeftBtn.SetTrigger(trig2); + arrowLeftBtn.SetTrigger(&trigLeft); + arrowLeftBtn.SetSelectable(false); + arrowLeftBtn.SetUpdateCallback(ScreenPositionWindowLeftClick); + + GuiImageData arrowRight(button_arrow_right_png); + GuiImage arrowRightImg(&arrowRight); + GuiImageData arrowRightOver(button_arrow_right_over_png); + GuiImage arrowRightOverImg(&arrowRightOver); + GuiButton arrowRightBtn(arrowRight.GetWidth(), arrowRight.GetHeight()); + arrowRightBtn.SetImage(&arrowRightImg); + arrowRightBtn.SetImageOver(&arrowRightOverImg); + arrowRightBtn.SetAlignment(ALIGN_RIGHT, ALIGN_MIDDLE); + arrowRightBtn.SetTrigger(trigA); + arrowRightBtn.SetTrigger(trig2); + arrowRightBtn.SetTrigger(&trigRight); + arrowRightBtn.SetSelectable(false); + arrowRightBtn.SetUpdateCallback(ScreenPositionWindowRightClick); + + GuiImageData arrowUp(button_arrow_up_png); + GuiImage arrowUpImg(&arrowUp); + GuiImageData arrowUpOver(button_arrow_up_over_png); + GuiImage arrowUpOverImg(&arrowUpOver); + GuiButton arrowUpBtn(arrowUp.GetWidth(), arrowUp.GetHeight()); + arrowUpBtn.SetImage(&arrowUpImg); + arrowUpBtn.SetImageOver(&arrowUpOverImg); + arrowUpBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + arrowUpBtn.SetTrigger(trigA); + arrowUpBtn.SetTrigger(trig2); + arrowUpBtn.SetTrigger(&trigUp); + arrowUpBtn.SetSelectable(false); + arrowUpBtn.SetUpdateCallback(ScreenPositionWindowUpClick); + + GuiImageData arrowDown(button_arrow_down_png); + GuiImage arrowDownImg(&arrowDown); + GuiImageData arrowDownOver(button_arrow_down_over_png); + GuiImage arrowDownOverImg(&arrowDownOver); + GuiButton arrowDownBtn(arrowDown.GetWidth(), arrowDown.GetHeight()); + arrowDownBtn.SetImage(&arrowDownImg); + arrowDownBtn.SetImageOver(&arrowDownOverImg); + arrowDownBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + arrowDownBtn.SetTrigger(trigA); + arrowDownBtn.SetTrigger(trig2); + arrowDownBtn.SetTrigger(&trigDown); + arrowDownBtn.SetSelectable(false); + arrowDownBtn.SetUpdateCallback(ScreenPositionWindowDownClick); + + GuiImageData screenPosition(screen_position_png); + GuiImage screenPositionImg(&screenPosition); + screenPositionImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + + settingText = new GuiText(NULL, 20, (GXColor){0, 0, 0, 255}); + char shift[10]; + sprintf(shift, "%i, %i", GCSettings.xshift, GCSettings.yshift); + settingText->SetText(shift); + + int currentX = GCSettings.xshift; + int currentY = GCSettings.yshift; + + w->Append(&arrowLeftBtn); + w->Append(&arrowRightBtn); + w->Append(&arrowUpBtn); + w->Append(&arrowDownBtn); + w->Append(&screenPositionImg); + w->Append(settingText); + + if(!SettingWindow("Screen Position",w)) + { + // undo changes + GCSettings.xshift = currentX; + GCSettings.yshift = currentY; + } + + delete(w); + delete(settingText); +} + +static int MenuSettingsVideo() +{ + int menu = MENU_NONE; + int ret; + int i = 0; + bool firstRun = true; + OptionList options; + + sprintf(options.name[i++], "Rendering"); + sprintf(options.name[i++], "Scaling"); + sprintf(options.name[i++], "Filtering"); + sprintf(options.name[i++], "Screen Zoom"); + sprintf(options.name[i++], "Screen Position"); + sprintf(options.name[i++], "Crosshair"); + sprintf(options.name[i++], "Video Mode"); + options.length = i; + +#ifdef HW_DOL + options.name[2][0] = 0; // disable hq2x on GameCube +#endif + + for(i=0; i < options.length; i++) + options.value[i][0] = 0; + + GuiText titleTxt("Game Settings - Video", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(50, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetCol2Position(200); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + ret = optionBrowser.GetClickedOption(); + + switch (ret) + { + case 0: + GCSettings.render++; + if (GCSettings.render > 2) + GCSettings.render = 0; + break; + + case 1: + GCSettings.widescreen ^= 1; + break; + + case 2: + GCSettings.FilterMethod++; + if (GCSettings.FilterMethod >= NUM_FILTERS) + GCSettings.FilterMethod = 0; + break; + + case 3: + ScreenZoomWindow(); + break; + + case 4: + ScreenPositionWindow(); + break; + + case 5: + GCSettings.crosshair ^= 1; + break; + + case 6: + GCSettings.videomode++; + if(GCSettings.videomode > 4) + GCSettings.videomode = 0; + break; + } + + if(ret >= 0 || firstRun) + { + firstRun = false; + + // don't allow original render mode if progressive video mode detected + if (GCSettings.render==0 && progressive) + GCSettings.render++; + + if (GCSettings.render == 0) + sprintf (options.value[0], "Original"); + else if (GCSettings.render == 1) + sprintf (options.value[0], "Filtered"); + else if (GCSettings.render == 2) + sprintf (options.value[0], "Unfiltered"); + + if(GCSettings.widescreen) + sprintf (options.value[1], "16:9 Correction"); + else + sprintf (options.value[1], "Default"); +#ifdef HW_RVL + sprintf (options.value[2], "%s", GetFilterName((RenderFilter)GCSettings.FilterMethod)); +#endif + sprintf (options.value[3], "%.2f%%, %.2f%%", GCSettings.zoomHor*100, GCSettings.zoomVert*100); + sprintf (options.value[4], "%d, %d", GCSettings.xshift, GCSettings.yshift); + sprintf (options.value[5], "%s", GCSettings.crosshair == 1 ? "On" : "Off"); + + switch(GCSettings.videomode) + { + case 0: + sprintf (options.value[6], "Automatic (Recommended)"); break; + case 1: + sprintf (options.value[6], "NTSC (480i)"); break; + case 2: + sprintf (options.value[6], "Progressive (480p)"); break; + case 3: + sprintf (options.value[6], "PAL (50Hz)"); break; + case 4: + sprintf (options.value[6], "PAL (60Hz)"); break; + } + optionBrowser.TriggerUpdate(); + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS; + } + } + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + return menu; +} + +/**************************************************************************** + * MenuSettings + ***************************************************************************/ +static int MenuSettings() +{ + int menu = MENU_NONE; + + GuiText titleTxt("Settings", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_long_png); + GuiImageData btnOutlineOver(button_long_over_png); + GuiImageData btnLargeOutline(button_large_png); + GuiImageData btnLargeOutlineOver(button_large_over_png); + GuiImageData iconFile(icon_settings_file_png); + GuiImageData iconMenu(icon_settings_menu_png); + GuiImageData iconNetwork(icon_settings_network_png); + + GuiText savingBtnTxt1("Saving", 22, (GXColor){0, 0, 0, 255}); + GuiText savingBtnTxt2("&", 18, (GXColor){0, 0, 0, 255}); + GuiText savingBtnTxt3("Loading", 22, (GXColor){0, 0, 0, 255}); + savingBtnTxt1.SetPosition(0, -20); + savingBtnTxt3.SetPosition(0, +20); + GuiImage savingBtnImg(&btnLargeOutline); + GuiImage savingBtnImgOver(&btnLargeOutlineOver); + GuiImage fileBtnIcon(&iconFile); + GuiButton savingBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + savingBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + savingBtn.SetPosition(-125, 120); + savingBtn.SetLabel(&savingBtnTxt1, 0); + savingBtn.SetLabel(&savingBtnTxt2, 1); + savingBtn.SetLabel(&savingBtnTxt3, 2); + savingBtn.SetImage(&savingBtnImg); + savingBtn.SetImageOver(&savingBtnImgOver); + savingBtn.SetIcon(&fileBtnIcon); + savingBtn.SetSoundOver(&btnSoundOver); + savingBtn.SetSoundClick(&btnSoundClick); + savingBtn.SetTrigger(trigA); + savingBtn.SetTrigger(trig2); + savingBtn.SetEffectGrow(); + + GuiText menuBtnTxt("Menu", 22, (GXColor){0, 0, 0, 255}); + menuBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-20); + GuiImage menuBtnImg(&btnLargeOutline); + GuiImage menuBtnImgOver(&btnLargeOutlineOver); + GuiImage menuBtnIcon(&iconMenu); + GuiButton menuBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + menuBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + menuBtn.SetPosition(125, 120); + menuBtn.SetLabel(&menuBtnTxt); + menuBtn.SetImage(&menuBtnImg); + menuBtn.SetImageOver(&menuBtnImgOver); + menuBtn.SetIcon(&menuBtnIcon); + menuBtn.SetSoundOver(&btnSoundOver); + menuBtn.SetSoundClick(&btnSoundClick); + menuBtn.SetTrigger(trigA); + menuBtn.SetTrigger(trig2); + menuBtn.SetEffectGrow(); + + GuiText networkBtnTxt("Network", 22, (GXColor){0, 0, 0, 255}); + networkBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-20); + GuiImage networkBtnImg(&btnLargeOutline); + GuiImage networkBtnImgOver(&btnLargeOutlineOver); + GuiImage networkBtnIcon(&iconNetwork); + GuiButton networkBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + networkBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + networkBtn.SetPosition(0, 250); + networkBtn.SetLabel(&networkBtnTxt); + networkBtn.SetImage(&networkBtnImg); + networkBtn.SetImageOver(&networkBtnImgOver); + networkBtn.SetIcon(&networkBtnIcon); + networkBtn.SetSoundOver(&btnSoundOver); + networkBtn.SetSoundClick(&btnSoundClick); + networkBtn.SetTrigger(trigA); + networkBtn.SetTrigger(trig2); + networkBtn.SetEffectGrow(); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(90, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + GuiText resetBtnTxt("Reset Settings", 22, (GXColor){0, 0, 0, 255}); + GuiImage resetBtnImg(&btnOutline); + GuiImage resetBtnImgOver(&btnOutlineOver); + GuiButton resetBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + resetBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + resetBtn.SetPosition(-90, -35); + resetBtn.SetLabel(&resetBtnTxt); + resetBtn.SetImage(&resetBtnImg); + resetBtn.SetImageOver(&resetBtnImgOver); + resetBtn.SetSoundOver(&btnSoundOver); + resetBtn.SetSoundClick(&btnSoundClick); + resetBtn.SetTrigger(trigA); + resetBtn.SetTrigger(trig2); + resetBtn.SetEffectGrow(); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&titleTxt); + w.Append(&savingBtn); + w.Append(&menuBtn); + w.Append(&networkBtn); + w.Append(&backBtn); + w.Append(&resetBtn); + + mainWindow->Append(&w); + + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + if(savingBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_FILE; + } + else if(menuBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_MENU; + } + else if(networkBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_NETWORK; + } + else if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESELECTION; + } + else if(resetBtn.GetState() == STATE_CLICKED) + { + resetBtn.ResetState(); + + int choice = WindowPrompt( + "Reset Settings", + "Are you sure that you want to reset your settings?", + "Yes", + "No"); + + if(choice == 1) + DefaultSettings(); + } + } + + HaltGui(); + mainWindow->Remove(&w); + return menu; +} + +/**************************************************************************** + * MenuSettingsFile + ***************************************************************************/ + +static int MenuSettingsFile() +{ + int menu = MENU_NONE; + int ret; + int i = 0; + bool firstRun = true; + OptionList options; + sprintf(options.name[i++], "Load Device"); + sprintf(options.name[i++], "Save Device"); + sprintf(options.name[i++], "Load Folder"); + sprintf(options.name[i++], "Save Folder"); + sprintf(options.name[i++], "Cheats Folder"); + sprintf(options.name[i++], "Screenshots Folder"); + sprintf(options.name[i++], "Auto Load"); + sprintf(options.name[i++], "Auto Save"); + options.length = i; + + for(i=0; i < options.length; i++) + options.value[i][0] = 0; + + GuiText titleTxt("Settings - Saving & Loading", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_long_png); + GuiImageData btnOutlineOver(button_long_over_png); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(90, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + optionBrowser.SetCol2Position(215); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + ret = optionBrowser.GetClickedOption(); + + switch (ret) + { + case 0: + GCSettings.LoadMethod++; + break; + + case 1: + GCSettings.SaveMethod++; + break; + + case 2: + OnScreenKeyboard(GCSettings.LoadFolder, MAXPATHLEN); + break; + + case 3: + OnScreenKeyboard(GCSettings.SaveFolder, MAXPATHLEN); + break; + + case 4: + OnScreenKeyboard(GCSettings.CheatFolder, MAXPATHLEN); + break; + + case 5: + OnScreenKeyboard(GCSettings.ScreenshotsFolder, MAXPATHLEN); + break; + + case 6: + GCSettings.AutoLoad++; + if (GCSettings.AutoLoad > 2) + GCSettings.AutoLoad = 0; + break; + + case 7: + GCSettings.AutoSave++; + if (GCSettings.AutoSave > 3) + GCSettings.AutoSave = 0; + break; + } + + if(ret >= 0 || firstRun) + { + firstRun = false; + + // some load/save methods are not implemented - here's where we skip them + // they need to be skipped in the order they were enumerated + + // no SD/USB ports on GameCube + #ifdef HW_DOL + if(GCSettings.LoadMethod == DEVICE_SD) + GCSettings.LoadMethod++; + if(GCSettings.SaveMethod == DEVICE_SD) + GCSettings.SaveMethod++; + if(GCSettings.LoadMethod == DEVICE_USB) + GCSettings.LoadMethod++; + if(GCSettings.SaveMethod == DEVICE_USB) + GCSettings.SaveMethod++; + #endif + + // saving to DVD is impossible + if(GCSettings.SaveMethod == DEVICE_DVD) + GCSettings.SaveMethod++; + + // don't allow SD Gecko on Wii + #ifdef HW_RVL + if(GCSettings.LoadMethod == DEVICE_SD_SLOTA) + GCSettings.LoadMethod++; + if(GCSettings.SaveMethod == DEVICE_SD_SLOTA) + GCSettings.SaveMethod++; + if(GCSettings.LoadMethod == DEVICE_SD_SLOTB) + GCSettings.LoadMethod++; + if(GCSettings.SaveMethod == DEVICE_SD_SLOTB) + GCSettings.SaveMethod++; + #endif + + // correct load/save methods out of bounds + if(GCSettings.LoadMethod > 6) + GCSettings.LoadMethod = 0; + if(GCSettings.SaveMethod > 6) + GCSettings.SaveMethod = 0; + + if (GCSettings.LoadMethod == DEVICE_AUTO) sprintf (options.value[0],"Auto Detect"); + else if (GCSettings.LoadMethod == DEVICE_SD) sprintf (options.value[0],"SD"); + else if (GCSettings.LoadMethod == DEVICE_USB) sprintf (options.value[0],"USB"); + else if (GCSettings.LoadMethod == DEVICE_DVD) sprintf (options.value[0],"DVD"); + else if (GCSettings.LoadMethod == DEVICE_SMB) sprintf (options.value[0],"Network"); + else if (GCSettings.LoadMethod == DEVICE_SD_SLOTA) sprintf (options.value[0],"SD Gecko Slot A"); + else if (GCSettings.LoadMethod == DEVICE_SD_SLOTB) sprintf (options.value[0],"SD Gecko Slot B"); + + if (GCSettings.SaveMethod == DEVICE_AUTO) sprintf (options.value[1],"Auto Detect"); + else if (GCSettings.SaveMethod == DEVICE_SD) sprintf (options.value[1],"SD"); + else if (GCSettings.SaveMethod == DEVICE_USB) sprintf (options.value[1],"USB"); + else if (GCSettings.SaveMethod == DEVICE_SMB) sprintf (options.value[1],"Network"); + else if (GCSettings.SaveMethod == DEVICE_SD_SLOTA) sprintf (options.value[1],"SD Gecko Slot A"); + else if (GCSettings.SaveMethod == DEVICE_SD_SLOTB) sprintf (options.value[1],"SD Gecko Slot B"); + + snprintf (options.value[2], 35, "%s", GCSettings.LoadFolder); + snprintf (options.value[3], 35, "%s", GCSettings.SaveFolder); + snprintf (options.value[4], 35, "%s", GCSettings.CheatFolder); + snprintf (options.value[5], 35, "%s", GCSettings.ScreenshotsFolder); + + if (GCSettings.AutoLoad == 0) sprintf (options.value[6],"Off"); + else if (GCSettings.AutoLoad == 1) sprintf (options.value[6],"SRAM"); + else if (GCSettings.AutoLoad == 2) sprintf (options.value[6],"Snapshot"); + + if (GCSettings.AutoSave == 0) sprintf (options.value[7],"Off"); + else if (GCSettings.AutoSave == 1) sprintf (options.value[7],"SRAM"); + else if (GCSettings.AutoSave == 2) sprintf (options.value[7],"Snapshot"); + else if (GCSettings.AutoSave == 3) sprintf (options.value[7],"Both"); + + optionBrowser.TriggerUpdate(); + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS; + } + } + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + return menu; +} + +/**************************************************************************** + * MenuSettingsMenu + ***************************************************************************/ + +static int MenuSettingsMenu() +{ + int menu = MENU_NONE; + int ret; + int i = 0; + bool firstRun = true; + OptionList options; + + sprintf(options.name[i++], "Exit Action"); + sprintf(options.name[i++], "Wiimote Orientation"); + sprintf(options.name[i++], "Music Volume"); + sprintf(options.name[i++], "Sound Effects Volume"); + sprintf(options.name[i++], "Rumble"); + sprintf(options.name[i++], "Language"); + options.length = i; + + for(i=0; i < options.length; i++) + options.value[i][0] = 0; + + GuiText titleTxt("Settings - Menu", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_long_png); + GuiImageData btnOutlineOver(button_long_over_png); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(90, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + optionBrowser.SetCol2Position(275); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + ret = optionBrowser.GetClickedOption(); + + switch (ret) + { + case 0: + GCSettings.ExitAction++; + if(GCSettings.ExitAction > 3) + GCSettings.ExitAction = 0; + break; + case 1: + GCSettings.WiimoteOrientation ^= 1; + break; + case 2: + GCSettings.MusicVolume += 10; + if(GCSettings.MusicVolume > 100) + GCSettings.MusicVolume = 0; + bgMusic->SetVolume(GCSettings.MusicVolume); + break; + case 3: + GCSettings.SFXVolume += 10; + if(GCSettings.SFXVolume > 100) + GCSettings.SFXVolume = 0; + break; + case 4: + GCSettings.Rumble ^= 1; + break; + case 5: + GCSettings.language++; + + if(GCSettings.language >= LANG_LENGTH) + GCSettings.language = LANG_JAPANESE; + + if(GCSettings.language == LANG_SIMP_CHINESE) + GCSettings.language = LANG_PORTUGUESE; + else if(GCSettings.language == LANG_JAPANESE) + GCSettings.language = LANG_ENGLISH; + + break; + } + + if(ret >= 0 || firstRun) + { + firstRun = false; + + #ifdef HW_RVL + if (GCSettings.ExitAction == 1) + sprintf (options.value[0], "Return to Wii Menu"); + else if (GCSettings.ExitAction == 2) + sprintf (options.value[0], "Power off Wii"); + else if (GCSettings.ExitAction == 3) + sprintf (options.value[0], "Return to Loader"); + else + sprintf (options.value[0], "Auto"); + #else // GameCube + if(GCSettings.ExitAction > 1) + GCSettings.ExitAction = 0; + if (GCSettings.ExitAction == 0) + sprintf (options.value[0], "Return to Loader"); + else + sprintf (options.value[0], "Reboot"); + + options.name[1][0] = 0; // Wiimote + options.name[2][0] = 0; // Music + options.name[3][0] = 0; // Sound Effects + options.name[4][0] = 0; // Rumble + #endif + + if (GCSettings.WiimoteOrientation == 0) + sprintf (options.value[1], "Vertical"); + else if (GCSettings.WiimoteOrientation == 1) + sprintf (options.value[1], "Horizontal"); + + if(GCSettings.MusicVolume > 0) + sprintf(options.value[2], "%d%%", GCSettings.MusicVolume); + else + sprintf(options.value[2], "Mute"); + + if(GCSettings.SFXVolume > 0) + sprintf(options.value[3], "%d%%", GCSettings.SFXVolume); + else + sprintf(options.value[3], "Mute"); + + if (GCSettings.Rumble == 1) + sprintf (options.value[4], "Enabled"); + else + sprintf (options.value[4], "Disabled"); + + switch(GCSettings.language) + { + case LANG_JAPANESE: sprintf(options.value[5], "Japanese"); break; + case LANG_ENGLISH: sprintf(options.value[5], "English"); break; + case LANG_GERMAN: sprintf(options.value[5], "German"); break; + case LANG_FRENCH: sprintf(options.value[5], "French"); break; + case LANG_SPANISH: sprintf(options.value[5], "Spanish"); break; + case LANG_ITALIAN: sprintf(options.value[5], "Italian"); break; + case LANG_DUTCH: sprintf(options.value[5], "Dutch"); break; + case LANG_SIMP_CHINESE: sprintf(options.value[5], "Chinese (Simplified)"); break; + case LANG_TRAD_CHINESE: sprintf(options.value[5], "Chinese (Traditional)"); break; + case LANG_KOREAN: sprintf(options.value[5], "Korean"); break; + case LANG_PORTUGUESE: sprintf(options.value[5], "Portuguese"); break; + case LANG_BRAZILIAN_PORTUGUESE: sprintf(options.value[5], "Brazilian Portuguese"); break; + case LANG_CATALAN: sprintf(options.value[5], "Catalan"); break; + case LANG_TURKISH: sprintf(options.value[5], "Turkish"); break; + } + + optionBrowser.TriggerUpdate(); + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS; + } + } + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + ResetText(); + return menu; +} + +/**************************************************************************** + * MenuSettingsNetwork + ***************************************************************************/ + +static int MenuSettingsNetwork() +{ + int menu = MENU_NONE; + int ret; + int i = 0; + bool firstRun = true; + OptionList options; + sprintf(options.name[i++], "SMB Share IP"); + sprintf(options.name[i++], "SMB Share Name"); + sprintf(options.name[i++], "SMB Share Username"); + sprintf(options.name[i++], "SMB Share Password"); + options.length = i; + + for(i=0; i < options.length; i++) + options.value[i][0] = 0; + + GuiText titleTxt("Settings - Network", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_long_png); + GuiImageData btnOutlineOver(button_long_over_png); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(90, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + optionBrowser.SetCol2Position(290); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + ret = optionBrowser.GetClickedOption(); + + switch (ret) + { + case 0: + OnScreenKeyboard(GCSettings.smbip, 80); + break; + + case 1: + OnScreenKeyboard(GCSettings.smbshare, 20); + break; + + case 2: + OnScreenKeyboard(GCSettings.smbuser, 20); + break; + + case 3: + OnScreenKeyboard(GCSettings.smbpwd, 20); + break; + } + + if(ret >= 0 || firstRun) + { + firstRun = false; + snprintf (options.value[0], 25, "%s", GCSettings.smbip); + snprintf (options.value[1], 19, "%s", GCSettings.smbshare); + snprintf (options.value[2], 19, "%s", GCSettings.smbuser); + snprintf (options.value[3], 19, "%s", GCSettings.smbpwd); + optionBrowser.TriggerUpdate(); + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS; + } + } + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + CloseShare(); + return menu; +} + +/**************************************************************************** + * MainMenu + ***************************************************************************/ + +void +MainMenu (int menu) +{ + static bool init = false; + int currentMenu = menu; + lastMenu = MENU_NONE; + + if(!init) + { + init = true; + #ifdef HW_RVL + pointer[0] = new GuiImageData(player1_point_png); + pointer[1] = new GuiImageData(player2_point_png); + pointer[2] = new GuiImageData(player3_point_png); + pointer[3] = new GuiImageData(player4_point_png); + #endif + + trigA = new GuiTrigger; + trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + trig2 = new GuiTrigger; + trig2->SetSimpleTrigger(-1, WPAD_BUTTON_2, 0); + } + + mainWindow = new GuiWindow(screenwidth, screenheight); + + if(menu == MENU_GAME) + { + gameScreen = new GuiImageData(gameScreenPng); + gameScreenImg = new GuiImage(gameScreen); + gameScreenImg->SetAlpha(192); + gameScreenImg->ColorStripe(30); + gameScreenImg->SetScaleX(screenwidth/(float)vmode->fbWidth); + gameScreenImg->SetScaleY(screenheight/(float)vmode->efbHeight); + } + else + { + gameScreenImg = new GuiImage(screenwidth, screenheight, (GXColor){175, 200, 215, 255}); + gameScreenImg->ColorStripe(10); + } + + mainWindow->Append(gameScreenImg); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData bgTop(bg_top_png); + bgTopImg = new GuiImage(&bgTop); + GuiImageData bgBottom(bg_bottom_png); + bgBottomImg = new GuiImage(&bgBottom); + bgBottomImg->SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + GuiImageData logo(logo_png); + GuiImage logoImg(&logo); + GuiImageData logoOver(logo_over_png); + GuiImage logoImgOver(&logoOver); + GuiText logoTxt(APPVERSION, 18, (GXColor){255, 255, 255, 255}); + logoTxt.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + logoTxt.SetPosition(0, 4); + btnLogo = new GuiButton(logoImg.GetWidth(), logoImg.GetHeight()); + btnLogo->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + btnLogo->SetPosition(-50, 24); + btnLogo->SetImage(&logoImg); + btnLogo->SetImageOver(&logoImgOver); + btnLogo->SetLabel(&logoTxt); + btnLogo->SetSoundOver(&btnSoundOver); + btnLogo->SetSoundClick(&btnSoundClick); + btnLogo->SetTrigger(trigA); + btnLogo->SetTrigger(trig2); + btnLogo->SetUpdateCallback(WindowCredits); + + mainWindow->Append(bgTopImg); + mainWindow->Append(bgBottomImg); + mainWindow->Append(btnLogo); + + if(currentMenu == MENU_GAMESELECTION) + ResumeGui(); + + // Load preferences + if(!LoadPrefs()) + SavePrefs(SILENT); + +#ifdef HW_RVL + static bool checkIOS = true; + + if(checkIOS) + { + u32 ios = IOS_GetVersion(); + + if(!SupportedIOS(ios)) + ErrorPrompt("The current IOS is unsupported. Functionality and/or stability may be adversely affected."); + else if(!SaneIOS(ios)) + ErrorPrompt("The current IOS has been altered (fake-signed). Functionality and/or stability may be adversely affected."); + } + + checkIOS = false; +#endif + + #ifndef NO_SOUND + bgMusic = new GuiSound(bg_music_ogg, bg_music_ogg_size, SOUND_OGG); + bgMusic->SetVolume(GCSettings.MusicVolume); + bgMusic->SetLoop(true); + enterSound = new GuiSound(enter_ogg, enter_ogg_size, SOUND_OGG); + enterSound->SetVolume(GCSettings.SFXVolume); + exitSound = new GuiSound(exit_ogg, exit_ogg_size, SOUND_OGG); + exitSound->SetVolume(GCSettings.SFXVolume); + if(currentMenu == MENU_GAMESELECTION) bgMusic->Play(); // startup music + #endif + + while(currentMenu != MENU_EXIT || SNESROMSize <= 0) + { + switch (currentMenu) + { + case MENU_GAMESELECTION: + currentMenu = MenuGameSelection(); + break; + case MENU_GAME: + currentMenu = MenuGame(); + break; + case MENU_GAME_LOAD: + currentMenu = MenuGameSaves(0); + break; + case MENU_GAME_SAVE: + currentMenu = MenuGameSaves(1); + break; + case MENU_GAMESETTINGS: + currentMenu = MenuGameSettings(); + break; + case MENU_GAMESETTINGS_MAPPINGS: + currentMenu = MenuSettingsMappings(); + break; + case MENU_GAMESETTINGS_MAPPINGS_CTRL: + currentMenu = MenuSettingsMappingsController(); + break; + case MENU_GAMESETTINGS_MAPPINGS_MAP: + currentMenu = MenuSettingsMappingsMap(); + break; + case MENU_GAMESETTINGS_VIDEO: + currentMenu = MenuSettingsVideo(); + break; + case MENU_GAMESETTINGS_CHEATS: + currentMenu = MenuGameCheats(); + break; + case MENU_SETTINGS: + currentMenu = MenuSettings(); + break; + case MENU_SETTINGS_FILE: + currentMenu = MenuSettingsFile(); + break; + case MENU_SETTINGS_MENU: + currentMenu = MenuSettingsMenu(); + break; + case MENU_SETTINGS_NETWORK: + currentMenu = MenuSettingsNetwork(); + break; + default: // unrecognized menu + currentMenu = MenuGameSelection(); + break; + } + lastMenu = currentMenu; + usleep(THREAD_SLEEP); + } + + #ifdef HW_RVL + ShutoffRumble(); + #endif + + CancelAction(); + HaltGui(); + + #ifdef HW_RVL + if(updatethread != LWP_THREAD_NULL) + LWP_JoinThread(updatethread, NULL); + #endif + + #ifndef NO_SOUND + delete bgMusic; + delete enterSound; + delete exitSound; + #endif + + delete btnLogo; + delete gameScreenImg; + delete bgTopImg; + delete bgBottomImg; + delete mainWindow; + + mainWindow = NULL; + + if(gameScreen) + delete gameScreen; + + if(gameScreenPng) + { + free(gameScreenPng); + gameScreenPng = NULL; + } + + // wait for keys to be depressed + while(MenuRequested()) + { + UpdatePads(); + usleep(THREAD_SLEEP); + } +} diff --git a/plugins/snes9x_gx/source/menu.h b/plugins/snes9x_gx/source/menu.h new file mode 100644 index 00000000..fc3cd73e --- /dev/null +++ b/plugins/snes9x_gx/source/menu.h @@ -0,0 +1,46 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * Tantric 2008-2010 + * + * menu.h + * + * Menu flow routines - handles all menu logic + ***************************************************************************/ + +#ifndef _MENU_H_ +#define _MENU_H_ + +#include <ogcsys.h> + +void InitGUIThreads(); +void MainMenu (int menuitem); +void ErrorPrompt(const char * msg); +int ErrorPromptRetry(const char * msg); +void InfoPrompt(const char * msg); +void ShowAction (const char *msg); +void CancelAction(); +void ShowProgress (const char *msg, int done, int total); +void ResetText(); + +enum +{ + MENU_EXIT = -1, + MENU_NONE, + MENU_SETTINGS, + MENU_SETTINGS_FILE, + MENU_SETTINGS_MENU, + MENU_SETTINGS_NETWORK, + MENU_GAMESELECTION, + MENU_GAME, + MENU_GAME_SAVE, + MENU_GAME_LOAD, + MENU_GAMESETTINGS, + MENU_GAMESETTINGS_MAPPINGS, + MENU_GAMESETTINGS_MAPPINGS_CTRL, + MENU_GAMESETTINGS_MAPPINGS_MAP, + MENU_GAMESETTINGS_VIDEO, + MENU_GAMESETTINGS_CHEATS +}; + +#endif diff --git a/plugins/snes9x_gx/source/networkop.cpp b/plugins/snes9x_gx/source/networkop.cpp new file mode 100644 index 00000000..55b8f1e4 --- /dev/null +++ b/plugins/snes9x_gx/source/networkop.cpp @@ -0,0 +1,399 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * Tantric 2008-2010 + * + * networkop.cpp + * + * Network and SMB support routines + ****************************************************************************/ + +#include <network.h> +#include <malloc.h> +#include <ogc/lwp_watchdog.h> +#include <smb.h> +#include <mxml.h> + +#include "snes9xgx.h" +#include "menu.h" +#include "fileop.h" +#include "filebrowser.h" +#include "utils/http.h" +#include "utils/unzip/unzip.h" +#include "utils/unzip/miniunz.h" + +static bool networkInit = false; +static bool networkShareInit = false; +char wiiIP[16] = { 0 }; + +#ifdef HW_RVL +static int netHalt = 0; +static bool updateChecked = true; // true if checked for app update +static char updateURL[128]; // URL of app update +bool updateFound = false; // true if an app update was found + +/**************************************************************************** + * UpdateCheck + * Checks for an update for the application + ***************************************************************************/ + +void UpdateCheck() +{ + // we only check for an update if we have internet + SD/USB + if(updateChecked || !networkInit) + return; + + if(!isMounted[DEVICE_SD] && !isMounted[DEVICE_USB]) + return; + + updateChecked = true; + u8 tmpbuffer[256]; + + if (http_request("http://snes9x-gx.googlecode.com/svn/trunk/update.xml", NULL, tmpbuffer, 256, SILENT) <= 0) + return; + + mxml_node_t *xml; + mxml_node_t *item; + + xml = mxmlLoadString(NULL, (char *)tmpbuffer, MXML_TEXT_CALLBACK); + + if(!xml) + return; + + // check settings version + item = mxmlFindElement(xml, xml, "app", "version", NULL, MXML_DESCEND); + if(item) // a version entry exists + { + const char * version = mxmlElementGetAttr(item, "version"); + + if(version && strlen(version) == 5) + { + int verMajor = version[0] - '0'; + int verMinor = version[2] - '0'; + int verPoint = version[4] - '0'; + int curMajor = APPVERSION[0] - '0'; + int curMinor = APPVERSION[2] - '0'; + int curPoint = APPVERSION[4] - '0'; + + // check that the versioning is valid and is a newer version + if((verMajor >= 0 && verMajor <= 9 && + verMinor >= 0 && verMinor <= 9 && + verPoint >= 0 && verPoint <= 9) && + (verMajor > curMajor || + (verMajor == curMajor && verMinor > curMinor) || + (verMajor == curMajor && verMinor == curMinor && verPoint > curPoint))) + { + item = mxmlFindElement(xml, xml, "file", NULL, NULL, MXML_DESCEND); + if(item) + { + const char * tmp = mxmlElementGetAttr(item, "url"); + if(tmp) + { + snprintf(updateURL, 128, "%s", tmp); + updateFound = false; + } + } + } + } + } + mxmlDelete(xml); +} + +static bool unzipArchive(char * zipfilepath, char * unzipfolderpath) +{ + unzFile uf = unzOpen(zipfilepath); + if (uf==NULL) + return false; + + if(chdir(unzipfolderpath)) // can't access dir + { + makedir(unzipfolderpath); // attempt to make dir + if(chdir(unzipfolderpath)) // still can't access dir + return false; + } + + extractZip(uf,0,1,0); + + unzCloseCurrentFile(uf); + return true; +} + +bool DownloadUpdate() +{ + bool result = false; + + if(updateURL[0] == 0 || appPath[0] == 0 || !ChangeInterface(appPath, NOTSILENT)) + { + ErrorPrompt("Update failed!"); + updateFound = false; // updating is finished (successful or not!) + return false; + } + + // stop checking if devices were removed/inserted + // since we're saving a file + HaltDeviceThread(); + + int device; + FindDevice(appPath, &device); + + char updateFile[50]; + sprintf(updateFile, "%s%s Update.zip", pathPrefix[device], APPNAME); + + FILE * hfile = fopen (updateFile, "wb"); + + if (hfile) + { + if(http_request(updateURL, hfile, NULL, (1024*1024*10), NOTSILENT) > 0) + { + fclose (hfile); + result = unzipArchive(updateFile, (char *)pathPrefix[device]); + } + else + { + fclose (hfile); + } + remove(updateFile); // delete update file + } + + // go back to checking if devices were inserted/removed + ResumeDeviceThread(); + + if(result) + InfoPrompt("Update successful!"); + else + ErrorPrompt("Update failed!"); + + updateFound = false; // updating is finished (successful or not!) + return result; +} + +/**************************************************************************** + * InitializeNetwork + * Initializes the Wii/GameCube network interface + ***************************************************************************/ + +static lwp_t networkthread = LWP_THREAD_NULL; +static u8 netstack[32768] ATTRIBUTE_ALIGN (32); + +static void * netcb (void *arg) +{ + s32 res=-1; + int retry; + int wait; + static bool prevInit = false; + + while(netHalt != 2) + { + retry = 5; + + while (retry>0 && (netHalt != 2)) + { + if(prevInit) + { + int i; + net_deinit(); + for(i=0; i < 400 && (netHalt != 2); i++) // 10 seconds to try to reset + { + res = net_get_status(); + if(res != -EBUSY) // trying to init net so we can't kill the net + { + usleep(2000); + net_wc24cleanup(); //kill the net + prevInit=false; // net_wc24cleanup is called only once + usleep(20000); + break; + } + usleep(20000); + } + } + + usleep(2000); + res = net_init_async(NULL, NULL); + + if(res != 0) + { + sleep(1); + retry--; + continue; + } + + res = net_get_status(); + wait = 400; // only wait 8 sec + while (res == -EBUSY && wait > 0 && (netHalt != 2)) + { + usleep(20000); + res = net_get_status(); + wait--; + } + + if(res==0) break; + retry--; + usleep(2000); + } + if (res == 0) + { + struct in_addr hostip; + hostip.s_addr = net_gethostip(); + if (hostip.s_addr) + { + strcpy(wiiIP, inet_ntoa(hostip)); + networkInit = true; + prevInit = true; + } + } + if(netHalt != 2) LWP_SuspendThread(networkthread); + } + return NULL; +} + +/**************************************************************************** + * StartNetworkThread + * + * Signals the network thread to resume, or creates a new thread + ***************************************************************************/ +void StartNetworkThread() +{ + netHalt = 0; + + if(networkthread == LWP_THREAD_NULL) + LWP_CreateThread(&networkthread, netcb, NULL, netstack, 8192, 40); + else + LWP_ResumeThread(networkthread); +} + +/**************************************************************************** + * StopNetworkThread + * + * Signals the network thread to stop + ***************************************************************************/ +void StopNetworkThread() +{ + if(networkthread == LWP_THREAD_NULL || !LWP_ThreadIsSuspended(networkthread)) + return; + + netHalt = 2; + LWP_ResumeThread(networkthread); + + // wait for thread to finish + LWP_JoinThread(networkthread, NULL); + networkthread = LWP_THREAD_NULL; +} + +#endif + +bool InitializeNetwork(bool silent) +{ +#ifdef HW_RVL + StopNetworkThread(); + + if(networkInit && net_gethostip() > 0) + return true; + + networkInit = false; +#else + if(networkInit) + return true; +#endif + + int retry = 1; + + while(retry) + { + ShowAction("Initializing network..."); + +#ifdef HW_RVL + u64 start = gettime(); + StartNetworkThread(); + + while (!LWP_ThreadIsSuspended(networkthread)) + { + usleep(50 * 1000); + + if(diff_sec(start, gettime()) > 10) // wait for 10 seconds max for net init + break; + } +#else + networkInit = !(if_config(wiiIP, NULL, NULL, true) < 0); +#endif + + CancelAction(); + + if(networkInit || silent) + break; + + retry = ErrorPromptRetry("Unable to initialize network!"); + +#ifdef HW_RVL + if(networkInit && net_gethostip() > 0) +#else + if(networkInit) +#endif + return true; + } + return networkInit; +} + +void CloseShare() +{ + if(networkShareInit) + smbClose("smb"); + networkShareInit = false; + isMounted[DEVICE_SMB] = false; +} + +/**************************************************************************** + * Mount SMB Share + ****************************************************************************/ + +bool +ConnectShare (bool silent) +{ + if(!InitializeNetwork(silent)) + return false; + + if(networkShareInit) + return true; + + int retry = 1; + int chkS = (strlen(GCSettings.smbshare) > 0) ? 0:1; + int chkI = (strlen(GCSettings.smbip) > 0) ? 0:1; + + // check that all parameters have been set + if(chkS + chkI > 0) + { + if(!silent) + { + char msg[50]; + char msg2[100]; + if(chkS + chkI > 1) // more than one thing is wrong + sprintf(msg, "Check settings.xml."); + else if(chkS) + sprintf(msg, "Share name is blank."); + else if(chkI) + sprintf(msg, "Share IP is blank."); + + sprintf(msg2, "Invalid network settings - %s", msg); + ErrorPrompt(msg2); + } + return false; + } + + while(retry) + { + if(!silent) + ShowAction ("Connecting to network share..."); + + if(smbInit(GCSettings.smbuser, GCSettings.smbpwd, GCSettings.smbshare, GCSettings.smbip)) + networkShareInit = true; + + if(networkShareInit || silent) + break; + + retry = ErrorPromptRetry("Failed to connect to network share."); + } + + if(!silent) + CancelAction(); + + return networkShareInit; +} diff --git a/plugins/snes9x_gx/source/networkop.h b/plugins/snes9x_gx/source/networkop.h new file mode 100644 index 00000000..3720c230 --- /dev/null +++ b/plugins/snes9x_gx/source/networkop.h @@ -0,0 +1,23 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * Tantric 2008-2010 + * + * networkop.h + * + * Network and SMB support routines + ****************************************************************************/ + +#ifndef _NETWORKOP_H_ +#define _NETWORKOP_H_ + +void UpdateCheck(); +bool DownloadUpdate(); +void StartNetworkThread(); +bool InitializeNetwork(bool silent); +bool ConnectShare (bool silent); +void CloseShare(); + +extern bool updateFound; + +#endif diff --git a/plugins/snes9x_gx/source/preferences.cpp b/plugins/snes9x_gx/source/preferences.cpp new file mode 100644 index 00000000..93527c59 --- /dev/null +++ b/plugins/snes9x_gx/source/preferences.cpp @@ -0,0 +1,661 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * Tantric 2008-2010 + * + * preferences.cpp + * + * Preferences save/load to XML file + ***************************************************************************/ + +#include <gccore.h> +#include <stdio.h> +#include <string.h> +#include <dirent.h> +#include <ogcsys.h> +#include <mxml.h> + +#include "snes9xgx.h" +#include "menu.h" +#include "fileop.h" +#include "filebrowser.h" +#include "input.h" +#include "button_mapping.h" + +struct SGCSettings GCSettings; + +/**************************************************************************** + * Prepare Preferences Data + * + * This sets up the save buffer for saving. + ***************************************************************************/ +static mxml_node_t *xml = NULL; +static mxml_node_t *data = NULL; +static mxml_node_t *section = NULL; +static mxml_node_t *item = NULL; +static mxml_node_t *elem = NULL; + +static char temp[200]; + +static const char * toStr(int i) +{ + sprintf(temp, "%d", i); + return temp; +} + +static const char * FtoStr(float i) +{ + sprintf(temp, "%.2f", i); + return temp; +} + +static void createXMLSection(const char * name, const char * description) +{ + section = mxmlNewElement(data, "section"); + mxmlElementSetAttr(section, "name", name); + mxmlElementSetAttr(section, "description", description); +} + +static void createXMLSetting(const char * name, const char * description, const char * value) +{ + item = mxmlNewElement(section, "setting"); + mxmlElementSetAttr(item, "name", name); + mxmlElementSetAttr(item, "value", value); + mxmlElementSetAttr(item, "description", description); +} + +static void createXMLController(unsigned int controller[], const char * name, const char * description) +{ + item = mxmlNewElement(section, "controller"); + mxmlElementSetAttr(item, "name", name); + mxmlElementSetAttr(item, "description", description); + + // create buttons + for(int i=0; i < MAXJP; i++) + { + elem = mxmlNewElement(item, "button"); + mxmlElementSetAttr(elem, "number", toStr(i)); + mxmlElementSetAttr(elem, "assignment", toStr(controller[i])); + } +} + +static const char * XMLSaveCallback(mxml_node_t *node, int where) +{ + const char *name; + + name = node->value.element.name; + + if(where == MXML_WS_BEFORE_CLOSE) + { + if(!strcmp(name, "file") || !strcmp(name, "section")) + return ("\n"); + else if(!strcmp(name, "controller")) + return ("\n\t"); + } + if (where == MXML_WS_BEFORE_OPEN) + { + if(!strcmp(name, "file")) + return ("\n"); + else if(!strcmp(name, "section")) + return ("\n\n"); + else if(!strcmp(name, "setting") || !strcmp(name, "controller")) + return ("\n\t"); + else if(!strcmp(name, "button")) + return ("\n\t\t"); + } + return (NULL); +} + +static int +preparePrefsData () +{ + xml = mxmlNewXML("1.0"); + mxmlSetWrapMargin(0); // disable line wrapping + + data = mxmlNewElement(xml, "file"); + mxmlElementSetAttr(data, "app", APPNAME); + mxmlElementSetAttr(data, "version", APPVERSION); + + createXMLSection("File", "File Settings"); + + createXMLSetting("AutoLoad", "Auto Load", toStr(GCSettings.AutoLoad)); + createXMLSetting("AutoSave", "Auto Save", toStr(GCSettings.AutoSave)); + createXMLSetting("LoadMethod", "Load Method", toStr(GCSettings.LoadMethod)); + createXMLSetting("SaveMethod", "Save Method", toStr(GCSettings.SaveMethod)); + createXMLSetting("LoadFolder", "Load Folder", GCSettings.LoadFolder); + createXMLSetting("LastFileLoaded", "Last File Loaded", GCSettings.LastFileLoaded); + createXMLSetting("SaveFolder", "Save Folder", GCSettings.SaveFolder); + createXMLSetting("CheatFolder", "Cheats Folder", GCSettings.CheatFolder); + createXMLSetting("ScreenshotsFolder", "Screenshots Folder", GCSettings.ScreenshotsFolder); + + createXMLSection("Network", "Network Settings"); + + createXMLSetting("smbip", "Share Computer IP", GCSettings.smbip); + createXMLSetting("smbshare", "Share Name", GCSettings.smbshare); + createXMLSetting("smbuser", "Share Username", GCSettings.smbuser); + createXMLSetting("smbpwd", "Share Password", GCSettings.smbpwd); + + createXMLSection("Video", "Video Settings"); + + createXMLSetting("videomode", "Video Mode", toStr(GCSettings.videomode)); + createXMLSetting("zoomHor", "Horizontal Zoom Level", FtoStr(GCSettings.zoomHor)); + createXMLSetting("zoomVert", "Vertical Zoom Level", FtoStr(GCSettings.zoomVert)); + createXMLSetting("render", "Video Filtering", toStr(GCSettings.render)); + createXMLSetting("widescreen", "Aspect Ratio Correction", toStr(GCSettings.widescreen)); + createXMLSetting("crosshair", "Crosshair", toStr(GCSettings.crosshair)); + createXMLSetting("FilterMethod", "Filter Method", toStr(GCSettings.FilterMethod)); + createXMLSetting("xshift", "Horizontal Video Shift", toStr(GCSettings.xshift)); + createXMLSetting("yshift", "Vertical Video Shift", toStr(GCSettings.yshift)); + + createXMLSection("Menu", "Menu Settings"); + + createXMLSetting("WiimoteOrientation", "Wiimote Orientation", toStr(GCSettings.WiimoteOrientation)); + createXMLSetting("ExitAction", "Exit Action", toStr(GCSettings.ExitAction)); + createXMLSetting("MusicVolume", "Music Volume", toStr(GCSettings.MusicVolume)); + createXMLSetting("SFXVolume", "Sound Effects Volume", toStr(GCSettings.SFXVolume)); + createXMLSetting("Rumble", "Rumble", toStr(GCSettings.Rumble)); + createXMLSetting("language", "Language", toStr(GCSettings.language)); + + createXMLSection("Controller", "Controller Settings"); + + createXMLSetting("Controller", "Controller", toStr(GCSettings.Controller)); + + createXMLController(btnmap[CTRL_PAD][CTRLR_GCPAD], "btnmap_pad_gcpad", "SNES Pad - GameCube Controller"); + createXMLController(btnmap[CTRL_PAD][CTRLR_WIIMOTE], "btnmap_pad_wiimote", "SNES Pad - Wiimote"); + createXMLController(btnmap[CTRL_PAD][CTRLR_CLASSIC], "btnmap_pad_classic", "SNES Pad - Classic Controller"); + createXMLController(btnmap[CTRL_PAD][CTRLR_NUNCHUK], "btnmap_pad_nunchuk", "SNES Pad - Nunchuk + Wiimote"); + createXMLController(btnmap[CTRL_SCOPE][CTRLR_GCPAD], "btnmap_scope_gcpad", "Superscope - GameCube Controller"); + createXMLController(btnmap[CTRL_SCOPE][CTRLR_WIIMOTE], "btnmap_scope_wiimote", "Superscope - Wiimote"); + createXMLController(btnmap[CTRL_MOUSE][CTRLR_GCPAD], "btnmap_mouse_gcpad", "Mouse - GameCube Controller"); + createXMLController(btnmap[CTRL_MOUSE][CTRLR_WIIMOTE], "btnmap_mouse_wiimote", "Mouse - Wiimote"); + createXMLController(btnmap[CTRL_JUST][CTRLR_GCPAD], "btnmap_just_gcpad", "Justifier - GameCube Controller"); + createXMLController(btnmap[CTRL_JUST][CTRLR_WIIMOTE], "btnmap_just_wiimote", "Justifier - Wiimote"); + + int datasize = mxmlSaveString(xml, (char *)savebuffer, SAVEBUFFERSIZE, XMLSaveCallback); + + mxmlDelete(xml); + + return datasize; +} + +/**************************************************************************** + * loadXMLSetting + * + * Load XML elements into variables for an individual variable + ***************************************************************************/ + +static void loadXMLSetting(char * var, const char * name, int maxsize) +{ + item = mxmlFindElement(xml, xml, "setting", "name", name, MXML_DESCEND); + if(item) + { + const char * tmp = mxmlElementGetAttr(item, "value"); + if(tmp) + snprintf(var, maxsize, "%s", tmp); + } +} +static void loadXMLSetting(int * var, const char * name) +{ + item = mxmlFindElement(xml, xml, "setting", "name", name, MXML_DESCEND); + if(item) + { + const char * tmp = mxmlElementGetAttr(item, "value"); + if(tmp) + *var = atoi(tmp); + } +} +static void loadXMLSetting(float * var, const char * name) +{ + item = mxmlFindElement(xml, xml, "setting", "name", name, MXML_DESCEND); + if(item) + { + const char * tmp = mxmlElementGetAttr(item, "value"); + if(tmp) + *var = atof(tmp); + } +} + +/**************************************************************************** + * loadXMLController + * + * Load XML elements into variables for a controller mapping + ***************************************************************************/ + +static void loadXMLController(unsigned int controller[], const char * name) +{ + item = mxmlFindElement(xml, xml, "controller", "name", name, MXML_DESCEND); + + if(item) + { + // populate buttons + for(int i=0; i < MAXJP; i++) + { + elem = mxmlFindElement(item, xml, "button", "number", toStr(i), MXML_DESCEND); + if(elem) + { + const char * tmp = mxmlElementGetAttr(elem, "assignment"); + if(tmp) + controller[i] = atoi(tmp); + } + } + } +} + +/**************************************************************************** + * decodePrefsData + * + * Decodes preferences - parses XML and loads preferences into the variables + ***************************************************************************/ + +static bool +decodePrefsData () +{ + bool result = false; + + xml = mxmlLoadString(NULL, (char *)savebuffer, MXML_TEXT_CALLBACK); + + if(xml) + { + // check settings version + item = mxmlFindElement(xml, xml, "file", "version", NULL, MXML_DESCEND); + if(item) // a version entry exists + { + const char * version = mxmlElementGetAttr(item, "version"); + + if(version && strlen(version) == 5) + { + // this code assumes version in format X.X.X + // XX.X.X, X.XX.X, or X.X.XX will NOT work + int verMajor = version[0] - '0'; + int verMinor = version[2] - '0'; + int verPoint = version[4] - '0'; + int curMajor = APPVERSION[0] - '0'; + int curMinor = APPVERSION[2] - '0'; + int curPoint = APPVERSION[4] - '0'; + + // first we'll check that the versioning is valid + if(!(verMajor >= 0 && verMajor <= 9 && + verMinor >= 0 && verMinor <= 9 && + verPoint >= 0 && verPoint <= 9)) + result = false; + else if(verMajor < 4) // less than version 4.0.0 + result = false; // reset settings + else if(verMajor == 4 && verMinor == 0 && verPoint < 2) // anything less than 4.0.2 + result = false; // reset settings + else if((verMajor*100 + verMinor*10 + verPoint) > + (curMajor*100 + curMinor*10 + curPoint)) // some future version + result = false; // reset settings + else + result = true; + } + } + + if(result) + { + // File Settings + + loadXMLSetting(&GCSettings.AutoLoad, "AutoLoad"); + loadXMLSetting(&GCSettings.AutoSave, "AutoSave"); + loadXMLSetting(&GCSettings.LoadMethod, "LoadMethod"); + loadXMLSetting(&GCSettings.SaveMethod, "SaveMethod"); + loadXMLSetting(GCSettings.LoadFolder, "LoadFolder", sizeof(GCSettings.LoadFolder)); + loadXMLSetting(GCSettings.LastFileLoaded, "LastFileLoaded", sizeof(GCSettings.LastFileLoaded)); + loadXMLSetting(GCSettings.SaveFolder, "SaveFolder", sizeof(GCSettings.SaveFolder)); + loadXMLSetting(GCSettings.CheatFolder, "CheatFolder", sizeof(GCSettings.CheatFolder)); + loadXMLSetting(GCSettings.ScreenshotsFolder, "ScreenshotsFolder", sizeof(GCSettings.ScreenshotsFolder)); + + // Network Settings + + loadXMLSetting(GCSettings.smbip, "smbip", sizeof(GCSettings.smbip)); + loadXMLSetting(GCSettings.smbshare, "smbshare", sizeof(GCSettings.smbshare)); + loadXMLSetting(GCSettings.smbuser, "smbuser", sizeof(GCSettings.smbuser)); + loadXMLSetting(GCSettings.smbpwd, "smbpwd", sizeof(GCSettings.smbpwd)); + + // Video Settings + + loadXMLSetting(&GCSettings.videomode, "videomode"); + loadXMLSetting(&GCSettings.zoomHor, "zoomHor"); + loadXMLSetting(&GCSettings.zoomVert, "zoomVert"); + loadXMLSetting(&GCSettings.render, "render"); + loadXMLSetting(&GCSettings.widescreen, "widescreen"); + loadXMLSetting(&GCSettings.crosshair, "crosshair"); + loadXMLSetting(&GCSettings.FilterMethod, "FilterMethod"); + loadXMLSetting(&GCSettings.xshift, "xshift"); + loadXMLSetting(&GCSettings.yshift, "yshift"); + + // Menu Settings + + loadXMLSetting(&GCSettings.WiimoteOrientation, "WiimoteOrientation"); + loadXMLSetting(&GCSettings.ExitAction, "ExitAction"); + loadXMLSetting(&GCSettings.MusicVolume, "MusicVolume"); + loadXMLSetting(&GCSettings.SFXVolume, "SFXVolume"); + loadXMLSetting(&GCSettings.Rumble, "Rumble"); + loadXMLSetting(&GCSettings.language, "language"); + + // Controller Settings + + loadXMLSetting(&GCSettings.Controller, "Controller"); + + loadXMLController(btnmap[CTRL_PAD][CTRLR_GCPAD], "btnmap_pad_gcpad"); + loadXMLController(btnmap[CTRL_PAD][CTRLR_WIIMOTE], "btnmap_pad_wiimote"); + loadXMLController(btnmap[CTRL_PAD][CTRLR_CLASSIC], "btnmap_pad_classic"); + loadXMLController(btnmap[CTRL_PAD][CTRLR_NUNCHUK], "btnmap_pad_nunchuk"); + loadXMLController(btnmap[CTRL_SCOPE][CTRLR_GCPAD], "btnmap_scope_gcpad"); + loadXMLController(btnmap[CTRL_SCOPE][CTRLR_WIIMOTE], "btnmap_scope_wiimote"); + loadXMLController(btnmap[CTRL_MOUSE][CTRLR_GCPAD], "btnmap_mouse_gcpad"); + loadXMLController(btnmap[CTRL_MOUSE][CTRLR_WIIMOTE], "btnmap_mouse_wiimote"); + loadXMLController(btnmap[CTRL_JUST][CTRLR_GCPAD], "btnmap_just_gcpad"); + loadXMLController(btnmap[CTRL_JUST][CTRLR_WIIMOTE], "btnmap_just_wiimote"); + } + mxmlDelete(xml); + } + return result; +} + +/**************************************************************************** + * FixInvalidSettings + * + * Attempts to correct at least some invalid settings - the ones that + * might cause crashes + ***************************************************************************/ +void FixInvalidSettings() +{ + if(GCSettings.LoadMethod > 6) + GCSettings.LoadMethod = DEVICE_AUTO; + if(GCSettings.SaveMethod > 6) + GCSettings.SaveMethod = DEVICE_AUTO; + if(!(GCSettings.zoomHor > 0.5 && GCSettings.zoomHor < 1.5)) + GCSettings.zoomHor = 1.0; + if(!(GCSettings.zoomVert > 0.5 && GCSettings.zoomVert < 1.5)) + GCSettings.zoomVert = 1.0; + if(!(GCSettings.xshift > -50 && GCSettings.xshift < 50)) + GCSettings.xshift = 0; + if(!(GCSettings.yshift > -50 && GCSettings.yshift < 50)) + GCSettings.yshift = 0; + if(!(GCSettings.MusicVolume >= 0 && GCSettings.MusicVolume <= 100)) + GCSettings.MusicVolume = 40; + if(!(GCSettings.SFXVolume >= 0 && GCSettings.SFXVolume <= 100)) + GCSettings.SFXVolume = 40; + if(GCSettings.language < 0 || GCSettings.language >= LANG_LENGTH) + GCSettings.language = LANG_ENGLISH; + if(GCSettings.Controller > CTRL_PAD4 || GCSettings.Controller < CTRL_MOUSE) + GCSettings.Controller = CTRL_PAD2; + if(!(GCSettings.render >= 0 && GCSettings.render < 3)) + GCSettings.render = 2; + if(!(GCSettings.videomode >= 0 && GCSettings.videomode < 5)) + GCSettings.videomode = 0; +} + +/**************************************************************************** + * DefaultSettings + * + * Sets all the defaults! + ***************************************************************************/ +void +DefaultSettings () +{ + memset (&GCSettings, 0, sizeof (GCSettings)); + + ResetControls(); // controller button mappings + + GCSettings.LoadMethod = DEVICE_AUTO; // Auto, SD, DVD, USB, Network (SMB) + GCSettings.SaveMethod = DEVICE_AUTO; // Auto, SD, USB, Network (SMB) + sprintf (GCSettings.LoadFolder, "%s/roms", APPFOLDER); // Path to game files + sprintf (GCSettings.SaveFolder, "%s/saves", APPFOLDER); // Path to save files + sprintf (GCSettings.CheatFolder, "%s/cheats", APPFOLDER); // Path to cheat files + sprintf (GCSettings.ScreenshotsFolder, "%s/screenshots", APPFOLDER); // Path to cheat files + GCSettings.AutoLoad = 1; + GCSettings.AutoSave = 1; + + GCSettings.Controller = CTRL_PAD2; + + GCSettings.videomode = 0; // automatic video mode detection + GCSettings.render = 2; // Unfiltered + GCSettings.FilterMethod = FILTER_NONE; // no hq2x + + GCSettings.widescreen = 0; // no aspect ratio correction + GCSettings.zoomHor = 1.0; // horizontal zoom level + GCSettings.zoomVert = 1.0; // vertical zoom level + GCSettings.xshift = 0; // horizontal video shift + GCSettings.yshift = 0; // vertical video shift + GCSettings.crosshair = 1; + + GCSettings.WiimoteOrientation = 0; + GCSettings.ExitAction = 0; + GCSettings.MusicVolume = 40; + GCSettings.SFXVolume = 40; + GCSettings.Rumble = 1; +#ifdef HW_RVL + GCSettings.language = CONF_GetLanguage(); + + if(GCSettings.language == LANG_JAPANESE || + GCSettings.language == LANG_SIMP_CHINESE || + GCSettings.language == LANG_TRAD_CHINESE || + GCSettings.language == LANG_KOREAN) + GCSettings.language = LANG_ENGLISH; +#else + GCSettings.language = LANG_ENGLISH; +#endif + + /****************** SNES9x Settings ***********************/ + + // Default ALL to false + memset (&Settings, 0, sizeof (Settings)); + + // General + + Settings.MouseMaster = true; + Settings.SuperScopeMaster = true; + Settings.JustifierMaster = true; + Settings.MultiPlayer5Master = true; + Settings.DontSaveOopsSnapshot = true; + Settings.ApplyCheats = true; + + Settings.BlockInvalidVRAMAccess = false; + Settings.HDMATimingHack = 100; + + // Sound defaults. On Wii this is 32Khz/16bit/Stereo + //Settings.SoundSync = true; + Settings.SixteenBitSound = true; + Settings.Stereo = true; + Settings.ReverseStereo = true; + Settings.SoundPlaybackRate = 32000; + Settings.SoundInputRate = 31953; + + // Graphics + Settings.Transparency = true; + Settings.SupportHiRes = true; + Settings.SkipFrames = AUTO_FRAMERATE; + Settings.TurboSkipFrames = 19; + Settings.DisplayFrameRate = false; + Settings.AutoDisplayMessages = 0; + Settings.InitialInfoStringTimeout = 200; // # frames to display messages for + + // Frame timings in 50hz and 60hz cpu mode + Settings.FrameTimePAL = 20000; + Settings.FrameTimeNTSC = 16667; +} + +/**************************************************************************** + * Save Preferences + ***************************************************************************/ +static char prefpath[MAXPATHLEN] = { 0 }; + +bool +SavePrefs (bool silent) +{ + char filepath[MAXPATHLEN]; + int datasize; + int offset = 0; + int device = 0; + + if(prefpath[0] != 0) + { + sprintf(filepath, "%s/%s", prefpath, PREF_FILE_NAME); + FindDevice(filepath, &device); + } + else if(appPath[0] != 0) + { + sprintf(filepath, "%s/%s", appPath, PREF_FILE_NAME); + strcpy(prefpath, appPath); + FindDevice(filepath, &device); + } + else + { + device = autoSaveMethod(silent); + + if(device == 0) + return false; + + sprintf(filepath, "%s%s", pathPrefix[device], APPFOLDER); + DIR *dir = opendir(filepath); + if (!dir) + { + if(mkdir(filepath, 0777) != 0) + return false; + sprintf(filepath, "%s%s/roms", pathPrefix[device], APPFOLDER); + if(mkdir(filepath, 0777) != 0) + return false; + sprintf(filepath, "%s%s/saves", pathPrefix[device], APPFOLDER); + if(mkdir(filepath, 0777) != 0) + return false; + } + else + { + closedir(dir); + } + sprintf(filepath, "%s%s/%s", pathPrefix[device], APPFOLDER, PREF_FILE_NAME); + sprintf(prefpath, "%s%s", pathPrefix[device], APPFOLDER); + } + + if(device == 0) + return false; + + if (!silent) + ShowAction ("Saving preferences..."); + + FixInvalidSettings(); + + AllocSaveBuffer (); + datasize = preparePrefsData (); + + offset = SaveFile(filepath, datasize, silent); + + FreeSaveBuffer (); + + CancelAction(); + + if (offset > 0) + { + if (!silent) + InfoPrompt("Preferences saved"); + return true; + } + return false; +} + +/**************************************************************************** + * Load Preferences from specified filepath + ***************************************************************************/ +bool +LoadPrefsFromMethod (char * path) +{ + bool retval = false; + int offset = 0; + char filepath[MAXPATHLEN]; + sprintf(filepath, "%s/%s", path, PREF_FILE_NAME); + + AllocSaveBuffer (); + + offset = LoadFile(filepath, SILENT); + + if (offset > 0) + retval = decodePrefsData (); + + FreeSaveBuffer (); + + if(retval) + { + strcpy(prefpath, path); + + if(appPath[0] == 0) + strcpy(appPath, prefpath); + } + + return retval; +} + +/**************************************************************************** + * Load Preferences + * Checks sources consecutively until we find a preference file + ***************************************************************************/ +static bool prefLoaded = false; + +bool LoadPrefs() +{ + if(prefLoaded) // already attempted loading + return true; + + bool prefFound = false; + char filepath[5][MAXPATHLEN]; + int numDevices; + +#ifdef HW_RVL + numDevices = 5; + sprintf(filepath[0], "%s", appPath); + sprintf(filepath[1], "sd:/apps/%s", APPFOLDER); + sprintf(filepath[2], "usb:/apps/%s", APPFOLDER); + sprintf(filepath[3], "sd:/%s", APPFOLDER); + sprintf(filepath[4], "usb:/%s", APPFOLDER); +#else + numDevices = 2; + sprintf(filepath[0], "carda:/%s", APPFOLDER); + sprintf(filepath[1], "cardb:/%s", APPFOLDER); +#endif + + for(int i=0; i<numDevices; i++) + { + prefFound = LoadPrefsFromMethod(filepath[i]); + + if(prefFound) + break; + } + + prefLoaded = true; // attempted to load preferences + + if(prefFound) + FixInvalidSettings(); + + // rename snes9x to snes9xgx + if(GCSettings.LoadMethod == DEVICE_SD) + { + if(ChangeInterface(DEVICE_SD, NOTSILENT) && opendir("sd:/snes9x")) + rename("sd:/snes9x", "sd:/snes9xgx"); + } + else if(GCSettings.LoadMethod == DEVICE_USB) + { + if(ChangeInterface(DEVICE_USB, NOTSILENT) && opendir("usb:/snes9x")) + rename("usb:/snes9x", "usb:/snes9xgx"); + } + else if(GCSettings.LoadMethod == DEVICE_SMB) + { + if(ChangeInterface(DEVICE_SMB, NOTSILENT) && opendir("smb:/snes9x")) + rename("smb:/snes9x", "smb:/snes9xgx"); + } + + // update folder locations + if(strcmp(GCSettings.LoadFolder, "snes9x/roms") == 0) + sprintf(GCSettings.LoadFolder, "snes9xgx/roms"); + + if(strcmp(GCSettings.SaveFolder, "snes9x/saves") == 0) + sprintf(GCSettings.SaveFolder, "snes9xgx/saves"); + + if(strcmp(GCSettings.CheatFolder, "snes9x/cheats") == 0) + sprintf(GCSettings.CheatFolder, "snes9xgx/cheats"); + + if(strcmp(GCSettings.ScreenshotsFolder, "snes9x/screenshots") == 0) + sprintf(GCSettings.ScreenshotsFolder, "snes9xgx/screenshots"); + + ResetText(); + return prefFound; +} diff --git a/plugins/snes9x_gx/source/preferences.h b/plugins/snes9x_gx/source/preferences.h new file mode 100644 index 00000000..3f766d32 --- /dev/null +++ b/plugins/snes9x_gx/source/preferences.h @@ -0,0 +1,14 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * Tantric 2008-2010 + * + * preferences.h + * + * Preferences save/load to XML file + ***************************************************************************/ + +void FixInvalidSettings(); +void DefaultSettings(); +bool SavePrefs (bool silent); +bool LoadPrefs (); diff --git a/plugins/snes9x_gx/source/s9xsupport.cpp b/plugins/snes9x_gx/source/s9xsupport.cpp new file mode 100644 index 00000000..579c9f38 --- /dev/null +++ b/plugins/snes9x_gx/source/s9xsupport.cpp @@ -0,0 +1,268 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * crunchy2 May 2007 + * Michniewski 2008 + * Tantric 2008-2010 + * + * s9xsupport.cpp + * + * Snes9x support functions + ***************************************************************************/ + +#include <gccore.h> +#include <ogcsys.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <ogc/lwp_watchdog.h> + +#include "snes9xgx.h" +#include "video.h" +#include "audio.h" +#include "snes9x/snes9x.h" +#include "snes9x/memmap.h" +#include "snes9x/display.h" +#include "snes9x/apu/apu.h" +#include "snes9x/controls.h" + +#define MAX_MESSAGE_LEN (36 * 3) + +static long long prev; +static long long now; + +/*** Miscellaneous Functions ***/ +void S9xExit() +{ + ExitApp(); +} + +void S9xMessage(int /*type */, int /*number */, const char *message) +{ + static char buffer[MAX_MESSAGE_LEN + 1]; + snprintf(buffer, MAX_MESSAGE_LEN, "%s", message); + S9xSetInfoString(buffer); +} + +void S9xAutoSaveSRAM() +{ + +} + +/*** Sound based functions ***/ +void S9xToggleSoundChannel(int c) +{ + static int sound_switch = 255; + + if (c == 8) + sound_switch = 255; + else + sound_switch ^= 1 << c; + + S9xSetSoundControl (sound_switch); +} + +/**************************************************************************** + * OpenSoundDevice + * + * Main initialisation for Wii sound system + ***************************************************************************/ +bool8 S9xOpenSoundDevice(void) +{ + InitAudio(); + return TRUE; +} + +/* eke-eke */ +void S9xInitSync() +{ + FrameTimer = 0; + prev = gettime(); +} + +/*** Synchronisation ***/ + +void S9xSyncSpeed () +{ + while (!S9xSyncSound()) + usleep(10); + + uint32 skipFrms = Settings.SkipFrames; + + if (Settings.TurboMode) + skipFrms = Settings.TurboSkipFrames; + + if (timerstyle == 0) /* use Wii vertical sync (VSYNC) with NTSC roms */ + { + while (FrameTimer == 0) + { + usleep(50); + } + + if (FrameTimer > skipFrms) + FrameTimer = skipFrms; + + if ((FrameTimer > 1) && (IPPU.SkippedFrames < skipFrms)) + { + IPPU.SkippedFrames++; + IPPU.RenderThisFrame = FALSE; + } + else + { + IPPU.SkippedFrames = 0; + IPPU.RenderThisFrame = TRUE; + } + } + else /* use internal timer for PAL roms */ + { + unsigned int timediffallowed = Settings.TurboMode ? 0 : Settings.FrameTime; + now = gettime(); + + if (diff_usec(prev, now) > timediffallowed) + { + /* Timer has already expired */ + if (IPPU.SkippedFrames < skipFrms) + { + IPPU.SkippedFrames++; + IPPU.RenderThisFrame = FALSE; + } + else + { + IPPU.SkippedFrames = 0; + IPPU.RenderThisFrame = TRUE; + } + } + else + { + /*** Ahead - so hold up ***/ + while (diff_usec(prev, now) < timediffallowed) + { + now = gettime(); + usleep(50); + } + IPPU.RenderThisFrame = TRUE; + IPPU.SkippedFrames = 0; + } + + prev = now; + } + + if (!Settings.TurboMode) + FrameTimer--; + return; +} + +/*** Video / Display related functions ***/ +bool8 S9xInitUpdate() +{ + return (TRUE); +} + +bool8 S9xDeinitUpdate(int Width, int Height) +{ + update_video(Width, Height); + return (TRUE); +} + +bool8 S9xContinueUpdate(int Width, int Height) +{ + return (TRUE); +} + +void S9xSetPalette() +{ + return; +} + +/*** Input functions ***/ +void S9xHandlePortCommand(s9xcommand_t cmd, int16 data1, int16 data2) +{ + return; +} + +bool S9xPollButton(uint32 id, bool * pressed) +{ + return 0; +} + +bool S9xPollAxis(uint32 id, int16 * value) +{ + return 0; +} + +bool S9xPollPointer(uint32 id, int16 * x, int16 * y) +{ + return 0; +} + +/**************************************************************************** + * Note that these are DUMMY functions, and only allow Snes9x to + * compile. Where possible, they will return an error signal. + ***************************************************************************/ + +const char *S9xChooseFilename(bool8 read_only) +{ + ExitApp(); + return NULL; +} + +const char * S9xChooseMovieFilename(bool8 read_only) +{ + ExitApp(); + return NULL; +} + +const char * S9xGetDirectory(enum s9x_getdirtype dirtype) +{ + ExitApp(); + return NULL; +} + +const char * S9xGetFilename(const char *ex, enum s9x_getdirtype dirtype) +{ + ExitApp(); + return NULL; +} + +const char * S9xGetFilenameInc(const char *e, enum s9x_getdirtype dirtype) +{ + ExitApp(); + return NULL; +} + +const char * S9xBasename(const char *name) +{ + ExitApp(); + return name; +} + +const char * S9xStringInput (const char * s) +{ + ExitApp(); + return s; +} + +void _splitpath(char const *buf, char *drive, char *dir, char *fname, char *ext) +{ + ExitApp(); +} + +void _makepath(char *filename, const char *drive, const char *dir, + const char *fname, const char *ext) +{ + ExitApp(); +} + +int dup(int fildes) +{ + ExitApp(); + return 1; +} + +int access(const char *pathname, int mode) +{ + ExitApp(); + return 1; +} diff --git a/plugins/snes9x_gx/source/snes9x/65c816.h b/plugins/snes9x_gx/source/snes9x/65c816.h new file mode 100644 index 00000000..995fcbbb --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/65c816.h @@ -0,0 +1,276 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _65C816_H_ +#define _65C816_H_ + +#define Carry 1 +#define Zero 2 +#define IRQ 4 +#define Decimal 8 +#define IndexFlag 16 +#define MemoryFlag 32 +#define Overflow 64 +#define Negative 128 +#define Emulation 256 + +#define SetCarry() (ICPU._Carry = 1) +#define ClearCarry() (ICPU._Carry = 0) +#define SetZero() (ICPU._Zero = 0) +#define ClearZero() (ICPU._Zero = 1) +#define SetIRQ() (Registers.PL |= IRQ) +#define ClearIRQ() (Registers.PL &= ~IRQ) +#define SetDecimal() (Registers.PL |= Decimal) +#define ClearDecimal() (Registers.PL &= ~Decimal) +#define SetIndex() (Registers.PL |= IndexFlag) +#define ClearIndex() (Registers.PL &= ~IndexFlag) +#define SetMemory() (Registers.PL |= MemoryFlag) +#define ClearMemory() (Registers.PL &= ~MemoryFlag) +#define SetOverflow() (ICPU._Overflow = 1) +#define ClearOverflow() (ICPU._Overflow = 0) +#define SetNegative() (ICPU._Negative = 0x80) +#define ClearNegative() (ICPU._Negative = 0) + +#define CheckCarry() (ICPU._Carry) +#define CheckZero() (ICPU._Zero == 0) +#define CheckIRQ() (Registers.PL & IRQ) +#define CheckDecimal() (Registers.PL & Decimal) +#define CheckIndex() (Registers.PL & IndexFlag) +#define CheckMemory() (Registers.PL & MemoryFlag) +#define CheckOverflow() (ICPU._Overflow) +#define CheckNegative() (ICPU._Negative & 0x80) +#define CheckEmulation() (Registers.P.W & Emulation) + +#define SetFlags(f) (Registers.P.W |= (f)) +#define ClearFlags(f) (Registers.P.W &= ~(f)) +#define CheckFlag(f) (Registers.PL & (f)) + +typedef union +{ +#ifdef LSB_FIRST + struct { uint8 l, h; } B; +#else + struct { uint8 h, l; } B; +#endif + uint16 W; +} pair; + +typedef union +{ +#ifdef LSB_FIRST + struct { uint8 xPCl, xPCh, xPB, z; } B; + struct { uint16 xPC, d; } W; +#else + struct { uint8 z, xPB, xPCh, xPCl; } B; + struct { uint16 d, xPC; } W; +#endif + uint32 xPBPC; +} PC_t; + +struct SRegisters +{ + uint8 DB; + pair P; + pair A; + pair D; + pair S; + pair X; + pair Y; + PC_t PC; +}; + +#define AL A.B.l +#define AH A.B.h +#define XL X.B.l +#define XH X.B.h +#define YL Y.B.l +#define YH Y.B.h +#define SL S.B.l +#define SH S.B.h +#define DL D.B.l +#define DH D.B.h +#define PL P.B.l +#define PH P.B.h +#define PBPC PC.xPBPC +#define PCw PC.W.xPC +#define PCh PC.B.xPCh +#define PCl PC.B.xPCl +#define PB PC.B.xPB + +extern struct SRegisters Registers; + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/apu/SNES_SPC.cpp b/plugins/snes9x_gx/source/snes9x/apu/SNES_SPC.cpp new file mode 100644 index 00000000..567b7ddc --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/SNES_SPC.cpp @@ -0,0 +1,564 @@ +// Core SPC emulation: CPU, timers, SMP registers, memory + +// snes_spc 0.9.0. http://www.slack.net/~ant/ + +#include "SNES_SPC.h" + +#include <string.h> + +/* Copyright (C) 2004-2007 Shay Green. This module 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 +module 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 module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "blargg_source.h" + +#define RAM (m.ram.ram) +#define REGS (m.smp_regs [0]) +#define REGS_IN (m.smp_regs [1]) + +// (n ? n : 256) +#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) + +// Note: SPC_MORE_ACCURACY exists mainly so I can run my validation tests, which +// do crazy echo buffer accesses. +#ifndef SPC_MORE_ACCURACY + #define SPC_MORE_ACCURACY 0 +#endif + +#ifdef BLARGG_ENABLE_OPTIMIZER + #include BLARGG_ENABLE_OPTIMIZER +#endif + + +//// Timers + +#if SPC_DISABLE_TEMPO + #define TIMER_DIV( t, n ) ((n) >> t->prescaler) + #define TIMER_MUL( t, n ) ((n) << t->prescaler) +#else + #define TIMER_DIV( t, n ) ((n) / t->prescaler) + #define TIMER_MUL( t, n ) ((n) * t->prescaler) +#endif + +SNES_SPC::Timer* SNES_SPC::run_timer_( Timer* t, rel_time_t time ) +{ + int elapsed = TIMER_DIV( t, time - t->next_time ) + 1; + t->next_time += TIMER_MUL( t, elapsed ); + + if ( t->enabled ) + { + int remain = IF_0_THEN_256( t->period - t->divider ); + int divider = t->divider + elapsed; + int over = elapsed - remain; + if ( over >= 0 ) + { + int n = over / t->period; + t->counter = (t->counter + 1 + n) & 0x0F; + divider = over - n * t->period; + } + t->divider = (uint8_t) divider; + } + return t; +} + +inline SNES_SPC::Timer* SNES_SPC::run_timer( Timer* t, rel_time_t time ) +{ + if ( time >= t->next_time ) + t = run_timer_( t, time ); + return t; +} + + +//// ROM + +void SNES_SPC::enable_rom( int enable ) +{ + if ( m.rom_enabled != enable ) + { + m.rom_enabled = dsp.rom_enabled = enable; + if ( enable ) + memcpy( m.hi_ram, &RAM [rom_addr], sizeof m.hi_ram ); + memcpy( &RAM [rom_addr], (enable ? m.rom : m.hi_ram), rom_size ); + // TODO: ROM can still get overwritten when DSP writes to echo buffer + } +} + + +//// DSP + +#if SPC_LESS_ACCURATE + int const max_reg_time = 29; + + signed char const SNES_SPC::reg_times_ [256] = + { + -1, 0,-11,-10,-15,-11, -2, -2, 4, 3, 14, 14, 26, 26, 14, 22, + 2, 3, 0, 1,-12, 0, 1, 1, 7, 6, 14, 14, 27, 14, 14, 23, + 5, 6, 3, 4, -1, 3, 4, 4, 10, 9, 14, 14, 26, -5, 14, 23, + 8, 9, 6, 7, 2, 6, 7, 7, 13, 12, 14, 14, 27, -4, 14, 24, + 11, 12, 9, 10, 5, 9, 10, 10, 16, 15, 14, 14, -2, -4, 14, 24, + 14, 15, 12, 13, 8, 12, 13, 13, 19, 18, 14, 14, -2,-36, 14, 24, + 17, 18, 15, 16, 11, 15, 16, 16, 22, 21, 14, 14, 28, -3, 14, 25, + 20, 21, 18, 19, 14, 18, 19, 19, 25, 24, 14, 14, 14, 29, 14, 25, + + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + }; + + #define RUN_DSP( time, offset ) \ + int count = (time) - (offset) - m.dsp_time;\ + if ( count >= 0 )\ + {\ + int clock_count = (count & ~(clocks_per_sample - 1)) + clocks_per_sample;\ + m.dsp_time += clock_count;\ + dsp.run( clock_count );\ + } +#else + #define RUN_DSP( time, offset ) \ + {\ + int count = (time) - m.dsp_time;\ + if ( !SPC_MORE_ACCURACY || count )\ + {\ + assert( count > 0 );\ + m.dsp_time = (time);\ + dsp.run( count );\ + }\ + } +#endif + +int SNES_SPC::dsp_read( rel_time_t time ) +{ + RUN_DSP( time, reg_times [REGS [r_dspaddr] & 0x7F] ); + + int result = dsp.read( REGS [r_dspaddr] & 0x7F ); + + #ifdef SPC_DSP_READ_HOOK + SPC_DSP_READ_HOOK( spc_time + time, (REGS [r_dspaddr] & 0x7F), result ); + #endif + + return result; +} + +inline void SNES_SPC::dsp_write( int data, rel_time_t time ) +{ + RUN_DSP( time, reg_times [REGS [r_dspaddr]] ) + #if SPC_LESS_ACCURATE + else if ( m.dsp_time == skipping_time ) + { + int r = REGS [r_dspaddr]; + if ( r == SPC_DSP::r_kon ) + m.skipped_kon |= data & ~dsp.read( SPC_DSP::r_koff ); + + if ( r == SPC_DSP::r_koff ) + { + m.skipped_koff |= data; + m.skipped_kon &= ~data; + } + } + #endif + + #ifdef SPC_DSP_WRITE_HOOK + SPC_DSP_WRITE_HOOK( m.spc_time + time, REGS [r_dspaddr], (uint8_t) data ); + #endif + + if ( REGS [r_dspaddr] <= 0x7F ) + dsp.write( REGS [r_dspaddr], data ); + else if ( !SPC_MORE_ACCURACY ) + dprintf( "SPC wrote to DSP register > $7F\n" ); +} + + +//// Memory access extras + +#if SPC_MORE_ACCURACY + #define MEM_ACCESS( time, addr ) \ + {\ + if ( time >= m.dsp_time )\ + {\ + RUN_DSP( time, max_reg_time );\ + }\ + } +#elif !defined (NDEBUG) + // Debug-only check for read/write within echo buffer, since this might result in + // inaccurate emulation due to the DSP not being caught up to the present. + + bool SNES_SPC::check_echo_access( int addr ) + { + if ( !(dsp.read( SPC_DSP::r_flg ) & 0x20) ) + { + int start = 0x100 * dsp.read( SPC_DSP::r_esa ); + int size = 0x800 * (dsp.read( SPC_DSP::r_edl ) & 0x0F); + int end = start + (size ? size : 4); + if ( start <= addr && addr < end ) + { + if ( !m.echo_accessed ) + { + m.echo_accessed = 1; + return true; + } + } + } + return false; + } + + #define MEM_ACCESS( time, addr ) check( !check_echo_access( (uint16_t) addr ) ); +#else + #define MEM_ACCESS( time, addr ) +#endif + + +//// CPU write + +#if SPC_MORE_ACCURACY +static unsigned char const glitch_probs [3] [256] = +{ + 0xC3,0x92,0x5B,0x1C,0xD1,0x92,0x5B,0x1C,0xDB,0x9C,0x72,0x18,0xCD,0x5C,0x38,0x0B, + 0xE1,0x9C,0x74,0x17,0xCF,0x75,0x45,0x0C,0xCF,0x6E,0x4A,0x0D,0xA3,0x3A,0x1D,0x08, + 0xDB,0xA0,0x82,0x19,0xD9,0x73,0x3C,0x0E,0xCB,0x76,0x52,0x0B,0xA5,0x46,0x1D,0x09, + 0xDA,0x74,0x55,0x0F,0xA2,0x3F,0x21,0x05,0x9A,0x40,0x20,0x07,0x63,0x1E,0x10,0x01, + 0xDF,0xA9,0x85,0x1D,0xD3,0x84,0x4B,0x0E,0xCF,0x6F,0x49,0x0F,0xB3,0x48,0x1E,0x05, + 0xD8,0x77,0x52,0x12,0xB7,0x49,0x23,0x06,0xAA,0x45,0x28,0x07,0x7D,0x28,0x0F,0x07, + 0xCC,0x7B,0x4A,0x0E,0xB2,0x4F,0x24,0x07,0xAD,0x43,0x2C,0x06,0x86,0x29,0x11,0x07, + 0xAE,0x48,0x1F,0x0A,0x76,0x21,0x19,0x05,0x76,0x21,0x14,0x05,0x44,0x11,0x0B,0x01, + 0xE7,0xAD,0x96,0x23,0xDC,0x86,0x59,0x0E,0xDC,0x7C,0x5F,0x15,0xBB,0x53,0x2E,0x09, + 0xD6,0x7C,0x4A,0x16,0xBB,0x4A,0x25,0x08,0xB3,0x4F,0x28,0x0B,0x8E,0x23,0x15,0x08, + 0xCF,0x7F,0x57,0x11,0xB5,0x4A,0x23,0x0A,0xAA,0x42,0x28,0x05,0x7D,0x22,0x12,0x03, + 0xA6,0x49,0x28,0x09,0x82,0x2B,0x0D,0x04,0x7A,0x20,0x0F,0x04,0x3D,0x0F,0x09,0x03, + 0xD1,0x7C,0x4C,0x0F,0xAF,0x4E,0x21,0x09,0xA8,0x46,0x2A,0x07,0x85,0x1F,0x0E,0x07, + 0xA6,0x3F,0x26,0x07,0x7C,0x24,0x14,0x07,0x78,0x22,0x16,0x04,0x46,0x12,0x0A,0x02, + 0xA6,0x41,0x2C,0x0A,0x7E,0x28,0x11,0x05,0x73,0x1B,0x14,0x05,0x3D,0x11,0x0A,0x02, + 0x70,0x22,0x17,0x05,0x48,0x13,0x08,0x03,0x3C,0x07,0x0D,0x07,0x26,0x07,0x06,0x01, + + 0xE0,0x9F,0xDA,0x7C,0x4F,0x18,0x28,0x0D,0xE9,0x9F,0xDA,0x7C,0x4F,0x18,0x1F,0x07, + 0xE6,0x97,0xD8,0x72,0x64,0x13,0x26,0x09,0xDC,0x67,0xA9,0x38,0x21,0x07,0x15,0x06, + 0xE9,0x91,0xD2,0x6B,0x63,0x14,0x2B,0x0E,0xD6,0x61,0xB7,0x41,0x2B,0x0E,0x10,0x09, + 0xCF,0x59,0xB0,0x2F,0x35,0x08,0x0F,0x07,0xB6,0x30,0x7A,0x21,0x17,0x07,0x09,0x03, + 0xE7,0xA3,0xE5,0x6B,0x65,0x1F,0x34,0x09,0xD8,0x6B,0xBE,0x45,0x27,0x07,0x10,0x07, + 0xDA,0x54,0xB1,0x39,0x2E,0x0E,0x17,0x08,0xA9,0x3C,0x86,0x22,0x16,0x06,0x07,0x03, + 0xD4,0x51,0xBC,0x3D,0x38,0x0A,0x13,0x06,0xB2,0x37,0x79,0x1C,0x17,0x05,0x0E,0x06, + 0xA7,0x31,0x74,0x1C,0x11,0x06,0x0C,0x02,0x6D,0x1A,0x38,0x10,0x0B,0x05,0x06,0x03, + 0xEB,0x9A,0xE1,0x7A,0x6F,0x13,0x34,0x0E,0xE6,0x75,0xC5,0x45,0x3E,0x0B,0x1A,0x05, + 0xD8,0x63,0xC1,0x40,0x3C,0x1B,0x19,0x06,0xB3,0x42,0x83,0x29,0x18,0x0A,0x08,0x04, + 0xD4,0x58,0xBA,0x43,0x3F,0x0A,0x1F,0x09,0xB1,0x33,0x8A,0x1F,0x1F,0x06,0x0D,0x05, + 0xAF,0x3C,0x7A,0x1F,0x16,0x08,0x0A,0x01,0x72,0x1B,0x52,0x0D,0x0B,0x09,0x06,0x01, + 0xCF,0x63,0xB7,0x47,0x40,0x10,0x14,0x06,0xC0,0x41,0x96,0x20,0x1C,0x09,0x10,0x05, + 0xA6,0x35,0x82,0x1A,0x20,0x0C,0x0E,0x04,0x80,0x1F,0x53,0x0F,0x0B,0x02,0x06,0x01, + 0xA6,0x31,0x81,0x1B,0x1D,0x01,0x08,0x08,0x7B,0x20,0x4D,0x19,0x0E,0x05,0x07,0x03, + 0x6B,0x17,0x49,0x07,0x0E,0x03,0x0A,0x05,0x37,0x0B,0x1F,0x06,0x04,0x02,0x07,0x01, + + 0xF0,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x47,0x1E,0x6E,0x1B,0x32,0x0A, + 0xF0,0xD6,0xEA,0xA4,0xED,0xC4,0xDE,0x82,0x98,0x1F,0x50,0x13,0x52,0x15,0x2A,0x0A, + 0xF1,0xD1,0xEB,0xA2,0xEB,0xB7,0xD8,0x69,0xA2,0x1F,0x5B,0x18,0x55,0x18,0x2C,0x0A, + 0xED,0xB5,0xDE,0x7E,0xE6,0x85,0xD3,0x59,0x59,0x0F,0x2C,0x09,0x24,0x07,0x15,0x09, + 0xF1,0xD6,0xEA,0xA0,0xEC,0xBB,0xDA,0x77,0xA9,0x23,0x58,0x14,0x5D,0x12,0x2F,0x09, + 0xF1,0xC1,0xE3,0x86,0xE4,0x87,0xD2,0x4E,0x68,0x15,0x26,0x0B,0x27,0x09,0x15,0x02, + 0xEE,0xA6,0xE0,0x5C,0xE0,0x77,0xC3,0x41,0x67,0x1B,0x3C,0x07,0x2A,0x06,0x19,0x07, + 0xE4,0x75,0xC6,0x43,0xCC,0x50,0x95,0x23,0x35,0x09,0x14,0x04,0x15,0x05,0x0B,0x04, + 0xEE,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x56,0x14,0x5A,0x12,0x26,0x0A, + 0xEE,0xBB,0xE7,0x7E,0xE9,0x8D,0xCB,0x49,0x67,0x11,0x34,0x07,0x2B,0x0B,0x14,0x07, + 0xED,0xA7,0xE5,0x76,0xE3,0x7E,0xC4,0x4B,0x77,0x14,0x34,0x08,0x27,0x07,0x14,0x04, + 0xE7,0x8B,0xD2,0x4C,0xCA,0x56,0x9E,0x31,0x36,0x0C,0x11,0x07,0x14,0x04,0x0A,0x02, + 0xF0,0x9B,0xEA,0x6F,0xE5,0x81,0xC4,0x43,0x74,0x10,0x30,0x0B,0x2D,0x08,0x1B,0x06, + 0xE6,0x83,0xCA,0x48,0xD9,0x56,0xA7,0x23,0x3B,0x09,0x12,0x09,0x15,0x07,0x0A,0x03, + 0xE5,0x5F,0xCB,0x3C,0xCF,0x48,0x91,0x22,0x31,0x0A,0x17,0x08,0x15,0x04,0x0D,0x02, + 0xD1,0x43,0x91,0x20,0xA9,0x2D,0x54,0x12,0x17,0x07,0x09,0x02,0x0C,0x04,0x05,0x03, +}; +#endif + +// divided into multiple functions to keep rarely-used functionality separate +// so often-used functionality can be optimized better by compiler + +// If write isn't preceded by read, data has this added to it +int const no_read_before_write = 0x2000; + +void SNES_SPC::cpu_write_smp_reg_( int data, rel_time_t time, int addr ) +{ + switch ( addr ) + { + case r_t0target: + case r_t1target: + case r_t2target: { + Timer* t = &m.timers [addr - r_t0target]; + int period = IF_0_THEN_256( data ); + if ( t->period != period ) + { + t = run_timer( t, time ); + #if SPC_MORE_ACCURACY + // Insane behavior when target is written just after counter is + // clocked and counter matches new period and new period isn't 1, 2, 4, or 8 + if ( t->divider == (period & 0xFF) && + t->next_time == time + TIMER_MUL( t, 1 ) && + ((period - 1) | ~0x0F) & period ) + { + //dprintf( "SPC pathological timer target write\n" ); + + // If the period is 3, 5, or 9, there's a probability this behavior won't occur, + // based on the previous period + int prob = 0xFF; + int old_period = t->period & 0xFF; + if ( period == 3 ) prob = glitch_probs [0] [old_period]; + if ( period == 5 ) prob = glitch_probs [1] [old_period]; + if ( period == 9 ) prob = glitch_probs [2] [old_period]; + + // The glitch suppresses incrementing of one of the counter bits, based on + // the lowest set bit in the new period + int b = 1; + while ( !(period & b) ) + b <<= 1; + + if ( (rand() >> 4 & 0xFF) <= prob ) + t->divider = (t->divider - b) & 0xFF; + } + #endif + t->period = period; + } + break; + } + + case r_t0out: + case r_t1out: + case r_t2out: + if ( !SPC_MORE_ACCURACY ) + dprintf( "SPC wrote to counter %d\n", (int) addr - r_t0out ); + + if ( data < no_read_before_write / 2 ) + run_timer( &m.timers [addr - r_t0out], time - 1 )->counter = 0; + break; + + // Registers that act like RAM + case 0x8: + case 0x9: + REGS_IN [addr] = (uint8_t) data; + break; + + case r_test: + if ( (uint8_t) data != 0x0A ) + dprintf( "SPC wrote to test register\n" ); + break; + + case r_control: + // port clears + if ( data & 0x10 ) + { + REGS_IN [r_cpuio0] = 0; + REGS_IN [r_cpuio1] = 0; + } + if ( data & 0x20 ) + { + REGS_IN [r_cpuio2] = 0; + REGS_IN [r_cpuio3] = 0; + } + + // timers + { + for ( int i = 0; i < timer_count; i++ ) + { + Timer* t = &m.timers [i]; + int enabled = data >> i & 1; + if ( t->enabled != enabled ) + { + t = run_timer( t, time ); + t->enabled = enabled; + if ( enabled ) + { + t->divider = 0; + t->counter = 0; + } + } + } + } + enable_rom( data & 0x80 ); + break; + } +} + +void SNES_SPC::cpu_write_smp_reg( int data, rel_time_t time, int addr ) +{ + if ( addr == r_dspdata ) // 99% + dsp_write( data, time ); + else + cpu_write_smp_reg_( data, time, addr ); +} + +void SNES_SPC::cpu_write_high( int data, int i, rel_time_t time ) +{ + if ( i < rom_size ) + { + m.hi_ram [i] = (uint8_t) data; + if ( m.rom_enabled ) + RAM [i + rom_addr] = m.rom [i]; // restore overwritten ROM + } + else + { + assert( *(&(RAM [0]) + i + rom_addr) == (uint8_t) data ); + *(&(RAM [0]) + i + rom_addr) = cpu_pad_fill; // restore overwritten padding + cpu_write( data, i + rom_addr - 0x10000, time ); + } +} + +int const bits_in_int = CHAR_BIT * sizeof (int); + +void SNES_SPC::cpu_write( int data, int addr, rel_time_t time ) +{ + MEM_ACCESS( time, addr ) + + // RAM + RAM [addr] = (uint8_t) data; + int reg = addr - 0xF0; + if ( reg >= 0 ) // 64% + { + // $F0-$FF + if ( reg < reg_count ) // 87% + { + REGS [reg] = (uint8_t) data; + + // Ports + #ifdef SPC_PORT_WRITE_HOOK + if ( (unsigned) (reg - r_cpuio0) < port_count ) + SPC_PORT_WRITE_HOOK( m.spc_time + time, (reg - r_cpuio0), + (uint8_t) data, ®S [r_cpuio0] ); + #endif + + // Registers other than $F2 and $F4-$F7 + //if ( reg != 2 && reg != 4 && reg != 5 && reg != 6 && reg != 7 ) + // TODO: this is a bit on the fragile side + if ( ((~0x2F00 << (bits_in_int - 16)) << reg) < 0 ) // 36% + cpu_write_smp_reg( data, time, reg ); + } + // High mem/address wrap-around + else + { + reg -= rom_addr - 0xF0; + if ( reg >= 0 ) // 1% in IPL ROM area or address wrapped around + cpu_write_high( data, reg, time ); + } + } +} + + +//// CPU read + +inline int SNES_SPC::cpu_read_smp_reg( int reg, rel_time_t time ) +{ + int result = REGS_IN [reg]; + reg -= r_dspaddr; + // DSP addr and data + if ( (unsigned) reg <= 1 ) // 4% 0xF2 and 0xF3 + { + result = REGS [r_dspaddr]; + if ( (unsigned) reg == 1 ) + result = dsp_read( time ); // 0xF3 + } + return result; +} + +int SNES_SPC::cpu_read( int addr, rel_time_t time ) +{ + MEM_ACCESS( time, addr ) + + // RAM + int result = RAM [addr]; + int reg = addr - 0xF0; + if ( reg >= 0 ) // 40% + { + reg -= 0x10; + if ( (unsigned) reg >= 0xFF00 ) // 21% + { + reg += 0x10 - r_t0out; + + // Timers + if ( (unsigned) reg < timer_count ) // 90% + { + Timer* t = &m.timers [reg]; + if ( time >= t->next_time ) + t = run_timer_( t, time ); + result = t->counter; + t->counter = 0; + } + // Other registers + else if ( reg < 0 ) // 10% + { + result = cpu_read_smp_reg( reg + r_t0out, time ); + } + else // 1% + { + assert( reg + (r_t0out + 0xF0 - 0x10000) < 0x100 ); + result = cpu_read( reg + (r_t0out + 0xF0 - 0x10000), time ); + } + } + } + + return result; +} + + +//// Run + +// Prefix and suffix for CPU emulator function +#define SPC_CPU_RUN_FUNC \ +BOOST::uint8_t* SNES_SPC::run_until_( time_t end_time )\ +{\ + rel_time_t rel_time = m.spc_time - end_time;\ + /*assert( rel_time <= 0 );*/\ + m.spc_time = end_time;\ + m.dsp_time += rel_time;\ + m.timers [0].next_time += rel_time;\ + m.timers [1].next_time += rel_time;\ + m.timers [2].next_time += rel_time; + +#define SPC_CPU_RUN_FUNC_END \ + m.spc_time += rel_time;\ + m.dsp_time -= rel_time;\ + m.timers [0].next_time -= rel_time;\ + m.timers [1].next_time -= rel_time;\ + m.timers [2].next_time -= rel_time;\ + /*assert( m.spc_time >= end_time );*/\ + return ®S [r_cpuio0];\ +} + +int const cpu_lag_max = 12 - 1; // DIV YA,X takes 12 clocks + +void SNES_SPC::end_frame( time_t end_time ) +{ + // Catch CPU up to as close to end as possible. If final instruction + // would exceed end, does NOT execute it and leaves m.spc_time < end. + if ( end_time > m.spc_time ) + run_until_( end_time ); + + m.spc_time -= end_time; + m.extra_clocks += end_time; + + // Greatest number of clocks early that emulation can stop early due to + // not being able to execute current instruction without going over + // allowed time. + assert( -cpu_lag_max <= m.spc_time && m.spc_time <= cpu_lag_max ); + + // Catch timers up to CPU + for ( int i = 0; i < timer_count; i++ ) + run_timer( &m.timers [i], 0 ); + + // Catch DSP up to CPU + if ( m.dsp_time < 0 ) + { + RUN_DSP( 0, max_reg_time ); + } + + // Save any extra samples beyond what should be generated + if ( m.buf_begin ) + save_extra(); +} + +// Inclusion here allows static memory access functions and better optimization +#include "SPC_CPU.h" diff --git a/plugins/snes9x_gx/source/snes9x/apu/SNES_SPC.h b/plugins/snes9x_gx/source/snes9x/apu/SNES_SPC.h new file mode 100644 index 00000000..baf90063 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/SNES_SPC.h @@ -0,0 +1,316 @@ +// SNES SPC-700 APU emulator + +// snes_spc 0.9.0 +#ifndef SNES_SPC_H +#define SNES_SPC_H + +#include "SPC_DSP.h" +#include "blargg_endian.h" + +#ifdef DEBUGGER +#include "snes9x.h" +#include "display.h" +#include "debug.h" +#endif + +struct SNES_SPC { +public: + typedef BOOST::uint8_t uint8_t; + + // Must be called once before using + blargg_err_t init(); + + // Sample pairs generated per second + enum { sample_rate = 32000 }; + +// Emulator use + + // Sets IPL ROM data. Library does not include ROM data. Most SPC music files + // don't need ROM, but a full emulator must provide this. + enum { rom_size = 0x40 }; + void init_rom( uint8_t const rom [rom_size] ); + + // Sets destination for output samples + typedef short sample_t; + void set_output( sample_t* out, int out_size ); + + // Number of samples written to output since last set + int sample_count() const; + + // Resets SPC to power-on state. This resets your output buffer, so you must + // call set_output() after this. + void reset(); + + // Emulates pressing reset switch on SNES. This resets your output buffer, so + // you must call set_output() after this. + void soft_reset(); + + // 1024000 SPC clocks per second, sample pair every 32 clocks + typedef int time_t; + enum { clock_rate = 1024000 }; + enum { clocks_per_sample = 32 }; + + // Emulated port read/write at specified time + enum { port_count = 4 }; + int read_port ( time_t, int port ); + void write_port( time_t, int port, int data ); + + // Runs SPC to end_time and starts a new time frame at 0 + void end_frame( time_t end_time ); + +// Sound control + + // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). + // Reduces emulation accuracy. + enum { voice_count = 8 }; + void mute_voices( int mask ); + + // If true, prevents channels and global volumes from being phase-negated. + // Only supported by fast DSP. + void disable_surround( bool disable = true ); + + // Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc. + enum { tempo_unit = 0x100 }; + void set_tempo( int ); + +// SPC music files + + // Loads SPC data into emulator + enum { spc_min_file_size = 0x10180 }; + enum { spc_file_size = 0x10200 }; + blargg_err_t load_spc( void const* in, long size ); + + // Clears echo region. Useful after loading an SPC as many have garbage in echo. + void clear_echo(); + + // Plays for count samples and write samples to out. Discards samples if out + // is NULL. Count must be a multiple of 2 since output is stereo. + blargg_err_t play( int count, sample_t* out ); + + // Skips count samples. Several times faster than play() when using fast DSP. + blargg_err_t skip( int count ); + +// State save/load (only available with accurate DSP) + +#if !SPC_NO_COPY_STATE_FUNCS + // Saves/loads state + enum { state_size = 68 * 1024L }; // maximum space needed when saving + typedef SPC_DSP::copy_func_t copy_func_t; + void copy_state( unsigned char** io, copy_func_t ); + + // Writes minimal header to spc_out + static void init_header( void* spc_out ); + + // Saves emulator state as SPC file data. Writes spc_file_size bytes to spc_out. + // Does not set up SPC header; use init_header() for that. + void save_spc( void* spc_out ); + + // Returns true if new key-on events occurred since last check. Useful for + // trimming silence while saving an SPC. + bool check_kon(); +#endif + +//// Snes9x Accessor + + void spc_allow_time_overflow( bool ); + + void dsp_set_spc_snapshot_callback( void (*callback) (void) ); + void dsp_dump_spc_snapshot( void ); + void dsp_set_stereo_switch( int ); + uint8_t dsp_reg_value( int, int ); + int dsp_envx_value( int ); + +//// Snes9x Debugger + +#ifdef DEBUGGER + void debug_toggle_trace( void ); + bool debug_is_enabled( void ); + void debug_do_trace( int, int, int, uint8_t const *, uint8_t *, int, int, int, int ); + void debug_op_print( char *, int, int, int, uint8_t const *, uint8_t *, int, int, int, int ); + void debug_io_print( char * ); +#endif + +public: + BLARGG_DISABLE_NOTHROW + + typedef BOOST::uint16_t uint16_t; + + // Time relative to m_spc_time. Speeds up code a bit by eliminating need to + // constantly add m_spc_time to time from CPU. CPU uses time that ends at + // 0 to eliminate reloading end time every instruction. It pays off. + typedef int rel_time_t; + + struct Timer + { + rel_time_t next_time; // time of next event + int prescaler; + int period; + int divider; + int enabled; + int counter; + }; + enum { reg_count = 0x10 }; + enum { timer_count = 3 }; + enum { extra_size = SPC_DSP::extra_size }; + + enum { signature_size = 35 }; + +private: + SPC_DSP dsp; + + #if SPC_LESS_ACCURATE + static signed char const reg_times_ [256]; + signed char reg_times [256]; + #endif + + struct state_t + { + Timer timers [timer_count]; + + uint8_t smp_regs [2] [reg_count]; + + struct + { + int pc; + int a; + int x; + int y; + int psw; + int sp; + } cpu_regs; + + rel_time_t dsp_time; + time_t spc_time; + bool echo_accessed; + + int tempo; + int skipped_kon; + int skipped_koff; + const char* cpu_error; + + int extra_clocks; + sample_t* buf_begin; + sample_t const* buf_end; + sample_t* extra_pos; + sample_t extra_buf [extra_size]; + + int rom_enabled; + uint8_t rom [rom_size]; + uint8_t hi_ram [rom_size]; + + unsigned char cycle_table [256]; + + struct + { + // padding to neutralize address overflow + union { + uint8_t padding1 [0x100]; + uint16_t align; // makes compiler align data for 16-bit access + } padding1 [1]; + uint8_t ram [0x10000]; + uint8_t padding2 [0x100]; + } ram; + }; + state_t m; + + enum { rom_addr = 0xFFC0 }; + + enum { skipping_time = 127 }; + + // Value that padding should be filled with + enum { cpu_pad_fill = 0xFF }; + + enum { + r_test = 0x0, r_control = 0x1, + r_dspaddr = 0x2, r_dspdata = 0x3, + r_cpuio0 = 0x4, r_cpuio1 = 0x5, + r_cpuio2 = 0x6, r_cpuio3 = 0x7, + r_f8 = 0x8, r_f9 = 0x9, + r_t0target = 0xA, r_t1target = 0xB, r_t2target = 0xC, + r_t0out = 0xD, r_t1out = 0xE, r_t2out = 0xF + }; + + void timers_loaded(); + void enable_rom( int enable ); + void reset_buf(); + void save_extra(); + void load_regs( uint8_t const in [reg_count] ); + void ram_loaded(); + void regs_loaded(); + void reset_time_regs(); + void reset_common( int timer_counter_init ); + + Timer* run_timer_ ( Timer* t, rel_time_t ); + Timer* run_timer ( Timer* t, rel_time_t ); + int dsp_read ( rel_time_t ); + void dsp_write ( int data, rel_time_t ); + void cpu_write_smp_reg_( int data, rel_time_t, int addr ); + void cpu_write_smp_reg ( int data, rel_time_t, int addr ); + void cpu_write_high ( int data, int i, rel_time_t ); + void cpu_write ( int data, int addr, rel_time_t ); + int cpu_read_smp_reg ( int i, rel_time_t ); + int cpu_read ( int addr, rel_time_t ); + unsigned CPU_mem_bit ( uint8_t const* pc, rel_time_t ); + + bool check_echo_access ( int addr ); + uint8_t* run_until_( time_t end_time ); + + struct spc_file_t + { + char signature [signature_size]; + uint8_t has_id666; + uint8_t version; + uint8_t pcl, pch; + uint8_t a; + uint8_t x; + uint8_t y; + uint8_t psw; + uint8_t sp; + char text [212]; + uint8_t ram [0x10000]; + uint8_t dsp [128]; + uint8_t unused [0x40]; + uint8_t ipl_rom [0x40]; + }; + + static char const signature [signature_size + 1]; + + void save_regs( uint8_t out [reg_count] ); + +// Snes9x timing hack + bool allow_time_overflow; +// Snes9x debugger +#ifdef DEBUGGER + FILE *apu_trace; + bool debug_trace; +#endif +}; + +#include <assert.h> + +inline int SNES_SPC::sample_count() const { return (m.extra_clocks >> 5) * 2; } + +inline int SNES_SPC::read_port( time_t t, int port ) +{ + assert( (unsigned) port < port_count ); + return run_until_( t ) [port]; +} + +inline void SNES_SPC::write_port( time_t t, int port, int data ) +{ + assert( (unsigned) port < port_count ); + run_until_( t ) [0x10 + port] = data; + m.ram.ram [0xF4 + port] = data; +} + +inline void SNES_SPC::mute_voices( int mask ) { dsp.mute_voices( mask ); } + +inline void SNES_SPC::disable_surround( bool disable ) { dsp.disable_surround( disable ); } + +#if !SPC_NO_COPY_STATE_FUNCS +inline bool SNES_SPC::check_kon() { return dsp.check_kon(); } +#endif + +inline void SNES_SPC::spc_allow_time_overflow( bool allow ) { allow_time_overflow = allow; } + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/apu/SNES_SPC_misc.cpp b/plugins/snes9x_gx/source/snes9x/apu/SNES_SPC_misc.cpp new file mode 100644 index 00000000..078120d2 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/SNES_SPC_misc.cpp @@ -0,0 +1,855 @@ +// SPC emulation support: init, sample buffering, reset, SPC loading + +// snes_spc 0.9.0. http://www.slack.net/~ant/ + +#include "SNES_SPC.h" + +#include <string.h> + +/* Copyright (C) 2004-2007 Shay Green. This module 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 +module 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 module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "blargg_source.h" + +#define RAM (m.ram.ram) +#define REGS (m.smp_regs [0]) +#define REGS_IN (m.smp_regs [1]) + +// (n ? n : 256) +#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) + + +//// Init + +blargg_err_t SNES_SPC::init() +{ + memset( &m, 0, sizeof m ); + dsp.init( RAM ); + + m.tempo = tempo_unit; + + // Most SPC music doesn't need ROM, and almost all the rest only rely + // on these two bytes + m.rom [0x3E] = 0xFF; + m.rom [0x3F] = 0xC0; + + static unsigned char const cycle_table [128] = + {// 01 23 45 67 89 AB CD EF + 0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x68, // 0 + 0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x46, // 1 + 0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x74, // 2 + 0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x38, // 3 + 0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x66, // 4 + 0x48,0x47,0x45,0x56,0x55,0x45,0x22,0x43, // 5 + 0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x75, // 6 + 0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x36, // 7 + 0x28,0x47,0x34,0x36,0x26,0x54,0x52,0x45, // 8 + 0x48,0x47,0x45,0x56,0x55,0x55,0x22,0xC5, // 9 + 0x38,0x47,0x34,0x36,0x26,0x44,0x52,0x44, // A + 0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x34, // B + 0x38,0x47,0x45,0x47,0x25,0x64,0x52,0x49, // C + 0x48,0x47,0x56,0x67,0x45,0x55,0x22,0x83, // D + 0x28,0x47,0x34,0x36,0x24,0x53,0x43,0x40, // E + 0x48,0x47,0x45,0x56,0x34,0x54,0x22,0x60, // F + }; + + // unpack cycle table + for ( int i = 0; i < 128; i++ ) + { + int n = cycle_table [i]; + m.cycle_table [i * 2 + 0] = n >> 4; + m.cycle_table [i * 2 + 1] = n & 0x0F; + } + + allow_time_overflow = false; + + dsp.rom = m.rom; + dsp.hi_ram = m.hi_ram; + +#ifdef DEBUGGER + apu_trace = NULL; + debug_trace = false; +#endif + + #if SPC_LESS_ACCURATE + memcpy( reg_times, reg_times_, sizeof reg_times ); + #endif + + reset(); + return 0; +} + +void SNES_SPC::init_rom( uint8_t const in [rom_size] ) +{ + memcpy( m.rom, in, sizeof m.rom ); +} + +void SNES_SPC::set_tempo( int t ) +{ + m.tempo = t; + int const timer2_shift = 4; // 64 kHz + int const other_shift = 3; // 8 kHz + + #if SPC_DISABLE_TEMPO + m.timers [2].prescaler = timer2_shift; + m.timers [1].prescaler = timer2_shift + other_shift; + m.timers [0].prescaler = timer2_shift + other_shift; + #else + if ( !t ) + t = 1; + int const timer2_rate = 1 << timer2_shift; + int rate = (timer2_rate * tempo_unit + (t >> 1)) / t; + if ( rate < timer2_rate / 4 ) + rate = timer2_rate / 4; // max 4x tempo + m.timers [2].prescaler = rate; + m.timers [1].prescaler = rate << other_shift; + m.timers [0].prescaler = rate << other_shift; + #endif +} + +// Timer registers have been loaded. Applies these to the timers. Does not +// reset timer prescalers or dividers. +void SNES_SPC::timers_loaded() +{ + int i; + for ( i = 0; i < timer_count; i++ ) + { + Timer* t = &m.timers [i]; + t->period = IF_0_THEN_256( REGS [r_t0target + i] ); + t->enabled = REGS [r_control] >> i & 1; + t->counter = REGS_IN [r_t0out + i] & 0x0F; + } + + set_tempo( m.tempo ); +} + +// Loads registers from unified 16-byte format +void SNES_SPC::load_regs( uint8_t const in [reg_count] ) +{ + memcpy( REGS, in, reg_count ); + memcpy( REGS_IN, REGS, reg_count ); + + // These always read back as 0 + REGS_IN [r_test ] = 0; + REGS_IN [r_control ] = 0; + REGS_IN [r_t0target] = 0; + REGS_IN [r_t1target] = 0; + REGS_IN [r_t2target] = 0; +} + +// RAM was just loaded from SPC, with $F0-$FF containing SMP registers +// and timer counts. Copies these to proper registers. +void SNES_SPC::ram_loaded() +{ + m.rom_enabled = dsp.rom_enabled = 0; + load_regs( &RAM [0xF0] ); + + // Put STOP instruction around memory to catch PC underflow/overflow + memset( m.ram.padding1, cpu_pad_fill, sizeof m.ram.padding1 ); + memset( m.ram.padding2, cpu_pad_fill, sizeof m.ram.padding2 ); +} + +// Registers were just loaded. Applies these new values. +void SNES_SPC::regs_loaded() +{ + enable_rom( REGS [r_control] & 0x80 ); + timers_loaded(); +} + +void SNES_SPC::reset_time_regs() +{ + m.cpu_error = 0; + m.echo_accessed = 0; + m.spc_time = 0; + m.dsp_time = 0; + #if SPC_LESS_ACCURATE + m.dsp_time = clocks_per_sample + 1; + #endif + + for ( int i = 0; i < timer_count; i++ ) + { + Timer* t = &m.timers [i]; + t->next_time = 1; + t->divider = 0; + } + + regs_loaded(); + + m.extra_clocks = 0; + reset_buf(); +} + +void SNES_SPC::reset_common( int timer_counter_init ) +{ + int i; + for ( i = 0; i < timer_count; i++ ) + REGS_IN [r_t0out + i] = timer_counter_init; + + // Run IPL ROM + memset( &m.cpu_regs, 0, sizeof m.cpu_regs ); + m.cpu_regs.pc = rom_addr; + + REGS [r_test ] = 0x0A; + REGS [r_control] = 0xB0; // ROM enabled, clear ports + for ( i = 0; i < port_count; i++ ) + REGS_IN [r_cpuio0 + i] = 0; + + reset_time_regs(); +} + +void SNES_SPC::soft_reset() +{ + reset_common( 0 ); + dsp.soft_reset(); +} + +void SNES_SPC::reset() +{ + m.cpu_regs.pc = 0xFFC0; + m.cpu_regs.a = 0x00; + m.cpu_regs.x = 0x00; + m.cpu_regs.y = 0x00; + m.cpu_regs.psw = 0x02; + m.cpu_regs.sp = 0xEF; + memset( RAM, 0x00, 0x10000 ); + ram_loaded(); + reset_common( 0x0F ); + dsp.reset(); +} + +char const SNES_SPC::signature [signature_size + 1] = + "SNES-SPC700 Sound File Data v0.30\x1A\x1A"; + +blargg_err_t SNES_SPC::load_spc( void const* data, long size ) +{ + spc_file_t const* const spc = (spc_file_t const*) data; + + // be sure compiler didn't insert any padding into fle_t + assert( sizeof (spc_file_t) == spc_min_file_size + 0x80 ); + + // Check signature and file size + if ( size < signature_size || memcmp( spc, signature, 27 ) ) + return "Not an SPC file"; + + if ( size < spc_min_file_size ) + return "Corrupt SPC file"; + + // CPU registers + m.cpu_regs.pc = spc->pch * 0x100 + spc->pcl; + m.cpu_regs.a = spc->a; + m.cpu_regs.x = spc->x; + m.cpu_regs.y = spc->y; + m.cpu_regs.psw = spc->psw; + m.cpu_regs.sp = spc->sp; + + // RAM and registers + memcpy( RAM, spc->ram, 0x10000 ); + ram_loaded(); + + // DSP registers + dsp.load( spc->dsp ); + + reset_time_regs(); + + return 0; +} + +void SNES_SPC::clear_echo() +{ + if ( !(dsp.read( SPC_DSP::r_flg ) & 0x20) ) + { + int addr = 0x100 * dsp.read( SPC_DSP::r_esa ); + int end = addr + 0x800 * (dsp.read( SPC_DSP::r_edl ) & 0x0F); + if ( end > 0x10000 ) + end = 0x10000; + memset( &RAM [addr], 0xFF, end - addr ); + } +} + + +//// Sample output + +void SNES_SPC::reset_buf() +{ + // Start with half extra buffer of silence + sample_t* out = m.extra_buf; + while ( out < &m.extra_buf [extra_size / 2] ) + *out++ = 0; + + m.extra_pos = out; + m.buf_begin = 0; + + dsp.set_output( 0, 0 ); +} + +void SNES_SPC::set_output( sample_t* out, int size ) +{ + require( (size & 1) == 0 ); // size must be even + + m.extra_clocks &= clocks_per_sample - 1; + if ( out ) + { + sample_t const* out_end = out + size; + m.buf_begin = out; + m.buf_end = out_end; + + // Copy extra to output + sample_t const* in = m.extra_buf; + while ( in < m.extra_pos && out < out_end ) + *out++ = *in++; + + // Handle output being full already + if ( out >= out_end ) + { + // Have DSP write to remaining extra space + out = dsp.extra(); + out_end = &dsp.extra() [extra_size]; + + // Copy any remaining extra samples as if DSP wrote them + while ( in < m.extra_pos ) + *out++ = *in++; + assert( out <= out_end ); + } + + dsp.set_output( out, out_end - out ); + } + else + { + reset_buf(); + } +} + +void SNES_SPC::save_extra() +{ + // Get end pointers + sample_t const* main_end = m.buf_end; // end of data written to buf + sample_t const* dsp_end = dsp.out_pos(); // end of data written to dsp.extra() + if ( m.buf_begin <= dsp_end && dsp_end <= main_end ) + { + main_end = dsp_end; + dsp_end = dsp.extra(); // nothing in DSP's extra + } + + // Copy any extra samples at these ends into extra_buf + sample_t* out = m.extra_buf; + sample_t const* in; + for ( in = m.buf_begin + sample_count(); in < main_end; in++ ) + *out++ = *in; + for ( in = dsp.extra(); in < dsp_end ; in++ ) + *out++ = *in; + + m.extra_pos = out; + assert( out <= &m.extra_buf [extra_size] ); +} + +blargg_err_t SNES_SPC::play( int count, sample_t* out ) +{ + require( (count & 1) == 0 ); // must be even + if ( count ) + { + set_output( out, count ); + end_frame( count * (clocks_per_sample / 2) ); + } + + const char* err = m.cpu_error; + m.cpu_error = 0; + return err; +} + +blargg_err_t SNES_SPC::skip( int count ) +{ + #if SPC_LESS_ACCURATE + if ( count > 2 * sample_rate * 2 ) + { + set_output( 0, 0 ); + + // Skip a multiple of 4 samples + time_t end = count; + count = (count & 3) + 1 * sample_rate * 2; + end = (end - count) * (clocks_per_sample / 2); + + m.skipped_kon = 0; + m.skipped_koff = 0; + + // Preserve DSP and timer synchronization + // TODO: verify that this really preserves it + int old_dsp_time = m.dsp_time + m.spc_time; + m.dsp_time = end - m.spc_time + skipping_time; + end_frame( end ); + m.dsp_time = m.dsp_time - skipping_time + old_dsp_time; + + dsp.write( SPC_DSP::r_koff, m.skipped_koff & ~m.skipped_kon ); + dsp.write( SPC_DSP::r_kon , m.skipped_kon ); + clear_echo(); + } + #endif + + return play( count, 0 ); +} + +//// Snes9x Accessor + +void SNES_SPC::dsp_set_spc_snapshot_callback( void (*callback) (void) ) +{ + dsp.set_spc_snapshot_callback( callback ); +} + +void SNES_SPC::dsp_dump_spc_snapshot( void ) +{ + dsp.dump_spc_snapshot(); +} + +void SNES_SPC::dsp_set_stereo_switch( int value ) +{ + dsp.set_stereo_switch( value ); +} + +SNES_SPC::uint8_t SNES_SPC::dsp_reg_value( int ch, int addr ) +{ + return dsp.reg_value( ch, addr ); +} + +int SNES_SPC::dsp_envx_value( int ch ) +{ + return dsp.envx_value( ch ); +} + +//// Snes9x debugger + +#ifdef DEBUGGER + +void SNES_SPC::debug_toggle_trace( void ) +{ + debug_trace = !debug_trace; + + if (debug_trace) + { + printf("APU tracing enabled.\n"); + ENSURE_TRACE_OPEN(apu_trace, "apu_trace.log", "wb") + } + else + { + printf("APU tracing disabled.\n"); + fclose(apu_trace); + apu_trace = NULL; + } +} + +bool SNES_SPC::debug_is_enabled( void ) { return debug_trace; } + +void SNES_SPC::debug_do_trace( int a, int x, int y, uint8_t const *pc, uint8_t *sp, int psw, int c, int nz, int dp ) +{ + char msg[512]; + + ENSURE_TRACE_OPEN(apu_trace, "apu_trace.log", "a") + + debug_op_print(msg, a, x, y, pc, sp, psw, c, nz, dp); + fprintf(apu_trace, "%s ", msg); + debug_io_print(msg); + fprintf(apu_trace, "%s ", msg); + S9xPrintHVPosition(msg); + fprintf(apu_trace, "%s\n", msg); +} + +void SNES_SPC::debug_op_print( char *buffer, int a, int x, int y, uint8_t const *pc, uint8_t *sp, int psw, int c, int nz, int dp ) +{ + static char mnemonics[256][20] = + { + "NOP", + "TCALL 0", + "SET1 $%02X.0", + "BBS $%02X.0,$%04X", + "OR A,$%02X", + "OR A,!$%04X", + "OR A,(X)", + "OR A,[$%02X+X]", + "OR A,#$%02X", + "OR $%02X,$%02X", + "OR1 C,$%04X.%d", + "ASL $%02X", + "MOV !$%04X,Y", + "PUSH PSW", + "TSET1 !$%04X", + "BRK", + "BPL $%04X", + "TCALL 1", + "CLR1 $%02X.0", + "BBC $%02X.0,$%04X", + "OR A,$%02X+X", + "OR A,!$%04X+X", + "OR A,!$%04X+Y", + "OR A,[$%02X]+Y", + "OR $%02X,#$%02X", + "OR (X),(Y)", + "DECW $%02X", + "ASL $%02X+X", + "ASL A", + "DEC X", + "CMP X,!$%04X", + "JMP [!$%04X+X]", + "CLRP", + "TCALL 2", + "SET1 $%02X.1", + "BBS $%02X.1,$%04X", + "AND A,$%02X", + "AND A,!$%04X", + "AND A,(X)", + "AND A,[$%02X+X]", + "AND A,#$%02X", + "AND $%02X,$%02X", + "OR1 C,/$%04X.%d", + "ROL $%02X", + "ROL !$%04X", + "PUSH A", + "CBNE $%02X,$%04X", + "BRA $%04X", + "BMI $%04X", + "TCALL 3", + "CLR1 $%02X.1", + "BBC $%02X.1,$%04X", + "AND A,$%02X+X", + "AND A,!$%04X+X", + "AND A,!$%04X+Y", + "AND A,[$%02X]+Y", + "AND $%02X,#$%02X", + "AND (X),(Y)", + "INCW $%02X", + "ROL $%02X+X", + "ROL A", + "INC X", + "CMP X,$%02X", + "CALL !$%04X", + "SETP", + "TCALL 4", + "SET1 $%02X.2", + "BBS $%02X.2,$%04X", + "EOR A,$%02X", + "EOR A,!$%04X", + "EOR A,(X)", + "EOR A,[$%02X+X]", + "EOR A,#$%02X", + "EOR $%02X,$%02X", + "AND1 C,$%04X.%d", + "LSR $%02X", + "LSR !$%04X", + "PUSH X", + "TCLR1 !$%04X", + "PCALL $%02X", + "BVC $%04X", + "TCALL 5", + "CLR1 $%02X.2", + "BBC $%02X.2,$%04X", + "EOR A,$%02X+X", + "EOR A,!$%04X+X", + "EOR A,!$%04X+Y", + "EOR A,[$%02X]+Y", + "EOR $%02X,#$%02X", + "EOR (X),(Y)", + "CMPW YA,$%02X", + "LSR $%02X+X", + "LSR A", + "MOV X,A", + "CMP Y,!$%04X", + "JMP !$%04X", + "CLRC", + "TCALL 6", + "SET1 $%02X.3", + "BBS $%02X.3,$%04X", + "CMP A,$%02X", + "CMP A,!$%04X", + "CMP A,(X)", + "CMP A,[$%02X+X]", + "CMP A,#$%02X", + "CMP $%02X,$%02X", + "AND1 C,/$%04X.%d", + "ROR $%02X", + "ROR !$%04X", + "PUSH Y", + "DBNZ $%02X,$%04X", + "RET", + "BVS $%04X", + "TCALL 7", + "CLR1 $%02X.3", + "BBC $%02X.3,$%04X", + "CMP A,$%02X+X", + "CMP A,!$%04X+X", + "CMP A,!$%04X+Y", + "CMP A,[$%02X]+Y", + "CMP $%02X,#$%02X", + "CMP (X),(Y)", + "ADDW YA,$%02X", + "ROR $%02X+X", + "ROR A", + "MOV A,X", + "CMP Y,$%02X", + "RET1", + "SETC", + "TCALL 8", + "SET1 $%02X.4", + "BBS $%02X.4,$%04X", + "ADC A,$%02X", + "ADC A,!$%04X", + "ADC A,(X)", + "ADC A,[$%02X+X]", + "ADC A,#$%02X", + "ADC $%02X,$%02X", + "EOR1 C,$%04X.%d", + "DEC $%02X", + "DEC !$%04X", + "MOV Y,#$%02X", + "POP PSW", + "MOV $%02X,#$%02X", + "BCC $%04X", + "TCALL 9", + "CLR1 $%02X.4", + "BBC $%02X.4,$%04X", + "ADC A,$%02X+X", + "ADC A,!$%04X+X", + "ADC A,!$%04X+Y", + "ADC A,[$%02X]+Y", + "ADC $%02X,#$%02X", + "ADC (X),(Y)", + "SUBW YA,$%02X", + "DEC $%02X+X", + "DEC A", + "MOV X,SP", + "DIV YA,X", + "XCN A", + "EI", + "TCALL 10", + "SET1 $%02X.5", + "BBS $%02X.5,$%04X", + "SBC A,$%02X", + "SBC A,!$%04X", + "SBC A,(X)", + "SBC A,[$%02X+X]", + "SBC A,#$%02X", + "SBC $%02X,$%02X", + "MOV1 C,$%04X.%d", + "INC $%02X", + "INC !$%04X", + "CMP Y,#$%02X", + "POP A", + "MOV (X)+,A", + "BCS $%04X", + "TCALL 11", + "CLR1 $%02X.5", + "BBC $%02X.5,$%04X", + "SBC A,$%02X+X", + "SBC A,!$%04X+X", + "SBC A,!$%04X+Y", + "SBC A,[$%02X]+Y", + "SBC $%02X,#$%02X", + "SBC (X),(Y)", + "MOVW YA,$%02X", + "INC $%02X+X", + "INC A", + "MOV SP,X", + "DAS A", + "MOV A,(X)+", + "DI", + "TCALL 12", + "SET1 $%02X.6", + "BBS $%02X.6,$%04X", + "MOV $%02X,A", + "MOV !$%04X,A", + "MOV (X),A", + "MOV [$%02X+X],A", + "CMP X,#$%02X", + "MOV !$%04X,X", + "MOV1 $%04X.%d,C", + "MOV $%02X,Y", + "ASL !$%04X", + "MOV X,#$%02X", + "POP X", + "MUL YA", + "BNE $%04X", + "TCALL 13", + "CLR1 $%02X.6", + "BBC $%02X.6,$%04X", + "MOV $%02X+X,A", + "MOV !$%04X+X,A", + "MOV !$%04X+Y,A", + "MOV [$%02X]+Y,A", + "MOV $%02X,X", + "MOV $%02X+Y,X", + "MOVW $%02X,YA", + "MOV $%02X+X,Y", + "DEC Y", + "MOV A,Y", + "CBNE $%02X+X,$%04X", + "DAA A", + "CLRV", + "TCALL 14", + "SET1 $%02X.7", + "BBS $%02X.7,$%04X", + "MOV A,$%02X", + "MOV A,!$%04X", + "MOV A,(X)", + "MOV A,[$%02X+X]", + "MOV A,#$%02X", + "MOV X,!$%04X", + "NOT1 $%04X.%d", + "MOV Y,$%02X", + "MOV Y,!$%04X", + "NOTC", + "POP Y", + "SLEEP", + "BEQ $%04X", + "TCALL 15", + "CLR1 $%02X.7", + "BBC $%02X.7,$%04X", + "MOV A,$%02X+X", + "MOV A,!$%04X+X", + "MOV A,!$%04X+Y", + "MOV A,[$%02X]+Y", + "MOV X,$%02X", + "MOV X,$%02X+Y", + "MOV $%02X,$%02X", + "MOV Y,$%02X+X", + "INC Y", + "MOV Y,A", + "DBNZ Y,$%04X", + "STOP" + }; + + static int modes[256] = + { + 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 1, 2, + 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 1, 1, + 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 5, 7, + 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 0, 1, + 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 1, 0, + 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 1, 1, + 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 5, 2, + 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 0, 2, + 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 0, 2, 4, + 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 2, 2, + 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 0, 2, 2, + 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 2, 2, + 2, 2, 0, 5, 0, 1, 2, 0, 0, 1, 6, 0, 1, 0, 2, 2, + 7, 2, 0, 5, 0, 1, 1, 0, 0, 0, 0, 0, 2, 2, 5, 2, + 2, 2, 0, 5, 0, 1, 2, 0, 0, 1, 6, 0, 1, 2, 2, 2, + 7, 2, 0, 5, 0, 1, 1, 0, 0, 0, 3, 0, 2, 2, 7, 2 + }; + + static int modesToBytes[] = + { + 2, 3, 1, 3, 3, 3, 3, 2 + }; + + int const n80 = 0x80; // nz + int const p20 = 0x20; // dp + int const z02 = 0x02; // nz + int const c01 = 0x01; // c + + #define GET_PC() (pc - ram) + #define GET_SP() (sp - 0x101 - ram) + #define GET_PSW( out )\ + {\ + out = psw & ~(n80 | p20 | z02 | c01);\ + out |= c >> 8 & c01;\ + out |= dp >> 3 & p20;\ + out |= ((nz >> 4) | nz) & n80;\ + if ( !(uint8_t) nz ) out |= z02;\ + } + + uint8_t const *ram = RAM; + + int addr; + int tsp, tpsw; + uint8_t d0, d1, d2; + + addr = GET_PC(); + tsp = GET_SP(); + GET_PSW(tpsw); + + d0 = *pc; + d1 = (addr < 0xffff) ? *(pc + 1) : 0; + d2 = (addr < 0xfffe) ? *(pc + 2) : 0; + + int mode = modes[d0]; + int bytes = modesToBytes[mode]; + char mnem[100]; + + switch (bytes) + { + case 1: + sprintf(buffer, "%04X %02X ", addr, d0); + break; + + case 2: + sprintf(buffer, "%04X %02X %02X ", addr, d0, d1); + break; + + case 3: + sprintf(buffer, "%04X %02X %02X %02X ", addr, d0, d1, d2); + break; + } + + switch (mode) + { + case 0: + sprintf(mnem, mnemonics[d0], d1); + break; + + case 1: + sprintf(mnem, mnemonics[d0], d1 + (d2 << 8)); + break; + + case 2: + strcpy (mnem, mnemonics[d0]); + break; + + case 3: + sprintf(mnem, mnemonics[d0], d2, d1); + break; + + case 4: + sprintf(mnem, mnemonics[d0], d2, d1); + break; + + case 5: + sprintf(mnem, mnemonics[d0], d1, addr + 3 + (int8_t) d2); + break; + + case 6: + sprintf(mnem, mnemonics[d0], (d1 + (d2 << 8)) & 0x1fff, d2 >> 5); + break; + + case 7: + sprintf(mnem, mnemonics[d0], addr + 2 + (int8_t) d1); + break; + } + + sprintf(buffer, "%s %-20s A:%02X X:%02X Y:%02X S:%02X P:%c%c%c%c%c%c%c%c ROM:%d", + buffer, mnem, a, x, y, tsp, + (tpsw & 0x80) ? 'N' : 'n', + (tpsw & 0x40) ? 'V' : 'v', + (tpsw & 0x20) ? 'P' : 'p', + (tpsw & 0x10) ? 'B' : 'b', + (tpsw & 0x08) ? 'H' : 'h', + (tpsw & 0x04) ? 'I' : 'i', + (tpsw & 0x02) ? 'Z' : 'z', + (tpsw & 0x01) ? 'C' : 'c', + m.rom_enabled ? 1 : 0); +} + +void SNES_SPC::debug_io_print( char *buffer ) +{ + sprintf(buffer, "i/o %02X/%02X %02X/%02X %02X/%02X %02X/%02X", + m.smp_regs[1][r_cpuio0], m.smp_regs[0][r_cpuio0], + m.smp_regs[1][r_cpuio1], m.smp_regs[0][r_cpuio1], + m.smp_regs[1][r_cpuio2], m.smp_regs[0][r_cpuio2], + m.smp_regs[1][r_cpuio3], m.smp_regs[0][r_cpuio3]); +} + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/apu/SNES_SPC_state.cpp b/plugins/snes9x_gx/source/snes9x/apu/SNES_SPC_state.cpp new file mode 100644 index 00000000..3d9d3f3a --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/SNES_SPC_state.cpp @@ -0,0 +1,142 @@ +// SPC emulation state save/load: copy_state(), save_spc() +// Separate file to avoid linking in unless needed + +// snes_spc 0.9.0. http://www.slack.net/‾ant/ + +#include "SNES_SPC.h" + +#if !SPC_NO_COPY_STATE_FUNCS + +#include <string.h> + +/* Copyright (C) 2004-2007 Shay Green. This module 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 +module 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 module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include <stdio.h> +#include "blargg_source.h" + +#define RAM (m.ram.ram) +#define REGS (m.smp_regs [0]) +#define REGS_IN (m.smp_regs [1]) + +void SNES_SPC::save_regs( uint8_t out [reg_count] ) +{ + // Use current timer counter values + for ( int i = 0; i < timer_count; i++ ) + out [r_t0out + i] = m.timers [i].counter; + + // Last written values + memcpy( out, REGS, r_t0out ); +} + +void SNES_SPC::init_header( void* spc_out ) +{ + spc_file_t* const spc = (spc_file_t*) spc_out; + + spc->has_id666 = 26; // has none + spc->version = 30; + memcpy( spc, signature, sizeof spc->signature ); + memset( spc->text, 0, sizeof spc->text ); +} + +void SNES_SPC::save_spc( void* spc_out ) +{ + spc_file_t* const spc = (spc_file_t*) spc_out; + + // CPU + spc->pcl = (uint8_t) (m.cpu_regs.pc >> 0); + spc->pch = (uint8_t) (m.cpu_regs.pc >> 8); + spc->a = m.cpu_regs.a; + spc->x = m.cpu_regs.x; + spc->y = m.cpu_regs.y; + spc->psw = m.cpu_regs.psw; + spc->sp = m.cpu_regs.sp; + + // RAM, ROM + memcpy( spc->ram, RAM, sizeof spc->ram ); + if ( m.rom_enabled ) + memcpy( spc->ram + rom_addr, m.hi_ram, sizeof m.hi_ram ); + memset( spc->unused, 0, sizeof spc->unused ); + memcpy( spc->ipl_rom, m.rom, sizeof spc->ipl_rom ); + + // SMP registers + save_regs( &spc->ram [0xF0] ); + int i; + for ( i = 0; i < port_count; i++ ) + spc->ram [0xF0 + r_cpuio0 + i] = REGS_IN [r_cpuio0 + i]; + + // DSP registers + for ( i = 0; i < SPC_DSP::register_count; i++ ) + spc->dsp [i] = dsp.read( i ); +} + +#undef IF_0_THEN_256 +#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) +void SNES_SPC::copy_state( unsigned char** io, copy_func_t copy ) +{ + SPC_State_Copier copier( io, copy ); + + // Make state data more readable by putting 64K RAM, 16 SMP registers, + // then DSP (with its 128 registers) first + + // RAM + enable_rom( 0 ); // will get re-enabled if necessary in regs_loaded() below + copier.copy( RAM, 0x10000 ); + + { + // SMP registers + uint8_t regs [reg_count]; + uint8_t regs_in [reg_count]; + + memcpy( regs, REGS, reg_count ); + memcpy( regs_in, REGS_IN, reg_count ); + + copier.copy( regs, sizeof regs ); + copier.copy( regs_in, sizeof regs_in ); + + memcpy( REGS, regs, reg_count); + memcpy( REGS_IN, regs_in, reg_count ); + + enable_rom( REGS [r_control] & 0x80 ); + } + + // CPU registers + SPC_COPY( uint16_t, m.cpu_regs.pc ); + SPC_COPY( uint8_t, m.cpu_regs.a ); + SPC_COPY( uint8_t, m.cpu_regs.x ); + SPC_COPY( uint8_t, m.cpu_regs.y ); + SPC_COPY( uint8_t, m.cpu_regs.psw ); + SPC_COPY( uint8_t, m.cpu_regs.sp ); + copier.extra(); + + SPC_COPY( int16_t, m.spc_time ); + SPC_COPY( int16_t, m.dsp_time ); + + // DSP + dsp.copy_state( io, copy ); + + // Timers + for ( int i = 0; i < timer_count; i++ ) + { + Timer* t = &m.timers [i]; + t->period = IF_0_THEN_256( REGS [r_t0target + i] ); + t->enabled = REGS [r_control] >> i & 1; + SPC_COPY( int16_t, t->next_time ); + SPC_COPY( uint8_t, t->divider ); + SPC_COPY( uint8_t, t->counter ); + copier.extra(); + } + + set_tempo( m.tempo ); + + copier.extra(); +} +#endif diff --git a/plugins/snes9x_gx/source/snes9x/apu/SPC_CPU.h b/plugins/snes9x_gx/source/snes9x/apu/SPC_CPU.h new file mode 100644 index 00000000..67fee8da --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/SPC_CPU.h @@ -0,0 +1,1228 @@ +// snes_spc 0.9.0. http://www.slack.net/~ant/ + +/* Copyright (C) 2004-2007 Shay Green. This module 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 +module 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 module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +//// Memory access + +#if SPC_MORE_ACCURACY + #define SUSPICIOUS_OPCODE( name ) ((void) 0) +#else + #define SUSPICIOUS_OPCODE( name ) dprintf( "SPC: suspicious opcode: " name "\n" ) +#endif + +#define CPU_READ( time, offset, addr )\ + cpu_read( addr, time + offset ) + +#define CPU_WRITE( time, offset, addr, data )\ + cpu_write( data, addr, time + offset ) + +#if SPC_MORE_ACCURACY + #define CPU_READ_TIMER( time, offset, addr, out )\ + { out = CPU_READ( time, offset, addr ); } + +#else + // timers are by far the most common thing read from dp + #define CPU_READ_TIMER( time, offset, addr_, out )\ + {\ + rel_time_t adj_time = time + offset;\ + int dp_addr = addr_;\ + int ti = dp_addr - (r_t0out + 0xF0);\ + if ( (unsigned) ti < timer_count )\ + {\ + Timer* t = &m.timers [ti];\ + if ( adj_time >= t->next_time )\ + t = run_timer_( t, adj_time );\ + out = t->counter;\ + t->counter = 0;\ + }\ + else\ + {\ + out = ram [dp_addr];\ + int i = dp_addr - 0xF0;\ + if ( (unsigned) i < 0x10 )\ + out = cpu_read_smp_reg( i, adj_time );\ + }\ + } +#endif + +#define TIME_ADJ( n ) (n) + +#define READ_TIMER( time, addr, out ) CPU_READ_TIMER( rel_time, TIME_ADJ(time), (addr), out ) +#define READ( time, addr ) CPU_READ ( rel_time, TIME_ADJ(time), (addr) ) +#define WRITE( time, addr, data ) CPU_WRITE( rel_time, TIME_ADJ(time), (addr), (data) ) + +#define DP_ADDR( addr ) (dp + (addr)) + +#define READ_DP_TIMER( time, addr, out ) CPU_READ_TIMER( rel_time, TIME_ADJ(time), DP_ADDR( addr ), out ) +#define READ_DP( time, addr ) READ ( time, DP_ADDR( addr ) ) +#define WRITE_DP( time, addr, data ) WRITE( time, DP_ADDR( addr ), data ) + +#define READ_PROG16( addr ) GET_LE16( ram + (addr) ) + +#define SET_PC( n ) (pc = ram + (n)) +#define GET_PC() (pc - ram) +#define READ_PC( pc ) (*(pc)) +#define READ_PC16( pc ) GET_LE16( pc ) + +// TODO: remove non-wrapping versions? +#define SPC_NO_SP_WRAPAROUND 0 + +#define SET_SP( v ) (sp = ram + 0x101 + (v)) +#define GET_SP() (sp - 0x101 - ram) + +#if SPC_NO_SP_WRAPAROUND +#define PUSH16( v ) (sp -= 2, SET_LE16( sp, v )) +#define PUSH( v ) (void) (*--sp = (uint8_t) (v)) +#define POP( out ) (void) ((out) = *sp++) + +#else +#define PUSH16( data )\ +{\ + int addr = (sp -= 2) - ram;\ + if ( addr > 0x100 )\ + {\ + SET_LE16( sp, data );\ + }\ + else\ + {\ + ram [(uint8_t) addr + 0x100] = (uint8_t) data;\ + sp [1] = (uint8_t) (data >> 8);\ + sp += 0x100;\ + }\ +} + +#define PUSH( data )\ +{\ + *--sp = (uint8_t) (data);\ + if ( sp - ram == 0x100 )\ + sp += 0x100;\ +} + +#define POP( out )\ +{\ + out = *sp++;\ + if ( sp - ram == 0x201 )\ + {\ + out = sp [-0x101];\ + sp -= 0x100;\ + }\ +} + +#endif + +#define MEM_BIT( rel ) CPU_mem_bit( pc, rel_time + rel ) + +unsigned SNES_SPC::CPU_mem_bit( uint8_t const* pc, rel_time_t rel_time ) +{ + unsigned addr = READ_PC16( pc ); + unsigned t = READ( 0, addr & 0x1FFF ) >> (addr >> 13); + return t << 8 & 0x100; +} + +//// Status flag handling + +// Hex value in name to clarify code and bit shifting. +// Flag stored in indicated variable during emulation +int const n80 = 0x80; // nz +int const v40 = 0x40; // psw +int const p20 = 0x20; // dp +int const b10 = 0x10; // psw +int const h08 = 0x08; // psw +int const i04 = 0x04; // psw +int const z02 = 0x02; // nz +int const c01 = 0x01; // c + +int const nz_neg_mask = 0x880; // either bit set indicates N flag set + +#define GET_PSW( out )\ +{\ + out = psw & ~(n80 | p20 | z02 | c01);\ + out |= c >> 8 & c01;\ + out |= dp >> 3 & p20;\ + out |= ((nz >> 4) | nz) & n80;\ + if ( !(uint8_t) nz ) out |= z02;\ +} + +#define SET_PSW( in )\ +{\ + psw = in;\ + c = in << 8;\ + dp = in << 3 & 0x100;\ + nz = (in << 4 & 0x800) | (~in & z02);\ +} + +SPC_CPU_RUN_FUNC +{ + uint8_t* const ram = RAM; + int a = m.cpu_regs.a; + int x = m.cpu_regs.x; + int y = m.cpu_regs.y; + uint8_t const* pc; + uint8_t* sp; + int psw; + int c; + int nz; + int dp; + + SET_PC( m.cpu_regs.pc ); + SET_SP( m.cpu_regs.sp ); + SET_PSW( m.cpu_regs.psw ); + + goto loop; + + + // Main loop + +cbranch_taken_loop: + pc += *(BOOST::int8_t const*) pc; +inc_pc_loop: + pc++; +loop: +{ + unsigned opcode; + unsigned data; + + check( (unsigned) a < 0x100 ); + check( (unsigned) x < 0x100 ); + check( (unsigned) y < 0x100 ); + + opcode = *pc; + if (allow_time_overflow && rel_time >= 0 ) + goto stop; + if ( (rel_time += m.cycle_table [opcode]) > 0 && !allow_time_overflow) + goto out_of_time; + + #ifdef SPC_CPU_OPCODE_HOOK + SPC_CPU_OPCODE_HOOK( GET_PC(), opcode ); + #endif + /* + //SUB_CASE_COUNTER( 1 ); + #define PROFILE_TIMER_LOOP( op, addr, len )\ + if ( opcode == op )\ + {\ + int cond = (unsigned) ((addr) - 0xFD) < 3 &&\ + pc [len] == 0xF0 && pc [len+1] == 0xFE - len;\ + SUB_CASE_COUNTER( op && cond );\ + } + + PROFILE_TIMER_LOOP( 0xEC, GET_LE16( pc + 1 ), 3 ); + PROFILE_TIMER_LOOP( 0xEB, pc [1], 2 ); + PROFILE_TIMER_LOOP( 0xE4, pc [1], 2 ); + */ + +#ifdef DEBUGGER + if (debug_trace) + debug_do_trace(a, x, y, pc, sp, psw, c, nz, dp); +#endif + + + // TODO: if PC is at end of memory, this will get wrong operand (very obscure) + data = *++pc; + switch ( opcode ) + { + +// Common instructions + +#define BRANCH( cond )\ +{\ + pc++;\ + pc += (BOOST::int8_t) data;\ + if ( cond )\ + goto loop;\ + pc -= (BOOST::int8_t) data;\ + rel_time -= 2;\ + goto loop;\ +} + + case 0xF0: // BEQ + BRANCH( !(uint8_t) nz ) // 89% taken + + case 0xD0: // BNE + BRANCH( (uint8_t) nz ) + + case 0x3F:{// CALL + int old_addr = GET_PC() + 2; + SET_PC( READ_PC16( pc ) ); + PUSH16( old_addr ); + goto loop; + } + + case 0x6F:// RET + #if SPC_NO_SP_WRAPAROUND + { + SET_PC( GET_LE16( sp ) ); + sp += 2; + } + #else + { + int addr = sp - ram; + SET_PC( GET_LE16( sp ) ); + sp += 2; + if ( addr < 0x1FF ) + goto loop; + + SET_PC( sp [-0x101] * 0x100 + ram [(uint8_t) addr + 0x100] ); + sp -= 0x100; + } + #endif + goto loop; + + case 0xE4: // MOV a,dp + ++pc; + // 80% from timer + READ_DP_TIMER( 0, data, a = nz ); + goto loop; + + case 0xFA:{// MOV dp,dp + int temp; + READ_DP_TIMER( -2, data, temp ); + data = temp + no_read_before_write ; + } + // fall through + case 0x8F:{// MOV dp,#imm + int temp = READ_PC( pc + 1 ); + pc += 2; + + #if !SPC_MORE_ACCURACY + { + int i = dp + temp; + ram [i] = (uint8_t) data; + i -= 0xF0; + if ( (unsigned) i < 0x10 ) // 76% + { + REGS [i] = (uint8_t) data; + + // Registers other than $F2 and $F4-$F7 + //if ( i != 2 && i != 4 && i != 5 && i != 6 && i != 7 ) + if ( ((~0x2F00 << (bits_in_int - 16)) << i) < 0 ) // 12% + cpu_write_smp_reg( data, rel_time, i ); + } + } + #else + WRITE_DP( 0, temp, data ); + #endif + goto loop; + } + + case 0xC4: // MOV dp,a + ++pc; + #if !SPC_MORE_ACCURACY + { + int i = dp + data; + ram [i] = (uint8_t) a; + i -= 0xF0; + if ( (unsigned) i < 0x10 ) // 39% + { + unsigned sel = i - 2; + REGS [i] = (uint8_t) a; + + if ( sel == 1 ) // 51% $F3 + dsp_write( a, rel_time ); + else if ( sel > 1 ) // 1% not $F2 or $F3 + cpu_write_smp_reg_( a, rel_time, i ); + } + } + #else + WRITE_DP( 0, data, a ); + #endif + goto loop; + +#define CASE( n ) case n: + +// Define common address modes based on opcode for immediate mode. Execution +// ends with data set to the address of the operand. +#define ADDR_MODES_( op )\ + CASE( op - 0x02 ) /* (X) */\ + data = x + dp;\ + pc--;\ + goto end_##op;\ + CASE( op + 0x0F ) /* (dp)+Y */\ + data = READ_PROG16( data + dp ) + y;\ + goto end_##op;\ + CASE( op - 0x01 ) /* (dp+X) */\ + data = READ_PROG16( ((uint8_t) (data + x)) + dp );\ + goto end_##op;\ + CASE( op + 0x0E ) /* abs+Y */\ + data += y;\ + goto abs_##op;\ + CASE( op + 0x0D ) /* abs+X */\ + data += x;\ + CASE( op - 0x03 ) /* abs */\ + abs_##op:\ + data += 0x100 * READ_PC( ++pc );\ + goto end_##op;\ + CASE( op + 0x0C ) /* dp+X */\ + data = (uint8_t) (data + x); + +#define ADDR_MODES_NO_DP( op )\ + ADDR_MODES_( op )\ + data += dp;\ + end_##op: + +#define ADDR_MODES( op )\ + ADDR_MODES_( op )\ + CASE( op - 0x04 ) /* dp */\ + data += dp;\ + end_##op: + +// 1. 8-bit Data Transmission Commands. Group I + + ADDR_MODES_NO_DP( 0xE8 ) // MOV A,addr + a = nz = READ( 0, data ); + goto inc_pc_loop; + + case 0xBF:{// MOV A,(X)+ + int temp = x + dp; + x = (uint8_t) (x + 1); + a = nz = READ( -1, temp ); + goto loop; + } + + case 0xE8: // MOV A,imm + a = data; + nz = data; + goto inc_pc_loop; + + case 0xF9: // MOV X,dp+Y + data = (uint8_t) (data + y); + case 0xF8: // MOV X,dp + READ_DP_TIMER( 0, data, x = nz ); + goto inc_pc_loop; + + case 0xE9: // MOV X,abs + data = READ_PC16( pc ); + ++pc; + data = READ( 0, data ); + case 0xCD: // MOV X,imm + x = data; + nz = data; + goto inc_pc_loop; + + case 0xFB: // MOV Y,dp+X + data = (uint8_t) (data + x); + case 0xEB: // MOV Y,dp + // 70% from timer + pc++; + READ_DP_TIMER( 0, data, y = nz ); + goto loop; + + case 0xEC:{// MOV Y,abs + int temp = READ_PC16( pc ); + pc += 2; + READ_TIMER( 0, temp, y = nz ); + //y = nz = READ( 0, temp ); + goto loop; + } + + case 0x8D: // MOV Y,imm + y = data; + nz = data; + goto inc_pc_loop; + +// 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2 + + ADDR_MODES_NO_DP( 0xC8 ) // MOV addr,A + WRITE( 0, data, a ); + goto inc_pc_loop; + + { + int temp; + case 0xCC: // MOV abs,Y + temp = y; + goto mov_abs_temp; + case 0xC9: // MOV abs,X + temp = x; + mov_abs_temp: + WRITE( 0, READ_PC16( pc ), temp ); + pc += 2; + goto loop; + } + + case 0xD9: // MOV dp+Y,X + data = (uint8_t) (data + y); + case 0xD8: // MOV dp,X + WRITE( 0, data + dp, x ); + goto inc_pc_loop; + + case 0xDB: // MOV dp+X,Y + data = (uint8_t) (data + x); + case 0xCB: // MOV dp,Y + WRITE( 0, data + dp, y ); + goto inc_pc_loop; + +// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3. + + case 0x7D: // MOV A,X + a = x; + nz = x; + goto loop; + + case 0xDD: // MOV A,Y + a = y; + nz = y; + goto loop; + + case 0x5D: // MOV X,A + x = a; + nz = a; + goto loop; + + case 0xFD: // MOV Y,A + y = a; + nz = a; + goto loop; + + case 0x9D: // MOV X,SP + x = nz = GET_SP(); + goto loop; + + case 0xBD: // MOV SP,X + SET_SP( x ); + goto loop; + + //case 0xC6: // MOV (X),A (handled by MOV addr,A in group 2) + + case 0xAF: // MOV (X)+,A + WRITE_DP( 0, x, a + no_read_before_write ); + x++; + goto loop; + +// 5. 8-BIT LOGIC OPERATION COMMANDS + +#define LOGICAL_OP( op, func )\ + ADDR_MODES( op ) /* addr */\ + data = READ( 0, data );\ + case op: /* imm */\ + nz = a func##= data;\ + goto inc_pc_loop;\ + { unsigned addr;\ + case op + 0x11: /* X,Y */\ + data = READ_DP( -2, y );\ + addr = x + dp;\ + goto addr_##op;\ + case op + 0x01: /* dp,dp */\ + data = READ_DP( -3, data );\ + case op + 0x10:{/*dp,imm*/\ + uint8_t const* addr2 = pc + 1;\ + pc += 2;\ + addr = READ_PC( addr2 ) + dp;\ + }\ + addr_##op:\ + nz = data func READ( -1, addr );\ + WRITE( 0, addr, nz );\ + goto loop;\ + } + + LOGICAL_OP( 0x28, & ); // AND + + LOGICAL_OP( 0x08, | ); // OR + + LOGICAL_OP( 0x48, ^ ); // EOR + +// 4. 8-BIT ARITHMETIC OPERATION COMMANDS + + ADDR_MODES( 0x68 ) // CMP addr + data = READ( 0, data ); + case 0x68: // CMP imm + nz = a - data; + c = ~nz; + nz &= 0xFF; + goto inc_pc_loop; + + case 0x79: // CMP (X),(Y) + data = READ_DP( -2, y ); + nz = READ_DP( -1, x ) - data; + c = ~nz; + nz &= 0xFF; + goto loop; + + case 0x69: // CMP dp,dp + data = READ_DP( -3, data ); + case 0x78: // CMP dp,imm + nz = READ_DP( -1, READ_PC( ++pc ) ) - data; + c = ~nz; + nz &= 0xFF; + goto inc_pc_loop; + + case 0x3E: // CMP X,dp + data += dp; + goto cmp_x_addr; + case 0x1E: // CMP X,abs + data = READ_PC16( pc ); + pc++; + cmp_x_addr: + data = READ( 0, data ); + case 0xC8: // CMP X,imm + nz = x - data; + c = ~nz; + nz &= 0xFF; + goto inc_pc_loop; + + case 0x7E: // CMP Y,dp + data += dp; + goto cmp_y_addr; + case 0x5E: // CMP Y,abs + data = READ_PC16( pc ); + pc++; + cmp_y_addr: + data = READ( 0, data ); + case 0xAD: // CMP Y,imm + nz = y - data; + c = ~nz; + nz &= 0xFF; + goto inc_pc_loop; + + { + int addr; + case 0xB9: // SBC (x),(y) + case 0x99: // ADC (x),(y) + pc--; // compensate for inc later + data = READ_DP( -2, y ); + addr = x + dp; + goto adc_addr; + case 0xA9: // SBC dp,dp + case 0x89: // ADC dp,dp + data = READ_DP( -3, data ); + case 0xB8: // SBC dp,imm + case 0x98: // ADC dp,imm + addr = READ_PC( ++pc ) + dp; + adc_addr: + nz = READ( -1, addr ); + goto adc_data; + +// catch ADC and SBC together, then decode later based on operand +#undef CASE +#define CASE( n ) case n: case (n) + 0x20: + ADDR_MODES( 0x88 ) // ADC/SBC addr + data = READ( 0, data ); + case 0xA8: // SBC imm + case 0x88: // ADC imm + addr = -1; // A + nz = a; + adc_data: { + int flags; + if ( opcode >= 0xA0 ) // SBC + data ^= 0xFF; + + flags = data ^ nz; + nz += data + (c >> 8 & 1); + flags ^= nz; + + psw = (psw & ~(v40 | h08)) | + (flags >> 1 & h08) | + ((flags + 0x80) >> 2 & v40); + c = nz; + if ( addr < 0 ) + { + a = (uint8_t) nz; + goto inc_pc_loop; + } + WRITE( 0, addr, /*(uint8_t)*/ nz ); + goto inc_pc_loop; + } + + } + +// 6. ADDITION & SUBTRACTION COMMANDS + +#define INC_DEC_REG( reg, op )\ + nz = reg op;\ + reg = (uint8_t) nz;\ + goto loop; + + case 0xBC: INC_DEC_REG( a, + 1 ) // INC A + case 0x3D: INC_DEC_REG( x, + 1 ) // INC X + case 0xFC: INC_DEC_REG( y, + 1 ) // INC Y + + case 0x9C: INC_DEC_REG( a, - 1 ) // DEC A + case 0x1D: INC_DEC_REG( x, - 1 ) // DEC X + case 0xDC: INC_DEC_REG( y, - 1 ) // DEC Y + + case 0x9B: // DEC dp+X + case 0xBB: // INC dp+X + data = (uint8_t) (data + x); + case 0x8B: // DEC dp + case 0xAB: // INC dp + data += dp; + goto inc_abs; + case 0x8C: // DEC abs + case 0xAC: // INC abs + data = READ_PC16( pc ); + pc++; + inc_abs: + nz = (opcode >> 4 & 2) - 1; + nz += READ( -1, data ); + WRITE( 0, data, /*(uint8_t)*/ nz ); + goto inc_pc_loop; + +// 7. SHIFT, ROTATION COMMANDS + + case 0x5C: // LSR A + c = 0; + case 0x7C:{// ROR A + nz = (c >> 1 & 0x80) | (a >> 1); + c = a << 8; + a = nz; + goto loop; + } + + case 0x1C: // ASL A + c = 0; + case 0x3C:{// ROL A + int temp = c >> 8 & 1; + c = a << 1; + nz = c | temp; + a = (uint8_t) nz; + goto loop; + } + + case 0x0B: // ASL dp + c = 0; + data += dp; + goto rol_mem; + case 0x1B: // ASL dp+X + c = 0; + case 0x3B: // ROL dp+X + data = (uint8_t) (data + x); + case 0x2B: // ROL dp + data += dp; + goto rol_mem; + case 0x0C: // ASL abs + c = 0; + case 0x2C: // ROL abs + data = READ_PC16( pc ); + pc++; + rol_mem: + nz = c >> 8 & 1; + nz |= (c = READ( -1, data ) << 1); + WRITE( 0, data, /*(uint8_t)*/ nz ); + goto inc_pc_loop; + + case 0x4B: // LSR dp + c = 0; + data += dp; + goto ror_mem; + case 0x5B: // LSR dp+X + c = 0; + case 0x7B: // ROR dp+X + data = (uint8_t) (data + x); + case 0x6B: // ROR dp + data += dp; + goto ror_mem; + case 0x4C: // LSR abs + c = 0; + case 0x6C: // ROR abs + data = READ_PC16( pc ); + pc++; + ror_mem: { + int temp = READ( -1, data ); + nz = (c >> 1 & 0x80) | (temp >> 1); + c = temp << 8; + WRITE( 0, data, nz ); + goto inc_pc_loop; + } + + case 0x9F: // XCN + nz = a = (a >> 4) | (uint8_t) (a << 4); + goto loop; + +// 8. 16-BIT TRANSMISION COMMANDS + + case 0xBA: // MOVW YA,dp + a = READ_DP( -2, data ); + nz = (a & 0x7F) | (a >> 1); + y = READ_DP( 0, (uint8_t) (data + 1) ); + nz |= y; + goto inc_pc_loop; + + case 0xDA: // MOVW dp,YA + WRITE_DP( -1, data, a ); + WRITE_DP( 0, (uint8_t) (data + 1), y + no_read_before_write ); + goto inc_pc_loop; + +// 9. 16-BIT OPERATION COMMANDS + + case 0x3A: // INCW dp + case 0x1A:{// DECW dp + int temp; + // low byte + data += dp; + temp = READ( -3, data ); + temp += (opcode >> 4 & 2) - 1; // +1 for INCW, -1 for DECW + nz = ((temp >> 1) | temp) & 0x7F; + WRITE( -2, data, /*(uint8_t)*/ temp ); + + // high byte + data = (uint8_t) (data + 1) + dp; + temp = (uint8_t) ((temp >> 8) + READ( -1, data )); + nz |= temp; + WRITE( 0, data, temp ); + + goto inc_pc_loop; + } + + case 0x7A: // ADDW YA,dp + case 0x9A:{// SUBW YA,dp + int lo = READ_DP( -2, data ); + int hi = READ_DP( 0, (uint8_t) (data + 1) ); + int result; + int flags; + + if ( opcode == 0x9A ) // SUBW + { + lo = (lo ^ 0xFF) + 1; + hi ^= 0xFF; + } + + lo += a; + result = y + hi + (lo >> 8); + flags = hi ^ y ^ result; + + psw = (psw & ~(v40 | h08)) | + (flags >> 1 & h08) | + ((flags + 0x80) >> 2 & v40); + c = result; + a = (uint8_t) lo; + result = (uint8_t) result; + y = result; + nz = (((lo >> 1) | lo) & 0x7F) | result; + + goto inc_pc_loop; + } + + case 0x5A: { // CMPW YA,dp + int temp = a - READ_DP( -1, data ); + nz = ((temp >> 1) | temp) & 0x7F; + temp = y + (temp >> 8); + temp -= READ_DP( 0, (uint8_t) (data + 1) ); + nz |= temp; + c = ~temp; + nz &= 0xFF; + goto inc_pc_loop; + } + +// 10. MULTIPLICATION & DIVISON COMMANDS + + case 0xCF: { // MUL YA + unsigned temp = y * a; + a = (uint8_t) temp; + nz = ((temp >> 1) | temp) & 0x7F; + y = temp >> 8; + nz |= y; + goto loop; + } + + case 0x9E: // DIV YA,X + { + unsigned ya = y * 0x100 + a; + + psw &= ~(h08 | v40); + + if ( y >= x ) + psw |= v40; + + if ( (y & 15) >= (x & 15) ) + psw |= h08; + + if ( y < x * 2 ) + { + a = ya / x; + y = ya - a * x; + } + else + { + a = 255 - (ya - x * 0x200) / (256 - x); + y = x + (ya - x * 0x200) % (256 - x); + } + + nz = (uint8_t) a; + a = (uint8_t) a; + + goto loop; + } + +// 11. DECIMAL COMPENSATION COMMANDS + + case 0xDF: // DAA + SUSPICIOUS_OPCODE( "DAA" ); + if ( a > 0x99 || c & 0x100 ) + { + a += 0x60; + c = 0x100; + } + + if ( (a & 0x0F) > 9 || psw & h08 ) + a += 0x06; + + nz = a; + a = (uint8_t) a; + goto loop; + + case 0xBE: // DAS + SUSPICIOUS_OPCODE( "DAS" ); + if ( a > 0x99 || !(c & 0x100) ) + { + a -= 0x60; + c = 0; + } + + if ( (a & 0x0F) > 9 || !(psw & h08) ) + a -= 0x06; + + nz = a; + a = (uint8_t) a; + goto loop; + +// 12. BRANCHING COMMANDS + + case 0x2F: // BRA rel + pc += (BOOST::int8_t) data; + goto inc_pc_loop; + + case 0x30: // BMI + BRANCH( (nz & nz_neg_mask) ) + + case 0x10: // BPL + BRANCH( !(nz & nz_neg_mask) ) + + case 0xB0: // BCS + BRANCH( c & 0x100 ) + + case 0x90: // BCC + BRANCH( !(c & 0x100) ) + + case 0x70: // BVS + BRANCH( psw & v40 ) + + case 0x50: // BVC + BRANCH( !(psw & v40) ) + + #define CBRANCH( cond )\ + {\ + pc++;\ + if ( cond )\ + goto cbranch_taken_loop;\ + rel_time -= 2;\ + goto inc_pc_loop;\ + } + + case 0x03: // BBS dp.bit,rel + case 0x23: + case 0x43: + case 0x63: + case 0x83: + case 0xA3: + case 0xC3: + case 0xE3: + CBRANCH( READ_DP( -4, data ) >> (opcode >> 5) & 1 ) + + case 0x13: // BBC dp.bit,rel + case 0x33: + case 0x53: + case 0x73: + case 0x93: + case 0xB3: + case 0xD3: + case 0xF3: + CBRANCH( !(READ_DP( -4, data ) >> (opcode >> 5) & 1) ) + + case 0xDE: // CBNE dp+X,rel + data = (uint8_t) (data + x); + // fall through + case 0x2E:{// CBNE dp,rel + int temp; + // 61% from timer + READ_DP_TIMER( -4, data, temp ); + CBRANCH( temp != a ) + } + + case 0x6E: { // DBNZ dp,rel + unsigned temp = READ_DP( -4, data ) - 1; + WRITE_DP( -3, (uint8_t) data, /*(uint8_t)*/ temp + no_read_before_write ); + CBRANCH( temp ) + } + + case 0xFE: // DBNZ Y,rel + y = (uint8_t) (y - 1); + BRANCH( y ) + + case 0x1F: // JMP [abs+X] + SET_PC( READ_PC16( pc ) + x ); + // fall through + case 0x5F: // JMP abs + SET_PC( READ_PC16( pc ) ); + goto loop; + +// 13. SUB-ROUTINE CALL RETURN COMMANDS + + case 0x0F:{// BRK + int temp; + int ret_addr = GET_PC(); + SUSPICIOUS_OPCODE( "BRK" ); + SET_PC( READ_PROG16( 0xFFDE ) ); // vector address verified + PUSH16( ret_addr ); + GET_PSW( temp ); + psw = (psw | b10) & ~i04; + PUSH( temp ); + goto loop; + } + + case 0x4F:{// PCALL offset + int ret_addr = GET_PC() + 1; + SET_PC( 0xFF00 | data ); + PUSH16( ret_addr ); + goto loop; + } + + case 0x01: // TCALL n + case 0x11: + case 0x21: + case 0x31: + case 0x41: + case 0x51: + case 0x61: + case 0x71: + case 0x81: + case 0x91: + case 0xA1: + case 0xB1: + case 0xC1: + case 0xD1: + case 0xE1: + case 0xF1: { + int ret_addr = GET_PC(); + SET_PC( READ_PROG16( 0xFFDE - (opcode >> 3) ) ); + PUSH16( ret_addr ); + goto loop; + } + +// 14. STACK OPERATION COMMANDS + + { + int temp; + case 0x7F: // RET1 + temp = *sp; + SET_PC( GET_LE16( sp + 1 ) ); + sp += 3; + goto set_psw; + case 0x8E: // POP PSW + POP( temp ); + set_psw: + SET_PSW( temp ); + goto loop; + } + + case 0x0D: { // PUSH PSW + int temp; + GET_PSW( temp ); + PUSH( temp ); + goto loop; + } + + case 0x2D: // PUSH A + PUSH( a ); + goto loop; + + case 0x4D: // PUSH X + PUSH( x ); + goto loop; + + case 0x6D: // PUSH Y + PUSH( y ); + goto loop; + + case 0xAE: // POP A + POP( a ); + goto loop; + + case 0xCE: // POP X + POP( x ); + goto loop; + + case 0xEE: // POP Y + POP( y ); + goto loop; + +// 15. BIT OPERATION COMMANDS + + case 0x02: // SET1 + case 0x22: + case 0x42: + case 0x62: + case 0x82: + case 0xA2: + case 0xC2: + case 0xE2: + case 0x12: // CLR1 + case 0x32: + case 0x52: + case 0x72: + case 0x92: + case 0xB2: + case 0xD2: + case 0xF2: { + int bit = 1 << (opcode >> 5); + int mask = ~bit; + if ( opcode & 0x10 ) + bit = 0; + data += dp; + WRITE( 0, data, (READ( -1, data ) & mask) | bit ); + goto inc_pc_loop; + } + + case 0x0E: // TSET1 abs + case 0x4E: // TCLR1 abs + data = READ_PC16( pc ); + pc += 2; + { + unsigned temp = READ( -2, data ); + nz = (uint8_t) (a - temp); + temp &= ~a; + if ( opcode == 0x0E ) + temp |= a; + WRITE( 0, data, temp ); + } + goto loop; + + case 0x4A: // AND1 C,mem.bit + c &= MEM_BIT( 0 ); + pc += 2; + goto loop; + + case 0x6A: // AND1 C,/mem.bit + c &= ~MEM_BIT( 0 ); + pc += 2; + goto loop; + + case 0x0A: // OR1 C,mem.bit + c |= MEM_BIT( -1 ); + pc += 2; + goto loop; + + case 0x2A: // OR1 C,/mem.bit + c |= ~MEM_BIT( -1 ); + pc += 2; + goto loop; + + case 0x8A: // EOR1 C,mem.bit + c ^= MEM_BIT( -1 ); + pc += 2; + goto loop; + + case 0xEA: // NOT1 mem.bit + data = READ_PC16( pc ); + pc += 2; + { + unsigned temp = READ( -1, data & 0x1FFF ); + temp ^= 1 << (data >> 13); + WRITE( 0, data & 0x1FFF, temp ); + } + goto loop; + + case 0xCA: // MOV1 mem.bit,C + data = READ_PC16( pc ); + pc += 2; + { + unsigned temp = READ( -2, data & 0x1FFF ); + unsigned bit = data >> 13; + temp = (temp & ~(1 << bit)) | ((c >> 8 & 1) << bit); + WRITE( 0, data & 0x1FFF, temp + no_read_before_write ); + } + goto loop; + + case 0xAA: // MOV1 C,mem.bit + c = MEM_BIT( 0 ); + pc += 2; + goto loop; + +// 16. PROGRAM PSW FLAG OPERATION COMMANDS + + case 0x60: // CLRC + c = 0; + goto loop; + + case 0x80: // SETC + c = ~0; + goto loop; + + case 0xED: // NOTC + c ^= 0x100; + goto loop; + + case 0xE0: // CLRV + psw &= ~(v40 | h08); + goto loop; + + case 0x20: // CLRP + dp = 0; + goto loop; + + case 0x40: // SETP + dp = 0x100; + goto loop; + + case 0xA0: // EI + SUSPICIOUS_OPCODE( "EI" ); + psw |= i04; + goto loop; + + case 0xC0: // DI + SUSPICIOUS_OPCODE( "DI" ); + psw &= ~i04; + goto loop; + +// 17. OTHER COMMANDS + + case 0x00: // NOP + goto loop; + + case 0xFF:{// STOP + // handle PC wrap-around + unsigned addr = GET_PC() - 1; + if ( addr >= 0x10000 ) + { + addr &= 0xFFFF; + SET_PC( addr ); + dprintf( "SPC: PC wrapped around\n" ); + goto loop; + } + } + // fall through + case 0xEF: // SLEEP + SUSPICIOUS_OPCODE( "STOP/SLEEP" ); + --pc; + rel_time = 0; + m.cpu_error = "SPC emulation error"; + goto stop; + } // switch + + assert( 0 ); // catch any unhandled instructions +} +out_of_time: + rel_time -= m.cycle_table [*pc]; // undo partial execution of opcode +stop: + + // Uncache registers + if ( GET_PC() >= 0x10000 ) + dprintf( "SPC: PC wrapped around\n" ); + m.cpu_regs.pc = (uint16_t) GET_PC(); + m.cpu_regs.sp = ( uint8_t) GET_SP(); + m.cpu_regs.a = ( uint8_t) a; + m.cpu_regs.x = ( uint8_t) x; + m.cpu_regs.y = ( uint8_t) y; + { + int temp; + GET_PSW( temp ); + m.cpu_regs.psw = (uint8_t) temp; + } +} +SPC_CPU_RUN_FUNC_END diff --git a/plugins/snes9x_gx/source/snes9x/apu/SPC_DSP.cpp b/plugins/snes9x_gx/source/snes9x/apu/SPC_DSP.cpp new file mode 100644 index 00000000..e6ba49ed --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/SPC_DSP.cpp @@ -0,0 +1,1072 @@ +// snes_spc 0.9.0. http://www.slack.net/~ant/ + +#include "SPC_DSP.h" + +#include "blargg_endian.h" +#include <string.h> + +/* Copyright (C) 2007 Shay Green. This module 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 +module 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 module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "blargg_source.h" + +#ifdef BLARGG_ENABLE_OPTIMIZER + #include BLARGG_ENABLE_OPTIMIZER +#endif + +#if INT_MAX < 0x7FFFFFFF + #error "Requires that int type have at least 32 bits" +#endif + +// TODO: add to blargg_endian.h +#define GET_LE16SA( addr ) ((BOOST::int16_t) GET_LE16( addr )) +#define GET_LE16A( addr ) GET_LE16( addr ) +#define SET_LE16A( addr, data ) SET_LE16( addr, data ) + +static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] = +{ + 0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80, + 0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF, + 0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A, + 0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF, + 0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67, + 0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x00,0x4E,0x7B,0xFF, + 0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F, + 0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF +}; + +// if ( io < -32768 ) io = -32768; +// if ( io > 32767 ) io = 32767; +#define CLAMP16( io )\ +{\ + if ( (int16_t) io != io )\ + io = (io >> 31) ^ 0x7FFF;\ +} + +// Access global DSP register +#define REG(n) m.regs [r_##n] + +// Access voice DSP register +#define VREG(r,n) r [v_##n] + +#define WRITE_SAMPLES( l, r, out ) \ +{\ + out [0] = l;\ + out [1] = r;\ + out += 2;\ + if ( out >= m.out_end )\ + {\ + check( out == m.out_end );\ + check( m.out_end != &m.extra [extra_size] || \ + (m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\ + out = m.extra;\ + m.out_end = &m.extra [extra_size];\ + }\ +}\ + +void SPC_DSP::set_output( sample_t* out, int size ) +{ + require( (size & 1) == 0 ); // must be even + if ( !out ) + { + out = m.extra; + size = extra_size; + } + m.out_begin = out; + m.out = out; + m.out_end = out + size; +} + +// Volume registers and efb are signed! Easy to forget int8_t cast. +// Prefixes are to avoid accidental use of locals with same names. + +// Gaussian interpolation + +static short const gauss [512] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, + 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, + 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, + 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, 25, 26, 27, 27, + 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 36, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 58, 59, 60, 61, 62, 64, 65, 66, 67, 69, 70, 71, 73, 74, 76, 77, + 78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 94, 95, 97, 99, 100, 102, + 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132, + 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168, + 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210, + 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257, + 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311, + 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370, + 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434, + 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504, + 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577, + 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654, + 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732, + 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811, + 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889, + 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965, + 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036, +1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102, +1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160, +1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210, +1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251, +1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280, +1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298, +1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305, +}; + +inline int SPC_DSP::interpolate( voice_t const* v ) +{ + // Make pointers into gaussian based on fractional position between samples + int offset = v->interp_pos >> 4 & 0xFF; + short const* fwd = gauss + 255 - offset; + short const* rev = gauss + offset; // mirror left half of gaussian + + int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; + int out; + out = (fwd [ 0] * in [0]) >> 11; + out += (fwd [256] * in [1]) >> 11; + out += (rev [256] * in [2]) >> 11; + out = (int16_t) out; + out += (rev [ 0] * in [3]) >> 11; + + CLAMP16( out ); + out &= ~1; + return out; +} + + +//// Counters + +int const simple_counter_range = 2048 * 5 * 3; // 30720 + +static unsigned const counter_rates [32] = +{ + simple_counter_range + 1, // never fires + 2048, 1536, + 1280, 1024, 768, + 640, 512, 384, + 320, 256, 192, + 160, 128, 96, + 80, 64, 48, + 40, 32, 24, + 20, 16, 12, + 10, 8, 6, + 5, 4, 3, + 2, + 1 +}; + +static unsigned const counter_offsets [32] = +{ + 1, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 0, + 0 +}; + +inline void SPC_DSP::init_counter() +{ + m.counter = 0; +} + +inline void SPC_DSP::run_counters() +{ + if ( --m.counter < 0 ) + m.counter = simple_counter_range - 1; +} + +inline unsigned SPC_DSP::read_counter( int rate ) +{ + return ((unsigned) m.counter + counter_offsets [rate]) % counter_rates [rate]; +} + + +//// Envelope + +inline void SPC_DSP::run_envelope( voice_t* const v ) +{ + int env = v->env; + if ( v->env_mode == env_release ) // 60% + { + if ( (env -= 0x8) < 0 ) + env = 0; + v->env = env; + } + else + { + int rate; + int env_data = VREG(v->regs,adsr1); + if ( m.t_adsr0 & 0x80 ) // 99% ADSR + { + if ( v->env_mode >= env_decay ) // 99% + { + env--; + env -= env >> 8; + rate = env_data & 0x1F; + if ( v->env_mode == env_decay ) // 1% + rate = (m.t_adsr0 >> 3 & 0x0E) + 0x10; + } + else // env_attack + { + rate = (m.t_adsr0 & 0x0F) * 2 + 1; + env += rate < 31 ? 0x20 : 0x400; + } + } + else // GAIN + { + int mode; + env_data = VREG(v->regs,gain); + mode = env_data >> 5; + if ( mode < 4 ) // direct + { + env = env_data * 0x10; + rate = 31; + } + else + { + rate = env_data & 0x1F; + if ( mode == 4 ) // 4: linear decrease + { + env -= 0x20; + } + else if ( mode < 6 ) // 5: exponential decrease + { + env--; + env -= env >> 8; + } + else // 6,7: linear increase + { + env += 0x20; + if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 ) + env += 0x8 - 0x20; // 7: two-slope linear increase + } + } + } + + // Sustain level + if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay ) + v->env_mode = env_sustain; + + v->hidden_env = env; + + // unsigned cast because linear decrease going negative also triggers this + if ( (unsigned) env > 0x7FF ) + { + env = (env < 0 ? 0 : 0x7FF); + if ( v->env_mode == env_attack ) + v->env_mode = env_decay; + } + + if ( !read_counter( rate ) ) + v->env = env; // nothing else is controlled by the counter + } +} + + +//// BRR Decoding + +inline void SPC_DSP::decode_brr( voice_t* v ) +{ + // Arrange the four input nybbles in 0xABCD order for easy decoding + int nybbles = m.t_brr_byte * 0x100 + m.ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF]; + + int const header = m.t_brr_header; + + // Write to next four samples in circular buffer + int* pos = &v->buf [v->buf_pos]; + int* end; + if ( (v->buf_pos += 4) >= brr_buf_size ) + v->buf_pos = 0; + + // Decode four samples + for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 ) + { + // Extract nybble and sign-extend + int s = (int16_t) nybbles >> 12; + + // Shift sample based on header + int const shift = header >> 4; + s = (s << shift) >> 1; + if ( shift >= 0xD ) // handle invalid range + s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0) + + // Apply IIR filter (8 is the most commonly used) + int const filter = header & 0x0C; + int const p1 = pos [brr_buf_size - 1]; + int const p2 = pos [brr_buf_size - 2] >> 1; + if ( filter >= 8 ) + { + s += p1; + s -= p2; + if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875 + { + s += p2 >> 4; + s += (p1 * -3) >> 6; + } + else // s += p1 * 0.8984375 - p2 * 0.40625 + { + s += (p1 * -13) >> 7; + s += (p2 * 3) >> 4; + } + } + else if ( filter ) // s += p1 * 0.46875 + { + s += p1 >> 1; + s += (-p1) >> 5; + } + + // Adjust and write sample + CLAMP16( s ); + s = (int16_t) (s * 2); + pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around + } +} + + +//// Misc + +#define MISC_CLOCK( n ) inline void SPC_DSP::misc_##n() + +MISC_CLOCK( 27 ) +{ + m.t_pmon = REG(pmon) & 0xFE; // voice 0 doesn't support PMON +} +MISC_CLOCK( 28 ) +{ + m.t_non = REG(non); + m.t_eon = REG(eon); + m.t_dir = REG(dir); +} +MISC_CLOCK( 29 ) +{ + if ( (m.every_other_sample ^= 1) != 0 ) + m.new_kon &= ~m.kon; // clears KON 63 clocks after it was last read +} +MISC_CLOCK( 30 ) +{ + if ( m.every_other_sample ) + { + m.kon = m.new_kon; + m.t_koff = REG(koff) | m.mute_mask; + } + + run_counters(); + + // Noise + if ( !read_counter( REG(flg) & 0x1F ) ) + { + int feedback = (m.noise << 13) ^ (m.noise << 14); + m.noise = (feedback & 0x4000) ^ (m.noise >> 1); + } +} + + +//// Voices + +#define VOICE_CLOCK( n ) void SPC_DSP::voice_##n( voice_t* const v ) + +inline VOICE_CLOCK( V1 ) +{ + m.t_dir_addr = m.t_dir * 0x100 + m.t_srcn * 4; + m.t_srcn = VREG(v->regs,srcn); +} +inline VOICE_CLOCK( V2 ) +{ + // Read sample pointer (ignored if not needed) + uint8_t const* entry = &m.ram [m.t_dir_addr]; + if ( !v->kon_delay ) + entry += 2; + m.t_brr_next_addr = GET_LE16A( entry ); + + m.t_adsr0 = VREG(v->regs,adsr0); + + // Read pitch, spread over two clocks + m.t_pitch = VREG(v->regs,pitchl); +} +inline VOICE_CLOCK( V3a ) +{ + m.t_pitch += (VREG(v->regs,pitchh) & 0x3F) << 8; +} +inline VOICE_CLOCK( V3b ) +{ + // Read BRR header and byte + m.t_brr_byte = m.ram [(v->brr_addr + v->brr_offset) & 0xFFFF]; + m.t_brr_header = m.ram [v->brr_addr]; // brr_addr doesn't need masking +} +VOICE_CLOCK( V3c ) +{ + // Pitch modulation using previous voice's output + if ( m.t_pmon & v->vbit ) + m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10; + + if ( v->kon_delay ) + { + // Get ready to start BRR decoding on next sample + if ( v->kon_delay == 5 ) + { + v->brr_addr = m.t_brr_next_addr; + v->brr_offset = 1; + v->buf_pos = 0; + m.t_brr_header = 0; // header is ignored on this sample + m.kon_check = true; + + if (take_spc_snapshot) + { + take_spc_snapshot = 0; + if (spc_snapshot_callback) + spc_snapshot_callback(); + } + } + + // Envelope is never run during KON + v->env = 0; + v->hidden_env = 0; + + // Disable BRR decoding until last three samples + v->interp_pos = 0; + if ( --v->kon_delay & 3 ) + v->interp_pos = 0x4000; + + // Pitch is never added during KON + m.t_pitch = 0; + } + + // Gaussian interpolation + { + int output = interpolate( v ); + + // Noise + if ( m.t_non & v->vbit ) + output = (int16_t) (m.noise * 2); + + // Apply envelope + m.t_output = (output * v->env) >> 11 & ~1; + v->t_envx_out = (uint8_t) (v->env >> 4); + } + + // Immediate silence due to end of sample or soft reset + if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 ) + { + v->env_mode = env_release; + v->env = 0; + } + + if ( m.every_other_sample ) + { + // KOFF + if ( m.t_koff & v->vbit ) + v->env_mode = env_release; + + // KON + if ( m.kon & v->vbit ) + { + v->kon_delay = 5; + v->env_mode = env_attack; + } + } + + // Run envelope for next sample + if ( !v->kon_delay ) + run_envelope( v ); +} + +inline void SPC_DSP::voice_output( voice_t const* v, int ch ) +{ + // Apply left/right volume + int amp = (m.t_output * (int8_t) VREG(v->regs,voll + ch)) >> 7; + amp *= ((stereo_switch & (1 << (v->voice_number + ch * voice_count))) ? 1 : 0); + + // Add to output total + m.t_main_out [ch] += amp; + CLAMP16( m.t_main_out [ch] ); + + // Optionally add to echo total + if ( m.t_eon & v->vbit ) + { + m.t_echo_out [ch] += amp; + CLAMP16( m.t_echo_out [ch] ); + } +} +VOICE_CLOCK( V4 ) +{ + // Decode BRR + m.t_looped = 0; + if ( v->interp_pos >= 0x4000 ) + { + decode_brr( v ); + + if ( (v->brr_offset += 2) >= brr_block_size ) + { + // Start decoding next BRR block + assert( v->brr_offset == brr_block_size ); + v->brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF; + if ( m.t_brr_header & 1 ) + { + v->brr_addr = m.t_brr_next_addr; + m.t_looped = v->vbit; + } + v->brr_offset = 1; + } + } + + // Apply pitch + v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch; + + // Keep from getting too far ahead (when using pitch modulation) + if ( v->interp_pos > 0x7FFF ) + v->interp_pos = 0x7FFF; + + // Output left + voice_output( v, 0 ); +} +inline VOICE_CLOCK( V5 ) +{ + // Output right + voice_output( v, 1 ); + + // ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier + int endx_buf = REG(endx) | m.t_looped; + + // Clear bit in ENDX if KON just began + if ( v->kon_delay == 5 ) + endx_buf &= ~v->vbit; + m.endx_buf = (uint8_t) endx_buf; +} +inline VOICE_CLOCK( V6 ) +{ + (void) v; // avoid compiler warning about unused v + m.outx_buf = (uint8_t) (m.t_output >> 8); +} +inline VOICE_CLOCK( V7 ) +{ + // Update ENDX + REG(endx) = m.endx_buf; + + m.envx_buf = v->t_envx_out; +} +inline VOICE_CLOCK( V8 ) +{ + // Update OUTX + VREG(v->regs,outx) = m.outx_buf; +} +inline VOICE_CLOCK( V9 ) +{ + // Update ENVX + VREG(v->regs,envx) = m.envx_buf; +} + +// Most voices do all these in one clock, so make a handy composite +inline VOICE_CLOCK( V3 ) +{ + voice_V3a( v ); + voice_V3b( v ); + voice_V3c( v ); +} + +// Common combinations of voice steps on different voices. This greatly reduces +// code size and allows everything to be inlined in these functions. +VOICE_CLOCK(V7_V4_V1) { voice_V7(v); voice_V1(v+3); voice_V4(v+1); } +VOICE_CLOCK(V8_V5_V2) { voice_V8(v); voice_V5(v+1); voice_V2(v+2); } +VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); } + + +//// Echo + +// Current echo buffer pointer for left/right channel +#define ECHO_PTR( ch ) (&m.ram [m.t_echo_ptr + ch * 2]) + +// Sample in echo history buffer, where 0 is the oldest +#define ECHO_FIR( i ) (m.echo_hist_pos [i]) + +// Calculate FIR point for left/right channel +#define CALC_FIR( i, ch ) ((ECHO_FIR( i + 1 ) [ch] * (int8_t) REG(fir + i * 0x10)) >> 6) + +#define ECHO_CLOCK( n ) inline void SPC_DSP::echo_##n() + +inline void SPC_DSP::echo_read( int ch ) +{ + int s; + if ( m.t_echo_ptr >= 0xffc0 && rom_enabled ) + s = GET_LE16SA( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0] ); + else + s = GET_LE16SA( ECHO_PTR( ch ) ); + // second copy simplifies wrap-around handling + ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1; +} + +ECHO_CLOCK( 22 ) +{ + // History + if ( ++m.echo_hist_pos >= &m.echo_hist [echo_hist_size] ) + m.echo_hist_pos = m.echo_hist; + + m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF; + echo_read( 0 ); + + // FIR (using l and r temporaries below helps compiler optimize) + int l = CALC_FIR( 0, 0 ); + int r = CALC_FIR( 0, 1 ); + + m.t_echo_in [0] = l; + m.t_echo_in [1] = r; +} +ECHO_CLOCK( 23 ) +{ + int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 ); + int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 ); + + m.t_echo_in [0] += l; + m.t_echo_in [1] += r; + + echo_read( 1 ); +} +ECHO_CLOCK( 24 ) +{ + int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 ); + int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 ); + + m.t_echo_in [0] += l; + m.t_echo_in [1] += r; +} +ECHO_CLOCK( 25 ) +{ + int l = m.t_echo_in [0] + CALC_FIR( 6, 0 ); + int r = m.t_echo_in [1] + CALC_FIR( 6, 1 ); + + l = (int16_t) l; + r = (int16_t) r; + + l += (int16_t) CALC_FIR( 7, 0 ); + r += (int16_t) CALC_FIR( 7, 1 ); + + CLAMP16( l ); + CLAMP16( r ); + + m.t_echo_in [0] = l & ~1; + m.t_echo_in [1] = r & ~1; +} +inline int SPC_DSP::echo_output( int ch ) +{ + int out = (int16_t) ((m.t_main_out [ch] * (int8_t) REG(mvoll + ch * 0x10)) >> 7) + + (int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7); + CLAMP16( out ); + return out; +} +ECHO_CLOCK( 26 ) +{ + // Left output volumes + // (save sample for next clock so we can output both together) + m.t_main_out [0] = echo_output( 0 ); + + // Echo feedback + int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7); + int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7); + + CLAMP16( l ); + CLAMP16( r ); + + m.t_echo_out [0] = l & ~1; + m.t_echo_out [1] = r & ~1; +} +ECHO_CLOCK( 27 ) +{ + // Output + int l = m.t_main_out [0]; + int r = echo_output( 1 ); + m.t_main_out [0] = 0; + m.t_main_out [1] = 0; + + // TODO: global muting isn't this simple (turns DAC on and off + // or something, causing small ~37-sample pulse when first muted) + if ( REG(flg) & 0x40 ) + { + l = 0; + r = 0; + } + + // Output sample to DAC + #ifdef SPC_DSP_OUT_HOOK + SPC_DSP_OUT_HOOK( l, r ); + #else + sample_t* out = m.out; + WRITE_SAMPLES( l, r, out ); + m.out = out; + #endif +} +ECHO_CLOCK( 28 ) +{ + m.t_echo_enabled = REG(flg); +} +inline void SPC_DSP::echo_write( int ch ) +{ + if ( !(m.t_echo_enabled & 0x20) ) + { + if ( m.t_echo_ptr >= 0xffc0 && rom_enabled ) + SET_LE16A( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0], m.t_echo_out [ch] ); + else + SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] ); + } + + m.t_echo_out [ch] = 0; +} +ECHO_CLOCK( 29 ) +{ + m.t_esa = REG(esa); + + if ( !m.echo_offset ) + m.echo_length = (REG(edl) & 0x0F) * 0x800; + + m.echo_offset += 4; + if ( m.echo_offset >= m.echo_length ) + m.echo_offset = 0; + + // Write left echo + echo_write( 0 ); + + m.t_echo_enabled = REG(flg); +} +ECHO_CLOCK( 30 ) +{ + // Write right echo + echo_write( 1 ); +} + + +//// Timing + +// Execute clock for a particular voice +#define V( clock, voice ) voice_##clock( &m.voices [voice] ); + +/* The most common sequence of clocks uses composite operations +for efficiency. For example, the following are equivalent to the +individual steps on the right: + +V(V7_V4_V1,2) -> V(V7,2) V(V4,3) V(V1,5) +V(V8_V5_V2,2) -> V(V8,2) V(V5,3) V(V2,4) +V(V9_V6_V3,2) -> V(V9,2) V(V6,3) V(V3,4) */ + +// Voice 0 1 2 3 4 5 6 7 +#define GEN_DSP_TIMING \ +PHASE( 0) V(V5,0)V(V2,1)\ +PHASE( 1) V(V6,0)V(V3,1)\ +PHASE( 2) V(V7_V4_V1,0)\ +PHASE( 3) V(V8_V5_V2,0)\ +PHASE( 4) V(V9_V6_V3,0)\ +PHASE( 5) V(V7_V4_V1,1)\ +PHASE( 6) V(V8_V5_V2,1)\ +PHASE( 7) V(V9_V6_V3,1)\ +PHASE( 8) V(V7_V4_V1,2)\ +PHASE( 9) V(V8_V5_V2,2)\ +PHASE(10) V(V9_V6_V3,2)\ +PHASE(11) V(V7_V4_V1,3)\ +PHASE(12) V(V8_V5_V2,3)\ +PHASE(13) V(V9_V6_V3,3)\ +PHASE(14) V(V7_V4_V1,4)\ +PHASE(15) V(V8_V5_V2,4)\ +PHASE(16) V(V9_V6_V3,4)\ +PHASE(17) V(V1,0) V(V7,5)V(V4,6)\ +PHASE(18) V(V8_V5_V2,5)\ +PHASE(19) V(V9_V6_V3,5)\ +PHASE(20) V(V1,1) V(V7,6)V(V4,7)\ +PHASE(21) V(V8,6)V(V5,7) V(V2,0) /* t_brr_next_addr order dependency */\ +PHASE(22) V(V3a,0) V(V9,6)V(V6,7) echo_22();\ +PHASE(23) V(V7,7) echo_23();\ +PHASE(24) V(V8,7) echo_24();\ +PHASE(25) V(V3b,0) V(V9,7) echo_25();\ +PHASE(26) echo_26();\ +PHASE(27) misc_27(); echo_27();\ +PHASE(28) misc_28(); echo_28();\ +PHASE(29) misc_29(); echo_29();\ +PHASE(30) misc_30();V(V3c,0) echo_30();\ +PHASE(31) V(V4,0) V(V1,2)\ + +#if !SPC_DSP_CUSTOM_RUN + +void SPC_DSP::run( int clocks_remain ) +{ + require( clocks_remain > 0 ); + + int const phase = m.phase; + m.phase = (phase + clocks_remain) & 31; + switch ( phase ) + { + loop: + + #define PHASE( n ) if ( n && !--clocks_remain ) break; case n: + GEN_DSP_TIMING + #undef PHASE + + if ( --clocks_remain ) + goto loop; + } +} + +#endif + + +//// Setup + +void SPC_DSP::init( void* ram_64k ) +{ + m.ram = (uint8_t*) ram_64k; + mute_voices( 0 ); + disable_surround( false ); + set_output( 0, 0 ); + reset(); + + stereo_switch = 0xffff; + take_spc_snapshot = 0; + spc_snapshot_callback = 0; + + #ifndef NDEBUG + // be sure this sign-extends + assert( (int16_t) 0x8000 == -0x8000 ); + + // be sure right shift preserves sign + assert( (-1 >> 1) == -1 ); + + // check clamp macro + int i; + i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF ); + i = -0x8001; CLAMP16( i ); assert( i == -0x8000 ); + + blargg_verify_byte_order(); + #endif +} + +void SPC_DSP::soft_reset_common() +{ + require( m.ram ); // init() must have been called already + + m.noise = 0x4000; + m.echo_hist_pos = m.echo_hist; + m.every_other_sample = 1; + m.echo_offset = 0; + m.phase = 0; + + init_counter(); + + for (int i = 0; i < voice_count; i++) + m.voices[i].voice_number = i; +} + +void SPC_DSP::soft_reset() +{ + REG(flg) = 0xE0; + soft_reset_common(); +} + +void SPC_DSP::load( uint8_t const regs [register_count] ) +{ + memcpy( m.regs, regs, sizeof m.regs ); + memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count ); + + // Internal state + for ( int i = voice_count; --i >= 0; ) + { + voice_t* v = &m.voices [i]; + v->brr_offset = 1; + v->vbit = 1 << i; + v->regs = &m.regs [i * 0x10]; + } + m.new_kon = REG(kon); + m.t_dir = REG(dir); + m.t_esa = REG(esa); + + soft_reset_common(); +} + +void SPC_DSP::reset() { load( initial_regs ); } + + +//// State save/load + +#if !SPC_NO_COPY_STATE_FUNCS + +void SPC_State_Copier::copy( void* state, size_t size ) +{ + func( buf, state, size ); +} + +int SPC_State_Copier::copy_int( int state, int size ) +{ + BOOST::uint8_t s [2]; + SET_LE16( s, state ); + func( buf, &s, size ); + return GET_LE16( s ); +} + +void SPC_State_Copier::skip( int count ) +{ + if ( count > 0 ) + { + char temp [64]; + memset( temp, 0, sizeof temp ); + do + { + int n = sizeof temp; + if ( n > count ) + n = count; + count -= n; + func( buf, temp, n ); + } + while ( count ); + } +} + +void SPC_State_Copier::extra() +{ + int n = 0; + SPC_State_Copier& copier = *this; + SPC_COPY( uint8_t, n ); + skip( n ); +} + +void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) +{ + SPC_State_Copier copier( io, copy ); + + // DSP registers + copier.copy( m.regs, register_count ); + + // Internal state + + // Voices + int i; + for ( i = 0; i < voice_count; i++ ) + { + voice_t* v = &m.voices [i]; + + // BRR buffer + int i; + for ( i = 0; i < brr_buf_size; i++ ) + { + int s = v->buf [i]; + SPC_COPY( int16_t, s ); + v->buf [i] = v->buf [i + brr_buf_size] = s; + } + + SPC_COPY( uint16_t, v->interp_pos ); + SPC_COPY( uint16_t, v->brr_addr ); + SPC_COPY( uint16_t, v->env ); + SPC_COPY( int16_t, v->hidden_env ); + SPC_COPY( uint8_t, v->buf_pos ); + SPC_COPY( uint8_t, v->brr_offset ); + SPC_COPY( uint8_t, v->kon_delay ); + { + int m = v->env_mode; + SPC_COPY( uint8_t, m ); + v->env_mode = (enum env_mode_t) m; + } + SPC_COPY( uint8_t, v->t_envx_out ); + + copier.extra(); + } + + // Echo history + for ( i = 0; i < echo_hist_size; i++ ) + { + int j; + for ( j = 0; j < 2; j++ ) + { + int s = m.echo_hist_pos [i] [j]; + SPC_COPY( int16_t, s ); + m.echo_hist [i] [j] = s; // write back at offset 0 + } + } + m.echo_hist_pos = m.echo_hist; + memcpy( &m.echo_hist [echo_hist_size], m.echo_hist, echo_hist_size * sizeof m.echo_hist [0] ); + + // Misc + SPC_COPY( uint8_t, m.every_other_sample ); + SPC_COPY( uint8_t, m.kon ); + + SPC_COPY( uint16_t, m.noise ); + SPC_COPY( uint16_t, m.counter ); + SPC_COPY( uint16_t, m.echo_offset ); + SPC_COPY( uint16_t, m.echo_length ); + SPC_COPY( uint8_t, m.phase ); + + SPC_COPY( uint8_t, m.new_kon ); + SPC_COPY( uint8_t, m.endx_buf ); + SPC_COPY( uint8_t, m.envx_buf ); + SPC_COPY( uint8_t, m.outx_buf ); + + SPC_COPY( uint8_t, m.t_pmon ); + SPC_COPY( uint8_t, m.t_non ); + SPC_COPY( uint8_t, m.t_eon ); + SPC_COPY( uint8_t, m.t_dir ); + SPC_COPY( uint8_t, m.t_koff ); + + SPC_COPY( uint16_t, m.t_brr_next_addr ); + SPC_COPY( uint8_t, m.t_adsr0 ); + SPC_COPY( uint8_t, m.t_brr_header ); + SPC_COPY( uint8_t, m.t_brr_byte ); + SPC_COPY( uint8_t, m.t_srcn ); + SPC_COPY( uint8_t, m.t_esa ); + SPC_COPY( uint8_t, m.t_echo_enabled ); + + SPC_COPY( int16_t, m.t_main_out [0] ); + SPC_COPY( int16_t, m.t_main_out [1] ); + SPC_COPY( int16_t, m.t_echo_out [0] ); + SPC_COPY( int16_t, m.t_echo_out [1] ); + SPC_COPY( int16_t, m.t_echo_in [0] ); + SPC_COPY( int16_t, m.t_echo_in [1] ); + + SPC_COPY( uint16_t, m.t_dir_addr ); + SPC_COPY( uint16_t, m.t_pitch ); + SPC_COPY( int16_t, m.t_output ); + SPC_COPY( uint16_t, m.t_echo_ptr ); + SPC_COPY( uint8_t, m.t_looped ); + + copier.extra(); +} +#endif + + +//// Snes9x Accessor + +void SPC_DSP::set_spc_snapshot_callback( void (*callback) (void) ) +{ + spc_snapshot_callback = callback; +} + +void SPC_DSP::dump_spc_snapshot( void ) +{ + take_spc_snapshot = 1; +} + +void SPC_DSP::set_stereo_switch( int value ) +{ + stereo_switch = value; +} + +SPC_DSP::uint8_t SPC_DSP::reg_value( int ch, int addr ) +{ + return m.voices[ch].regs[addr]; +} + +int SPC_DSP::envx_value( int ch ) +{ + return m.voices[ch].env; +} diff --git a/plugins/snes9x_gx/source/snes9x/apu/SPC_DSP.h b/plugins/snes9x_gx/source/snes9x/apu/SPC_DSP.h new file mode 100644 index 00000000..61d05ab5 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/SPC_DSP.h @@ -0,0 +1,319 @@ +// Highly accurate SNES SPC-700 DSP emulator + +// snes_spc 0.9.0 +#ifndef SPC_DSP_H +#define SPC_DSP_H + +#include "blargg_common.h" + +extern "C" { typedef void (*dsp_copy_func_t)( unsigned char** io, void* state, size_t ); } + +class SPC_DSP { +public: + typedef BOOST::uint8_t uint8_t; + +// Setup + + // Initializes DSP and has it use the 64K RAM provided + void init( void* ram_64k ); + + // Sets destination for output samples. If out is NULL or out_size is 0, + // doesn't generate any. + typedef short sample_t; + void set_output( sample_t* out, int out_size ); + + // Number of samples written to output since it was last set, always + // a multiple of 2. Undefined if more samples were generated than + // output buffer could hold. + int sample_count() const; + +// Emulation + + // Resets DSP to power-on state + void reset(); + + // Emulates pressing reset switch on SNES + void soft_reset(); + + // Reads/writes DSP registers. For accuracy, you must first call run() + // to catch the DSP up to present. + int read ( int addr ) const; + void write( int addr, int data ); + + // Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks + // a pair of samples is be generated. + void run( int clock_count ); + +// Sound control + + // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). + // Reduces emulation accuracy. + enum { voice_count = 8 }; + void mute_voices( int mask ); + +// State + + // Resets DSP and uses supplied values to initialize registers + enum { register_count = 128 }; + void load( uint8_t const regs [register_count] ); + + // Saves/loads exact emulator state + enum { state_size = 640 }; // maximum space needed when saving + typedef dsp_copy_func_t copy_func_t; + void copy_state( unsigned char** io, copy_func_t ); + + // Returns non-zero if new key-on events occurred since last call + bool check_kon(); + +// Snes9x Accessor + + int stereo_switch; + int take_spc_snapshot; + int rom_enabled; // mirror + uint8_t *rom, *hi_ram; // mirror + void (*spc_snapshot_callback) (void); + + void set_spc_snapshot_callback( void (*callback) (void) ); + void dump_spc_snapshot( void ); + void set_stereo_switch( int ); + uint8_t reg_value( int, int ); + int envx_value( int ); + +// DSP register addresses + + // Global registers + enum { + r_mvoll = 0x0C, r_mvolr = 0x1C, + r_evoll = 0x2C, r_evolr = 0x3C, + r_kon = 0x4C, r_koff = 0x5C, + r_flg = 0x6C, r_endx = 0x7C, + r_efb = 0x0D, r_pmon = 0x2D, + r_non = 0x3D, r_eon = 0x4D, + r_dir = 0x5D, r_esa = 0x6D, + r_edl = 0x7D, + r_fir = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F + }; + + // Voice registers + enum { + v_voll = 0x00, v_volr = 0x01, + v_pitchl = 0x02, v_pitchh = 0x03, + v_srcn = 0x04, v_adsr0 = 0x05, + v_adsr1 = 0x06, v_gain = 0x07, + v_envx = 0x08, v_outx = 0x09 + }; + +public: + enum { extra_size = 16 }; + sample_t* extra() { return m.extra; } + sample_t const* out_pos() const { return m.out; } + void disable_surround( bool ) { } // not supported +public: + BLARGG_DISABLE_NOTHROW + + typedef BOOST::int8_t int8_t; + typedef BOOST::int16_t int16_t; + + enum { echo_hist_size = 8 }; + + enum env_mode_t { env_release, env_attack, env_decay, env_sustain }; + enum { brr_buf_size = 12 }; + struct voice_t + { + int buf [brr_buf_size*2];// decoded samples (twice the size to simplify wrap handling) + int buf_pos; // place in buffer where next samples will be decoded + int interp_pos; // relative fractional position in sample (0x1000 = 1.0) + int brr_addr; // address of current BRR block + int brr_offset; // current decoding offset in BRR block + uint8_t* regs; // pointer to voice's DSP registers + int vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc. + int kon_delay; // KON delay/current setup phase + env_mode_t env_mode; + int env; // current envelope level + int hidden_env; // used by GAIN mode 7, very obscure quirk + uint8_t t_envx_out; + int voice_number; + }; +private: + enum { brr_block_size = 9 }; + + struct state_t + { + uint8_t regs [register_count]; + + // Echo history keeps most recent 8 samples (twice the size to simplify wrap handling) + int echo_hist [echo_hist_size * 2] [2]; + int (*echo_hist_pos) [2]; // &echo_hist [0 to 7] + + int every_other_sample; // toggles every sample + int kon; // KON value when last checked + int noise; + int counter; + int echo_offset; // offset from ESA in echo buffer + int echo_length; // number of bytes that echo_offset will stop at + int phase; // next clock cycle to run (0-31) + bool kon_check; // set when a new KON occurs + + // Hidden registers also written to when main register is written to + int new_kon; + uint8_t endx_buf; + uint8_t envx_buf; + uint8_t outx_buf; + + // Temporary state between clocks + + // read once per sample + int t_pmon; + int t_non; + int t_eon; + int t_dir; + int t_koff; + + // read a few clocks ahead then used + int t_brr_next_addr; + int t_adsr0; + int t_brr_header; + int t_brr_byte; + int t_srcn; + int t_esa; + int t_echo_enabled; + + // internal state that is recalculated every sample + int t_dir_addr; + int t_pitch; + int t_output; + int t_looped; + int t_echo_ptr; + + // left/right sums + int t_main_out [2]; + int t_echo_out [2]; + int t_echo_in [2]; + + voice_t voices [voice_count]; + + // non-emulation state + uint8_t* ram; // 64K shared RAM between DSP and SMP + int mute_mask; + sample_t* out; + sample_t* out_end; + sample_t* out_begin; + sample_t extra [extra_size]; + }; + state_t m; + + void init_counter(); + void run_counters(); + unsigned read_counter( int rate ); + + int interpolate( voice_t const* v ); + void run_envelope( voice_t* const v ); + void decode_brr( voice_t* v ); + + void misc_27(); + void misc_28(); + void misc_29(); + void misc_30(); + + void voice_output( voice_t const* v, int ch ); + void voice_V1( voice_t* const ); + void voice_V2( voice_t* const ); + void voice_V3( voice_t* const ); + void voice_V3a( voice_t* const ); + void voice_V3b( voice_t* const ); + void voice_V3c( voice_t* const ); + void voice_V4( voice_t* const ); + void voice_V5( voice_t* const ); + void voice_V6( voice_t* const ); + void voice_V7( voice_t* const ); + void voice_V8( voice_t* const ); + void voice_V9( voice_t* const ); + void voice_V7_V4_V1( voice_t* const ); + void voice_V8_V5_V2( voice_t* const ); + void voice_V9_V6_V3( voice_t* const ); + + void echo_read( int ch ); + int echo_output( int ch ); + void echo_write( int ch ); + void echo_22(); + void echo_23(); + void echo_24(); + void echo_25(); + void echo_26(); + void echo_27(); + void echo_28(); + void echo_29(); + void echo_30(); + + void soft_reset_common(); +}; + +#include <assert.h> + +inline int SPC_DSP::sample_count() const { return m.out - m.out_begin; } + +inline int SPC_DSP::read( int addr ) const +{ + assert( (unsigned) addr < register_count ); + return m.regs [addr]; +} + +inline void SPC_DSP::write( int addr, int data ) +{ + assert( (unsigned) addr < register_count ); + + m.regs [addr] = (uint8_t) data; + switch ( addr & 0x0F ) + { + case v_envx: + m.envx_buf = (uint8_t) data; + break; + + case v_outx: + m.outx_buf = (uint8_t) data; + break; + + case 0x0C: + if ( addr == r_kon ) + m.new_kon = (uint8_t) data; + + if ( addr == r_endx ) // always cleared, regardless of data written + { + m.endx_buf = 0; + m.regs [r_endx] = 0; + } + break; + } +} + +inline void SPC_DSP::mute_voices( int mask ) { m.mute_mask = mask; } + +inline bool SPC_DSP::check_kon() +{ + bool old = m.kon_check; + m.kon_check = 0; + return old; +} + +#if !SPC_NO_COPY_STATE_FUNCS + +class SPC_State_Copier { + SPC_DSP::copy_func_t func; + unsigned char** buf; +public: + SPC_State_Copier( unsigned char** p, SPC_DSP::copy_func_t f ) { func = f; buf = p; } + void copy( void* state, size_t size ); + int copy_int( int state, int size ); + void skip( int count ); + void extra(); +}; + +#define SPC_COPY( type, state )\ +{\ + state = (BOOST::type) copier.copy_int( state, sizeof (BOOST::type) );\ + assert( (BOOST::type) state == state );\ +} + +#endif + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/apu/SPC_Filter.cpp b/plugins/snes9x_gx/source/snes9x/apu/SPC_Filter.cpp new file mode 100644 index 00000000..b3d57708 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/SPC_Filter.cpp @@ -0,0 +1,68 @@ +// snes_spc 0.9.0. http://www.slack.net/~ant/ + +#include "SPC_Filter.h" + +#include <string.h> + +/* Copyright (C) 2007 Shay Green. This module 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 +module 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 module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "blargg_source.h" + +void SPC_Filter::clear() { memset( ch, 0, sizeof ch ); } + +SPC_Filter::SPC_Filter() +{ + gain = gain_unit; + bass = bass_norm; + clear(); +} + +void SPC_Filter::run( short* io, int count ) +{ + require( (count & 1) == 0 ); // must be even + + int const gain = this->gain; + int const bass = this->bass; + chan_t* c = &ch [2]; + do + { + // cache in registers + int sum = (--c)->sum; + int pp1 = c->pp1; + int p1 = c->p1; + + for ( int i = 0; i < count; i += 2 ) + { + // Low-pass filter (two point FIR with coeffs 0.25, 0.75) + int f = io [i] + p1; + p1 = io [i] * 3; + + // High-pass filter ("leaky integrator") + int delta = f - pp1; + pp1 = f; + int s = sum >> (gain_bits + 2); + sum += (delta * gain) - (sum >> bass); + + // Clamp to 16 bits + if ( (short) s != s ) + s = (s >> 31) ^ 0x7FFF; + + io [i] = (short) s; + } + + c->p1 = p1; + c->pp1 = pp1; + c->sum = sum; + ++io; + } + while ( c != ch ); +} diff --git a/plugins/snes9x_gx/source/snes9x/apu/SPC_Filter.h b/plugins/snes9x_gx/source/snes9x/apu/SPC_Filter.h new file mode 100644 index 00000000..d5c83cb8 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/SPC_Filter.h @@ -0,0 +1,47 @@ +// Simple low-pass and high-pass filter to better match sound output of a SNES + +// snes_spc 0.9.0 +#ifndef SPC_FILTER_H +#define SPC_FILTER_H + +#include "blargg_common.h" + +struct SPC_Filter { +public: + + // Filters count samples of stereo sound in place. Count must be a multiple of 2. + typedef short sample_t; + void run( sample_t* io, int count ); + +// Optional features + + // Clears filter to silence + void clear(); + + // Sets gain (volume), where gain_unit is normal. Gains greater than gain_unit + // are fine, since output is clamped to 16-bit sample range. + enum { gain_unit = 0x100 }; + void set_gain( int gain ); + + // Sets amount of bass (logarithmic scale) + enum { bass_none = 0 }; + enum { bass_norm = 8 }; // normal amount + enum { bass_max = 31 }; + void set_bass( int bass ); + +public: + SPC_Filter(); + BLARGG_DISABLE_NOTHROW +private: + enum { gain_bits = 8 }; + int gain; + int bass; + struct chan_t { int p1, pp1, sum; }; + chan_t ch [2]; +}; + +inline void SPC_Filter::set_gain( int g ) { gain = g; } + +inline void SPC_Filter::set_bass( int b ) { bass = b; } + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/apu/apu.cpp b/plugins/snes9x_gx/source/snes9x/apu/apu.cpp new file mode 100644 index 00000000..f0fd8f93 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/apu.cpp @@ -0,0 +1,661 @@ +/*********************************************************************************** + 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), + + (c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2011 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 - 2011 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2011 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2011 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. + ***********************************************************************************/ + + +#include <math.h> +#include "snes9x.h" +#include "apu.h" +#include "snapshot.h" +#include "display.h" +#include "linear_resampler.h" +#include "hermite_resampler.h" + +#define APU_DEFAULT_INPUT_RATE 32000 +#define APU_MINIMUM_SAMPLE_COUNT 512 +#define APU_MINIMUM_SAMPLE_BLOCK 128 +#define APU_NUMERATOR_NTSC 15664 +#define APU_DENOMINATOR_NTSC 328125 +#define APU_NUMERATOR_PAL 34176 +#define APU_DENOMINATOR_PAL 709379 +#define APU_DEFAULT_RESAMPLER HermiteResampler + +SNES_SPC *spc_core = NULL; + +static uint8 APUROM[64] = +{ + 0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0, + 0xFC, 0x8F, 0xAA, 0xF4, 0x8F, 0xBB, 0xF5, 0x78, + 0xCC, 0xF4, 0xD0, 0xFB, 0x2F, 0x19, 0xEB, 0xF4, + 0xD0, 0xFC, 0x7E, 0xF4, 0xD0, 0x0B, 0xE4, 0xF5, + 0xCB, 0xF4, 0xD7, 0x00, 0xFC, 0xD0, 0xF3, 0xAB, + 0x01, 0x10, 0xEF, 0x7E, 0xF4, 0x10, 0xEB, 0xBA, + 0xF6, 0xDA, 0x00, 0xBA, 0xF4, 0xC4, 0xF4, 0xDD, + 0x5D, 0xD0, 0xDB, 0x1F, 0x00, 0x00, 0xC0, 0xFF +}; + +namespace spc +{ + static apu_callback sa_callback = NULL; + static void *extra_data = NULL; + + static bool8 sound_in_sync = TRUE; + static bool8 sound_enabled = FALSE; + + static int buffer_size; + static int lag_master = 0; + static int lag = 0; + + static uint8 *landing_buffer = NULL; + static uint8 *shrink_buffer = NULL; + + static Resampler *resampler = NULL; + + static int32 reference_time; + static uint32 remainder; + + static const int timing_hack_numerator = SNES_SPC::tempo_unit; + static int timing_hack_denominator = SNES_SPC::tempo_unit; + /* Set these to NTSC for now. Will change to PAL in S9xAPUTimingSetSpeedup + if necessary on game load. */ + static uint32 ratio_numerator = APU_NUMERATOR_NTSC; + static uint32 ratio_denominator = APU_DENOMINATOR_NTSC; +} + +static void EightBitize (uint8 *, int); +static void DeStereo (uint8 *, int); +static void ReverseStereo (uint8 *, int); +void UpdatePlaybackRate (void); +static void from_apu_to_state (uint8 **, void *, size_t); +static void to_apu_from_state (uint8 **, void *, size_t); +static void SPCSnapshotCallback (void); +static inline int S9xAPUGetClock (int32); +static inline int S9xAPUGetClockRemainder (int32); + + +static void EightBitize (uint8 *buffer, int sample_count) +{ + uint8 *buf8 = (uint8 *) buffer; + int16 *buf16 = (int16 *) buffer; + + for (int i = 0; i < sample_count; i++) + buf8[i] = (uint8) ((buf16[i] / 256) + 128); +} + +static void DeStereo (uint8 *buffer, int sample_count) +{ + int16 *buf = (int16 *) buffer; + int32 s1, s2; + + for (int i = 0; i < sample_count >> 1; i++) + { + s1 = (int32) buf[2 * i]; + s2 = (int32) buf[2 * i + 1]; + buf[i] = (int16) ((s1 + s2) >> 1); + } +} + +static void ReverseStereo (uint8 *src_buffer, int sample_count) +{ + int16 *buffer = (int16 *) src_buffer; + + for (int i = 0; i < sample_count; i += 2) + { + buffer[i + 1] ^= buffer[i]; + buffer[i] ^= buffer[i + 1]; + buffer[i + 1] ^= buffer[i]; + } +} + +bool8 S9xMixSamples (uint8 *buffer, int sample_count) +{ + static int shrink_buffer_size = -1; + uint8 *dest; + + if (!Settings.SixteenBitSound || !Settings.Stereo) + { + /* We still need both stereo samples for generating the mono sample */ + if (!Settings.Stereo) + sample_count <<= 1; + + /* We still have to generate 16-bit samples for bit-dropping, too */ + if (shrink_buffer_size < (sample_count << 1)) + { + delete[] spc::shrink_buffer; + spc::shrink_buffer = new uint8[sample_count << 1]; + shrink_buffer_size = sample_count << 1; + } + + dest = spc::shrink_buffer; + } + else + dest = buffer; + + if (Settings.Mute) + { + memset(dest, 0, sample_count << 1); + spc::resampler->clear(); + + return (FALSE); + } + else + { + if (spc::resampler->avail() >= (sample_count + spc::lag)) + { + spc::resampler->read((short *) dest, sample_count); + if (spc::lag == spc::lag_master) + spc::lag = 0; + } + else + { + memset(buffer, (Settings.SixteenBitSound ? 0 : 128), (sample_count << (Settings.SixteenBitSound ? 1 : 0)) >> (Settings.Stereo ? 0 : 1)); + if (spc::lag == 0) + spc::lag = spc::lag_master; + + return (FALSE); + } + } + + if (Settings.ReverseStereo && Settings.Stereo) + ReverseStereo(dest, sample_count); + + if (!Settings.Stereo || !Settings.SixteenBitSound) + { + if (!Settings.Stereo) + { + DeStereo(dest, sample_count); + sample_count >>= 1; + } + + if (!Settings.SixteenBitSound) + EightBitize(dest, sample_count); + + memcpy(buffer, dest, (sample_count << (Settings.SixteenBitSound ? 1 : 0))); + } + + return (TRUE); +} + +int S9xGetSampleCount (void) +{ + return (spc::resampler->avail() >> (Settings.Stereo ? 0 : 1)); +} + +void S9xFinalizeSamples (void) +{ + if (!Settings.Mute) + { + if (!spc::resampler->push((short *) spc::landing_buffer, spc_core->sample_count())) + { + /* We weren't able to process the entire buffer. Potential overrun. */ + spc::sound_in_sync = FALSE; + + if (Settings.SoundSync && !Settings.TurboMode) + return; + } + } + + if (!Settings.SoundSync || Settings.TurboMode || Settings.Mute) + spc::sound_in_sync = TRUE; + else + if (spc::resampler->space_empty() >= spc::resampler->space_filled()) + spc::sound_in_sync = TRUE; + else + spc::sound_in_sync = FALSE; + + spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); +} + +void S9xLandSamples (void) +{ + if (spc::sa_callback != NULL) + spc::sa_callback(spc::extra_data); + else + S9xFinalizeSamples(); +} + +void S9xClearSamples (void) +{ + spc::resampler->clear(); + spc::lag = spc::lag_master; +} + +bool8 S9xSyncSound (void) +{ + if (!Settings.SoundSync || spc::sound_in_sync) + return (TRUE); + + S9xLandSamples(); + + return (spc::sound_in_sync); +} + +void S9xSetSamplesAvailableCallback (apu_callback callback, void *data) +{ + spc::sa_callback = callback; + spc::extra_data = data; +} + +void UpdatePlaybackRate (void) +{ + if (Settings.SoundInputRate == 0) + Settings.SoundInputRate = APU_DEFAULT_INPUT_RATE; + + double time_ratio = (double) Settings.SoundInputRate * spc::timing_hack_numerator / (Settings.SoundPlaybackRate * spc::timing_hack_denominator); + spc::resampler->time_ratio(time_ratio); +} + +bool8 S9xInitSound (int buffer_ms, int lag_ms) +{ + // buffer_ms : buffer size given in millisecond + // lag_ms : allowable time-lag given in millisecond + + int sample_count = buffer_ms * 32000 / 1000; + int lag_sample_count = lag_ms * 32000 / 1000; + + spc::lag_master = lag_sample_count; + if (Settings.Stereo) + spc::lag_master <<= 1; + spc::lag = spc::lag_master; + + if (sample_count < APU_MINIMUM_SAMPLE_COUNT) + sample_count = APU_MINIMUM_SAMPLE_COUNT; + + spc::buffer_size = sample_count; + if (Settings.Stereo) + spc::buffer_size <<= 1; + if (Settings.SixteenBitSound) + spc::buffer_size <<= 1; + + printf("Sound buffer size: %d (%d samples)\n", spc::buffer_size, sample_count); + + if (spc::landing_buffer) + delete[] spc::landing_buffer; + spc::landing_buffer = new uint8[spc::buffer_size * 2]; + if (!spc::landing_buffer) + return (FALSE); + + /* The resampler and spc unit use samples (16-bit short) as + arguments. Use 2x in the resampler for buffer leveling with SoundSync */ + if (!spc::resampler) + { + spc::resampler = new APU_DEFAULT_RESAMPLER(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); + if (!spc::resampler) + { + delete[] spc::landing_buffer; + return (FALSE); + } + } + else + spc::resampler->resize(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); + + spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + + UpdatePlaybackRate(); + + spc::sound_enabled = S9xOpenSoundDevice(); + + return (spc::sound_enabled); +} + +void S9xSetSoundControl (uint8 voice_switch) +{ + spc_core->dsp_set_stereo_switch(voice_switch << 8 | voice_switch); +} + +void S9xSetSoundMute (bool8 mute) +{ + Settings.Mute = mute; + if (!spc::sound_enabled) + Settings.Mute = TRUE; +} + +void S9xDumpSPCSnapshot (void) +{ + spc_core->dsp_dump_spc_snapshot(); +} + +static void SPCSnapshotCallback (void) +{ + S9xSPCDump(S9xGetFilenameInc((".spc"), SPC_DIR)); + printf("Dumped key-on triggered spc snapshot.\n"); +} + +bool8 S9xInitAPU (void) +{ + spc_core = new SNES_SPC; + if (!spc_core) + return (FALSE); + + spc_core->init(); + spc_core->init_rom(APUROM); + + spc_core->dsp_set_spc_snapshot_callback(SPCSnapshotCallback); + + spc::landing_buffer = NULL; + spc::shrink_buffer = NULL; + spc::resampler = NULL; + + return (TRUE); +} + +void S9xDeinitAPU (void) +{ + if (spc_core) + { + delete spc_core; + spc_core = NULL; + } + + if (spc::resampler) + { + delete spc::resampler; + spc::resampler = NULL; + } + + if (spc::landing_buffer) + { + delete[] spc::landing_buffer; + spc::landing_buffer = NULL; + } + + if (spc::shrink_buffer) + { + delete[] spc::shrink_buffer; + spc::shrink_buffer = NULL; + } +} + +static inline int S9xAPUGetClock (int32 cpucycles) +{ + return (spc::ratio_numerator * (cpucycles - spc::reference_time) + spc::remainder) / + spc::ratio_denominator; +} + +static inline int S9xAPUGetClockRemainder (int32 cpucycles) +{ + return (spc::ratio_numerator * (cpucycles - spc::reference_time) + spc::remainder) % + spc::ratio_denominator; +} + +uint8 S9xAPUReadPort (int port) +{ + return ((uint8) spc_core->read_port(S9xAPUGetClock(CPU.Cycles), port)); +} + +void S9xAPUWritePort (int port, uint8 byte) +{ + spc_core->write_port(S9xAPUGetClock(CPU.Cycles), port, byte); +} + +void S9xAPUSetReferenceTime (int32 cpucycles) +{ + spc::reference_time = cpucycles; +} + +void S9xAPUExecute (void) +{ + /* Accumulate partial APU cycles */ + spc_core->end_frame(S9xAPUGetClock(CPU.Cycles)); + + spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles); + + S9xAPUSetReferenceTime(CPU.Cycles); +} + +void S9xAPUEndScanline (void) +{ + S9xAPUExecute(); + + if (spc_core->sample_count() >= APU_MINIMUM_SAMPLE_BLOCK || !spc::sound_in_sync) + S9xLandSamples(); +} + +void S9xAPUTimingSetSpeedup (int ticks) +{ + if (ticks != 0) + printf("APU speedup hack: %d\n", ticks); + + spc::timing_hack_denominator = SNES_SPC::tempo_unit - ticks; + spc_core->set_tempo(spc::timing_hack_denominator); + + spc::ratio_numerator = Settings.PAL ? APU_NUMERATOR_PAL : APU_NUMERATOR_NTSC; + spc::ratio_denominator = Settings.PAL ? APU_DENOMINATOR_PAL : APU_DENOMINATOR_NTSC; + spc::ratio_denominator = spc::ratio_denominator * spc::timing_hack_denominator / spc::timing_hack_numerator; + + UpdatePlaybackRate(); +} + +void S9xAPUAllowTimeOverflow (bool allow) +{ + spc_core->spc_allow_time_overflow(allow); +} + +void S9xResetAPU (void) +{ + spc::reference_time = 0; + spc::remainder = 0; + spc_core->reset(); + spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + + spc::resampler->clear(); +} + +void S9xSoftResetAPU (void) +{ + spc::reference_time = 0; + spc::remainder = 0; + spc_core->soft_reset(); + spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + + spc::resampler->clear(); +} + +static void from_apu_to_state (uint8 **buf, void *var, size_t size) +{ + memcpy(*buf, var, size); + *buf += size; +} + +static void to_apu_from_state (uint8 **buf, void *var, size_t size) +{ + memcpy(var, *buf, size); + *buf += size; +} + +void S9xAPUSaveState (uint8 *block) +{ + uint8 *ptr = block; + + spc_core->copy_state(&ptr, from_apu_to_state); + + SET_LE32(ptr, spc::reference_time); + ptr += sizeof(int32); + SET_LE32(ptr, spc::remainder); +} + +void S9xAPULoadState (uint8 *block) +{ + uint8 *ptr = block; + + S9xResetAPU(); + + spc_core->copy_state(&ptr, to_apu_from_state); + + spc::reference_time = GET_LE32(ptr); + ptr += sizeof(int32); + spc::remainder = GET_LE32(ptr); +} diff --git a/plugins/snes9x_gx/source/snes9x/apu/apu.h b/plugins/snes9x_gx/source/snes9x/apu/apu.h new file mode 100644 index 00000000..358469da --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/apu.h @@ -0,0 +1,219 @@ +/*********************************************************************************** + 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), + + (c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2011 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 - 2011 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2011 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2011 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. + ***********************************************************************************/ + + +#ifndef _APU_H_ +#define _APU_H_ + +#include "snes9x.h" +#include "SNES_SPC.h" + +typedef void (*apu_callback) (void *); + +#define SPC_SAVE_STATE_BLOCK_SIZE (SNES_SPC::state_size + 8) + +bool8 S9xInitAPU (void); +void S9xDeinitAPU (void); +void S9xResetAPU (void); +void S9xSoftResetAPU (void); +uint8 S9xAPUReadPort (int); +void S9xAPUWritePort (int, uint8); +void S9xAPUExecute (void); +void S9xAPUEndScanline (void); +void S9xAPUSetReferenceTime (int32); +void S9xAPUTimingSetSpeedup (int); +void S9xAPUAllowTimeOverflow (bool); +void S9xAPULoadState (uint8 *); +void S9xAPUSaveState (uint8 *); +void S9xDumpSPCSnapshot (void); + +bool8 S9xInitSound (int, int); +bool8 S9xOpenSoundDevice (void); + +bool8 S9xSyncSound (void); +int S9xGetSampleCount (void); +void S9xSetSoundControl (uint8); +void S9xSetSoundMute (bool8); +void S9xLandSamples (void); +void S9xFinalizeSamples (void); +void S9xClearSamples (void); +bool8 S9xMixSamples (uint8 *, int); +void S9xSetSamplesAvailableCallback (apu_callback, void *); + +extern SNES_SPC *spc_core; + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/apu/blargg_common.h b/plugins/snes9x_gx/source/snes9x/apu/blargg_common.h new file mode 100644 index 00000000..75edff39 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/blargg_common.h @@ -0,0 +1,186 @@ +// Sets up common environment for Shay Green's libraries. +// To change configuration options, modify blargg_config.h, not this file. + +// snes_spc 0.9.0 +#ifndef BLARGG_COMMON_H +#define BLARGG_COMMON_H + +#include <stddef.h> +#include <stdlib.h> +#include <assert.h> +#include <limits.h> + +#undef BLARGG_COMMON_H +// allow blargg_config.h to #include blargg_common.h +#include "blargg_config.h" +#ifndef BLARGG_COMMON_H +#define BLARGG_COMMON_H + +// BLARGG_RESTRICT: equivalent to restrict, where supported +#if defined (__GNUC__) || _MSC_VER >= 1100 + #define BLARGG_RESTRICT __restrict +#else + #define BLARGG_RESTRICT +#endif + +// STATIC_CAST(T,expr): Used in place of static_cast<T> (expr) +#ifndef STATIC_CAST + #define STATIC_CAST(T,expr) ((T) (expr)) +#endif + +// blargg_err_t (0 on success, otherwise error string) +#ifndef blargg_err_t + typedef const char* blargg_err_t; +#endif + +// blargg_vector - very lightweight vector of POD types (no constructor/destructor) +template<class T> +class blargg_vector { + T* begin_; + size_t size_; +public: + blargg_vector() : begin_( 0 ), size_( 0 ) { } + ~blargg_vector() { free( begin_ ); } + size_t size() const { return size_; } + T* begin() const { return begin_; } + T* end() const { return begin_ + size_; } + blargg_err_t resize( size_t n ) + { + // TODO: blargg_common.cpp to hold this as an outline function, ugh + void* p = realloc( begin_, n * sizeof (T) ); + if ( p ) + begin_ = (T*) p; + else if ( n > size_ ) // realloc failure only a problem if expanding + return "Out of memory"; + size_ = n; + return 0; + } + void clear() { void* p = begin_; begin_ = 0; size_ = 0; free( p ); } + T& operator [] ( size_t n ) const + { + assert( n <= size_ ); // <= to allow past-the-end value + return begin_ [n]; + } +}; + +#ifndef BLARGG_DISABLE_NOTHROW + // throw spec mandatory in ISO C++ if operator new can return NULL + #if __cplusplus >= 199711 || defined (__GNUC__) + #define BLARGG_THROWS( spec ) throw spec + #else + #define BLARGG_THROWS( spec ) + #endif + #define BLARGG_DISABLE_NOTHROW \ + void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\ + void operator delete ( void* p ) { free( p ); } + #define BLARGG_NEW new +#else + #include <new> + #define BLARGG_NEW new (std::nothrow) +#endif + +// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant) +#define BLARGG_4CHAR( a, b, c, d ) \ + ((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF)) + +// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0. +#ifndef BOOST_STATIC_ASSERT + #ifdef _MSC_VER + // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified + #define BOOST_STATIC_ASSERT( expr ) \ + void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] ) + #else + // Some other compilers fail when declaring same function multiple times in class, + // so differentiate them by line + #define BOOST_STATIC_ASSERT( expr ) \ + void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] ) + #endif +#endif + +// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1, +// compiler is assumed to support bool. If undefined, availability is determined. +#ifndef BLARGG_COMPILER_HAS_BOOL + #if defined (__MWERKS__) + #if !__option(bool) + #define BLARGG_COMPILER_HAS_BOOL 0 + #endif + #elif defined (_MSC_VER) + #if _MSC_VER < 1100 + #define BLARGG_COMPILER_HAS_BOOL 0 + #endif + #elif defined (__GNUC__) + // supports bool + #elif __cplusplus < 199711 + #define BLARGG_COMPILER_HAS_BOOL 0 + #endif +#endif +#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL + // If you get errors here, modify your blargg_config.h file + typedef int bool; + const bool true = 1; + const bool false = 0; +#endif + +// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough + +#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF + typedef long blargg_long; +#else + typedef int blargg_long; +#endif + +#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF + typedef unsigned long blargg_ulong; +#else + typedef unsigned blargg_ulong; +#endif + +// BOOST::int8_t etc. + +// HAVE_STDINT_H: If defined, use <stdint.h> for int8_t etc. +#if defined (HAVE_STDINT_H) + #include <stdint.h> + #define BOOST + +// HAVE_INTTYPES_H: If defined, use <stdint.h> for int8_t etc. +#elif defined (HAVE_INTTYPES_H) + #include <inttypes.h> + #define BOOST + +#else + struct BOOST + { + #if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F + typedef signed char int8_t; + typedef unsigned char uint8_t; + #else + // No suitable 8-bit type available + typedef struct see_blargg_common_h int8_t; + typedef struct see_blargg_common_h uint8_t; + #endif + + #if USHRT_MAX == 0xFFFF + typedef short int16_t; + typedef unsigned short uint16_t; + #else + // No suitable 16-bit type available + typedef struct see_blargg_common_h int16_t; + typedef struct see_blargg_common_h uint16_t; + #endif + + #if ULONG_MAX == 0xFFFFFFFF + typedef long int32_t; + typedef unsigned long uint32_t; + #elif UINT_MAX == 0xFFFFFFFF + typedef int int32_t; + typedef unsigned int uint32_t; + #else + // No suitable 32-bit type available + typedef struct see_blargg_common_h int32_t; + typedef struct see_blargg_common_h uint32_t; + #endif + }; +#endif + +#endif +#endif diff --git a/plugins/snes9x_gx/source/snes9x/apu/blargg_config.h b/plugins/snes9x_gx/source/snes9x/apu/blargg_config.h new file mode 100644 index 00000000..9dc69db8 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/blargg_config.h @@ -0,0 +1,24 @@ +// snes_spc 0.9.0 user configuration file. Don't replace when updating library. + +// snes_spc 0.9.0 +#ifndef BLARGG_CONFIG_H +#define BLARGG_CONFIG_H + +// Uncomment to disable debugging checks +//#define NDEBUG 1 + +// Uncomment to enable platform-specific (and possibly non-portable) optimizations +//#define BLARGG_NONPORTABLE 1 + +// Uncomment if automatic byte-order determination doesn't work +//#define BLARGG_BIG_ENDIAN 1 + +// Uncomment if you get errors in the bool section of blargg_common.h +//#define BLARGG_COMPILER_HAS_BOOL 1 + +// Use standard config.h if present +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/apu/blargg_endian.h b/plugins/snes9x_gx/source/snes9x/apu/blargg_endian.h new file mode 100644 index 00000000..f2daca64 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/blargg_endian.h @@ -0,0 +1,185 @@ +// CPU Byte Order Utilities + +// snes_spc 0.9.0 +#ifndef BLARGG_ENDIAN +#define BLARGG_ENDIAN + +#include "blargg_common.h" + +// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16) +#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ + defined (__x86_64__) || defined (__ia64__) || defined (__i386__) + #define BLARGG_CPU_X86 1 + #define BLARGG_CPU_CISC 1 +#endif + +#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc) + #define BLARGG_CPU_POWERPC 1 + #define BLARGG_CPU_RISC 1 +#endif + +// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only +// one may be #defined to 1. Only needed if something actually depends on byte order. +#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN) +#ifdef __GLIBC__ + // GCC handles this for us + #include <endian.h> + #if __BYTE_ORDER == __LITTLE_ENDIAN + #define BLARGG_LITTLE_ENDIAN 1 + #elif __BYTE_ORDER == __BIG_ENDIAN + #define BLARGG_BIG_ENDIAN 1 + #endif +#else + +#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \ + (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234) + #define BLARGG_LITTLE_ENDIAN 1 +#endif + +#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \ + defined (__sparc__) || BLARGG_CPU_POWERPC || \ + (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321) + #define BLARGG_BIG_ENDIAN 1 +#elif !defined (__mips__) + // No endian specified; assume little-endian, since it's most common + #define BLARGG_LITTLE_ENDIAN 1 +#endif +#endif +#endif + +#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN + #undef BLARGG_LITTLE_ENDIAN + #undef BLARGG_BIG_ENDIAN +#endif + +inline void blargg_verify_byte_order() +{ + #ifndef NDEBUG + #if BLARGG_BIG_ENDIAN + volatile int i = 1; + assert( *(volatile char*) &i == 0 ); + #elif BLARGG_LITTLE_ENDIAN + volatile int i = 1; + assert( *(volatile char*) &i != 0 ); + #endif + #endif +} + +inline unsigned get_le16( void const* p ) +{ + return (unsigned) ((unsigned char const*) p) [1] << 8 | + (unsigned) ((unsigned char const*) p) [0]; +} + +inline unsigned get_be16( void const* p ) +{ + return (unsigned) ((unsigned char const*) p) [0] << 8 | + (unsigned) ((unsigned char const*) p) [1]; +} + +inline blargg_ulong get_le32( void const* p ) +{ + return (blargg_ulong) ((unsigned char const*) p) [3] << 24 | + (blargg_ulong) ((unsigned char const*) p) [2] << 16 | + (blargg_ulong) ((unsigned char const*) p) [1] << 8 | + (blargg_ulong) ((unsigned char const*) p) [0]; +} + +inline blargg_ulong get_be32( void const* p ) +{ + return (blargg_ulong) ((unsigned char const*) p) [0] << 24 | + (blargg_ulong) ((unsigned char const*) p) [1] << 16 | + (blargg_ulong) ((unsigned char const*) p) [2] << 8 | + (blargg_ulong) ((unsigned char const*) p) [3]; +} + +inline void set_le16( void* p, unsigned n ) +{ + ((unsigned char*) p) [1] = (unsigned char) (n >> 8); + ((unsigned char*) p) [0] = (unsigned char) n; +} + +inline void set_be16( void* p, unsigned n ) +{ + ((unsigned char*) p) [0] = (unsigned char) (n >> 8); + ((unsigned char*) p) [1] = (unsigned char) n; +} + +inline void set_le32( void* p, blargg_ulong n ) +{ + ((unsigned char*) p) [0] = (unsigned char) n; + ((unsigned char*) p) [1] = (unsigned char) (n >> 8); + ((unsigned char*) p) [2] = (unsigned char) (n >> 16); + ((unsigned char*) p) [3] = (unsigned char) (n >> 24); +} + +inline void set_be32( void* p, blargg_ulong n ) +{ + ((unsigned char*) p) [3] = (unsigned char) n; + ((unsigned char*) p) [2] = (unsigned char) (n >> 8); + ((unsigned char*) p) [1] = (unsigned char) (n >> 16); + ((unsigned char*) p) [0] = (unsigned char) (n >> 24); +} + +#if BLARGG_NONPORTABLE + // Optimized implementation if byte order is known + #if BLARGG_LITTLE_ENDIAN + #define GET_LE16( addr ) (*(BOOST::uint16_t*) (addr)) + #define GET_LE32( addr ) (*(BOOST::uint32_t*) (addr)) + #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) + #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) + #elif BLARGG_BIG_ENDIAN + #define GET_BE16( addr ) (*(BOOST::uint16_t*) (addr)) + #define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr)) + #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) + #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) + + #if BLARGG_CPU_POWERPC + // PowerPC has special byte-reversed instructions + #if defined (__MWERKS__) + #define GET_LE16( addr ) (__lhbrx( addr, 0 )) + #define GET_LE32( addr ) (__lwbrx( addr, 0 )) + #define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 )) + #define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 )) + #elif defined (__GNUC__) + #define GET_LE16( addr ) ({unsigned ppc_lhbrx_; asm( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr), "0" (ppc_lhbrx_) ); ppc_lhbrx_;}) + #define GET_LE32( addr ) ({unsigned ppc_lwbrx_; asm( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr), "0" (ppc_lwbrx_) ); ppc_lwbrx_;}) + #define SET_LE16( addr, in ) ({asm( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) );}) + #define SET_LE32( addr, in ) ({asm( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) );}) + #endif + #endif + #endif +#endif + +#ifndef GET_LE16 + #define GET_LE16( addr ) get_le16( addr ) + #define SET_LE16( addr, data ) set_le16( addr, data ) +#endif + +#ifndef GET_LE32 + #define GET_LE32( addr ) get_le32( addr ) + #define SET_LE32( addr, data ) set_le32( addr, data ) +#endif + +#ifndef GET_BE16 + #define GET_BE16( addr ) get_be16( addr ) + #define SET_BE16( addr, data ) set_be16( addr, data ) +#endif + +#ifndef GET_BE32 + #define GET_BE32( addr ) get_be32( addr ) + #define SET_BE32( addr, data ) set_be32( addr, data ) +#endif + +// auto-selecting versions + +inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); } +inline void set_le( BOOST::uint32_t* p, blargg_ulong n ) { SET_LE32( p, n ); } +inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); } +inline void set_be( BOOST::uint32_t* p, blargg_ulong n ) { SET_BE32( p, n ); } +inline unsigned get_le( BOOST::uint16_t* p ) { return GET_LE16( p ); } +inline blargg_ulong get_le( BOOST::uint32_t* p ) { return GET_LE32( p ); } +inline unsigned get_be( BOOST::uint16_t* p ) { return GET_BE16( p ); } +inline blargg_ulong get_be( BOOST::uint32_t* p ) { return GET_BE32( p ); } + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/apu/blargg_source.h b/plugins/snes9x_gx/source/snes9x/apu/blargg_source.h new file mode 100644 index 00000000..5e45c4fb --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/blargg_source.h @@ -0,0 +1,100 @@ +/* Included at the beginning of library source files, after all other #include lines. +Sets up helpful macros and services used in my source code. They don't need +module an annoying module prefix on their names since they are defined after +all other #include lines. */ + +// snes_spc 0.9.0 +#ifndef BLARGG_SOURCE_H +#define BLARGG_SOURCE_H + +// If debugging is enabled, abort program if expr is false. Meant for checking +// internal state and consistency. A failed assertion indicates a bug in the module. +// void assert( bool expr ); +#include <assert.h> + +// If debugging is enabled and expr is false, abort program. Meant for checking +// caller-supplied parameters and operations that are outside the control of the +// module. A failed requirement indicates a bug outside the module. +// void require( bool expr ); +#undef require +#define require( expr ) assert( expr ) + +// Like printf() except output goes to debug log file. Might be defined to do +// nothing (not even evaluate its arguments). +// void dprintf( const char* format, ... ); +static inline void blargg_dprintf_( const char*, ... ) { } +#undef dprintf +#define dprintf (1) ? (void) 0 : blargg_dprintf_ + +// If enabled, evaluate expr and if false, make debug log entry with source file +// and line. Meant for finding situations that should be examined further, but that +// don't indicate a problem. In all cases, execution continues normally. +#undef check +#define check( expr ) ((void) 0) + +// If expr yields error string, return it from current function, otherwise continue. +#undef RETURN_ERR +#define RETURN_ERR( expr ) do { \ + blargg_err_t blargg_return_err_ = (expr); \ + if ( blargg_return_err_ ) return blargg_return_err_; \ + } while ( 0 ) + +// If ptr is 0, return out of memory error string. +#undef CHECK_ALLOC +#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 ) + +// Avoid any macros which evaluate their arguments multiple times +#undef min +#undef max + +#define DEF_MIN_MAX( type ) \ + static inline type min( type x, type y ) { if ( x < y ) return x; return y; }\ + static inline type max( type x, type y ) { if ( y < x ) return x; return y; } + +DEF_MIN_MAX( int ) +DEF_MIN_MAX( unsigned ) +DEF_MIN_MAX( long ) +DEF_MIN_MAX( unsigned long ) +DEF_MIN_MAX( float ) +DEF_MIN_MAX( double ) + +#undef DEF_MIN_MAX + +/* +// using const references generates crappy code, and I am currenly only using these +// for built-in types, so they take arguments by value + +// TODO: remove +inline int min( int x, int y ) +template<class T> +inline T min( T x, T y ) +{ + if ( x < y ) + return x; + return y; +} + +template<class T> +inline T max( T x, T y ) +{ + if ( x < y ) + return y; + return x; +} +*/ + +// TODO: good idea? bad idea? +#undef byte +#define byte byte_ +typedef unsigned char byte; + +// deprecated +#define BLARGG_CHECK_ALLOC CHECK_ALLOC +#define BLARGG_RETURN_ERR RETURN_ERR + +// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check +#ifdef BLARGG_SOURCE_BEGIN + #include BLARGG_SOURCE_BEGIN +#endif + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/apu/hermite_resampler.h b/plugins/snes9x_gx/source/snes9x/apu/hermite_resampler.h new file mode 100644 index 00000000..30ee1032 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/hermite_resampler.h @@ -0,0 +1,144 @@ +/* Simple resampler based on bsnes's ruby audio library */ + +#ifndef __HERMITE_RESAMPLER_H +#define __HERMITE_RESAMPLER_H + +#include "resampler.h" + +#undef CLAMP +#undef SHORT_CLAMP +#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) +#define SHORT_CLAMP(n) ((short) CLAMP((n), -32768, 32767)) + +class HermiteResampler : public Resampler +{ + protected: + + double r_step; + double r_frac; + int r_left[4], r_right[4]; + + double + hermite (double mu1, double a, double b, double c, double d) + { + const double tension = 0.0; //-1 = low, 0 = normal, 1 = high + const double bias = 0.0; //-1 = left, 0 = even, 1 = right + + double mu2, mu3, m0, m1, a0, a1, a2, a3; + + mu2 = mu1 * mu1; + mu3 = mu2 * mu1; + + m0 = (b - a) * (1 + bias) * (1 - tension) / 2; + m0 += (c - b) * (1 - bias) * (1 - tension) / 2; + m1 = (c - b) * (1 + bias) * (1 - tension) / 2; + m1 += (d - c) * (1 - bias) * (1 - tension) / 2; + + a0 = +2 * mu3 - 3 * mu2 + 1; + a1 = mu3 - 2 * mu2 + mu1; + a2 = mu3 - mu2; + a3 = -2 * mu3 + 3 * mu2; + + return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); + } + + public: + HermiteResampler (int num_samples) : Resampler (num_samples) + { + clear (); + } + + ~HermiteResampler () + { + } + + void + time_ratio (double ratio) + { + r_step = ratio; + clear (); + } + + void + clear (void) + { + ring_buffer::clear (); + r_frac = 1.0; + r_left [0] = r_left [1] = r_left [2] = r_left [3] = 0; + r_right[0] = r_right[1] = r_right[2] = r_right[3] = 0; + } + + void + read (short *data, int num_samples) + { + int i_position = start >> 1; + short *internal_buffer = (short *) buffer; + int o_position = 0; + int consumed = 0; + + while (o_position < num_samples && consumed < buffer_size) + { + int s_left = internal_buffer[i_position]; + int s_right = internal_buffer[i_position + 1]; + int max_samples = buffer_size >> 1; + const double margin_of_error = 1.0e-10; + + if (fabs(r_step - 1.0) < margin_of_error) + { + data[o_position] = (short) s_left; + data[o_position + 1] = (short) s_right; + + o_position += 2; + i_position += 2; + if (i_position >= max_samples) + i_position -= max_samples; + consumed += 2; + + continue; + } + + while (r_frac <= 1.0 && o_position < num_samples) + { + data[o_position] = SHORT_CLAMP (hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3])); + data[o_position + 1] = SHORT_CLAMP (hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3])); + + o_position += 2; + + r_frac += r_step; + } + + if (r_frac > 1.0) + { + r_left [0] = r_left [1]; + r_left [1] = r_left [2]; + r_left [2] = r_left [3]; + r_left [3] = s_left; + + r_right[0] = r_right[1]; + r_right[1] = r_right[2]; + r_right[2] = r_right[3]; + r_right[3] = s_right; + + r_frac -= 1.0; + + i_position += 2; + if (i_position >= max_samples) + i_position -= max_samples; + consumed += 2; + } + } + + size -= consumed << 1; + start += consumed << 1; + if (start >= buffer_size) + start -= buffer_size; + } + + inline int + avail (void) + { + return (int) floor (((size >> 2) - r_frac) / r_step) * 2; + } +}; + +#endif /* __HERMITE_RESAMPLER_H */ diff --git a/plugins/snes9x_gx/source/snes9x/apu/license.txt b/plugins/snes9x_gx/source/snes9x/apu/license.txt new file mode 100644 index 00000000..5ab7695a --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/license.txt @@ -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! + + diff --git a/plugins/snes9x_gx/source/snes9x/apu/linear_resampler.h b/plugins/snes9x_gx/source/snes9x/apu/linear_resampler.h new file mode 100644 index 00000000..35789db1 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/linear_resampler.h @@ -0,0 +1,115 @@ +/* Simple fixed-point linear resampler by BearOso*/ + +#ifndef __LINEAR_RESAMPLER_H +#define __LINEAR_RESAMPLER_H + +#include "resampler.h" +#include "snes9x.h" + +static const int f_prec = 15; +static const uint32 f__one = (1 << f_prec); + +#define lerp(t, a, b) (((((b) - (a)) * (t)) >> f_prec) + (a)) + +class LinearResampler : public Resampler +{ + protected: + uint32 f__r_step; + uint32 f__inv_r_step; + uint32 f__r_frac; + int r_left, r_right; + + public: + LinearResampler (int num_samples) : Resampler (num_samples) + { + f__r_frac = 0; + } + + ~LinearResampler () + { + } + + void + time_ratio (double ratio) + { + if (ratio == 0.0) + ratio = 1.0; + f__r_step = (uint32) (ratio * f__one); + f__inv_r_step = (uint32) (f__one / ratio); + clear (); + } + + void + clear (void) + { + ring_buffer::clear (); + f__r_frac = 0; + r_left = 0; + r_right = 0; + } + + void + read (short *data, int num_samples) + { + int i_position = start >> 1; + short *internal_buffer = (short *) buffer; + int o_position = 0; + int consumed = 0; + int max_samples = (buffer_size >> 1); + + while (o_position < num_samples && consumed < buffer_size) + { + if (f__r_step == f__one) + { + data[o_position] = internal_buffer[i_position]; + data[o_position + 1] = internal_buffer[i_position + 1]; + + o_position += 2; + i_position += 2; + if (i_position >= max_samples) + i_position -= max_samples; + consumed += 2; + + continue; + } + + while (f__r_frac <= f__one && o_position < num_samples) + { + data[o_position] = lerp (f__r_frac, + r_left, + internal_buffer[i_position]); + data[o_position + 1] = lerp (f__r_frac, + r_right, + internal_buffer[i_position + 1]); + + o_position += 2; + + f__r_frac += f__r_step; + } + + if (f__r_frac > f__one) + { + f__r_frac -= f__one; + r_left = internal_buffer[i_position]; + r_right = internal_buffer[i_position + 1]; + i_position += 2; + if (i_position >= max_samples) + i_position -= max_samples; + consumed += 2; + } + } + + size -= consumed << 1; + start += consumed << 1; + if (start >= buffer_size) + start -= buffer_size; + } + + inline int + avail (void) + { + return (((size >> 2) * f__inv_r_step) - ((f__r_frac * f__inv_r_step) >> f_prec)) >> (f_prec - 1); + } +}; + +#endif /* __LINEAR_RESAMPLER_H */ diff --git a/plugins/snes9x_gx/source/snes9x/apu/resampler.h b/plugins/snes9x_gx/source/snes9x/apu/resampler.h new file mode 100644 index 00000000..2e62addb --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/resampler.h @@ -0,0 +1,60 @@ +/* Simple resampler based on bsnes's ruby audio library */ + +#ifndef __RESAMPLER_H +#define __RESAMPLER_H + +#include "ring_buffer.h" + +class Resampler : public ring_buffer +{ + public: + virtual void clear (void) = 0; + virtual void time_ratio (double) = 0; + virtual void read (short *, int) = 0; + virtual int avail (void) = 0; + + Resampler (int num_samples) : ring_buffer (num_samples << 1) + { + } + + ~Resampler () + { + } + + inline bool + push (short *src, int num_samples) + { + if (max_write () < num_samples) + return false; + + !num_samples || ring_buffer::push ((unsigned char *) src, num_samples << 1); + + return true; + } + + inline int + space_empty (void) + { + return buffer_size - size; + } + + inline int + space_filled (void) + { + return size; + } + + inline int + max_write (void) + { + return space_empty () >> 1; + } + + inline void + resize (int num_samples) + { + ring_buffer::resize (num_samples << 1); + } +}; + +#endif /* __RESAMPLER_H */ diff --git a/plugins/snes9x_gx/source/snes9x/apu/ring_buffer.h b/plugins/snes9x_gx/source/snes9x/apu/ring_buffer.h new file mode 100644 index 00000000..b743c471 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/apu/ring_buffer.h @@ -0,0 +1,111 @@ +/* Simple byte-based ring buffer. Licensed under public domain (C) BearOso. */ + +#ifndef __RING_BUFFER_H +#define __RING_BUFFER_H + +#include <string.h> + +#undef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +class ring_buffer +{ +protected: + int size; + int buffer_size; + int start; + unsigned char *buffer; + +public: + ring_buffer (int buffer_size) + { + this->buffer_size = buffer_size; + buffer = new unsigned char[this->buffer_size]; + memset (buffer, 0, this->buffer_size); + + size = 0; + start = 0; + } + + ~ring_buffer (void) + { + delete[] buffer; + } + + bool + push (unsigned char *src, int bytes) + { + if (space_empty () < bytes) + return false; + + int end = (start + size) % buffer_size; + int first_write_size = MIN (bytes, buffer_size - end); + + memcpy (buffer + end, src, first_write_size); + + if (bytes > first_write_size) + memcpy (buffer, src + first_write_size, bytes - first_write_size); + + size += bytes; + + return true; + } + + bool + pull (unsigned char *dst, int bytes) + { + if (space_filled () < bytes) + return false; + + memcpy (dst, buffer + start, MIN (bytes, buffer_size - start)); + + if (bytes > (buffer_size - start)) + memcpy (dst + (buffer_size - start), buffer, bytes - (buffer_size - start)); + + start = (start + bytes) % buffer_size; + size -= bytes; + + return true; + } + + inline int + space_empty (void) + { + return buffer_size - size; + } + + inline int + space_filled (void) + { + return size; + } + + void + clear (void) + { + start = 0; + size = 0; + memset (buffer, 0, buffer_size); + } + + void + resize (int size) + { + delete[] buffer; + buffer_size = size; + buffer = new unsigned char[buffer_size]; + memset (buffer, 0, this->buffer_size); + + size = 0; + start = 0; + } + + inline void + cache_silence (void) + { + clear (); + size = buffer_size; + } +}; + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/bsx.cpp b/plugins/snes9x_gx/source/snes9x/bsx.cpp new file mode 100644 index 00000000..abee8a76 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/bsx.cpp @@ -0,0 +1,1206 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + +// Dreamer Nom wrote: +// Large thanks to John Weidman for all his initial research +// Thanks to Seph3 for his modem notes + + +#include "snes9x.h" +#include "memmap.h" +#include "display.h" + +//#define BSX_DEBUG + +#define BIOS_SIZE 0x100000 +#define FLASH_SIZE 0x200000 +#define PSRAM_SIZE 0x80000 + +#define Map Memory.Map +#define BlockIsRAM Memory.BlockIsRAM +#define BlockIsROM Memory.BlockIsROM +#define RAM Memory.RAM +#define SRAM Memory.SRAM +#define PSRAM Memory.BSRAM +#define BIOSROM Memory.BIOSROM +#define MAP_BSX Memory.MAP_BSX +#define MAP_CPU Memory.MAP_CPU +#define MAP_PPU Memory.MAP_PPU +#define MAP_NONE Memory.MAP_NONE + +#define BSXPPUBASE 0x2180 + +struct SBSX_RTC +{ + int hours; + int minutes; + int seconds; + int ticks; +}; + +static struct SBSX_RTC BSX_RTC; + +// flash card vendor information +static const uint8 flashcard[20] = +{ + 0x4D, 0x00, 0x50, 0x00, // vendor id + 0x00, 0x00, // ? + 0x2B, 0x00, // 2MB Flash (1MB = 0x2A) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8 init2192[32] = // FIXME +{ + 00, 00, 00, 00, 00, // unknown + 01, 01, 00, 00, 00, + 00, // seconds (?) + 00, // minutes + 00, // hours + 10, 10, 10, 10, 10, // unknown + 10, 10, 10, 10, 10, // dummy + 00, 00, 00, 00, 00, 00, 00, 00, 00 +}; + +static bool8 FlashMode; +static uint32 FlashSize; +static uint8 *MapROM, *FlashROM; + +static void BSX_Map_SNES (void); +static void BSX_Map_LoROM (void); +static void BSX_Map_HiROM (void); +static void BSX_Map_MMC (void); +static void BSX_Map_FlashIO (void); +static void BSX_Map_SRAM (void); +static void BSX_Map_PSRAM (void); +static void BSX_Map_BIOS (void); +static void BSX_Map_RAM (void); +static void BSX_Map_Dirty (void); +static void BSX_Map (void); +static void BSX_Set_Bypass_FlashIO (uint16, uint8); +static uint8 BSX_Get_Bypass_FlashIO (uint16); +static bool8 BSX_LoadBIOS (void); +static void map_psram_mirror_sub (uint32); +static int is_bsx (unsigned char *); + + +static void BSX_Map_SNES (void) +{ + // These maps will be partially overwritten + + int c; + + // Banks 00->3F and 80->BF + for (c = 0; c < 0x400; c += 16) + { + Map[c + 0] = Map[c + 0x800] = RAM; + Map[c + 1] = Map[c + 0x801] = RAM; + BlockIsRAM[c + 0] = BlockIsRAM[c + 0x800] = TRUE; + BlockIsRAM[c + 1] = BlockIsRAM[c + 0x801] = TRUE; + + Map[c + 2] = Map[c + 0x802] = (uint8 *) MAP_PPU; + Map[c + 3] = Map[c + 0x803] = (uint8 *) MAP_PPU; + Map[c + 4] = Map[c + 0x804] = (uint8 *) MAP_CPU; + Map[c + 5] = Map[c + 0x805] = (uint8 *) MAP_CPU; + Map[c + 6] = Map[c + 0x806] = (uint8 *) MAP_NONE; + Map[c + 7] = Map[c + 0x807] = (uint8 *) MAP_NONE; + } +} + +static void BSX_Map_LoROM (void) +{ + // These maps will be partially overwritten + + int i, c; + + // Banks 00->3F and 80->BF + for (c = 0; c < 0x400; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Map[i] = Map[i + 0x800] = &MapROM[(c << 11) % FlashSize] - 0x8000; + BlockIsRAM[i] = BlockIsRAM[i + 0x800] = BSX.write_enable; + BlockIsROM[i] = BlockIsROM[i + 0x800] = !BSX.write_enable; + } + } + + // Banks 40->7F and C0->FF + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 8; i++) + Map[i + 0x400] = Map[i + 0xC00] = &MapROM[(c << 11) % FlashSize]; + + for (i = c + 8; i < c + 16; i++) + Map[i + 0x400] = Map[i + 0xC00] = &MapROM[(c << 11) % FlashSize] - 0x8000; + + for (i = c; i < c + 16; i++) + { + BlockIsRAM[i + 0x400] = BlockIsRAM[i + 0xC00] = BSX.write_enable; + BlockIsROM[i + 0x400] = BlockIsROM[i + 0xC00] = !BSX.write_enable; + } + } +} + +static void BSX_Map_HiROM (void) +{ + // These maps will be partially overwritten + + int i, c; + + // Banks 00->3F and 80->BF + for (c = 0; c < 0x400; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Map[i] = Map[i + 0x800] = &MapROM[(c << 12) % FlashSize]; + BlockIsRAM[i] = BlockIsRAM[i + 0x800] = BSX.write_enable; + BlockIsROM[i] = BlockIsROM[i + 0x800] = !BSX.write_enable; + } + } + + // Banks 40->7F and C0->FF + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 16; i++) + { + Map[i + 0x400] = Map[i + 0xC00] = &MapROM[(c << 12) % FlashSize]; + BlockIsRAM[i + 0x400] = BlockIsRAM[i + 0xC00] = BSX.write_enable; + BlockIsROM[i + 0x400] = BlockIsROM[i + 0xC00] = !BSX.write_enable; + } + } +} + +static void BSX_Map_MMC (void) +{ + int c; + + // Banks 01->0E:5000-5FFF + for (c = 0x010; c < 0x0F0; c += 16) + { + Map[c + 5] = (uint8 *) MAP_BSX; + BlockIsRAM[c + 5] = BlockIsROM[c + 5] = FALSE; + } +} + +static void BSX_Map_FlashIO (void) +{ + int c; + + if (BSX.MMC[0x0C] || BSX.MMC[0x0D]) + { + // Bank C0:0000, 2AAA, 5555, FF00-FF1F + for (c = 0; c < 16; c++) + { + Map[c + 0xC00] = (uint8 *) MAP_BSX; + BlockIsRAM[c + 0xC00] = TRUE; + BlockIsROM[c + 0xC00] = FALSE; + } + } +} + +static void BSX_Map_SRAM (void) +{ + int c; + + // Banks 10->17:5000-5FFF + for (c = 0x100; c < 0x180; c += 16) + { + Map[c + 5] = (uint8 *) SRAM + ((c & 0x70) << 8) - 0x5000; + BlockIsRAM[c + 5] = TRUE; + BlockIsROM[c + 5] = FALSE; + } +} + +static void map_psram_mirror_sub (uint32 bank) +{ + int i, c; + + bank <<= 4; + + if (BSX.MMC[0x02]) + { + for (c = 0; c < 0x100; c += 16) + { + for (i = c; i < c + 16; i++) + { + Map[i + bank] = &PSRAM[(c << 12) % PSRAM_SIZE]; + BlockIsRAM[i + bank] = TRUE; + BlockIsROM[i + bank] = FALSE; + } + } + } + else + { + for (c = 0; c < 0x100; c += 16) + { + for (i = c; i < c + 8; i++) + Map[i + bank] = &PSRAM[(c << 11) % PSRAM_SIZE]; + + for (i = c + 8; i < c + 16; i++) + Map[i + bank] = &PSRAM[(c << 11) % PSRAM_SIZE] - 0x8000; + + for (i = c; i < c + 16; i++) + { + BlockIsRAM[i + bank] = TRUE; + BlockIsROM[i + bank] = FALSE; + } + } + } +} + +static void BSX_Map_PSRAM (void) +{ + int c; + + // Banks 70->77:0000-FFFF + // FIXME: could be toggled by $03 + for (c = 0; c < 0x80; c++) + { + Map[c + 0x700] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; + BlockIsRAM[c + 0x700] = TRUE; + BlockIsROM[c + 0x700] = FALSE; + } + + // Banks 20->3F:6000-7FFF mirrors 70->77:6000-7FFF + for (c = 0x200; c < 0x400; c += 16) + { + Map[c + 6] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; + Map[c + 7] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; + BlockIsRAM[c + 6] = TRUE; + BlockIsRAM[c + 7] = TRUE; + BlockIsROM[c + 6] = FALSE; + BlockIsROM[c + 7] = FALSE; + } + + if (!BSX.MMC[0x05]) + // Banks 40->4F:0000-FFFF mirrors 70->77:0000-7FFF + map_psram_mirror_sub(0x40); + + if (!BSX.MMC[0x06]) + // Banks 50->5F:0000-FFFF mirrors 70->77:0000-7FFF + map_psram_mirror_sub(0x50); + + // FIXME + if (!BSX.MMC[0x03]) + // Banks 60->6F:0000-FFFF mirrors 70->77:0000-7FFF (?) + map_psram_mirror_sub(0x60); +} + +static void BSX_Map_BIOS (void) +{ + int i,c; + + // Banks 00->1F:8000-FFFF + if (BSX.MMC[0x07]) + { + for (c = 0; c < 0x200; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Map[i] = &BIOSROM[(c << 11) % BIOS_SIZE] - 0x8000; + BlockIsRAM[i] = FALSE; + BlockIsROM[i] = TRUE; + } + } + } + + // Banks 80->9F:8000-FFFF + if (BSX.MMC[0x08]) + { + for (c = 0; c < 0x200; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Map[i + 0x800] = &BIOSROM[(c << 11) % BIOS_SIZE] - 0x8000; + BlockIsRAM[i + 0x800] = FALSE; + BlockIsROM[i + 0x800] = TRUE; + } + } + } +} + +static void BSX_Map_RAM (void) +{ + int c; + + // Banks 7E->7F + for (c = 0; c < 16; c++) + { + Map[c + 0x7E0] = RAM; + Map[c + 0x7F0] = RAM + 0x10000; + BlockIsRAM[c + 0x7E0] = TRUE; + BlockIsRAM[c + 0x7F0] = TRUE; + BlockIsROM[c + 0x7E0] = FALSE; + BlockIsROM[c + 0x7F0] = FALSE; + } +} + +static void BSX_Map_Dirty (void) +{ + // for the quick bank change + + int i, c; + + // Banks 00->1F and 80->9F:8000-FFFF + if (BSX.MMC[0x02]) + { + for (c = 0; c < 0x200; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Map[i] = Map[i + 0x800] = &MapROM[(c << 12) % FlashSize]; + BlockIsRAM[i] = BlockIsRAM[i + 0x800] = BSX.write_enable; + BlockIsROM[i] = BlockIsROM[i + 0x800] = !BSX.write_enable; + } + } + } + else + { + for (c = 0; c < 0x200; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Map[i] = Map[i + 0x800] = &MapROM[(c << 11) % FlashSize] - 0x8000; + BlockIsRAM[i] = BlockIsRAM[i + 0x800] = BSX.write_enable; + BlockIsROM[i] = BlockIsROM[i + 0x800] = !BSX.write_enable; + } + } + } +} + +static void BSX_Map (void) +{ +#ifdef BSX_DEBUG + printf("BS: Remapping\n"); + for (int i = 0; i < 32; i++) + printf("BS: MMC %02X: %d\n", i, BSX.MMC[i]); +#endif + + memcpy(BSX.prevMMC, BSX.MMC, sizeof(BSX.MMC)); + + // Do a quick bank change + if (BSX.dirty2 && !BSX.dirty) + { + BSX_Map_Dirty(); + BSX_Map_BIOS(); + + BSX.dirty2 = FALSE; + + Memory.map_WriteProtectROM(); + return; + } + + if (BSX.MMC[0x01]) + { + MapROM = PSRAM; + FlashSize = PSRAM_SIZE; + } + else + { + MapROM = FlashROM; + FlashSize = FLASH_SIZE; + } + + BSX_Map_SNES(); + + if (BSX.MMC[0x02]) + BSX_Map_HiROM(); + else + BSX_Map_LoROM(); + + BSX_Map_PSRAM(); + BSX_Map_SRAM(); + BSX_Map_RAM(); + + BSX_Map_BIOS(); + BSX_Map_FlashIO(); + BSX_Map_MMC(); + + // Monitor new register changes + BSX.dirty = FALSE; + BSX.dirty2 = FALSE; + + Memory.map_WriteProtectROM(); +} + +static uint8 BSX_Get_Bypass_FlashIO (uint16 offset) +{ + if (BSX.MMC[0x02]) + return (MapROM[offset]); + else + { + if (offset < 0x8000) + return (MapROM[offset]); + else + return (MapROM[offset - 0x8000]); + } +} + +static void BSX_Set_Bypass_FlashIO (uint16 offset, uint8 byte) +{ + if (BSX.MMC[0x02]) + MapROM[offset] = byte; + else + { + if (offset < 0x8000) + MapROM[offset] = byte; + else + MapROM[offset - 0x8000] = byte; + } +} + +uint8 S9xGetBSX (uint32 address) +{ + uint8 bank = (address >> 16) & 0xFF; + uint16 offset = address & 0xFFFF; + uint8 t = 0; + + // MMC + if ((bank >= 0x01 && bank <= 0x0E) && (offset == 0x5000)) + return (BSX.MMC[bank]); + + // Flash IO + if (bank == 0xC0) + { + // default: read-through mode + t = BSX_Get_Bypass_FlashIO(offset); + + // note: may be more registers, purposes unknown + switch (offset) + { + case 0x0002: + if (BSX.flash_enable) + t = 0x80; // status register? + break; + + case 0x5555: + if (BSX.flash_enable) + t = 0x80; // ??? + break; + + case 0xFF00: + case 0xFF02: + case 0xFF04: + case 0xFF06: + case 0xFF08: + case 0xFF0A: + case 0xFF0C: + case 0xFF0E: + case 0xFF10: + case 0xFF12: + // return flash vendor information + if (BSX.read_enable) + t = flashcard[offset - 0xFF00]; + break; + } + } + + return (t); +} + +void S9xSetBSX (uint8 byte, uint32 address) +{ + uint8 bank = (address >> 16) & 0xFF; + uint16 offset = address & 0xFFFF; + + // MMC + if ((bank >= 0x01 && bank <= 0x0E) && (offset == 0x5000)) + { + switch (bank) + { + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + if (BSX.MMC[bank] != byte) + { + BSX.MMC[bank] = byte; + BSX.dirty = TRUE; + } + break; + + case 0x07: + case 0x08: + if (BSX.MMC[bank] != byte) + { + BSX.MMC[bank] = byte; + BSX.dirty2 = TRUE; + } + break; + + case 0x0E: + BSX.MMC[bank] = byte; + if (byte && (BSX.dirty || BSX.dirty2)) + BSX_Map(); + break; + } + } + + // Flash IO + if (bank == 0xC0) + { + BSX.old_write = BSX.new_write; + BSX.new_write = address; + + // ???: double writes to the desired address will bypass + // flash registers + if (BSX.old_write == BSX.new_write && BSX.write_enable) + { + BSX_Set_Bypass_FlashIO(offset, byte); + return; + } + + // flash command handling + // note: incomplete + switch (offset) + { + case 0x0000: + BSX.flash_command <<= 8; + BSX.flash_command |= byte; + if ((BSX.flash_command & 0xFFFF) == 0x38D0) + { + // retrieve information about the flash card + BSX.flash_enable = TRUE; + BSX.read_enable = TRUE; + } + break; + + case 0x2AAA: + BSX.flash_command <<= 8; + BSX.flash_command |= byte; + break; + + case 0x5555: + BSX.flash_command <<= 8; + BSX.flash_command |= byte; + + switch (BSX.flash_command & 0xFFFFFF) + { + case 0xAA55F0: + // turn off flash i/o + BSX.flash_enable = FALSE; + BSX.write_enable = FALSE; + BSX.read_enable = FALSE; + break; + + case 0xAA55A0: + // enable writing to flash + BSX.old_write = 0; + BSX.new_write = 0; + BSX.flash_enable = TRUE; + BSX.write_enable = TRUE; + BSX_Map(); + break; + + case 0xAA5570: + // turn on write-protection + BSX.write_enable = FALSE; + BSX_Map(); + break; + + case 0xAA5580: + case 0xAA5510: + // ??? + break; + + } + + break; + } + } +} + +uint8 S9xGetBSXPPU (uint16 address) +{ + uint8 t; + + // known read registers + switch (address) + { + // Test register low? (r/w) + case 0x2188: + t = BSX.PPU[0x2188 - BSXPPUBASE]; + break; + + // Test register high? (r/w) + case 0x2189: + t = BSX.PPU[0x2189 - BSXPPUBASE]; + break; + + case 0x218A: + t = BSX.PPU[0x218A - BSXPPUBASE]; + break; + + case 0x218C: + t = BSX.PPU[0x218C - BSXPPUBASE]; + break; + + // Transmission number low? (r/w) + case 0x218E: + t = BSX.PPU[0x218E - BSXPPUBASE]; + break; + + // Transmission number high? (r/w) + case 0x218F: + t = BSX.PPU[0x218F - BSXPPUBASE]; + break; + + // Status register? (r) + case 0x2190: + t = BSX.PPU[0x2190 - BSXPPUBASE]; + break; + + // Data register? (r/w) + case 0x2192: + t = BSX.PPU[0x2192 - BSXPPUBASE]; + + // test + t = BSX.test2192[BSX.out_index++]; + if (BSX.out_index == 32) + BSX.out_index = 0; + + BSX_RTC.ticks++; + if (BSX_RTC.ticks >= 1000) + { + BSX_RTC.ticks = 0; + BSX_RTC.seconds++; + } + if (BSX_RTC.seconds >= 60) + { + BSX_RTC.seconds = 0; + BSX_RTC.minutes++; + } + if (BSX_RTC.minutes >= 60) + { + BSX_RTC.minutes = 0; + BSX_RTC.hours++; + } + if (BSX_RTC.hours >= 24) + BSX_RTC.hours = 0; + + BSX.test2192[10] = BSX_RTC.seconds; + BSX.test2192[11] = BSX_RTC.minutes; + BSX.test2192[12] = BSX_RTC.hours; + + break; + + // Transmission status? (r/w) + case 0x2193: + // Data ready when bits 2/3 clear? + t = BSX.PPU[0x2193 - BSXPPUBASE] & ~0x0C; + break; + + // Reset? (r/w) + case 0x2194: + t = BSX.PPU[0x2194 - BSXPPUBASE]; + break; + + // Unknown (r) + case 0x2196: + t = BSX.PPU[0x2196 - BSXPPUBASE]; + break; + + // Unknown (r/w) + case 0x2197: + t = BSX.PPU[0x2197 - BSXPPUBASE]; + break; + + // Modem protocol? (r/w) + case 0x2199: + t = BSX.PPU[0x2199 - BSXPPUBASE]; + break; + + default: + t = OpenBus; + break; + } + + return (t); +} + +void S9xSetBSXPPU (uint8 byte, uint16 address) +{ + // known write registers + switch (address) + { + // Test register low? (r/w) + case 0x2188: + BSX.PPU[0x2188 - BSXPPUBASE] = byte; + break; + + // Test register high? (r/w) + case 0x2189: + BSX.PPU[0x2189 - BSXPPUBASE] = byte; + break; + + case 0x218A: + BSX.PPU[0x218A - BSXPPUBASE] = byte; + break; + + case 0x218B: + BSX.PPU[0x218B - BSXPPUBASE] = byte; + break; + + case 0x218C: + BSX.PPU[0x218C - BSXPPUBASE] = byte; + break; + + // Transmission number low? (r/w) + case 0x218E: + BSX.PPU[0x218E - BSXPPUBASE] = byte; + break; + + // Transmission number high? (r/w) + case 0x218F: + BSX.PPU[0x218F - BSXPPUBASE] = byte; + + // ? + BSX.PPU[0x218E - BSXPPUBASE] >>= 1; + BSX.PPU[0x218E - BSXPPUBASE] = BSX.PPU[0x218F - BSXPPUBASE] - BSX.PPU[0x218E - BSXPPUBASE]; + BSX.PPU[0x218F - BSXPPUBASE] >>= 1; + + BSX.PPU[0x2190 - BSXPPUBASE] = 0x80; // ? + break; + + // Strobe assert? (w) + case 0x2191: + BSX.PPU[0x2191 - BSXPPUBASE] = byte; + BSX.out_index = 0; + break; + + // Data register? (r/w) + case 0x2192: + BSX.PPU[0x2192 - BSXPPUBASE] = 0x01; // ? + BSX.PPU[0x2190 - BSXPPUBASE] = 0x80; // ? + break; + + // Transmission status? (r/w) + case 0x2193: + BSX.PPU[0x2193 - BSXPPUBASE] = byte; + break; + + // Reset? (r/w) + case 0x2194: + BSX.PPU[0x2194 - BSXPPUBASE] = byte; + break; + + // Unknown (r/w) + case 0x2197: + BSX.PPU[0x2197 - BSXPPUBASE] = byte; + break; + + // Modem protocol? (r/w) + case 0x2199: + // Lots of modem strings written here when + // connection is lost or no uplink established + BSX.PPU[0x2199 - BSXPPUBASE] = byte; + break; + } +} + +uint8 * S9xGetBasePointerBSX (uint32 address) +{ + return (MapROM); +} + +static bool8 BSX_LoadBIOS (void) +{ +#ifdef GEKKO + return FALSE; // We're not loading the BIOS! +#endif + + FILE *fp; + char path[PATH_MAX + 1], name[PATH_MAX + 1]; + bool8 r = FALSE; + + strcpy(path, S9xGetDirectory(BIOS_DIR)); + strcat(path, SLASH_STR); + strcpy(name, path); + strcat(name, "BS-X.bin"); + + fp = fopen(name, "rb"); + if (!fp) + { + strcpy(name, path); + strcat(name, "BS-X.bios"); + fp = fopen(name, "rb"); + } + + if (fp) + { + size_t size; + + size = fread((void *) BIOSROM, 1, BIOS_SIZE, fp); + fclose(fp); + if (size == BIOS_SIZE) + r = TRUE; + } + +#ifdef BSX_DEBUG + if (r) + printf("BS: BIOS found.\n"); + else + printf("BS: BIOS not found!\n"); +#endif + + return (r); +} + +void S9xInitBSX (void) +{ + Settings.BS = FALSE; + + if (!memcmp(&Memory.ROM[0x7FC0], "Satellaview BS-X ", 21)) + { + // BS-X itself + + Settings.BS = TRUE; + Settings.BSXItself = TRUE; + + Memory.LoROM = TRUE; + Memory.HiROM = FALSE; + + memmove(BIOSROM, Memory.ROM, BIOS_SIZE); + + FlashMode = FALSE; + FlashSize = FLASH_SIZE; + + BSX.bootup = TRUE; + } + else + { + Settings.BSXItself = FALSE; + + int r1, r2; + + r1 = (is_bsx(Memory.ROM + 0x7FC0) == 1); + r2 = (is_bsx(Memory.ROM + 0xFFC0) == 1); + Settings.BS = (r1 | r2) ? TRUE : FALSE; + + if (Settings.BS) + { + // BS games + + Memory.LoROM = r1 ? TRUE : FALSE; + Memory.HiROM = r2 ? TRUE : FALSE; + + uint8 *header = r1 ? Memory.ROM + 0x7FC0 : Memory.ROM + 0xFFC0; + + FlashMode = (header[0x18] & 0xEF) == 0x20 ? FALSE : TRUE; + FlashSize = (header[0x19] & 0x20) ? PSRAM_SIZE : FLASH_SIZE; + +#ifdef BSX_DEBUG + for (int i = 0; i <= 0x1F; i++) + printf("BS: ROM Header %02X: %02X\n", i, header[i]); + printf("BS: FlashMode: %d, FlashSize: %x\n", FlashMode, FlashSize); +#endif + + BSX.bootup = Settings.BSXBootup; + + if (!BSX_LoadBIOS()) + { + BSX.bootup = FALSE; + memset(BIOSROM, 0, BIOS_SIZE); + } + } + } + + if (Settings.BS) + { + MapROM = NULL; + FlashROM = Memory.ROM; + + time_t t; + struct tm *tmr; + + time(&t); + tmr = localtime(&t); + + BSX_RTC.ticks = 0; + memcpy(BSX.test2192, init2192, sizeof(init2192)); + BSX.test2192[10] = BSX_RTC.seconds = tmr->tm_sec; + BSX.test2192[11] = BSX_RTC.minutes = tmr->tm_min; + BSX.test2192[12] = BSX_RTC.hours = tmr->tm_hour; +#ifdef BSX_DEBUG + printf("BS: Current Time: %02d:%02d:%02d\n", BSX_RTC.hours, BSX_RTC.minutes, BSX_RTC.seconds); +#endif + SNESGameFixes.SRAMInitialValue = 0x00; + } +} + +void S9xResetBSX (void) +{ + if (Settings.BSXItself) + memset(Memory.ROM, 0, FLASH_SIZE); + + memset(BSX.PPU, 0, sizeof(BSX.PPU)); + memset(BSX.MMC, 0, sizeof(BSX.MMC)); + memset(BSX.prevMMC, 0, sizeof(BSX.prevMMC)); + + BSX.dirty = FALSE; + BSX.dirty2 = FALSE; + BSX.flash_enable = FALSE; + BSX.write_enable = FALSE; + BSX.read_enable = FALSE; + BSX.flash_command = 0; + BSX.old_write = 0; + BSX.new_write = 0; + + BSX.out_index = 0; + memset(BSX.output, 0, sizeof(BSX.output)); + + // starting from the bios + if (BSX.bootup) + BSX.MMC[0x07] = BSX.MMC[0x08] = 0x80; + else + { + BSX.MMC[0x02] = FlashMode ? 0x80: 0; + + // per bios: run from psram or flash card + if (FlashSize == PSRAM_SIZE) + { + memcpy(PSRAM, FlashROM, PSRAM_SIZE); + + BSX.MMC[0x01] = 0x80; + BSX.MMC[0x03] = 0x80; + BSX.MMC[0x04] = 0x80; + BSX.MMC[0x0C] = 0x80; + BSX.MMC[0x0D] = 0x80; + } + else + { + BSX.MMC[0x03] = 0x80; + BSX.MMC[0x05] = 0x80; + BSX.MMC[0x06] = 0x80; + } + + BSX.MMC[0x0E] = 0x80; + } + + BSX_Map(); +} + +void S9xBSXPostLoadState (void) +{ + uint8 temp[16]; + bool8 pd1, pd2; + + pd1 = BSX.dirty; + pd2 = BSX.dirty2; + memcpy(temp, BSX.MMC, sizeof(BSX.MMC)); + + memcpy(BSX.MMC, BSX.prevMMC, sizeof(BSX.MMC)); + BSX_Map(); + + memcpy(BSX.MMC, temp, sizeof(BSX.MMC)); + BSX.dirty = pd1; + BSX.dirty2 = pd2; +} + +static bool valid_normal_bank (unsigned char bankbyte) +{ + switch (bankbyte) + { + case 32: case 33: case 48: case 49: + return (true); + break; + } + + return (false); +} + +static int is_bsx (unsigned char *p) +{ + if ((p[26] == 0x33 || p[26] == 0xFF) && (!p[21] || (p[21] & 131) == 128) && valid_normal_bank(p[24])) + { + unsigned char m = p[22]; + + if (!m && !p[23]) + return (2); + + if ((m == 0xFF && p[23] == 0xFF) || (!(m & 0xF) && ((m >> 4) - 1 < 12))) + return (1); + } + + return (0); +} diff --git a/plugins/snes9x_gx/source/snes9x/bsx.h b/plugins/snes9x_gx/source/snes9x/bsx.h new file mode 100644 index 00000000..d88bb193 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/bsx.h @@ -0,0 +1,211 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _BSX_H_ +#define _BSX_H_ + +struct SBSX +{ + bool8 dirty; // Changed register values + bool8 dirty2; // Changed register values + bool8 bootup; // Start in bios mapping + bool8 flash_enable; // Flash state + bool8 write_enable; // ROM write protection + bool8 read_enable; // Allow card vendor reading + uint32 flash_command; // Flash command + uint32 old_write; // Previous flash write address + uint32 new_write; // Current flash write address + uint8 out_index; + uint8 output[32]; + uint8 PPU[32]; + uint8 MMC[16]; + uint8 prevMMC[16]; + uint8 test2192[32]; +}; + +extern struct SBSX BSX; + +uint8 S9xGetBSX (uint32); +void S9xSetBSX (uint8, uint32); +uint8 S9xGetBSXPPU (uint16); +void S9xSetBSXPPU (uint8, uint16); +uint8 * S9xGetBasePointerBSX (uint32); +void S9xInitBSX (void); +void S9xResetBSX (void); +void S9xBSXPostLoadState (void); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/c4.cpp b/plugins/snes9x_gx/source/snes9x/c4.cpp new file mode 100644 index 00000000..d586e79e --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/c4.cpp @@ -0,0 +1,330 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include <math.h> +#include "snes9x.h" +#include "memmap.h" + +#define C4_PI 3.14159265 + +int16 C4WFXVal; +int16 C4WFYVal; +int16 C4WFZVal; +int16 C4WFX2Val; +int16 C4WFY2Val; +int16 C4WFDist; +int16 C4WFScale; +int16 C41FXVal; +int16 C41FYVal; +int16 C41FAngleRes; +int16 C41FDist; +int16 C41FDistVal; + +static double tanval; +static double c4x, c4y, c4z; +static double c4x2, c4y2, c4z2; + + +void C4TransfWireFrame (void) +{ + c4x = (double) C4WFXVal; + c4y = (double) C4WFYVal; + c4z = (double) C4WFZVal - 0x95; + + // Rotate X + tanval = -(double) C4WFX2Val * C4_PI * 2 / 128; + c4y2 = c4y * cos(tanval) - c4z * sin(tanval); + c4z2 = c4y * sin(tanval) + c4z * cos(tanval); + + // Rotate Y + tanval = -(double) C4WFY2Val * C4_PI * 2 / 128; + c4x2 = c4x * cos(tanval) + c4z2 * sin(tanval); + c4z = c4x * -sin(tanval) + c4z2 * cos(tanval); + + // Rotate Z + tanval = -(double) C4WFDist * C4_PI * 2 / 128; + c4x = c4x2 * cos(tanval) - c4y2 * sin(tanval); + c4y = c4x2 * sin(tanval) + c4y2 * cos(tanval); + + // Scale + C4WFXVal = (int16) (c4x * (double) C4WFScale / (0x90 * (c4z + 0x95)) * 0x95); + C4WFYVal = (int16) (c4y * (double) C4WFScale / (0x90 * (c4z + 0x95)) * 0x95); +} + +void C4TransfWireFrame2 (void) +{ + c4x = (double) C4WFXVal; + c4y = (double) C4WFYVal; + c4z = (double) C4WFZVal; + + // Rotate X + tanval = -(double) C4WFX2Val * C4_PI * 2 / 128; + c4y2 = c4y * cos(tanval) - c4z * sin(tanval); + c4z2 = c4y * sin(tanval) + c4z * cos(tanval); + + // Rotate Y + tanval = -(double) C4WFY2Val * C4_PI * 2 / 128; + c4x2 = c4x * cos(tanval) + c4z2 * sin(tanval); + c4z = c4x * -sin(tanval) + c4z2 * cos(tanval); + + // Rotate Z + tanval = -(double) C4WFDist * C4_PI * 2 / 128; + c4x = c4x2 * cos(tanval) - c4y2 * sin(tanval); + c4y = c4x2 * sin(tanval) + c4y2 * cos(tanval); + + // Scale + C4WFXVal = (int16) (c4x * (double) C4WFScale / 0x100); + C4WFYVal = (int16) (c4y * (double) C4WFScale / 0x100); +} + +void C4CalcWireFrame (void) +{ + C4WFXVal = C4WFX2Val - C4WFXVal; + C4WFYVal = C4WFY2Val - C4WFYVal; + + if (abs(C4WFXVal) > abs(C4WFYVal)) + { + C4WFDist = abs(C4WFXVal) + 1; + C4WFYVal = (int16) (256 * (double) C4WFYVal / abs(C4WFXVal)); + if (C4WFXVal < 0) + C4WFXVal = -256; + else + C4WFXVal = 256; + } + else + { + if (C4WFYVal != 0) + { + C4WFDist = abs(C4WFYVal) + 1; + C4WFXVal = (int16) (256 * (double) C4WFXVal / abs(C4WFYVal)); + if (C4WFYVal < 0) + C4WFYVal = -256; + else + C4WFYVal = 256; + } + else + C4WFDist = 0; + } +} + +void C4Op1F (void) +{ + if (C41FXVal == 0) + { + if (C41FYVal > 0) + C41FAngleRes = 0x80; + else + C41FAngleRes = 0x180; + } + else + { + tanval = (double) C41FYVal / C41FXVal; + C41FAngleRes = (int16) (atan(tanval) / (C4_PI * 2) * 512); + C41FAngleRes = C41FAngleRes; + if (C41FXVal< 0) + C41FAngleRes += 0x100; + C41FAngleRes &= 0x1FF; + } +} + +void C4Op15 (void) +{ + tanval = sqrt((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); + C41FDist = (int16) tanval; +} + +void C4Op0D (void) +{ + tanval = sqrt((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); + tanval = C41FDistVal / tanval; + C41FYVal = (int16) (C41FYVal * tanval * 0.99); + C41FXVal = (int16) (C41FXVal * tanval * 0.98); +} + +uint8 * S9xGetBasePointerC4 (uint16 Address) +{ + if (Address >= 0x7f40 && Address <= 0x7f5e) + return (NULL); + return (Memory.C4RAM - 0x6000); +} + +uint8 * S9xGetMemPointerC4 (uint16 Address) +{ + if (Address >= 0x7f40 && Address <= 0x7f5e) + return (NULL); + return (Memory.C4RAM - 0x6000 + (Address & 0xffff)); +} diff --git a/plugins/snes9x_gx/source/snes9x/c4.h b/plugins/snes9x_gx/source/snes9x/c4.h new file mode 100644 index 00000000..9b4c6070 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/c4.h @@ -0,0 +1,211 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _C4_H_ +#define _C4_H_ + +extern int16 C4WFXVal; +extern int16 C4WFYVal; +extern int16 C4WFZVal; +extern int16 C4WFX2Val; +extern int16 C4WFY2Val; +extern int16 C4WFDist; +extern int16 C4WFScale; +extern int16 C41FXVal; +extern int16 C41FYVal; +extern int16 C41FAngleRes; +extern int16 C41FDist; +extern int16 C41FDistVal; + +void C4TransfWireFrame (void); +void C4TransfWireFrame2 (void); +void C4CalcWireFrame (void); +void C4Op0D (void); +void C4Op15 (void); +void C4Op1F (void); +void S9xInitC4 (void); +void S9xSetC4 (uint8, uint16); +uint8 S9xGetC4 (uint16); +uint8 * S9xGetBasePointerC4 (uint16); +uint8 * S9xGetMemPointerC4 (uint16); + +static inline uint8 * C4GetMemPointer (uint32 Address) +{ + return (Memory.ROM + ((Address & 0xff0000) >> 1) + (Address & 0x7fff)); +} + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/c4emu.cpp b/plugins/snes9x_gx/source/snes9x/c4emu.cpp new file mode 100644 index 00000000..65e0f553 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/c4emu.cpp @@ -0,0 +1,1245 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include <math.h> +#include "snes9x.h" +#include "memmap.h" +#include "sar.h" + +static int16 C4SinTable[512] = +{ + 0, 402, 804, 1206, 1607, 2009, 2410, 2811, + 3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997, + 6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126, + 9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167, + 12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090, + 15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869, + 18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475, + 20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884, + 23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073, + 25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020, + 27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707, + 28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117, + 30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237, + 31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057, + 32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568, + 32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765, + 32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647, + 32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214, + 32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471, + 31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425, + 30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086, + 28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466, + 27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583, + 25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453, + 23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097, + 20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537, + 18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800, + 15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910, + 12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896, + 9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786, + 6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611, + 3211, 2811, 2410, 2009, 1607, 1206, 804, 402, + 0, -402, -804, -1206, -1607, -2009, -2410, -2811, + -3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997, + -6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126, + -9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167, + -12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090, + -15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869, + -18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475, + -20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884, + -23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073, + -25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020, + -27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707, + -28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117, + -30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237, + -31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057, + -32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568, + -32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765, + -32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647, + -32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214, + -32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471, + -31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425, + -30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086, + -28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466, + -27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583, + -25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453, + -23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097, + -20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537, + -18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800, + -15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910, + -12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896, + -9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786, + -6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611, + -3211, -2811, -2410, -2009, -1607, -1206, -804, -402 +}; + +static int16 C4CosTable[512] = +{ + 32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647, + 32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214, + 32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471, + 31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425, + 30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086, + 28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466, + 27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583, + 25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453, + 23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097, + 20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537, + 18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800, + 15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910, + 12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896, + 9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786, + 6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611, + 3211, 2811, 2410, 2009, 1607, 1206, 804, 402, + 0, -402, -804, -1206, -1607, -2009, -2410, -2811, + -3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997, + -6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126, + -9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167, + -12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090, + -15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869, + -18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475, + -20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884, + -23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073, + -25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020, + -27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707, + -28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117, + -30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237, + -31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057, + -32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568, + -32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765, + -32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647, + -32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214, + -32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471, + -31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425, + -30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086, + -28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466, + -27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583, + -25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453, + -23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097, + -20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537, + -18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800, + -15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910, + -12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896, + -9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786, + -6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611, + -3211, -2811, -2410, -2009, -1607, -1206, -804, -402, + 0, 402, 804, 1206, 1607, 2009, 2410, 2811, + 3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997, + 6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126, + 9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167, + 12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090, + 15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869, + 18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475, + 20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884, + 23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073, + 25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020, + 27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707, + 28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117, + 30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237, + 31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057, + 32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568, + 32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765 +}; + +static uint8 C4TestPattern[12 * 4] = +{ + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, + 0x80, 0xff, 0xff, 0x7f, + 0x00, 0x80, 0x00, 0xff, + 0x7f, 0x00, 0xff, 0x7f, + 0xff, 0x7f, 0xff, 0xff, + 0x00, 0x00, 0x01, 0xff, + 0xff, 0xfe, 0x00, 0x01, + 0x00, 0xff, 0xfe, 0x00 +}; + +static void C4ConvOAM (void); +static void C4DoScaleRotate (int); +static void C4DrawLine (int32, int32, int16, int32, int32, int16, uint8); +static void C4DrawWireFrame (void); +static void C4TransformLines (void); +static void C4BitPlaneWave (void); +static void C4SprDisintegrate (void); +static void C4ProcessSprites (void); + + +static void C4ConvOAM (void) +{ + uint8 *OAMptr = Memory.C4RAM + (Memory.C4RAM[0x626] << 2); + for (uint8 *i = Memory.C4RAM + 0x1fd; i > OAMptr; i -= 4) + *i = 0xe0; // Clear OAM-to-be + + uint8 *OAMptr2; + uint16 globalX, globalY; + int16 SprX, SprY; + uint8 SprName, SprAttr; + uint8 SprCount; + + globalX = READ_WORD(Memory.C4RAM + 0x0621); + globalY = READ_WORD(Memory.C4RAM + 0x0623); + OAMptr2 = Memory.C4RAM + 0x200 + (Memory.C4RAM[0x626] >> 2); + +#ifdef DEBUGGER + if (Memory.C4RAM[0x625] != 0) + printf("$6625=%02x, expected 00\n", Memory.C4RAM[0x625]); + if ((Memory.C4RAM[0x626] >> 2) != Memory.C4RAM[0x629]) + printf("$6629=%02x, expected %02x\n", Memory.C4RAM[0x629], (Memory.C4RAM[0x626] >> 2)); + if (((uint16) Memory.C4RAM[0x626] << 2) != READ_WORD(Memory.C4RAM + 0x627)) + printf("$6627=%04x, expected %04x\n", READ_WORD(Memory.C4RAM + 0x627), ((uint16) Memory.C4RAM[0x626] << 2)); +#endif + + if (Memory.C4RAM[0x0620] != 0) + { + SprCount = 128 - Memory.C4RAM[0x626]; + + uint8 offset = (Memory.C4RAM[0x626] & 3) * 2; + uint8 *srcptr = Memory.C4RAM + 0x220; + + for (int i = Memory.C4RAM[0x0620]; i > 0 && SprCount > 0; i--, srcptr += 16) + { + SprX = READ_WORD(srcptr) - globalX; + SprY = READ_WORD(srcptr + 2) - globalY; + SprName = srcptr[5]; + SprAttr = srcptr[4] | srcptr[0x06]; // XXX: mask bits? + + uint8 *sprptr = C4GetMemPointer(READ_3WORD(srcptr + 7)); + if (*sprptr != 0) + { + int16 X, Y; + + for (int SprCnt = *sprptr++; SprCnt > 0 && SprCount > 0; SprCnt--, sprptr += 4) + { + X = (int8) sprptr[1]; + if (SprAttr & 0x40) + X = -X - ((sprptr[0] & 0x20) ? 16 : 8); // flip X + X += SprX; + + if (X >= -16 && X <= 272) + { + Y = (int8) sprptr[2]; + if (SprAttr & 0x80) + Y = -Y - ((sprptr[0] & 0x20) ? 16 : 8); + Y += SprY; + + if (Y >= -16 && Y <= 224) + { + OAMptr[0] = X & 0xff; + OAMptr[1] = (uint8) Y; + OAMptr[2] = SprName + sprptr[3]; + OAMptr[3] = SprAttr ^ (sprptr[0] & 0xc0); // XXX: Carry from SprName addition? + + *OAMptr2 &= ~(3 << offset); + if (X & 0x100) + *OAMptr2 |= 1 << offset; + if (sprptr[0] & 0x20) + *OAMptr2 |= 2 << offset; + + OAMptr += 4; + SprCount--; + + offset = (offset + 2) & 6; + if (offset == 0) + OAMptr2++; + } + } + } + } + else + if (SprCount > 0) + { + // XXX: Should we be testing -16<=SprX<=272 and -16<=SprY<=224? + OAMptr[0] = (uint8) SprX; + OAMptr[1] = (uint8) SprY; + OAMptr[2] = SprName; + OAMptr[3] = SprAttr; + + *OAMptr2 &= ~(3 << offset); + if (SprX & 0x100) + *OAMptr2 |= 3 << offset; + else + *OAMptr2 |= 2 << offset; + + OAMptr += 4; + SprCount--; + + offset = (offset + 2) & 6; + if (offset == 0) + OAMptr2++; + } + } + } +} + +static void C4DoScaleRotate (int row_padding) +{ + int16 A, B, C, D; + + // Calculate matrix + int32 XScale = READ_WORD(Memory.C4RAM + 0x1f8f); + if (XScale & 0x8000) + XScale = 0x7fff; + + int32 YScale = READ_WORD(Memory.C4RAM + 0x1f92); + if (YScale & 0x8000) + YScale = 0x7fff; + + if (READ_WORD(Memory.C4RAM + 0x1f80) == 0) // no rotation + { + // XXX: only do this for C and D? + // XXX: and then only when YScale is 0x1000? + A = (int16) XScale; + B = 0; + C = 0; + D = (int16) YScale; + } + else + if (READ_WORD(Memory.C4RAM + 0x1f80) == 128) // 90 degree rotation + { + // XXX: Really do this? + A = 0; + B = (int16) (-YScale); + C = (int16) XScale; + D = 0; + } + else + if (READ_WORD(Memory.C4RAM + 0x1f80) == 256) // 180 degree rotation + { + // XXX: Really do this? + A = (int16) (-XScale); + B = 0; + C = 0; + D = (int16) (-YScale); + } + else + if (READ_WORD(Memory.C4RAM + 0x1f80) == 384) // 270 degree rotation + { + // XXX: Really do this? + A = 0; + B = (int16) YScale; + C = (int16) (-XScale); + D = 0; + } + else + { + A = (int16) SAR(C4CosTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * XScale, 15); + B = (int16) (-SAR(C4SinTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * YScale, 15)); + C = (int16) SAR(C4SinTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * XScale, 15); + D = (int16) SAR(C4CosTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * YScale, 15); + } + + // Calculate Pixel Resolution + uint8 w = Memory.C4RAM[0x1f89] & ~7; + uint8 h = Memory.C4RAM[0x1f8c] & ~7; + + //printf("%dx%d XScale=%04x YScale=%04x angle=%03x\n", w, h, XScale, YScale, READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff); + //printf("Matrix: [%10g %10g] [%04x %04x]\n", A / 4096.0, B / 4096.0, A & 0xffff, B & 0xffff); + //printf(" [%10g %10g] [%04x %04x]\n", C / 4096.0, D / 4096.0, C & 0xffff, D & 0xffff); + + // Clear the output RAM + memset(Memory.C4RAM, 0, (w + row_padding / 4) * h / 2); + + int32 Cx = (int16) READ_WORD(Memory.C4RAM + 0x1f83); + int32 Cy = (int16) READ_WORD(Memory.C4RAM + 0x1f86); + +#ifdef DEBUGGER + if (Memory.C4RAM[0x1f97] != 0) + printf("$7f97=%02x, expected 00\n", Memory.C4RAM[0x1f97]); + if ((Cx & ~1) != w / 2 || (Cy & ~1) != h / 2) + printf("Center is not middle of image! (%d, %d) != (%d, %d)\n", Cx, Cy, w / 2, h / 2); +#endif + + // Calculate start position (i.e. (Ox, Oy) = (0, 0)) + // The low 12 bits are fractional, so (Cx<<12) gives us the Cx we want in the function. + // We do Cx*A etc normally because the matrix parameters already have the fractional parts. + int32 LineX = (Cx << 12) - Cx * A - Cx * B; + int32 LineY = (Cy << 12) - Cy * C - Cy * D; + + // Start loop + uint32 X, Y; + uint8 byte; + int outidx = 0; + uint8 bit = 0x80; + + for (int y = 0; y < h; y++) + { + X = LineX; + Y = LineY; + + for (int x = 0; x < w; x++) + { + if ((X >> 12) >= w || (Y >> 12) >= h) + byte = 0; + else + { + uint32 addr = (Y >> 12) * w + (X >> 12); + byte = Memory.C4RAM[0x600 + (addr >> 1)]; + if (addr & 1) + byte >>= 4; + } + + // De-bitplanify + if (byte & 1) + Memory.C4RAM[outidx] |= bit; + if (byte & 2) + Memory.C4RAM[outidx + 1] |= bit; + if (byte & 4) + Memory.C4RAM[outidx + 16] |= bit; + if (byte & 8) + Memory.C4RAM[outidx + 17] |= bit; + + bit >>= 1; + if (bit == 0) + { + bit = 0x80; + outidx += 32; + } + + X += A; // Add 1 to output x => add an A and a C + Y += C; + } + + outidx += 2 + row_padding; + if (outidx & 0x10) + outidx &= ~0x10; + else + outidx -= w * 4 + row_padding; + + LineX += B; // Add 1 to output y => add a B and a D + LineY += D; + } +} + +static void C4DrawLine (int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color) +{ + // Transform coordinates + C4WFXVal = (int16) X1; + C4WFYVal = (int16) Y1; + C4WFZVal = Z1; + C4WFScale = Memory.C4RAM[0x1f90]; + C4WFX2Val = Memory.C4RAM[0x1f86]; + C4WFY2Val = Memory.C4RAM[0x1f87]; + C4WFDist = Memory.C4RAM[0x1f88]; + C4TransfWireFrame2(); + X1 = (C4WFXVal + 48) << 8; + Y1 = (C4WFYVal + 48) << 8; + + C4WFXVal = (int16) X2; + C4WFYVal = (int16) Y2; + C4WFZVal = Z2; + C4TransfWireFrame2(); + X2 = (C4WFXVal + 48) << 8; + Y2 = (C4WFYVal + 48) << 8; + + // Get line info + C4WFXVal = (int16) (X1 >> 8); + C4WFYVal = (int16) (Y1 >> 8); + C4WFX2Val = (int16) (X2 >> 8); + C4WFY2Val = (int16) (Y2 >> 8); + C4CalcWireFrame(); + X2 = (int16) C4WFXVal; + Y2 = (int16) C4WFYVal; + + // Render line + for (int i = C4WFDist ? C4WFDist : 1; i > 0; i--) + { + if (X1 > 0xff && Y1 > 0xff && X1 < 0x6000 && Y1 < 0x6000) + { + uint16 addr = (((Y1 >> 8) >> 3) << 8) - (((Y1 >> 8) >> 3) << 6) + (((X1 >> 8) >> 3) << 4) + ((Y1 >> 8) & 7) * 2; + uint8 bit = 0x80 >> ((X1 >> 8) & 7); + + Memory.C4RAM[addr + 0x300] &= ~bit; + Memory.C4RAM[addr + 0x301] &= ~bit; + if (Color & 1) + Memory.C4RAM[addr + 0x300] |= bit; + if (Color & 2) + Memory.C4RAM[addr + 0x301] |= bit; + } + + X1 += X2; + Y1 += Y2; + } +} + +static void C4DrawWireFrame (void) +{ + uint8 *line = C4GetMemPointer(READ_3WORD(Memory.C4RAM + 0x1f80)); + uint8 *point1, *point2; + int16 X1, Y1, Z1; + int16 X2, Y2, Z2; + uint8 Color; + +#ifdef DEBUGGER + if (READ_3WORD(Memory.C4RAM + 0x1f8f) & 0xff00ff) + printf("wireframe: Unexpected value in $7f8f: %06x\n", READ_3WORD(Memory.C4RAM + 0x1f8f)); + if (READ_3WORD(Memory.C4RAM + 0x1fa4) != 0x001000) + printf("wireframe: Unexpected value in $7fa4: %06x\n", READ_3WORD(Memory.C4RAM + 0x1fa4)); +#endif + + for (int i = Memory.C4RAM[0x0295]; i > 0; i--, line += 5) + { + if (line[0] == 0xff && line[1] == 0xff) + { + uint8 *tmp = line - 5; + while (tmp[2] == 0xff && tmp[3] == 0xff) + tmp -= 5; + point1 = C4GetMemPointer((Memory.C4RAM[0x1f82] << 16) | (tmp[2] << 8) | tmp[3]); + } + else + point1 = C4GetMemPointer((Memory.C4RAM[0x1f82] << 16) | (line[0] << 8) | line[1]); + + point2 = C4GetMemPointer((Memory.C4RAM[0x1f82] << 16) | (line[2] << 8) | line[3]); + + X1 = (point1[0] << 8) | point1[1]; + Y1 = (point1[2] << 8) | point1[3]; + Z1 = (point1[4] << 8) | point1[5]; + X2 = (point2[0] << 8) | point2[1]; + Y2 = (point2[2] << 8) | point2[3]; + Z2 = (point2[4] << 8) | point2[5]; + + Color = line[4]; + + C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color); + } +} + +static void C4TransformLines (void) +{ + C4WFX2Val = Memory.C4RAM[0x1f83]; + C4WFY2Val = Memory.C4RAM[0x1f86]; + C4WFDist = Memory.C4RAM[0x1f89]; + C4WFScale = Memory.C4RAM[0x1f8c]; + +#ifdef DEBUGGER + if (Memory.C4RAM[0x1f8a] != 0x90) + printf("lines: $7f8a = %02x, expected 90\n", READ_WORD(Memory.C4RAM + 0x1f8a)); +#endif + + // Transform vertices + uint8 *ptr = Memory.C4RAM; + + for (int i = READ_WORD(Memory.C4RAM + 0x1f80); i > 0; i--, ptr += 0x10) + { + C4WFXVal = READ_WORD(ptr + 1); + C4WFYVal = READ_WORD(ptr + 5); + C4WFZVal = READ_WORD(ptr + 9); + C4TransfWireFrame(); + + // Displace + WRITE_WORD(ptr + 1, C4WFXVal + 0x80); + WRITE_WORD(ptr + 5, C4WFYVal + 0x50); + } + + WRITE_WORD(Memory.C4RAM + 0x600, 23); + WRITE_WORD(Memory.C4RAM + 0x602, 0x60); + WRITE_WORD(Memory.C4RAM + 0x605, 0x40); + WRITE_WORD(Memory.C4RAM + 0x600 + 8, 23); + WRITE_WORD(Memory.C4RAM + 0x602 + 8, 0x60); + WRITE_WORD(Memory.C4RAM + 0x605 + 8, 0x40); + + ptr = Memory.C4RAM + 0xb02; + uint8 *ptr2 = Memory.C4RAM; + + for (int i = READ_WORD(Memory.C4RAM + 0xb00); i > 0; i--, ptr += 2, ptr2 += 8) + { + C4WFXVal = READ_WORD(Memory.C4RAM + (ptr[0] << 4) + 1); + C4WFYVal = READ_WORD(Memory.C4RAM + (ptr[0] << 4) + 5); + C4WFX2Val = READ_WORD(Memory.C4RAM + (ptr[1] << 4) + 1); + C4WFY2Val = READ_WORD(Memory.C4RAM + (ptr[1] << 4) + 5); + C4CalcWireFrame(); + + WRITE_WORD(ptr2 + 0x600, C4WFDist ? C4WFDist : 1); + WRITE_WORD(ptr2 + 0x602, C4WFXVal); + WRITE_WORD(ptr2 + 0x605, C4WFYVal); + } +} + +static void C4BitPlaneWave (void) +{ + static uint16 bmpdata[] = + { + 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000A, 0x000C, 0x000E, + 0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020A, 0x020C, 0x020E, + 0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040A, 0x040C, 0x040E, + 0x0600, 0x0602, 0x0604, 0x0606, 0x0608, 0x060A, 0x060C, 0x060E, + 0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080A, 0x080C, 0x080E + }; + + uint8 *dst = Memory.C4RAM; + uint32 waveptr = Memory.C4RAM[0x1f83]; + uint16 mask1 = 0xc0c0; + uint16 mask2 = 0x3f3f; + +#ifdef DEBUGGER + if (READ_3WORD(Memory.C4RAM + 0x1f80) != Memory.C4RAM[waveptr + 0xb00]) + printf("$7f80=%06x, expected %02x\n", READ_3WORD(Memory.C4RAM + 0x1f80), Memory.C4RAM[waveptr + 0xb00]); +#endif + + for (int j = 0; j < 0x10; j++) + { + do + { + int16 height = -((int8) Memory.C4RAM[waveptr + 0xb00]) - 16; + + for (int i = 0; i < 40; i++) + { + uint16 tmp = READ_WORD(dst + bmpdata[i]) & mask2; + if (height >= 0) + { + if (height < 8) + tmp |= mask1 & READ_WORD(Memory.C4RAM + 0xa00 + height * 2); + else + tmp |= mask1 & 0xff00; + } + + WRITE_WORD(dst + bmpdata[i], tmp); + + height++; + } + + waveptr = (waveptr + 1) & 0x7f; + mask1 = (mask1 >> 2) | (mask1 << 6); + mask2 = (mask2 >> 2) | (mask2 << 6); + } + while (mask1 != 0xc0c0); + + dst += 16; + + do + { + int16 height = -((int8) Memory.C4RAM[waveptr + 0xb00]) - 16; + + for (int i = 0; i < 40; i++) + { + uint16 tmp = READ_WORD(dst + bmpdata[i]) & mask2; + if (height >= 0) + { + if (height < 8) + tmp |= mask1 & READ_WORD(Memory.C4RAM + 0xa10 + height * 2); + else + tmp |= mask1 & 0xff00; + } + + WRITE_WORD(dst + bmpdata[i], tmp); + + height++; + } + + waveptr = (waveptr + 1) & 0x7f; + mask1 = (mask1 >> 2) | (mask1 << 6); + mask2 = (mask2 >> 2) | (mask2 << 6); + } + while (mask1 != 0xc0c0); + + dst += 16; + } +} + +static void C4SprDisintegrate (void) +{ + uint8 *src; + uint8 width, height; + uint32 StartX, StartY; + int32 scaleX, scaleY; + int32 Cx, Cy; + + width = Memory.C4RAM[0x1f89]; + height = Memory.C4RAM[0x1f8c]; + Cx = (int16) READ_WORD(Memory.C4RAM + 0x1f80); + Cy = (int16) READ_WORD(Memory.C4RAM + 0x1f83); + +#ifdef DEBUGGER + if ((Cx & ~1) != width / 2 || (Cy & ~1) != height / 2) + printf("Center is not middle of image for disintegrate! (%d, %d) != (%d, %d)\n", Cx, Cy, width / 2, height / 2); +#endif + + scaleX = (int16) READ_WORD(Memory.C4RAM + 0x1f86); + scaleY = (int16) READ_WORD(Memory.C4RAM + 0x1f8f); + StartX = -Cx * scaleX + (Cx << 8); + StartY = -Cy * scaleY + (Cy << 8); + + src = Memory.C4RAM + 0x600; + + memset(Memory.C4RAM, 0, width * height / 2); + + for (uint32 y = StartY, i = 0; i < height; i++, y += scaleY) + { + for (uint32 x = StartX, j = 0; j < width; j++, x += scaleX) + { + if ((x >> 8) < width && (y >> 8) < height && (y >> 8) * width + (x >> 8) < 0x2000) + { + uint8 pixel = (j & 1) ? (*src >> 4) : *src; + int idx = (y >> 11) * width * 4 + (x >> 11) * 32 + ((y >> 8) & 7) * 2; + uint8 mask = 0x80 >> ((x >> 8) & 7); + + if (pixel & 1) + Memory.C4RAM[idx] |= mask; + if (pixel & 2) + Memory.C4RAM[idx + 1] |= mask; + if (pixel & 4) + Memory.C4RAM[idx + 16] |= mask; + if (pixel & 8) + Memory.C4RAM[idx + 17] |= mask; + } + + if (j & 1) + src++; + } + } +} + +static void C4ProcessSprites (void) +{ + switch (Memory.C4RAM[0x1f4d]) + { + case 0x00: // Build OAM + #ifdef DEBUGGER + //printf("00 00 Build OAM!\n"); + #endif + C4ConvOAM(); + break; + + case 0x03: // Scale/Rotate + #ifdef DEBUGGER + //printf("00 03 Scale/Rotate!\n"); + #endif + C4DoScaleRotate(0); + break; + + case 0x05: // Transform Lines + #ifdef DEBUGGER + //printf("00 05 Transform Lines!\n"); + #endif + C4TransformLines(); + break; + + case 0x07: // Scale/Rotate + #ifdef DEBUGGER + //printf("00 07 Scale/Rotate!\n"); + #endif + C4DoScaleRotate(64); + break; + + case 0x08: // Draw wireframe + #ifdef DEBUGGER + //printf("00 08 Draw wireframe!\n"); + #endif + C4DrawWireFrame(); + break; + + case 0x0b: // Disintegrate + #ifdef DEBUGGER + //printf("00 0b Disintegrate!\n"); + #endif + C4SprDisintegrate(); + break; + + case 0x0c: // Wave + #ifdef DEBUGGER + //printf("00 0b Wave!\n"); + #endif + C4BitPlaneWave(); + break; + + default: + #ifdef DEBUGGER + printf("Unknown C4 sprite command (%02x)\n", Memory.C4RAM[0x1f4d]); + #endif + break; + } +} + +void S9xInitC4 (void) +{ + // Stupid zsnes code, we can't do the logical thing without breaking savestates + // Memory.C4RAM = &Memory.FillRAM [0x6000]; + memset(Memory.C4RAM, 0, 0x2000); +} + +uint8 S9xGetC4 (uint16 Address) +{ + if (Address == 0x7f5e) + return (0); + + return (Memory.C4RAM[Address - 0x6000]); +} + +void S9xSetC4 (uint8 byte, uint16 Address) +{ + Memory.C4RAM[Address - 0x6000] = byte; + + if (Address == 0x7f4f) + { + if (Memory.C4RAM[0x1f4d] == 0x0e && byte < 0x40 && (byte & 3) == 0) + { + #ifdef DEBUGGER + printf("Test command %02x 0e used!\n", byte); + #endif + Memory.C4RAM[0x1f80] = byte >> 2; + } + else + { + switch (byte) + { + case 0x00: // Sprite + #ifdef DEBUGGER + //printf("00 Sprite!\n"); + #endif + C4ProcessSprites(); + break; + + case 0x01: // Draw wireframe + #ifdef DEBUGGER + //printf("01 Draw wireframe!\n"); + if (Memory.C4RAM[0x1f4d] != 8) + printf("$7f4d=%02x, expected 08 for command 01 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + memset(Memory.C4RAM + 0x300, 0, 16 * 12 * 3 * 4); + C4DrawWireFrame(); + break; + + case 0x05: // Propulsion (?) + { + #ifdef DEBUGGER + //printf("05 Propulsion (?)!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 05 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + int32 tmp = 0x10000; + if (READ_WORD(Memory.C4RAM + 0x1f83)) + tmp = SAR((tmp / READ_WORD(Memory.C4RAM + 0x1f83)) * READ_WORD(Memory.C4RAM + 0x1f81), 8); + + WRITE_WORD(Memory.C4RAM + 0x1f80, (uint16) tmp); + break; + } + + case 0x0d: // Set vector length + #ifdef DEBUGGER + //printf("0d Set vector length!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 0d %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + C41FXVal = READ_WORD(Memory.C4RAM + 0x1f80); + C41FYVal = READ_WORD(Memory.C4RAM + 0x1f83); + C41FDistVal = READ_WORD(Memory.C4RAM + 0x1f86); + C4Op0D(); + WRITE_WORD(Memory.C4RAM + 0x1f89, C41FXVal); + WRITE_WORD(Memory.C4RAM + 0x1f8c, C41FYVal); + break; + + case 0x10: // Polar to rectangluar + { + #ifdef DEBUGGER + //printf("10 Polar->Rect!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 10 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + int32 tmp; + int32 r1; + r1 = READ_WORD(Memory.C4RAM + 0x1f83); + if (r1 & 0x8000) + r1 |= ~0x7fff; + else + r1 &= 0x7fff; + + tmp = SAR(r1 * C4CosTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * 2, 16); + WRITE_3WORD(Memory.C4RAM + 0x1f86, tmp); + tmp = SAR(r1 * C4SinTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * 2, 16); + WRITE_3WORD(Memory.C4RAM + 0x1f89, (tmp - SAR(tmp, 6))); + break; + } + + case 0x13: // Polar to rectangluar + { + #ifdef DEBUGGER + //printf("13 Polar->Rect!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 13 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + int32 tmp; + tmp = SAR((int32) READ_WORD(Memory.C4RAM + 0x1f83) * C4CosTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * 2, 8); + WRITE_3WORD(Memory.C4RAM + 0x1f86, tmp); + tmp = SAR((int32) READ_WORD(Memory.C4RAM + 0x1f83) * C4SinTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * 2, 8); + WRITE_3WORD(Memory.C4RAM + 0x1f89, tmp); + break; + } + + case 0x15: // Pythagorean + #ifdef DEBUGGER + //printf("15 Pythagorean!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 15 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + C41FXVal = READ_WORD(Memory.C4RAM + 0x1f80); + C41FYVal = READ_WORD(Memory.C4RAM + 0x1f83); + //C4Op15(); // optimized to: + C41FDist = (int16) sqrt((double) C41FXVal * C41FXVal + (double) C41FYVal * C41FYVal); + WRITE_WORD(Memory.C4RAM + 0x1f80, C41FDist); + break; + + case 0x1f: // atan + #ifdef DEBUGGER + //printf("1f atan!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 1f %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + C41FXVal = READ_WORD(Memory.C4RAM + 0x1f80); + C41FYVal = READ_WORD(Memory.C4RAM + 0x1f83); + C4Op1F(); + WRITE_WORD(Memory.C4RAM + 0x1f86, C41FAngleRes); + break; + + case 0x22: // Trapezoid + { + #ifdef DEBUGGER + //printf("22 Trapezoid!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 22 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + int16 angle1 = READ_WORD(Memory.C4RAM + 0x1f8c) & 0x1ff; + int16 angle2 = READ_WORD(Memory.C4RAM + 0x1f8f) & 0x1ff; + + #ifdef DEBUGGER + if (C4CosTable[angle1] == 0) + fprintf(stderr, "22 Trapezoid: Invalid tangent! angle1=%d\n", angle1); + if (C4CosTable[angle2] == 0) + fprintf(stderr, "22 Trapezoid: Invalid tangent! angle2=%d\n", angle2); + #endif + + int32 tan1 = (C4CosTable[angle1] != 0) ? ((((int32) C4SinTable[angle1]) << 16) / C4CosTable[angle1]) : 0x80000000; + int32 tan2 = (C4CosTable[angle2] != 0) ? ((((int32) C4SinTable[angle2]) << 16) / C4CosTable[angle2]) : 0x80000000; + + int16 y = READ_WORD(Memory.C4RAM + 0x1f83) - READ_WORD(Memory.C4RAM + 0x1f89); + int16 left, right; + + for (int j = 0; j < 225; j++) + { + if (y >= 0) + { + left = SAR((int32) tan1 * y, 16) - READ_WORD(Memory.C4RAM + 0x1f80) + READ_WORD(Memory.C4RAM + 0x1f86); + right = SAR((int32) tan2 * y, 16) - READ_WORD(Memory.C4RAM + 0x1f80) + READ_WORD(Memory.C4RAM + 0x1f86) + READ_WORD(Memory.C4RAM + 0x1f93); + + if (left < 0 && right < 0) + { + left = 1; + right = 0; + } + else + if (left < 0) + left = 0; + else + if (right < 0) + right = 0; + + if (left > 255 && right > 255) + { + left = 255; + right = 254; + } + else + if (left > 255) + left = 255; + else + if (right > 255) + right = 255; + } + else + { + left = 1; + right = 0; + } + + Memory.C4RAM[j + 0x800] = (uint8) left; + Memory.C4RAM[j + 0x900] = (uint8) right; + + y++; + } + + break; + } + + case 0x25: // Multiply + { + #ifdef DEBUGGER + //printf("25 Multiply!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 25 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + int32 foo = READ_3WORD(Memory.C4RAM + 0x1f80); + int32 bar = READ_3WORD(Memory.C4RAM + 0x1f83); + foo *= bar; + WRITE_3WORD(Memory.C4RAM + 0x1f80, foo); + break; + } + + case 0x2d: // Transform Coords + #ifdef DEBUGGER + //printf("2d Transform Coords!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 2d %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + if (READ_3WORD(Memory.C4RAM + 0x1f8f) & 0xff00ff) + printf("2d transform coords: Unexpected value in $7f8f: %06x\n", READ_3WORD(Memory.C4RAM + 0x1f8f)); + if (READ_3WORD(Memory.C4RAM + 0x1f8c) != 0x001000) + printf("0d transform coords: Unexpected value in $7f8c: %06x\n", READ_3WORD(Memory.C4RAM + 0x1f8c)); + #endif + C4WFXVal = READ_WORD(Memory.C4RAM + 0x1f81); + C4WFYVal = READ_WORD(Memory.C4RAM + 0x1f84); + C4WFZVal = READ_WORD(Memory.C4RAM + 0x1f87); + C4WFX2Val = Memory.C4RAM[0x1f89]; + C4WFY2Val = Memory.C4RAM[0x1f8a]; + C4WFDist = Memory.C4RAM[0x1f8b]; + C4WFScale = READ_WORD(Memory.C4RAM + 0x1f90); + C4TransfWireFrame2(); + WRITE_WORD(Memory.C4RAM + 0x1f80, C4WFXVal); + WRITE_WORD(Memory.C4RAM + 0x1f83, C4WFYVal); + break; + + case 0x40: // Sum + { + #ifdef DEBUGGER + //printf("40 Sum!\n"); + if (Memory.C4RAM[0x1f4d] != 0x0e) + printf("$7f4d=%02x, expected 0e for command 40 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + uint16 sum = 0; + for (int i = 0; i < 0x800; sum += Memory.C4RAM[i++]) ; + WRITE_WORD(Memory.C4RAM + 0x1f80, sum); + break; + } + + case 0x54: // Square + { + #ifdef DEBUGGER + //printf("54 Square!\n"); + if (Memory.C4RAM[0x1f4d] != 0x0e) + printf("$7f4d=%02x, expected 0e for command 54 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + int64 a = SAR((int64) READ_3WORD(Memory.C4RAM + 0x1f80) << 40, 40); + //printf("%08X%08X\n", (uint32) (a>>32), (uint32) (a&0xFFFFFFFF)); + a *= a; + //printf("%08X%08X\n", (uint32) (a>>32), (uint32) (a&0xFFFFFFFF)); + WRITE_3WORD(Memory.C4RAM + 0x1f83, a); + WRITE_3WORD(Memory.C4RAM + 0x1f86, (a >> 24)); + break; + } + + case 0x5c: // Immediate Reg + #ifdef DEBUGGER + //printf("5c Immediate Reg!\n"); + if (Memory.C4RAM[0x1f4d] != 0x0e) + printf("$7f4d=%02x, expected 0e for command 5c %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + for (int i = 0; i < 12 * 4; i++) + Memory.C4RAM[i] = C4TestPattern[i]; + break; + + case 0x89: // Immediate ROM + #ifdef DEBUGGER + //printf("89 Immediate ROM!\n"); + if (Memory.C4RAM[0x1f4d] != 0x0e) + printf("$7f4d=%02x, expected 0e for command 89 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + Memory.C4RAM[0x1f80] = 0x36; + Memory.C4RAM[0x1f81] = 0x43; + Memory.C4RAM[0x1f82] = 0x05; + break; + + default: + #ifdef DEBUGGER + printf("Unknown C4 command (%02x)\n", byte); + #endif + break; + } + } + } + else + if (Address == 0x7f47) + { + #ifdef DEBUGGER + //printf("C4 load memory %06x => %04x, %04x bytes\n", READ_3WORD(Memory.C4RAM + 0x1f40), READ_WORD(Memory.C4RAM + 0x1f45), READ_WORD(Memory.C4RAM + 0x1f43)); + if (byte != 0) + printf("C4 load: non-0 written to $7f47! Wrote %02x\n", byte); + if (READ_WORD(Memory.C4RAM + 0x1f45) < 0x6000 || (READ_WORD(Memory.C4RAM + 0x1f45) + READ_WORD(Memory.C4RAM + 0x1f43)) > 0x6c00) + printf("C4 load: Dest unusual! It's %04x\n", READ_WORD(Memory.C4RAM + 0x1f45)); + #endif + memmove(Memory.C4RAM + (READ_WORD(Memory.C4RAM + 0x1f45) & 0x1fff), C4GetMemPointer(READ_3WORD(Memory.C4RAM + 0x1f40)), READ_WORD(Memory.C4RAM + 0x1f43)); + } +} diff --git a/plugins/snes9x_gx/source/snes9x/cheats.cpp b/plugins/snes9x_gx/source/snes9x/cheats.cpp new file mode 100644 index 00000000..e4d648d0 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/cheats.cpp @@ -0,0 +1,578 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include <ctype.h> +#include "snes9x.h" +#include "memmap.h" +#include "cheats.h" + +#define WRAM_BITS ALL_BITS +#define SRAM_BITS ALL_BITS + (0x20000 >> 5) +#define IRAM_BITS ALL_BITS + (0x30000 >> 5) + +#define BIT_CLEAR(a, v) (a)[(v) >> 5] &= ~(1 << ((v) & 31)) + +#define TEST_BIT(a, v) ((a)[(v) >> 5] & (1 << ((v) & 31))) + +#define _S9XCHTC(c, a, b) \ + ((c) == S9X_LESS_THAN ? (a) < (b) : \ + (c) == S9X_GREATER_THAN ? (a) > (b) : \ + (c) == S9X_LESS_THAN_OR_EQUAL ? (a) <= (b) : \ + (c) == S9X_GREATER_THAN_OR_EQUAL ? (a) >= (b) : \ + (c) == S9X_EQUAL ? (a) == (b) : \ + (a) != (b)) + +#define _S9XCHTD(s, m, o) \ + ((s) == S9X_8_BITS ? ((uint8) (*((m) + (o)))) : \ + (s) == S9X_16_BITS ? ((uint16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ + (s) == S9X_24_BITS ? ((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16))) : \ + ((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) + +#define _S9XCHTDS(s, m, o) \ + ((s) == S9X_8_BITS ? ((int8) (*((m) + (o)))) : \ + (s) == S9X_16_BITS ? ((int16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ + (s) == S9X_24_BITS ? (((int32) ((*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16)) << 8)) >> 8): \ + ((int32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) + +static bool8 S9xAllHex (const char *, int); + + +static bool8 S9xAllHex (const char *code, int len) +{ + for (int i = 0; i < len; i++) + if ((code[i] < '0' || code[i] > '9') && (code[i] < 'a' || code[i] > 'f') && (code[i] < 'A' || code[i] > 'F')) + return (FALSE); + + return (TRUE); +} + +const char * S9xProActionReplayToRaw (const char *code, uint32 &address, uint8 &byte) +{ + uint32 data = 0; + + if (strlen(code) != 8 || !S9xAllHex(code, 8) || sscanf(code, "%x", &data) != 1) + return ("Invalid Pro Action Replay code - should be 8 hex digits in length."); + + address = data >> 8; + byte = (uint8) data; + + return (NULL); +} + +const char * S9xGoldFingerToRaw (const char *code, uint32 &address, bool8 &sram, uint8 &num_bytes, uint8 bytes[3]) +{ + char tmp[15]; + int i; + + if (strlen(code) != 14) + return ("Invalid Gold Finger code - should be 14 hex digits in length."); + + strncpy(tmp, code, 5); + tmp[5] = 0; + if (sscanf(tmp, "%x", &address) != 1) + return ("Invalid Gold Finger code."); + + for (i = 0; i < 3; i++) + { + unsigned int byte; + + strncpy(tmp, code + 5 + i * 2, 2); + tmp[2] = 0; + if (sscanf(tmp, "%x", &byte) != 1) + break; + bytes[i] = (uint8) byte; + } + + num_bytes = i; + sram = code[13] == '1'; + + return (NULL); +} + +const char * S9xGameGenieToRaw (const char *code, uint32 &address, uint8 &byte) +{ + char new_code[12]; + + if (strlen(code) != 9 || *(code + 4) != '-' || !S9xAllHex(code, 4) || !S9xAllHex(code + 5, 4)) + return ("Invalid Game Genie(tm) code - should be 'xxxx-xxxx'."); + + strcpy(new_code, "0x"); + strncpy(new_code + 2, code, 4); + strcpy(new_code + 6, code + 5); + + static const char *real_hex = "0123456789ABCDEF"; + static const char *genie_hex = "DF4709156BC8A23E"; + + for (int i = 2; i < 10; i++) + { + if (islower(new_code[i])) + new_code[i] = toupper(new_code[i]); + + int j; + for (j = 0; j < 16; j++) + { + if (new_code[i] == genie_hex[j]) + { + new_code[i] = real_hex[j]; + break; + } + } + + if (j == 16) + return ("Invalid hex-character in Game Genie(tm) code."); + } + + uint32 data = 0; + sscanf(new_code, "%x", &data); + byte = (uint8) (data >> 24); + address = data & 0xffffff; + address = ((address & 0x003c00) << 10) + + ((address & 0x00003c) << 14) + + ((address & 0xf00000) >> 8) + + ((address & 0x000003) << 10) + + ((address & 0x00c000) >> 6) + + ((address & 0x0f0000) >> 12) + + ((address & 0x0003c0) >> 6); + + return (NULL); +} + +void S9xStartCheatSearch (SCheatData *d) +{ + memmove(d->CWRAM, d->RAM, 0x20000); + memmove(d->CSRAM, d->SRAM, 0x10000); + memmove(d->CIRAM, &d->FillRAM[0x3000], 0x2000); + memset((char *) d->ALL_BITS, 0xff, 0x32000 >> 3); +} + +void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, S9xCheatDataSize size, bool8 is_signed, bool8 update) +{ + int l, i; + + switch (size) + { + case S9X_8_BITS: l = 0; break; + case S9X_16_BITS: l = 1; break; + case S9X_24_BITS: l = 2; break; + default: + case S9X_32_BITS: l = 3; break; + } + + if (is_signed) + { + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->RAM, i), _S9XCHTDS(size, d->CWRAM, i))) + { + if (update) + d->CWRAM[i] = d->RAM[i]; + } + else + BIT_CLEAR(d->WRAM_BITS, i); + } + + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT(d->SRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->SRAM, i), _S9XCHTDS(size, d->CSRAM, i))) + { + if (update) + d->CSRAM[i] = d->SRAM[i]; + } + else + BIT_CLEAR(d->SRAM_BITS, i); + } + + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT(d->IRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->FillRAM + 0x3000, i), _S9XCHTDS(size, d->CIRAM, i))) + { + if (update) + d->CIRAM[i] = d->FillRAM[i + 0x3000]; + } + else + BIT_CLEAR(d->IRAM_BITS, i); + } + } + else + { + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->RAM, i), _S9XCHTD(size, d->CWRAM, i))) + { + if (update) + d->CWRAM[i] = d->RAM[i]; + } + else + BIT_CLEAR(d->WRAM_BITS, i); + } + + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT(d->SRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->SRAM, i), _S9XCHTD(size, d->CSRAM, i))) + { + if (update) + d->CSRAM[i] = d->SRAM[i]; + } + else + BIT_CLEAR(d->SRAM_BITS, i); + } + + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT(d->IRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->FillRAM + 0x3000, i), _S9XCHTD(size, d->CIRAM, i))) + { + if (update) + d->CIRAM[i] = d->FillRAM[i + 0x3000]; + } + else + BIT_CLEAR(d->IRAM_BITS, i); + } + } + + for (i = 0x20000 - l; i < 0x20000; i++) + BIT_CLEAR(d->WRAM_BITS, i); + + for (i = 0x10000 - l; i < 0x10000; i++) + BIT_CLEAR(d->SRAM_BITS, i); +} + +void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, S9xCheatDataSize size, uint32 value, bool8 is_signed, bool8 update) +{ + int l, i; + + switch (size) + { + case S9X_8_BITS: l = 0; break; + case S9X_16_BITS: l = 1; break; + case S9X_24_BITS: l = 2; break; + default: + case S9X_32_BITS: l = 3; break; + } + + if (is_signed) + { + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->RAM, i), (int32) value)) + { + if (update) + d->CWRAM[i] = d->RAM[i]; + } + else + BIT_CLEAR(d->WRAM_BITS, i); + } + + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT(d->SRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->SRAM, i), (int32) value)) + { + if (update) + d->CSRAM[i] = d->SRAM[i]; + } + else + BIT_CLEAR(d->SRAM_BITS, i); + } + + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT(d->IRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->FillRAM + 0x3000, i), (int32) value)) + { + if (update) + d->CIRAM[i] = d->FillRAM[i + 0x3000]; + } + else + BIT_CLEAR(d->IRAM_BITS, i); + } + } + else + { + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->RAM, i), value)) + { + if (update) + d->CWRAM[i] = d->RAM[i]; + } + else + BIT_CLEAR(d->WRAM_BITS, i); + } + + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT(d->SRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->SRAM, i), value)) + { + if (update) + d->CSRAM[i] = d->SRAM[i]; + } + else + BIT_CLEAR(d->SRAM_BITS, i); + } + + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT(d->IRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->FillRAM + 0x3000, i), value)) + { + if (update) + d->CIRAM[i] = d->FillRAM[i + 0x3000]; + } + else + BIT_CLEAR(d->IRAM_BITS, i); + } + } + + for (i = 0x20000 - l; i < 0x20000; i++) + BIT_CLEAR(d->WRAM_BITS, i); + + for (i = 0x10000 - l; i < 0x10000; i++) + BIT_CLEAR(d->SRAM_BITS, i); +} + +void S9xSearchForAddress (SCheatData *d, S9xCheatComparisonType cmp, S9xCheatDataSize size, uint32 value, bool8 update) +{ + int l, i; + + switch (size) + { + case S9X_8_BITS: l = 0; break; + case S9X_16_BITS: l = 1; break; + case S9X_24_BITS: l = 2; break; + default: + case S9X_32_BITS: l = 3; break; + } + + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, i, (int32) value)) + { + if (update) + d->CWRAM[i] = d->RAM[i]; + } + else + BIT_CLEAR(d->WRAM_BITS, i); + } + + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT(d->SRAM_BITS, i) && _S9XCHTC(cmp, i + 0x20000, (int32) value)) + { + if (update) + d->CSRAM[i] = d->SRAM[i]; + } + else + BIT_CLEAR(d->SRAM_BITS, i); + } + + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT(d->IRAM_BITS, i) && _S9XCHTC(cmp, i + 0x30000, (int32) value)) + { + if (update) + d->CIRAM[i] = d->FillRAM[i + 0x3000]; + } + else + BIT_CLEAR(d->IRAM_BITS, i); + } + + for (i = 0x20000 - l; i < 0x20000; i++) + BIT_CLEAR(d->WRAM_BITS, i); + + for (i = 0x10000 - l; i < 0x10000; i++) + BIT_CLEAR(d->SRAM_BITS, i); +} + +void S9xOutputCheatSearchResults (SCheatData *d) +{ + int i; + + for (i = 0; i < 0x20000; i++) + { + if (TEST_BIT(d->WRAM_BITS, i)) + printf("WRAM: %05x: %02x\n", i, d->RAM[i]); + } + + for (i = 0; i < 0x10000; i++) + { + if (TEST_BIT(d->SRAM_BITS, i)) + printf("SRAM: %04x: %02x\n", i, d->SRAM[i]); + } + + for (i = 0; i < 0x2000; i++) + { + if (TEST_BIT(d->IRAM_BITS, i)) + printf("IRAM: %05x: %02x\n", i, d->FillRAM[i + 0x3000]); + } +} diff --git a/plugins/snes9x_gx/source/snes9x/cheats.h b/plugins/snes9x_gx/source/snes9x/cheats.h new file mode 100644 index 00000000..51ed71fb --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/cheats.h @@ -0,0 +1,262 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _CHEATS_H_ +#define _CHEATS_H_ + +#define MAX_CHEATS 150 + +struct SCheat +{ + uint32 address; + uint8 byte; + uint8 saved_byte; + bool8 enabled; + bool8 saved; + char name[22]; +}; + +struct SCheatData +{ + struct SCheat c[MAX_CHEATS]; + uint32 num_cheats; + uint8 CWRAM[0x20000]; + uint8 CSRAM[0x10000]; + uint8 CIRAM[0x2000]; + uint8 *RAM; + uint8 *FillRAM; + uint8 *SRAM; + uint32 ALL_BITS[0x32000 >> 5]; + uint8 CWatchRAM[0x32000]; +}; + +struct Watch +{ + bool on; + int size; + int format; + uint32 address; + char buf[12]; + char desc[32]; +}; + +typedef enum +{ + S9X_LESS_THAN, + S9X_GREATER_THAN, + S9X_LESS_THAN_OR_EQUAL, + S9X_GREATER_THAN_OR_EQUAL, + S9X_EQUAL, + S9X_NOT_EQUAL +} S9xCheatComparisonType; + +typedef enum +{ + S9X_8_BITS, + S9X_16_BITS, + S9X_24_BITS, + S9X_32_BITS +} S9xCheatDataSize; + +extern SCheatData Cheat; +extern Watch watches[16]; + +void S9xApplyCheat (uint32); +void S9xApplyCheats (void); +void S9xRemoveCheat (uint32); +void S9xRemoveCheats (void); +void S9xDeleteCheat (uint32); +void S9xDeleteCheats (void); +void S9xEnableCheat (uint32); +void S9xDisableCheat (uint32); +void S9xAddCheat (bool8, bool8, uint32, uint8); +void S9xInitCheatData (void); +void S9xInitWatchedAddress (void); +bool8 S9xLoadCheatFile (const char *); +bool8 S9xSaveCheatFile (const char *); + +void S9xStartCheatSearch (SCheatData *); +void S9xSearchForChange (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, bool8, bool8); +void S9xSearchForValue (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, uint32, bool8, bool8); +void S9xSearchForAddress (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, uint32, bool8); +void S9xOutputCheatSearchResults (SCheatData *); + +const char * S9xGameGenieToRaw (const char *, uint32 &, uint8 &); +const char * S9xProActionReplayToRaw (const char *, uint32 &, uint8 &); +const char * S9xGoldFingerToRaw (const char *, uint32 &, bool8 &, uint8 &, uint8 bytes[3]); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/cheats2.cpp b/plugins/snes9x_gx/source/snes9x/cheats2.cpp new file mode 100644 index 00000000..d174c5cf --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/cheats2.cpp @@ -0,0 +1,406 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "cheats.h" + +static uint8 S9xGetByteFree (uint32); +static void S9xSetByteFree (uint8, uint32); + + +static uint8 S9xGetByteFree (uint32 address) +{ + uint32 Cycles = CPU.Cycles; + uint32 WaitAddress = CPU.WaitAddress; + uint8 byte; + + byte = S9xGetByte(address); + + CPU.WaitAddress = WaitAddress; + CPU.Cycles = Cycles; + + return (byte); +} + +static void S9xSetByteFree (uint8 byte, uint32 address) +{ + uint32 Cycles = CPU.Cycles; + uint32 WaitAddress = CPU.WaitAddress; + + S9xSetByte(byte, address); + + CPU.WaitAddress = WaitAddress; + CPU.Cycles = Cycles; +} + +void S9xInitWatchedAddress (void) +{ + for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++) + watches[i].on = false; + +} + +void S9xInitCheatData (void) +{ + Cheat.RAM = Memory.RAM; + Cheat.SRAM = Memory.SRAM; + Cheat.FillRAM = Memory.FillRAM; +} + +void S9xAddCheat (bool8 enable, bool8 save_current_value, uint32 address, uint8 byte) +{ + if (Cheat.num_cheats < sizeof(Cheat.c) / sizeof(Cheat.c[0])) + { + Cheat.c[Cheat.num_cheats].address = address; + Cheat.c[Cheat.num_cheats].byte = byte; + Cheat.c[Cheat.num_cheats].enabled = enable; + + if (save_current_value) + { + Cheat.c[Cheat.num_cheats].saved_byte = S9xGetByteFree(address); + Cheat.c[Cheat.num_cheats].saved = TRUE; + } + + Cheat.num_cheats++; + } +} + +void S9xDeleteCheat (uint32 which1) +{ + if (which1 < Cheat.num_cheats) + { + if (Cheat.c[which1].enabled) + S9xRemoveCheat(which1); + + memmove(&Cheat.c[which1], &Cheat.c[which1 + 1], sizeof(Cheat.c[0]) * (Cheat.num_cheats - which1 - 1)); + + Cheat.num_cheats--; + } +} + +void S9xDeleteCheats (void) +{ + S9xRemoveCheats(); + Cheat.num_cheats = 0; +} + +void S9xRemoveCheat (uint32 which1) +{ + if (Cheat.c[which1].saved) + { + uint32 address = Cheat.c[which1].address; + + int block = (address & 0xffffff) >> MEMMAP_SHIFT; + uint8 *ptr = Memory.Map[block]; + + if (ptr >= (uint8 *) CMemory::MAP_LAST) + *(ptr + (address & 0xffff)) = Cheat.c[which1].saved_byte; + else + S9xSetByteFree(Cheat.c[which1].saved_byte, address); + } +} + +void S9xRemoveCheats (void) +{ + for (uint32 i = 0; i < Cheat.num_cheats; i++) + if (Cheat.c[i].enabled) + S9xRemoveCheat(i); +} + +void S9xEnableCheat (uint32 which1) +{ + if (which1 < Cheat.num_cheats && !Cheat.c[which1].enabled) + { + Cheat.c[which1].enabled = TRUE; + S9xApplyCheat(which1); + } +} + +void S9xDisableCheat (uint32 which1) +{ + if (which1 < Cheat.num_cheats && Cheat.c[which1].enabled) + { + S9xRemoveCheat(which1); + Cheat.c[which1].enabled = FALSE; + } +} + +void S9xApplyCheat (uint32 which1) +{ + uint32 address = Cheat.c[which1].address; + + if (!Cheat.c[which1].saved) + { + Cheat.c[which1].saved_byte = S9xGetByteFree(address); + Cheat.c[which1].saved = TRUE; + } + + int block = (address & 0xffffff) >> MEMMAP_SHIFT; + uint8 *ptr = Memory.Map[block]; + + if (ptr >= (uint8 *) CMemory::MAP_LAST) + *(ptr + (address & 0xffff)) = Cheat.c[which1].byte; + else + S9xSetByteFree(Cheat.c[which1].byte, address); +} + +void S9xApplyCheats (void) +{ + if (Settings.ApplyCheats) + { + for (uint32 i = 0; i < Cheat.num_cheats; i++) + if (Cheat.c[i].enabled) + S9xApplyCheat(i); + } +} + +bool8 S9xLoadCheatFile (const char *filename) +{ + FILE *fs; + uint8 data[28]; + + Cheat.num_cheats = 0; + + fs = fopen(filename, "rb"); + if (!fs) + return (FALSE); + + while (fread((void *) data, 1, 28, fs) == 28) + { + Cheat.c[Cheat.num_cheats].enabled = (data[0] & 4) == 0; + Cheat.c[Cheat.num_cheats].byte = data[1]; + Cheat.c[Cheat.num_cheats].address = data[2] | (data[3] << 8) | (data[4] << 16); + Cheat.c[Cheat.num_cheats].saved_byte = data[5]; + Cheat.c[Cheat.num_cheats].saved = (data[0] & 8) != 0; + memmove(Cheat.c[Cheat.num_cheats].name, &data[8], 20); + Cheat.c[Cheat.num_cheats++].name[20] = 0; + } + + fclose(fs); + + return (TRUE); +} + +bool8 S9xSaveCheatFile (const char *filename) +{ + if (Cheat.num_cheats == 0) + { + remove(filename); + return (TRUE); + } + + FILE *fs; + uint8 data[28]; + + fs = fopen(filename, "wb"); + if (!fs) + return (FALSE); + + for (uint32 i = 0; i < Cheat.num_cheats; i++) + { + ZeroMemory(data, 28); + + if (i == 0) + { + data[6] = 254; + data[7] = 252; + } + + if (!Cheat.c[i].enabled) + data[0] |= 4; + + if (Cheat.c[i].saved) + data[0] |= 8; + + data[1] = Cheat.c[i].byte; + data[2] = (uint8) (Cheat.c[i].address >> 0); + data[3] = (uint8) (Cheat.c[i].address >> 8); + data[4] = (uint8) (Cheat.c[i].address >> 16); + data[5] = Cheat.c[i].saved_byte; + + memmove(&data[8], Cheat.c[i].name, 19); + + if (fwrite(data, 28, 1, fs) != 1) + { + fclose(fs); + return (FALSE); + } + } + + return (fclose(fs) == 0); +} diff --git a/plugins/snes9x_gx/source/snes9x/clip.cpp b/plugins/snes9x_gx/source/snes9x/clip.cpp new file mode 100644 index 00000000..8e6baa35 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/clip.cpp @@ -0,0 +1,405 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" + +static uint8 region_map[6][6] = +{ + { 0, 0x01, 0x03, 0x07, 0x0f, 0x1f }, + { 0, 0, 0x02, 0x06, 0x0e, 0x1e }, + { 0, 0, 0, 0x04, 0x0c, 0x1c }, + { 0, 0, 0, 0, 0x08, 0x18 }, + { 0, 0, 0, 0, 0, 0x10 } +}; + +static inline uint8 CalcWindowMask (int, uint8, uint8); +static inline void StoreWindowRegions (uint8, struct ClipData *, int, int16 *, uint8 *, bool8, bool8 s = FALSE); + + +static inline uint8 CalcWindowMask (int i, uint8 W1, uint8 W2) +{ + if (!PPU.ClipWindow1Enable[i]) + { + if (!PPU.ClipWindow2Enable[i]) + return (0); + else + { + if (!PPU.ClipWindow2Inside[i]) + return (~W2); + return (W2); + } + } + else + { + if (!PPU.ClipWindow2Enable[i]) + { + if (!PPU.ClipWindow1Inside[i]) + return (~W1); + return (W1); + } + else + { + if (!PPU.ClipWindow1Inside[i]) + W1 = ~W1; + if (!PPU.ClipWindow2Inside[i]) + W2 = ~W2; + + switch (PPU.ClipWindowOverlapLogic[i]) + { + case 0: // OR + return (W1 | W2); + + case 1: // AND + return (W1 & W2); + + case 2: // XOR + return (W1 ^ W2); + + case 3: // XNOR + return (~(W1 ^ W2)); + } + } + } + + // Never get here + return (0); +} + +static inline void StoreWindowRegions (uint8 Mask, struct ClipData *Clip, int n_regions, int16 *windows, uint8 *drawing_modes, bool8 sub, bool8 StoreMode0) +{ + int ct = 0; + + for (int j = 0; j < n_regions; j++) + { + int DrawMode = drawing_modes[j]; + if (sub) + DrawMode |= 1; + if (Mask & (1 << j)) + DrawMode = 0; + + if (!StoreMode0 && !DrawMode) + continue; + + if (ct > 0 && Clip->Right[ct - 1] == windows[j] && Clip->DrawMode[ct - 1] == DrawMode) + Clip->Right[ct - 1] = windows[j + 1]; // This region borders with and has the same drawing mode as the previous region: merge them. + else + { + // Add a new region to the BG + Clip->Left[ct] = windows[j]; + Clip->Right[ct] = windows[j + 1]; + Clip->DrawMode[ct] = DrawMode; + ct++; + } + } + + Clip->Count = ct; +} + +void S9xComputeClipWindows (void) +{ + int16 windows[6] = { 0, 256, 256, 256, 256, 256 }; + uint8 drawing_modes[5] = { 0, 0, 0, 0, 0 }; + int n_regions = 1; + int i, j; + + // Calculate window regions. We have at most 5 regions, because we have 6 control points + // (screen edges, window 1 left & right, and window 2 left & right). + + if (PPU.Window1Left <= PPU.Window1Right) + { + if (PPU.Window1Left > 0) + { + windows[2] = 256; + windows[1] = PPU.Window1Left; + n_regions = 2; + } + + if (PPU.Window1Right < 255) + { + windows[n_regions + 1] = 256; + windows[n_regions] = PPU.Window1Right + 1; + n_regions++; + } + } + + if (PPU.Window2Left <= PPU.Window2Right) + { + for (i = 0; i <= n_regions; i++) + { + if (PPU.Window2Left == windows[i]) + break; + + if (PPU.Window2Left < windows[i]) + { + for (j = n_regions; j >= i; j--) + windows[j + 1] = windows[j]; + + windows[i] = PPU.Window2Left; + n_regions++; + break; + } + } + + for (; i <= n_regions; i++) + { + if (PPU.Window2Right + 1 == windows[i]) + break; + + if (PPU.Window2Right + 1 < windows[i]) + { + for (j = n_regions; j >= i; j--) + windows[j + 1] = windows[j]; + + windows[i] = PPU.Window2Right + 1; + n_regions++; + break; + } + } + } + + // Get a bitmap of which regions correspond to each window. + + uint8 W1, W2; + + if (PPU.Window1Left <= PPU.Window1Right) + { + for (i = 0; windows[i] != PPU.Window1Left; i++) ; + for (j = i; windows[j] != PPU.Window1Right + 1; j++) ; + W1 = region_map[i][j]; + } + else + W1 = 0; + + if (PPU.Window2Left <= PPU.Window2Right) + { + for (i = 0; windows[i] != PPU.Window2Left; i++) ; + for (j = i; windows[j] != PPU.Window2Right + 1; j++) ; + W2 = region_map[i][j]; + } + else + W2 = 0; + + // Color Window affects the drawing mode for each region. + // Modes are: 3=Draw as normal, 2=clip color (math only), 1=no math (draw only), 0=nothing. + + uint8 CW_color = 0, CW_math = 0; + uint8 CW = CalcWindowMask(5, W1, W2); + + switch (Memory.FillRAM[0x2130] & 0xc0) + { + case 0x00: CW_color = 0; break; + case 0x40: CW_color = ~CW; break; + case 0x80: CW_color = CW; break; + case 0xc0: CW_color = 0xff; break; + } + + switch (Memory.FillRAM[0x2130] & 0x30) + { + case 0x00: CW_math = 0; break; + case 0x10: CW_math = ~CW; break; + case 0x20: CW_math = CW; break; + case 0x30: CW_math = 0xff; break; + } + + for (i = 0; i < n_regions; i++) + { + if (!(CW_color & (1 << i))) + drawing_modes[i] |= 1; + if (!(CW_math & (1 << i))) + drawing_modes[i] |= 2; + } + + // Store backdrop clip window (draw everywhere color window allows) + + StoreWindowRegions(0, &IPPU.Clip[0][5], n_regions, windows, drawing_modes, FALSE, TRUE); + StoreWindowRegions(0, &IPPU.Clip[1][5], n_regions, windows, drawing_modes, TRUE, TRUE); + + // Store per-BG and OBJ clip windows + + for (j = 0; j < 5; j++) + { + uint8 W = Settings.DisableGraphicWindows ? 0 : CalcWindowMask(j, W1, W2); + for (int sub = 0; sub < 2; sub++) + { + if (Memory.FillRAM[sub + 0x212e] & (1 << j)) + StoreWindowRegions(W, &IPPU.Clip[sub][j], n_regions, windows, drawing_modes, sub); + else + StoreWindowRegions(0, &IPPU.Clip[sub][j], n_regions, windows, drawing_modes, sub); + } + } +} diff --git a/plugins/snes9x_gx/source/snes9x/controls.cpp b/plugins/snes9x_gx/source/snes9x/controls.cpp new file mode 100644 index 00000000..b94a4021 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/controls.cpp @@ -0,0 +1,3710 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include <map> +#include <set> +#include <vector> +#include <string> +#include <algorithm> +#include <assert.h> + +#include "snes9x.h" +#include "memmap.h" +#include "apu/apu.h" +#include "snapshot.h" +#include "controls.h" +#include "crosshairs.h" +#include "movie.h" +#include "display.h" +#ifdef NETPLAY_SUPPORT +#include "netplay.h" +#endif + +#ifdef GEKKO +#include "../snes9xgx.h" +#endif + +using namespace std; + +#define NONE (-2) +#define MP5 (-1) +#define JOYPAD0 0 +#define JOYPAD1 1 +#define JOYPAD2 2 +#define JOYPAD3 3 +#define JOYPAD4 4 +#define JOYPAD5 5 +#define JOYPAD6 6 +#define JOYPAD7 7 +#define MOUSE0 8 +#define MOUSE1 9 +#define SUPERSCOPE 10 +#define ONE_JUSTIFIER 11 +#define TWO_JUSTIFIERS 12 +#define NUMCTLS 13 // This must be LAST + +#define POLL_ALL NUMCTLS + +#define SUPERSCOPE_FIRE 0x80 +#define SUPERSCOPE_CURSOR 0x40 +#define SUPERSCOPE_TURBO 0x20 +#define SUPERSCOPE_PAUSE 0x10 +#define SUPERSCOPE_OFFSCREEN 0x02 + +#define JUSTIFIER_TRIGGER 0x80 +#define JUSTIFIER_START 0x20 +#define JUSTIFIER_SELECT 0x08 + +#define MAP_UNKNOWN (-1) +#define MAP_NONE 0 +#define MAP_BUTTON 1 +#define MAP_AXIS 2 +#define MAP_POINTER 3 + +#define FLAG_IOBIT0 (Memory.FillRAM[0x4213] & 0x40) +#define FLAG_IOBIT1 (Memory.FillRAM[0x4213] & 0x80) +#define FLAG_IOBIT(n) ((n) ? (FLAG_IOBIT1) : (FLAG_IOBIT0)) + +bool8 pad_read = 0, pad_read_last = 0; +uint8 read_idx[2 /* ports */][2 /* per port */]; + +struct exemulti +{ + int32 pos; + bool8 data1; + s9xcommand_t *script; +}; + +struct crosshair +{ + uint8 set; + uint8 img; + uint8 fg, bg; +}; + +static struct +{ + int16 x, y; + int16 V_adj; + bool8 V_var; + int16 H_adj; + bool8 H_var; + bool8 mapped; +} pseudopointer[8]; + +static struct +{ + uint16 buttons; + uint16 turbos; + uint16 toggleturbo; + uint16 togglestick; + uint8 turbo_ct; +} joypad[8]; + +static struct +{ + uint8 delta_x, delta_y; + int16 old_x, old_y; + int16 cur_x, cur_y; + uint8 buttons; + uint32 ID; + struct crosshair crosshair; +} mouse[2]; + +static struct +{ + int16 x, y; + uint8 phys_buttons; + uint8 next_buttons; + uint8 read_buttons; + uint32 ID; + struct crosshair crosshair; +} superscope; + +static struct +{ + int16 x[2], y[2]; + uint8 buttons; + bool8 offscreen[2]; + uint32 ID[2]; + struct crosshair crosshair[2]; +} justifier; + +static struct +{ + int8 pads[4]; +} mp5[2]; + +static set<struct exemulti *> exemultis; +static set<uint32> pollmap[NUMCTLS + 1]; +static map<uint32, s9xcommand_t> keymap; +static vector<s9xcommand_t *> multis; +static uint8 turbo_time; +static uint8 pseudobuttons[256]; +static bool8 FLAG_LATCH = FALSE; +static int32 curcontrollers[2] = { NONE, NONE }; +static int32 newcontrollers[2] = { JOYPAD0, NONE }; +static char buf[256]; + +static const char *color_names[32] = +{ + "Trans", + "Black", + "25Grey", + "50Grey", + "75Grey", + "White", + "Red", + "Orange", + "Yellow", + "Green", + "Cyan", + "Sky", + "Blue", + "Violet", + "MagicPink", + "Purple", + NULL, + "tBlack", + "t25Grey", + "t50Grey", + "t75Grey", + "tWhite", + "tRed", + "tOrange", + "tYellow", + "tGreen", + "tCyan", + "tSky", + "tBlue", + "tViolet", + "tMagicPink", + "tPurple" +}; + +static const char *speed_names[4] = +{ + "Var", + "Slow", + "Med", + "Fast" +}; + +static const int ptrspeeds[4] = { 1, 1, 4, 8 }; + +// Note: these should be in asciibetical order! +#define THE_COMMANDS \ + S(BeginRecordingMovie), \ + S(ClipWindows), \ + S(Debugger), \ + S(DecEmuTurbo), \ + S(DecFrameRate), \ + S(DecFrameTime), \ + S(DecTurboSpeed), \ + S(EmuTurbo), \ + S(EndRecordingMovie), \ + S(ExitEmu), \ + S(IncEmuTurbo), \ + S(IncFrameRate), \ + S(IncFrameTime), \ + S(IncTurboSpeed), \ + S(LoadFreezeFile), \ + S(LoadMovie), \ + S(LoadOopsFile), \ + S(Pause), \ + S(QuickLoad000), \ + S(QuickLoad001), \ + S(QuickLoad002), \ + S(QuickLoad003), \ + S(QuickLoad004), \ + S(QuickLoad005), \ + S(QuickLoad006), \ + S(QuickLoad007), \ + S(QuickLoad008), \ + S(QuickLoad009), \ + S(QuickLoad010), \ + S(QuickSave000), \ + S(QuickSave001), \ + S(QuickSave002), \ + S(QuickSave003), \ + S(QuickSave004), \ + S(QuickSave005), \ + S(QuickSave006), \ + S(QuickSave007), \ + S(QuickSave008), \ + S(QuickSave009), \ + S(QuickSave010), \ + S(Reset), \ + S(SaveFreezeFile), \ + S(SaveSPC), \ + S(Screenshot), \ + S(SeekToFrame), \ + S(SoftReset), \ + S(SoundChannel0), \ + S(SoundChannel1), \ + S(SoundChannel2), \ + S(SoundChannel3), \ + S(SoundChannel4), \ + S(SoundChannel5), \ + S(SoundChannel6), \ + S(SoundChannel7), \ + S(SoundChannelsOn), \ + S(SwapJoypads), \ + S(ToggleBG0), \ + S(ToggleBG1), \ + S(ToggleBG2), \ + S(ToggleBG3), \ + S(ToggleEmuTurbo), \ + S(ToggleHDMA), \ + S(ToggleSprites), \ + S(ToggleTransparency) \ + +#define S(x) x + +enum command_numbers +{ + THE_COMMANDS, + LAST_COMMAND +}; + +#undef S +#define S(x) #x + +static const char *command_names[LAST_COMMAND + 1] = +{ + THE_COMMANDS, + NULL +}; + +#undef S +#undef THE_COMMANDS + +static void DisplayStateChange (const char *, bool8); +static void DoGunLatch (int, int); +static int maptype (int); +static bool strless (const char *, const char *); +static int findstr (const char *, const char **, int); +static int get_threshold (const char **); +static const char * maptypename (int); +static int32 ApplyMulti (s9xcommand_t *, int32, int16); +static void do_polling (int); +static void UpdatePolledMouse (int); + + +static string& operator += (string &s, int i) +{ + snprintf(buf, sizeof(buf), "%d", i); + s.append(buf); + return (s); +} + +static string& operator += (string &s, double d) +{ + snprintf(buf, sizeof(buf), "%g", d); + s.append(buf); + return (s); +} + +static void DisplayStateChange (const char *str, bool8 on) +{ + snprintf(buf, sizeof(buf), "%s: %s", str, on ? "on":"off"); + S9xSetInfoString(buf); +} + +static void DoGunLatch (int x, int y) +{ + x += 40; + + if (x > 295) + x = 295; + else + if (x < 40) + x = 40; + + if (y > PPU.ScreenHeight - 1) + y = PPU.ScreenHeight - 1; + else + if (y < 0) + y = 0; + + PPU.GunVLatch = (uint16) (y + 1); + PPU.GunHLatch = (uint16) x; +} + +static int maptype (int t) +{ + switch (t) + { + case S9xNoMapping: + return (MAP_NONE); + + case S9xButtonJoypad: + case S9xButtonMouse: + case S9xButtonSuperscope: + case S9xButtonJustifier: + case S9xButtonCommand: + case S9xButtonPseudopointer: + case S9xButtonPort: + case S9xButtonMulti: + return (MAP_BUTTON); + + case S9xAxisJoypad: + case S9xAxisPseudopointer: + case S9xAxisPseudobuttons: + case S9xAxisPort: + return (MAP_AXIS); + + case S9xPointer: + case S9xPointerPort: + return (MAP_POINTER); + + default: + return (MAP_UNKNOWN); + } +} + +void S9xControlsReset (void) +{ + S9xControlsSoftReset(); + mouse[0].buttons &= ~0x30; + mouse[1].buttons &= ~0x30; + justifier.buttons &= ~JUSTIFIER_SELECT; +} + +void S9xControlsSoftReset (void) +{ + for (set<struct exemulti *>::iterator it = exemultis.begin(); it != exemultis.end(); it++) + delete *it; + exemultis.clear(); + + for (int i = 0; i < 2; i++) + for (int j = 0; j < 2; j++) + read_idx[i][j]=0; + + FLAG_LATCH = FALSE; +} + +void S9xUnmapAllControls (void) +{ + S9xControlsReset(); + + keymap.clear(); + + for (int i = 0; i < (int) multis.size(); i++) + free(multis[i]); + multis.clear(); + + for (int i = 0; i < NUMCTLS + 1; i++) + pollmap[i].clear(); + + for (int i = 0; i < 8; i++) + { + pseudopointer[i].x = 0; + pseudopointer[i].y = 0; + pseudopointer[i].H_adj = 0; + pseudopointer[i].V_adj = 0; + pseudopointer[i].H_var = 0; + pseudopointer[i].V_var = 0; + pseudopointer[i].mapped = false; + + joypad[i].buttons = 0; + joypad[i].turbos = 0; + joypad[i].turbo_ct = 0; + } + + for (int i = 0; i < 2; i++) + { + mouse[i].old_x = mouse[i].old_y = 0; + mouse[i].cur_x = mouse[i].cur_y = 0; + mouse[i].buttons = 1; + mouse[i].ID = InvalidControlID; + + if (!(mouse[i].crosshair.set & 1)) + mouse[i].crosshair.img = 0; // no image for mouse because its only logical position is game-specific, not known by the emulator + if (!(mouse[i].crosshair.set & 2)) + mouse[i].crosshair.fg = 5; + if (!(mouse[i].crosshair.set & 4)) + mouse[i].crosshair.bg = 1; + + justifier.x[i] = justifier.y[i] = 0; + justifier.offscreen[i] = 0; + justifier.ID[i] = InvalidControlID; + + if (!(justifier.crosshair[i].set & 1)) + justifier.crosshair[i].img = 4; + if (!(justifier.crosshair[i].set & 2)) + justifier.crosshair[i].fg = i ? 14 : 12; + if (!(justifier.crosshair[i].set & 4)) + justifier.crosshair[i].bg = 1; + } + + justifier.buttons = 0; + + superscope.x = superscope.y = 0; + superscope.phys_buttons = 0; + superscope.next_buttons = 0; + superscope.read_buttons = 0; + superscope.ID = InvalidControlID; + + if (!(superscope.crosshair.set & 1)) + superscope.crosshair.img = 2; + if (!(superscope.crosshair.set & 2)) + superscope.crosshair.fg = 5; + if (!(superscope.crosshair.set & 4)) + superscope.crosshair.bg = 1; + + ZeroMemory(pseudobuttons, sizeof(pseudobuttons)); + + turbo_time = 1; +} + +void S9xSetController (int port, enum controllers controller, int8 id1, int8 id2, int8 id3, int8 id4) +{ + if (port < 0 || port > 1) + return; + + switch (controller) + { + case CTL_NONE: + break; + + case CTL_JOYPAD: + if (id1 < 0 || id1 > 7) + break; + + newcontrollers[port] = JOYPAD0 + id1; + return; + + case CTL_MOUSE: + if (id1 < 0 || id1 > 1) + break; + if (!Settings.MouseMaster) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Mouse: MouseMaster disabled"); + break; + } + + newcontrollers[port] = MOUSE0 + id1; + return; + + case CTL_SUPERSCOPE: + if (!Settings.SuperScopeMaster) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Superscope: SuperScopeMaster disabled"); + break; + } + + newcontrollers[port] = SUPERSCOPE; + return; + + case CTL_JUSTIFIER: + if (id1 < 0 || id1 > 1) + break; + if (!Settings.JustifierMaster) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select Konami Justifier: JustifierMaster disabled"); + break; + } + + newcontrollers[port] = ONE_JUSTIFIER + id1; + return; + + case CTL_MP5: + if (id1 < -1 || id1 > 7) + break; + if (id2 < -1 || id2 > 7) + break; + if (id3 < -1 || id3 > 7) + break; + if (id4 < -1 || id4 > 7) + break; + if (!Settings.MultiPlayer5Master) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select MP5: MultiPlayer5Master disabled"); + break; + } + + newcontrollers[port] = MP5; + mp5[port].pads[0] = (id1 < 0) ? NONE : JOYPAD0 + id1; + mp5[port].pads[1] = (id2 < 0) ? NONE : JOYPAD0 + id2; + mp5[port].pads[2] = (id3 < 0) ? NONE : JOYPAD0 + id3; + mp5[port].pads[3] = (id4 < 0) ? NONE : JOYPAD0 + id4; + return; + + default: + fprintf(stderr, "Unknown controller type %d\n", controller); + break; + } + + newcontrollers[port] = NONE; +} + +bool S9xVerifyControllers (void) +{ + bool ret = false; + int port, i, used[NUMCTLS]; + + for (i = 0; i < NUMCTLS; used[i++] = 0) ; + + for (port = 0; port < 2; port++) + { + switch (i = newcontrollers[port]) + { + case MOUSE0: + case MOUSE1: + if (!Settings.MouseMaster) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Mouse: MouseMaster disabled"); + newcontrollers[port] = NONE; + ret = true; + break; + } + + if (used[i]++ > 0) + { + snprintf(buf, sizeof(buf), "Mouse%d used more than once! Disabling extra instances", i - MOUSE0 + 1); + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); + newcontrollers[port] = NONE; + ret = true; + break; + } + + break; + + case SUPERSCOPE: + if (!Settings.SuperScopeMaster) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Superscope: SuperScopeMaster disabled"); + newcontrollers[port] = NONE; + ret = true; + break; + } + + if (used[i]++ > 0) + { + snprintf(buf, sizeof(buf), "Superscope used more than once! Disabling extra instances"); + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); + newcontrollers[port] = NONE; + ret = true; + break; + } + + break; + + case ONE_JUSTIFIER: + case TWO_JUSTIFIERS: + if (!Settings.JustifierMaster) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select Konami Justifier: JustifierMaster disabled"); + newcontrollers[port] = NONE; + ret = true; + break; + } + + if (used[ONE_JUSTIFIER]++ > 0) + { + snprintf(buf, sizeof(buf), "Justifier used more than once! Disabling extra instances"); + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); + newcontrollers[port] = NONE; + ret = true; + break; + } + + break; + + case MP5: + if (!Settings.MultiPlayer5Master) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select MP5: MultiPlayer5Master disabled"); + newcontrollers[port] = NONE; + ret = true; + break; + } + + for (i = 0; i < 4; i++) + { + if (mp5[port].pads[i] != NONE) + { + if (used[mp5[port].pads[i] - JOYPAD0]++ > 0) + { + snprintf(buf, sizeof(buf), "Joypad%d used more than once! Disabling extra instances", mp5[port].pads[i] - JOYPAD0 + 1); + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); + mp5[port].pads[i] = NONE; + ret = true; + break; + } + } + } + + break; + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + if (used[i - JOYPAD0]++ > 0) + { + snprintf(buf, sizeof(buf), "Joypad%d used more than once! Disabling extra instances", i - JOYPAD0 + 1); + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); + newcontrollers[port] = NONE; + ret = true; + break; + } + + break; + + default: + break; + } + } + + return (ret); +} + +void S9xGetController (int port, enum controllers *controller, int8 *id1, int8 *id2, int8 *id3, int8 *id4) +{ + int i; + + *controller = CTL_NONE; + *id1 = *id2 = *id3 = *id4 = -1; + + if (port < 0 || port > 1) + return; + + switch (i = newcontrollers[port]) + { + case MP5: + *controller = CTL_MP5; + *id1 = (mp5[port].pads[0] == NONE) ? -1 : mp5[port].pads[0] - JOYPAD0; + *id2 = (mp5[port].pads[1] == NONE) ? -1 : mp5[port].pads[1] - JOYPAD0; + *id3 = (mp5[port].pads[2] == NONE) ? -1 : mp5[port].pads[2] - JOYPAD0; + *id4 = (mp5[port].pads[3] == NONE) ? -1 : mp5[port].pads[3] - JOYPAD0; + return; + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + *controller = CTL_JOYPAD; + *id1 = i - JOYPAD0; + return; + + case MOUSE0: + case MOUSE1: + *controller = CTL_MOUSE; + *id1 = i - MOUSE0; + return; + + case SUPERSCOPE: + *controller = CTL_SUPERSCOPE; + *id1 = 1; + return; + + case ONE_JUSTIFIER: + case TWO_JUSTIFIERS: + *controller = CTL_JUSTIFIER; + *id1 = i - ONE_JUSTIFIER; + return; + } +} + +void S9xReportControllers (void) +{ + static char mes[128]; + char *c = mes; + + S9xVerifyControllers(); + + for (int port = 0; port < 2; port++) + { + c += sprintf(c, "Port %d: ", port + 1); + + switch (newcontrollers[port]) + { + case NONE: + c += sprintf(c, "<none>. "); + break; + + case MP5: + c += sprintf(c, "MP5 with pads"); + for (int i = 0; i < 4; i++) + { + if (mp5[port].pads[i] == NONE) + c += sprintf(c, " <none>. "); + else + c += sprintf(c, " #%d. ", mp5[port].pads[i] + 1 - JOYPAD0); + } + + break; + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + c += sprintf(c, "Pad #%d. ", (int) (newcontrollers[port] - JOYPAD0 + 1)); + break; + + case MOUSE0: + case MOUSE1: + c += sprintf(c, "Mouse #%d. ", (int) (newcontrollers[port] - MOUSE0 + 1)); + break; + + case SUPERSCOPE: + if (port == 0) + c += sprintf(c, "Superscope (cannot fire). "); + else + c += sprintf(c, "Superscope. "); + break; + + case ONE_JUSTIFIER: + if (port == 0) + c += sprintf(c, "Blue Justifier (cannot fire). "); + else + c += sprintf(c, "Blue Justifier. "); + break; + + case TWO_JUSTIFIERS: + if (port == 0) + c += sprintf(c, "Blue and Pink Justifiers (cannot fire). "); + else + c += sprintf(c, "Blue and Pink Justifiers. "); + break; + } + } + + S9xMessage(S9X_INFO, S9X_CONFIG_INFO, mes); +} + +char * S9xGetCommandName (s9xcommand_t command) +{ + string s; + char c; + + switch (command.type) + { + case S9xButtonJoypad: + if (command.button.joypad.buttons == 0) + return (strdup("None")); + if (command.button.joypad.buttons & 0x000f) + return (strdup("None")); + + s = "Joypad"; + s += command.button.joypad.idx + 1; + + c = ' '; + if (command.button.joypad.toggle) { if (c) s += c; s += "Toggle"; c = 0; } + if (command.button.joypad.sticky) { if (c) s += c; s += "Sticky"; c = 0; } + if (command.button.joypad.turbo ) { if (c) s += c; s += "Turbo"; c = 0; } + + c = ' '; + if (command.button.joypad.buttons & SNES_UP_MASK ) { s += c; s += "Up"; c = '+'; } + if (command.button.joypad.buttons & SNES_DOWN_MASK ) { s += c; s += "Down"; c = '+'; } + if (command.button.joypad.buttons & SNES_LEFT_MASK ) { s += c; s += "Left"; c = '+'; } + if (command.button.joypad.buttons & SNES_RIGHT_MASK ) { s += c; s += "Right"; c = '+'; } + if (command.button.joypad.buttons & SNES_A_MASK ) { s += c; s += "A"; c = '+'; } + if (command.button.joypad.buttons & SNES_B_MASK ) { s += c; s += "B"; c = '+'; } + if (command.button.joypad.buttons & SNES_X_MASK ) { s += c; s += "X"; c = '+'; } + if (command.button.joypad.buttons & SNES_Y_MASK ) { s += c; s += "Y"; c = '+'; } + if (command.button.joypad.buttons & SNES_TL_MASK ) { s += c; s += "L"; c = '+'; } + if (command.button.joypad.buttons & SNES_TR_MASK ) { s += c; s += "R"; c = '+'; } + if (command.button.joypad.buttons & SNES_START_MASK ) { s += c; s += "Start"; c = '+'; } + if (command.button.joypad.buttons & SNES_SELECT_MASK) { s += c; s += "Select"; c = '+'; } + + break; + + case S9xButtonMouse: + if (!command.button.mouse.left && !command.button.mouse.right) + return (strdup("None")); + + s = "Mouse"; + s += command.button.mouse.idx + 1; + s += " "; + + if (command.button.mouse.left ) s += "L"; + if (command.button.mouse.right) s += "R"; + + break; + + case S9xButtonSuperscope: + if (!command.button.scope.fire && !command.button.scope.cursor && !command.button.scope.turbo && !command.button.scope.pause && !command.button.scope.aim_offscreen) + return (strdup("None")); + + s = "Superscope"; + + if (command.button.scope.aim_offscreen) s += " AimOffscreen"; + + c = ' '; + if (command.button.scope.fire ) { s += c; s += "Fire"; c = '+'; } + if (command.button.scope.cursor) { s += c; s += "Cursor"; c = '+'; } + if (command.button.scope.turbo ) { s += c; s += "ToggleTurbo"; c = '+'; } + if (command.button.scope.pause ) { s += c; s += "Pause"; c = '+'; } + + break; + + case S9xButtonJustifier: + if (!command.button.justifier.trigger && !command.button.justifier.start && !command.button.justifier.aim_offscreen) + return (strdup("None")); + + s = "Justifier"; + s += command.button.justifier.idx + 1; + + if (command.button.justifier.aim_offscreen) s += " AimOffscreen"; + + c = ' '; + if (command.button.justifier.trigger) { s += c; s += "Trigger"; c = '+'; } + if (command.button.justifier.start ) { s += c; s += "Start"; c = '+'; } + + break; + + case S9xButtonCommand: + if (command.button.command >= LAST_COMMAND) + return (strdup("None")); + + return (strdup(command_names[command.button.command])); + + case S9xPointer: + if (!command.pointer.aim_mouse0 && !command.pointer.aim_mouse1 && !command.pointer.aim_scope && !command.pointer.aim_justifier0 && !command.pointer.aim_justifier1) + return (strdup("None")); + + s = "Pointer"; + + c = ' '; + if (command.pointer.aim_mouse0 ) { s += c; s += "Mouse1"; c = '+'; } + if (command.pointer.aim_mouse1 ) { s += c; s += "Mouse2"; c = '+'; } + if (command.pointer.aim_scope ) { s += c; s += "Superscope"; c = '+'; } + if (command.pointer.aim_justifier0) { s += c; s += "Justifier1"; c = '+'; } + if (command.pointer.aim_justifier1) { s += c; s += "Justifier2"; c = '+'; } + + break; + + case S9xButtonPseudopointer: + if (!command.button.pointer.UD && !command.button.pointer.LR) + return (strdup("None")); + if (command.button.pointer.UD == -2 || command.button.pointer.LR == -2) + return (strdup("None")); + + s = "ButtonToPointer "; + s += command.button.pointer.idx + 1; + + if (command.button.pointer.UD) s += (command.button.pointer.UD == 1) ? 'd' : 'u'; + if (command.button.pointer.LR) s += (command.button.pointer.LR == 1) ? 'r' : 'l'; + + s += " "; + s += speed_names[command.button.pointer.speed_type]; + + break; + + case S9xAxisJoypad: + s = "Joypad"; + s += command.axis.joypad.idx + 1; + s += " Axis "; + + switch (command.axis.joypad.axis) + { + case 0: s += (command.axis.joypad.invert ? "Right/Left" : "Left/Right"); break; + case 1: s += (command.axis.joypad.invert ? "Down/Up" : "Up/Down" ); break; + case 2: s += (command.axis.joypad.invert ? "A/Y" : "Y/A" ); break; + case 3: s += (command.axis.joypad.invert ? "B/X" : "X/B" ); break; + case 4: s += (command.axis.joypad.invert ? "R/L" : "L/R" ); break; + default: return (strdup("None")); + } + + s += " T="; + s += int((command.axis.joypad.threshold + 1) * 1000 / 256) / 10.0; + s += "%"; + + break; + + case S9xAxisPseudopointer: + s = "AxisToPointer "; + s += command.axis.pointer.idx + 1; + s += command.axis.pointer.HV ? 'v' : 'h'; + s += " "; + + if (command.axis.pointer.invert) s += "-"; + + s += speed_names[command.axis.pointer.speed_type]; + + break; + + case S9xAxisPseudobuttons: + s = "AxisToButtons "; + s += command.axis.button.negbutton; + s += "/"; + s += command.axis.button.posbutton; + s += " T="; + s += int((command.axis.button.threshold + 1) * 1000 / 256) / 10.0; + s += "%"; + + break; + + case S9xButtonPort: + case S9xAxisPort: + case S9xPointerPort: + return (strdup("BUG: Port should have handled this instead of calling S9xGetCommandName()")); + + case S9xNoMapping: + return (strdup("None")); + + case S9xButtonMulti: + { + if (command.button.multi_idx >= (int) multis.size()) + return (strdup("None")); + + s = "{"; + if (multis[command.button.multi_idx]->multi_press) s = "+{"; + + bool sep = false; + + for (s9xcommand_t *m = multis[command.button.multi_idx]; m->multi_press != 3; m++) + { + if (m->type == S9xNoMapping) + { + s += ";"; + sep = false; + } + else + { + if (sep) s += ","; + if (m->multi_press == 1) s += "+"; + if (m->multi_press == 2) s += "-"; + + s += S9xGetCommandName(*m); + sep = true; + } + } + + s += "}"; + + break; + } + + default: + return (strdup("BUG: Unknown command type")); + } + + return (strdup(s.c_str())); +} + +static bool strless (const char *a, const char *b) +{ + return (strcmp(a, b) < 0); +} + +static int findstr (const char *needle, const char **haystack, int numstr) +{ + const char **r; + + r = lower_bound(haystack, haystack + numstr, needle, strless); + if (r >= haystack + numstr || strcmp(needle, *r)) + return (-1); + + return (r - haystack); +} + +static int get_threshold (const char **ss) +{ + const char *s = *ss; + int i; + + if (s[0] != 'T' || s[1] != '=') + return (-1); + + s += 2; + i = 0; + + if (s[0] == '0') + { + if (s[1] != '.') + return (-1); + + s++; + } + else + { + do + { + if (*s < '0' || *s > '9') + return (-1); + + i = i * 10 + 10 * (*s - '0'); + if (i > 1000) + return (-1); + + s++; + } + while (*s != '.' && *s != '%'); + } + + if (*s == '.') + { + if (s[1] < '0' || s[1] > '9' || s[2] != '%') + return (-1); + + i += s[1] - '0'; + } + + if (i > 1000) + return (-1); + + *ss = s; + + return (i); +} + +s9xcommand_t S9xGetCommandT (const char *name) +{ + s9xcommand_t cmd; + int i, j; + const char *s; + + ZeroMemory(&cmd, sizeof(cmd)); + cmd.type = S9xBadMapping; + cmd.multi_press = 0; + cmd.button_norpt = 0; + + if (!strcmp(name, "None")) + cmd.type = S9xNoMapping; + else + if (!strncmp(name, "Joypad", 6)) + { + if (name[6] < '1' || name[6] > '8' || name[7] != ' ') + return (cmd); + + if (!strncmp(name + 8, "Axis ", 5)) + { + cmd.axis.joypad.idx = name[6] - '1'; + s = name + 13; + + if (!strncmp(s, "Left/Right ", 11)) { j = 0; i = 0; s += 11; } + else + if (!strncmp(s, "Right/Left ", 11)) { j = 0; i = 1; s += 11; } + else + if (!strncmp(s, "Up/Down ", 8)) { j = 1; i = 0; s += 8; } + else + if (!strncmp(s, "Down/Up ", 8)) { j = 1; i = 1; s += 8; } + else + if (!strncmp(s, "Y/A ", 4)) { j = 2; i = 0; s += 4; } + else + if (!strncmp(s, "A/Y ", 4)) { j = 2; i = 1; s += 4; } + else + if (!strncmp(s, "X/B ", 4)) { j = 3; i = 0; s += 4; } + else + if (!strncmp(s, "B/X ", 4)) { j = 3; i = 1; s += 4; } + else + if (!strncmp(s, "L/R ", 4)) { j = 4; i = 0; s += 4; } + else + if (!strncmp(s, "R/L ", 4)) { j = 4; i = 1; s += 4; } + else + return (cmd); + + cmd.axis.joypad.axis = j; + cmd.axis.joypad.invert = i; + i = get_threshold(&s); + if (i < 0) + return (cmd); + cmd.axis.joypad.threshold = (i - 1) * 256 / 1000; + + cmd.type = S9xAxisJoypad; + } + else + { + cmd.button.joypad.idx = name[6] - '1'; + s = name + 8; + i = 0; + + if ((cmd.button.joypad.toggle = strncmp(s, "Toggle", 6) ? 0 : 1)) s += i = 6; + if ((cmd.button.joypad.sticky = strncmp(s, "Sticky", 6) ? 0 : 1)) s += i = 6; + if ((cmd.button.joypad.turbo = strncmp(s, "Turbo", 5) ? 0 : 1)) s += i = 5; + + if (cmd.button.joypad.toggle && !(cmd.button.joypad.sticky || cmd.button.joypad.turbo)) + return (cmd); + + if (i) + { + if (*s != ' ') + return (cmd); + s++; + } + + i = 0; + + if (!strncmp(s, "Up", 2)) { i |= SNES_UP_MASK; s += 2; if (*s == '+') s++; } + if (!strncmp(s, "Down", 4)) { i |= SNES_DOWN_MASK; s += 4; if (*s == '+') s++; } + if (!strncmp(s, "Left", 4)) { i |= SNES_LEFT_MASK; s += 4; if (*s == '+') s++; } + if (!strncmp(s, "Right", 5)) { i |= SNES_RIGHT_MASK; s += 5; if (*s == '+') s++; } + + if (*s == 'A') { i |= SNES_A_MASK; s++; if (*s == '+') s++; } + if (*s == 'B') { i |= SNES_B_MASK; s++; if (*s == '+') s++; } + if (*s == 'X') { i |= SNES_X_MASK; s++; if (*s == '+') s++; } + if (*s == 'Y') { i |= SNES_Y_MASK; s++; if (*s == '+') s++; } + if (*s == 'L') { i |= SNES_TL_MASK; s++; if (*s == '+') s++; } + if (*s == 'R') { i |= SNES_TR_MASK; s++; if (*s == '+') s++; } + + if (!strncmp(s, "Start", 5)) { i |= SNES_START_MASK; s += 5; if (*s == '+') s++; } + if (!strncmp(s, "Select", 6)) { i |= SNES_SELECT_MASK; s += 6; } + + if (i == 0 || *s != 0 || *(s - 1) == '+') + return (cmd); + + cmd.button.joypad.buttons = i; + + cmd.type = S9xButtonJoypad; + } + } + else + if (!strncmp(name, "Mouse", 5)) + { + if (name[5] < '1' || name[5] > '2' || name[6] != ' ') + return (cmd); + + cmd.button.mouse.idx = name[5] - '1'; + s = name + 7; + i = 0; + + if ((cmd.button.mouse.left = (*s == 'L'))) s += i = 1; + if ((cmd.button.mouse.right = (*s == 'R'))) s += i = 1; + + if (i == 0 || *s != 0) + return (cmd); + + cmd.type = S9xButtonMouse; + } + else + if (!strncmp(name, "Superscope ", 11)) + { + s = name + 11; + i = 0; + + if ((cmd.button.scope.aim_offscreen = strncmp(s, "AimOffscreen", 12) ? 0 : 1)) { s += i = 12; if (*s == ' ') s++; else if (*s != 0) return (cmd); } + if ((cmd.button.scope.fire = strncmp(s, "Fire", 4) ? 0 : 1)) { s += i = 4; if (*s == '+') s++; } + if ((cmd.button.scope.cursor = strncmp(s, "Cursor", 6) ? 0 : 1)) { s += i = 6; if (*s == '+') s++; } + if ((cmd.button.scope.turbo = strncmp(s, "ToggleTurbo", 11) ? 0 : 1)) { s += i = 11; if (*s == '+') s++; } + if ((cmd.button.scope.pause = strncmp(s, "Pause", 5) ? 0 : 1)) { s += i = 5; } + + if (i == 0 || *s != 0 || *(s - 1) == '+') + return (cmd); + + cmd.type = S9xButtonSuperscope; + } + else + if (!strncmp(name, "Justifier", 9)) + { + if (name[9] < '1' || name[9] > '2' || name[10] != ' ') + return (cmd); + + cmd.button.justifier.idx = name[9] - '1'; + s = name + 11; + i = 0; + + if ((cmd.button.justifier.aim_offscreen = strncmp(s, "AimOffscreen", 12) ? 0 : 1)) { s += i = 12; if (*s == ' ') s++; else if (*s != 0) return (cmd); } + if ((cmd.button.justifier.trigger = strncmp(s, "Trigger", 7) ? 0 : 1)) { s += i = 7; if (*s == '+') s++; } + if ((cmd.button.justifier.start = strncmp(s, "Start", 5) ? 0 : 1)) { s += i = 5; } + + if (i == 0 || *s != 0 || *(s - 1) == '+') + return (cmd); + + cmd.type = S9xButtonJustifier; + } + else + if (!strncmp(name, "Pointer ", 8)) + { + s = name + 8; + i = 0; + + if ((cmd.pointer.aim_mouse0 = strncmp(s, "Mouse1", 6) ? 0 : 1)) { s += i = 6; if (*s == '+') s++; } + if ((cmd.pointer.aim_mouse1 = strncmp(s, "Mouse2", 6) ? 0 : 1)) { s += i = 6; if (*s == '+') s++; } + if ((cmd.pointer.aim_scope = strncmp(s, "Superscope", 10) ? 0 : 1)) { s += i = 10; if (*s == '+') s++; } + if ((cmd.pointer.aim_justifier0 = strncmp(s, "Justifier1", 10) ? 0 : 1)) { s += i = 10; if (*s == '+') s++; } + if ((cmd.pointer.aim_justifier1 = strncmp(s, "Justifier2", 10) ? 0 : 1)) { s += i = 10; } + + if (i == 0 || *s != 0 || *(s - 1) == '+') + return (cmd); + + cmd.type = S9xPointer; + } + else + if (!strncmp(name, "ButtonToPointer ", 16)) + { + if (name[16] < '1' || name[16] > '8') + return (cmd); + + cmd.button.pointer.idx = name[16] - '1'; + s = name + 17; + i = 0; + + if ((cmd.button.pointer.UD = (*s == 'u' ? -1 : (*s == 'd' ? 1 : 0)))) s += i = 1; + if ((cmd.button.pointer.LR = (*s == 'l' ? -1 : (*s == 'r' ? 1 : 0)))) s += i = 1; + + if (i == 0 || *(s++) != ' ') + return (cmd); + + for (i = 0; i < 4; i++) + if (!strcmp(s, speed_names[i])) + break; + if (i > 3) + return (cmd); + + cmd.button.pointer.speed_type = i; + + cmd.type = S9xButtonPseudopointer; + } + else + if (!strncmp(name, "AxisToPointer ", 14)) + { + if (name[14] < '1' || name[14] > '8') + return (cmd); + + cmd.axis.pointer.idx = name[14] - '1'; + s= name + 15; + i = 0; + + if (*s == 'h') + cmd.axis.pointer.HV = 0; + else + if (*s == 'v') + cmd.axis.pointer.HV = 1; + else + return (cmd); + + if (s[1] != ' ') + return (cmd); + + s += 2; + if ((cmd.axis.pointer.invert = *s == '-')) + s++; + + for (i = 0; i < 4; i++) + if (!strcmp(s, speed_names[i])) + break; + if (i > 3) + return (cmd); + + cmd.axis.pointer.speed_type = i; + + cmd.type = S9xAxisPseudopointer; + } + else + if (!strncmp(name, "AxisToButtons ", 14)) + { + s = name + 14; + + if (s[0] == '0') + { + if (s[1] != '/') + return (cmd); + + cmd.axis.button.negbutton = 0; + s += 2; + } + else + { + i = 0; + do + { + if (*s < '0' || *s > '9') + return (cmd); + + i = i * 10 + *s - '0'; + if (i > 255) + return (cmd); + } + while (*++s != '/'); + + cmd.axis.button.negbutton = i; + s++; + } + + if (s[0] == '0') + { + if (s[1] != ' ') + return (cmd); + + cmd.axis.button.posbutton = 0; + s += 2; + } + else + { + i = 0; + do + { + if (*s < '0' || *s > '9') + return (cmd); + + i = i * 10 + *s - '0'; + if (i > 255) + return (cmd); + } + while (*++s != ' '); + + cmd.axis.button.posbutton = i; + s++; + } + + i = get_threshold(&s); + if (i < 0) + return (cmd); + cmd.axis.button.threshold = (i - 1) * 256 / 1000; + + cmd.type = S9xAxisPseudobuttons; + } + else + if (!strncmp(name, "MULTI#", 6)) + { + i = strtol(name + 6, (char **) &s, 10); + if (s != NULL && *s != '\0') + return (cmd); + if (i >= (int) multis.size()) + return (cmd); + + cmd.button.multi_idx = i; + cmd.type = S9xButtonMulti; + } + else + if (((name[0] == '+' && name[1] == '{') || name[0] == '{') && name[strlen(name) - 1] == '}') + { + if (multis.size() > 2147483640) + { + fprintf(stderr, "Too many multis!"); + return (cmd); + } + + string x; + int n; + + j = 2; + for (i = (name[0] == '+') ? 2 : 1; name[i] != '\0'; i++) + { + if (name[i] == ',' || name[i] == ';') + { + if (name[i] == ';') + j++; + if (++j > 2147483640) + { + fprintf(stderr, "Multi too long!"); + return (cmd); + } + } + + if (name[i] == '{') + return (cmd); + } + + s9xcommand_t *c = (s9xcommand_t *) calloc(j, sizeof(s9xcommand_t)); + if (c == NULL) + { + perror("malloc error while parsing multi"); + return (cmd); + } + + n = 0; + i = (name[0] == '+') ? 2 : 1; + + do + { + if (name[i] == ';') + { + c[n].type = S9xNoMapping; + c[n].multi_press = 0; + c[n].button_norpt = 0; + + j = i; + } + else + if (name[i] == ',') + { + free(c); + return (cmd); + } + else + { + uint8 press = 0; + + if (name[0] == '+') + { + if (name[i] == '+') + press = 1; + else + if (name[i] == '-') + press = 2; + else + { + free(c); + return (cmd); + } + + i++; + } + + for (j = i; name[j] != ';' && name[j] != ',' && name[j] != '}'; j++) ; + + x.assign(name + i, j - i); + c[n] = S9xGetCommandT(x.c_str()); + c[n].multi_press = press; + + if (maptype(c[n].type) != MAP_BUTTON) + { + free(c); + return (cmd); + } + + if (name[j] == ';') + j--; + } + + i = j + 1; + n++; + } + while (name[i] != '\0'); + + c[n].type = S9xNoMapping; + c[n].multi_press = 3; + + multis.push_back(c); + + cmd.button.multi_idx = multis.size() - 1; + cmd.type = S9xButtonMulti; + } + else + { + i = findstr(name, command_names, LAST_COMMAND); + if (i < 0) + return (cmd); + + cmd.type = S9xButtonCommand; + cmd.button.command = i; + } + + return (cmd); +} + +const char ** S9xGetAllSnes9xCommands (void) +{ + return (command_names); +} + +s9xcommand_t S9xGetMapping (uint32 id) +{ + if (keymap.count(id) == 0) + { + s9xcommand_t cmd; + cmd.type = S9xNoMapping; + return (cmd); + } + else + return (keymap[id]); +} + +static const char * maptypename (int t) +{ + switch (t) + { + case MAP_NONE: return ("unmapped"); + case MAP_BUTTON: return ("button"); + case MAP_AXIS: return ("axis"); + case MAP_POINTER: return ("pointer"); + default: return ("unknown"); + } +} + +void S9xUnmapID (uint32 id) +{ + for (int i = 0; i < NUMCTLS + 1; i++) + pollmap[i].erase(id); + + if (mouse[0].ID == id) mouse[0].ID = InvalidControlID; + if (mouse[1].ID == id) mouse[1].ID = InvalidControlID; + if (superscope.ID == id) superscope.ID = InvalidControlID; + if (justifier.ID[0] == id) justifier.ID[0] = InvalidControlID; + if (justifier.ID[1] == id) justifier.ID[1] = InvalidControlID; + + if (id >= PseudoPointerBase) + pseudopointer[id - PseudoPointerBase].mapped = false; + + keymap.erase(id); +} + +bool S9xMapButton (uint32 id, s9xcommand_t mapping, bool poll) +{ + int t; + + if (id == InvalidControlID) + { + fprintf(stderr, "Cannot map InvalidControlID\n"); + return (false); + } + + t = maptype(mapping.type); + + if (t == MAP_NONE) + { + S9xUnmapID(id); + return (true); + } + + if (t != MAP_BUTTON) + return (false); + + t = maptype(S9xGetMapping(id).type); + + if (t != MAP_NONE && t != MAP_BUTTON) + fprintf(stderr, "WARNING: Remapping ID 0x%08x from %s to button\n", id, maptypename(t)); + + if (id >= PseudoPointerBase) + { + fprintf(stderr, "ERROR: Refusing to map pseudo-pointer #%d as a button\n", id - PseudoPointerBase); + return (false); + } + + t = -1; + + if (poll) + { + if (id >= PseudoButtonBase) + fprintf(stderr, "INFO: Ignoring attempt to set pseudo-button #%d to polling\n", id - PseudoButtonBase); + else + { + switch (mapping.type) + { + case S9xButtonJoypad: + t = JOYPAD0 + mapping.button.joypad.idx; + break; + + case S9xButtonMouse: + t = MOUSE0 + mapping.button.mouse.idx; + break; + + case S9xButtonSuperscope: + t = SUPERSCOPE; + break; + + case S9xButtonJustifier: + t = ONE_JUSTIFIER + mapping.button.justifier.idx; + break; + + case S9xButtonCommand: + case S9xButtonPseudopointer: + case S9xButtonPort: + case S9xButtonMulti: + t = POLL_ALL; + break; + } + } + } + + S9xUnmapID(id); + + keymap[id] = mapping; + + if (t >= 0) + pollmap[t].insert(id); + + return (true); +} + +void S9xReportButton (uint32 id, bool pressed) +{ + if (keymap.count(id) == 0) + return; + + if (keymap[id].type == S9xNoMapping) + return; + + if (maptype(keymap[id].type) != MAP_BUTTON) + { + fprintf(stderr, "ERROR: S9xReportButton called on %s ID 0x%08x\n", maptypename(maptype(keymap[id].type)), id); + return; + } + + if (keymap[id].type == S9xButtonCommand) // skips the "already-pressed check" unless it's a command, as a hack to work around the following problem: + if (keymap[id].button_norpt == pressed) // FIXME: this makes the controls "stick" after loading a savestate while recording a movie and holding any button + return; + + keymap[id].button_norpt = pressed; + + S9xApplyCommand(keymap[id], pressed, 0); +} + +bool S9xMapPointer (uint32 id, s9xcommand_t mapping, bool poll) +{ + int t; + + if (id == InvalidControlID) + { + fprintf(stderr, "Cannot map InvalidControlID\n"); + return (false); + } + + t = maptype(mapping.type); + + if (t == MAP_NONE) + { + S9xUnmapID(id); + return (true); + } + + if (t != MAP_POINTER) + return (false); + + t = maptype(S9xGetMapping(id).type); + + if (t != MAP_NONE && t != MAP_POINTER) + fprintf(stderr, "WARNING: Remapping ID 0x%08x from %s to pointer\n", id, maptypename(t)); + + if (id < PseudoPointerBase && id >= PseudoButtonBase) + { + fprintf(stderr, "ERROR: Refusing to map pseudo-button #%d as a pointer\n", id - PseudoButtonBase); + return (false); + } + + if (mapping.type == S9xPointer) + { + if (mapping.pointer.aim_mouse0 && mouse[0].ID != InvalidControlID && mouse[0].ID != id) + { + fprintf(stderr, "ERROR: Rejecting attempt to control Mouse1 with two pointers\n"); + return (false); + } + + if (mapping.pointer.aim_mouse1 && mouse[1].ID != InvalidControlID && mouse[1].ID != id) + { + fprintf(stderr, "ERROR: Rejecting attempt to control Mouse2 with two pointers\n"); + return (false); + } + + if (mapping.pointer.aim_scope && superscope.ID != InvalidControlID && superscope.ID != id) + { + fprintf(stderr, "ERROR: Rejecting attempt to control SuperScope with two pointers\n"); + return (false); + } + + if (mapping.pointer.aim_justifier0 && justifier.ID[0] != InvalidControlID && justifier.ID[0] != id) + { + fprintf(stderr, "ERROR: Rejecting attempt to control Justifier1 with two pointers\n"); + return (false); + } + + if (mapping.pointer.aim_justifier1 && justifier.ID[1] != InvalidControlID && justifier.ID[1] != id) + { + fprintf(stderr, "ERROR: Rejecting attempt to control Justifier2 with two pointers\n"); + return (false); + } + } + + S9xUnmapID(id); + + if (poll) + { + if (id >= PseudoPointerBase) + fprintf(stderr, "INFO: Ignoring attempt to set pseudo-pointer #%d to polling\n", id - PseudoPointerBase); + else + { + switch (mapping.type) + { + case S9xPointer: + if (mapping.pointer.aim_mouse0 ) pollmap[MOUSE0 ].insert(id); + if (mapping.pointer.aim_mouse1 ) pollmap[MOUSE1 ].insert(id); + if (mapping.pointer.aim_scope ) pollmap[SUPERSCOPE ].insert(id); + if (mapping.pointer.aim_justifier0) pollmap[ONE_JUSTIFIER ].insert(id); + if (mapping.pointer.aim_justifier1) pollmap[TWO_JUSTIFIERS].insert(id); + break; + + case S9xPointerPort: + pollmap[POLL_ALL].insert(id); + break; + } + } + } + + if (id >= PseudoPointerBase) + pseudopointer[id - PseudoPointerBase].mapped = true; + + keymap[id] = mapping; + + if (mapping.pointer.aim_mouse0 ) mouse[0].ID = id; + if (mapping.pointer.aim_mouse1 ) mouse[1].ID = id; + if (mapping.pointer.aim_scope ) superscope.ID = id; + if (mapping.pointer.aim_justifier0) justifier.ID[0] = id; + if (mapping.pointer.aim_justifier1) justifier.ID[1] = id; + + return (true); +} + +void S9xReportPointer (uint32 id, int16 x, int16 y) +{ + if (keymap.count(id) == 0) + return; + + if (keymap[id].type == S9xNoMapping) + return; + + if (maptype(keymap[id].type) != MAP_POINTER) + { + fprintf(stderr, "ERROR: S9xReportPointer called on %s ID 0x%08x\n", maptypename(maptype(keymap[id].type)), id); + return; + } + + S9xApplyCommand(keymap[id], x, y); +} + +bool S9xMapAxis (uint32 id, s9xcommand_t mapping, bool poll) +{ + int t; + + if (id == InvalidControlID) + { + fprintf(stderr, "Cannot map InvalidControlID\n"); + return (false); + } + + t = maptype(mapping.type); + + if (t == MAP_NONE) + { + S9xUnmapID(id); + return (true); + } + + if (t != MAP_AXIS) + return (false); + + t = maptype(S9xGetMapping(id).type); + + if (t != MAP_NONE && t != MAP_AXIS) + fprintf(stderr, "WARNING: Remapping ID 0x%08x from %s to axis\n", id, maptypename(t)); + + if (id >= PseudoPointerBase) + { + fprintf(stderr, "ERROR: Refusing to map pseudo-pointer #%d as an axis\n", id - PseudoPointerBase); + return (false); + } + + t = -1; + + if (poll) + { + switch (mapping.type) + { + case S9xAxisJoypad: + t = JOYPAD0 + mapping.axis.joypad.idx; + break; + + case S9xAxisPseudopointer: + case S9xAxisPseudobuttons: + case S9xAxisPort: + t=POLL_ALL; + break; + } + } + + S9xUnmapID(id); + + keymap[id] = mapping; + + if (t >= 0) + pollmap[t].insert(id); + + return (true); +} + +void S9xReportAxis (uint32 id, int16 value) +{ + if (keymap.count(id) == 0) + return; + + if (keymap[id].type == S9xNoMapping) + return; + + if (maptype(keymap[id].type) != MAP_AXIS) + { + fprintf(stderr, "ERROR: S9xReportAxis called on %s ID 0x%08x\n", maptypename(maptype(keymap[id].type)), id); + return; + } + + S9xApplyCommand(keymap[id], value, 0); +} + +static int32 ApplyMulti (s9xcommand_t *multi, int32 pos, int16 data1) +{ + while (1) + { + if (multi[pos].multi_press == 3) + return (-1); + + if (multi[pos].type == S9xNoMapping) + break; + + if (multi[pos].multi_press) + S9xApplyCommand(multi[pos], multi[pos].multi_press == 1, 0); + else + S9xApplyCommand(multi[pos], data1, 0); + + pos++; + } + + return (pos + 1); +} + +void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2) +{ + int i; + + switch (cmd.type) + { + case S9xNoMapping: + return; + + case S9xButtonJoypad: + if (cmd.button.joypad.toggle) + { + if (!data1) + return; + + uint16 r = cmd.button.joypad.buttons; + + if (cmd.button.joypad.turbo) joypad[cmd.button.joypad.idx].toggleturbo ^= r; + if (cmd.button.joypad.sticky) joypad[cmd.button.joypad.idx].togglestick ^= r; + } + else + { + uint16 r, s, t, st; + + s = t = st = 0; + r = cmd.button.joypad.buttons; + st = r & joypad[cmd.button.joypad.idx].togglestick & joypad[cmd.button.joypad.idx].toggleturbo; + r ^= st; + t = r & joypad[cmd.button.joypad.idx].toggleturbo; + r ^= t; + s = r & joypad[cmd.button.joypad.idx].togglestick; + r ^= s; + + if (cmd.button.joypad.turbo && cmd.button.joypad.sticky) + { + uint16 x = r; r = st; st = x; + x = s; s = t; t = x; + } + else + if (cmd.button.joypad.turbo) + { + uint16 x = r; r = t; t = x; + x = s; s = st; st = x; + } + else + if (cmd.button.joypad.sticky) + { + uint16 x = r; r = s; s = x; + x = t; t = st; st = x; + } + + if (data1) + { + if (!Settings.UpAndDown && !S9xMoviePlaying()) // if up+down isn't allowed AND we are NOT playing a movie, + { + if (cmd.button.joypad.buttons & (SNES_LEFT_MASK | SNES_RIGHT_MASK)) + { + // if we're pressing left or right, then unpress and unturbo them both first + // so we don't end up hittnig left AND right accidentally. + // Note though that the user can still do it on purpose, if Settings.UpAndDown = true. + // This is a feature, look up glitches in tLoZ:aLttP to find out why. + joypad[cmd.button.joypad.idx].buttons &= ~(SNES_LEFT_MASK | SNES_RIGHT_MASK); + joypad[cmd.button.joypad.idx].turbos &= ~(SNES_LEFT_MASK | SNES_RIGHT_MASK); + } + + if (cmd.button.joypad.buttons & (SNES_UP_MASK | SNES_DOWN_MASK)) + { + // and ditto for up/down + joypad[cmd.button.joypad.idx].buttons &= ~(SNES_UP_MASK | SNES_DOWN_MASK); + joypad[cmd.button.joypad.idx].turbos &= ~(SNES_UP_MASK | SNES_DOWN_MASK); + } + } + + joypad[cmd.button.joypad.idx].buttons |= r; + joypad[cmd.button.joypad.idx].turbos |= t; + joypad[cmd.button.joypad.idx].buttons ^= s; + joypad[cmd.button.joypad.idx].buttons &= ~(joypad[cmd.button.joypad.idx].turbos & st); + joypad[cmd.button.joypad.idx].turbos ^= st; + } + else + { + joypad[cmd.button.joypad.idx].buttons &= ~r; + joypad[cmd.button.joypad.idx].buttons &= ~(joypad[cmd.button.joypad.idx].turbos & t); + joypad[cmd.button.joypad.idx].turbos &= ~t; + } + } + + return; + + case S9xButtonMouse: + i = 0; + if (cmd.button.mouse.left ) i |= 0x40; + if (cmd.button.mouse.right) i |= 0x80; + + if (data1) + mouse[cmd.button.mouse.idx].buttons |= i; + else + mouse[cmd.button.mouse.idx].buttons &= ~i; + + return; + + case S9xButtonSuperscope: + i = 0; + if (cmd.button.scope.fire ) i |= SUPERSCOPE_FIRE; + if (cmd.button.scope.cursor ) i |= SUPERSCOPE_CURSOR; + if (cmd.button.scope.pause ) i |= SUPERSCOPE_PAUSE; + if (cmd.button.scope.aim_offscreen) i |= SUPERSCOPE_OFFSCREEN; + + if (data1) + { + superscope.phys_buttons |= i; + + if (cmd.button.scope.turbo) + { + superscope.phys_buttons ^= SUPERSCOPE_TURBO; + + if (superscope.phys_buttons & SUPERSCOPE_TURBO) + superscope.next_buttons |= superscope.phys_buttons & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR); + else + superscope.next_buttons &= ~(SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR); + } + + superscope.next_buttons |= i & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR | SUPERSCOPE_PAUSE); + + if (!S9xMovieActive()) // PPU modification during non-recordable command screws up movie synchronization + if ((superscope.next_buttons & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR)) && curcontrollers[1] == SUPERSCOPE && !(superscope.phys_buttons & SUPERSCOPE_OFFSCREEN)) + DoGunLatch(superscope.x, superscope.y); + } + else + { + superscope.phys_buttons &= ~i; + superscope.next_buttons &= SUPERSCOPE_OFFSCREEN | ~i; + } + + return; + + case S9xButtonJustifier: + i = 0; + if (cmd.button.justifier.trigger) i |= JUSTIFIER_TRIGGER; + if (cmd.button.justifier.start ) i |= JUSTIFIER_START; + if (cmd.button.justifier.aim_offscreen) justifier.offscreen[cmd.button.justifier.idx] = data1 ? 1 : 0; + i >>= cmd.button.justifier.idx; + + if (data1) + justifier.buttons |= i; + else + justifier.buttons &= ~i; + + return; + + case S9xButtonCommand: + if (((enum command_numbers) cmd.button.command) >= LAST_COMMAND) + { + fprintf(stderr, "Unknown command %04x\n", cmd.button.command); + return; + } + + if (!data1) + { + switch (i = cmd.button.command) + { + case EmuTurbo: + Settings.TurboMode = FALSE; + break; + } + } + else + { + switch ((enum command_numbers) (i = cmd.button.command)) + { + case ExitEmu: + S9xExit(); + break; + + case Reset: + S9xReset(); + break; + + case SoftReset: + S9xMovieUpdateOnReset(); + if (S9xMoviePlaying()) + S9xMovieStop(TRUE); + S9xSoftReset(); + break; + + case EmuTurbo: + Settings.TurboMode = TRUE; + break; + + case ToggleEmuTurbo: + Settings.TurboMode = !Settings.TurboMode; + DisplayStateChange("Turbo mode", Settings.TurboMode); + break; + + case ClipWindows: + Settings.DisableGraphicWindows = !Settings.DisableGraphicWindows; + DisplayStateChange("Graphic clip windows", !Settings.DisableGraphicWindows); + break; + + case Debugger: + #ifdef DEBUGGER + CPU.Flags |= DEBUG_MODE_FLAG; + #endif + break; + + case IncFrameRate: + if (Settings.SkipFrames == AUTO_FRAMERATE) + Settings.SkipFrames = 1; + else + if (Settings.SkipFrames < 10) + Settings.SkipFrames++; + + if (Settings.SkipFrames == AUTO_FRAMERATE) + S9xSetInfoString("Auto frame skip"); + else + { + sprintf(buf, "Frame skip: %d", Settings.SkipFrames - 1); + S9xSetInfoString(buf); + } + + break; + + case DecFrameRate: + if (Settings.SkipFrames <= 1) + Settings.SkipFrames = AUTO_FRAMERATE; + else + if (Settings.SkipFrames != AUTO_FRAMERATE) + Settings.SkipFrames--; + + if (Settings.SkipFrames == AUTO_FRAMERATE) + S9xSetInfoString("Auto frame skip"); + else + { + sprintf(buf, "Frame skip: %d", Settings.SkipFrames - 1); + S9xSetInfoString(buf); + } + + break; + + case IncEmuTurbo: + if (Settings.TurboSkipFrames < 20) + Settings.TurboSkipFrames += 1; + else + if (Settings.TurboSkipFrames < 200) + Settings.TurboSkipFrames += 5; + sprintf(buf, "Turbo frame skip: %d", Settings.TurboSkipFrames); + S9xSetInfoString(buf); + break; + + case DecEmuTurbo: + if (Settings.TurboSkipFrames > 20) + Settings.TurboSkipFrames -= 5; + else + if (Settings.TurboSkipFrames > 0) + Settings.TurboSkipFrames -= 1; + sprintf(buf, "Turbo frame skip: %d", Settings.TurboSkipFrames); + S9xSetInfoString(buf); + break; + + case IncFrameTime: // Increase emulated frame time by 1ms + Settings.FrameTime += 1000; + sprintf(buf, "Emulated frame time: %dms", Settings.FrameTime / 1000); + S9xSetInfoString(buf); + break; + + case DecFrameTime: // Decrease emulated frame time by 1ms + if (Settings.FrameTime >= 1000) + Settings.FrameTime -= 1000; + sprintf(buf, "Emulated frame time: %dms", Settings.FrameTime / 1000); + S9xSetInfoString(buf); + break; + + case IncTurboSpeed: + if (turbo_time >= 120) + break; + turbo_time++; + sprintf(buf, "Turbo speed: %d", turbo_time); + S9xSetInfoString(buf); + break; + + case DecTurboSpeed: + if (turbo_time <= 1) + break; + turbo_time--; + sprintf(buf, "Turbo speed: %d", turbo_time); + S9xSetInfoString(buf); + break; + + case LoadFreezeFile: + S9xUnfreezeGame(S9xChooseFilename(TRUE)); + break; + + case SaveFreezeFile: + S9xFreezeGame(S9xChooseFilename(FALSE)); + break; + + case LoadOopsFile: + { + char filename[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + _splitpath(Memory.ROMFilename, drive, dir, def, ext); + snprintf(filename, PATH_MAX + 1, "%s%s%s.%.*s", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, _MAX_EXT - 1, "oops"); + + if (S9xUnfreezeGame(filename)) + { + sprintf(buf, "%s.%.*s loaded", def, _MAX_EXT - 1, "oops"); + S9xSetInfoString (buf); + } + else + S9xMessage(S9X_ERROR, S9X_FREEZE_FILE_NOT_FOUND, "Oops file not found"); + + break; + } + + case Pause: + Settings.Paused = !Settings.Paused; + DisplayStateChange("Pause", Settings.Paused); + #if defined(NETPLAY_SUPPORT) && !defined(__WIN32__) + S9xNPSendPause(Settings.Paused); + #endif + break; + + case QuickLoad000: + case QuickLoad001: + case QuickLoad002: + case QuickLoad003: + case QuickLoad004: + case QuickLoad005: + case QuickLoad006: + case QuickLoad007: + case QuickLoad008: + case QuickLoad009: + case QuickLoad010: + { + char filename[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + _splitpath(Memory.ROMFilename, drive, dir, def, ext); + snprintf(filename, PATH_MAX + 1, "%s%s%s.%03d", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, i - QuickLoad000); + + if (S9xUnfreezeGame(filename)) + { + sprintf(buf, "%s.%03d loaded", def, i - QuickLoad000); + S9xSetInfoString(buf); + } + else + S9xMessage(S9X_ERROR, S9X_FREEZE_FILE_NOT_FOUND, "Freeze file not found"); + + break; + } + + case QuickSave000: + case QuickSave001: + case QuickSave002: + case QuickSave003: + case QuickSave004: + case QuickSave005: + case QuickSave006: + case QuickSave007: + case QuickSave008: + case QuickSave009: + case QuickSave010: + { + char filename[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + _splitpath(Memory.ROMFilename, drive, dir, def, ext); + snprintf(filename, PATH_MAX + 1, "%s%s%s.%03d", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, i - QuickSave000); + + sprintf(buf, "%s.%03d saved", def, i - QuickSave000); + S9xSetInfoString(buf); + + S9xFreezeGame(filename); + break; + } + + case SaveSPC: + S9xDumpSPCSnapshot(); + break; + + case Screenshot: + Settings.TakeScreenshot = TRUE; + break; + + case SoundChannel0: + case SoundChannel1: + case SoundChannel2: + case SoundChannel3: + case SoundChannel4: + case SoundChannel5: + case SoundChannel6: + case SoundChannel7: + S9xToggleSoundChannel(i - SoundChannel0); + sprintf(buf, "Sound channel %d toggled", i - SoundChannel0); + S9xSetInfoString(buf); + break; + + case SoundChannelsOn: + S9xToggleSoundChannel(8); + S9xSetInfoString("All sound channels on"); + break; + + case ToggleBG0: + Settings.BG_Forced ^= 1; + DisplayStateChange("BG#0", !(Settings.BG_Forced & 1)); + break; + + case ToggleBG1: + Settings.BG_Forced ^= 2; + DisplayStateChange("BG#1", !(Settings.BG_Forced & 2)); + break; + + case ToggleBG2: + Settings.BG_Forced ^= 4; + DisplayStateChange("BG#2", !(Settings.BG_Forced & 4)); + break; + + case ToggleBG3: + Settings.BG_Forced ^= 8; + DisplayStateChange("BG#3", !(Settings.BG_Forced & 8)); + break; + + case ToggleSprites: + Settings.BG_Forced ^= 16; + DisplayStateChange("Sprites", !(Settings.BG_Forced & 16)); + break; + + case ToggleHDMA: + Settings.DisableHDMA = !Settings.DisableHDMA; + DisplayStateChange("HDMA emulation", !Settings.DisableHDMA); + break; + + case ToggleTransparency: + Settings.Transparency = !Settings.Transparency; + DisplayStateChange("Transparency effects", Settings.Transparency); + break; + + case BeginRecordingMovie: + if (S9xMovieActive()) + S9xMovieStop(FALSE); + S9xMovieCreate(S9xChooseMovieFilename(FALSE), 0xFF, MOVIE_OPT_FROM_RESET, NULL, 0); + break; + + case LoadMovie: + if (S9xMovieActive()) + S9xMovieStop(FALSE); + S9xMovieOpen(S9xChooseMovieFilename(TRUE), FALSE); + break; + + case EndRecordingMovie: + if (S9xMovieActive()) + S9xMovieStop(FALSE); + break; + + case SwapJoypads: + if ((curcontrollers[0] != NONE && !(curcontrollers[0] >= JOYPAD0 && curcontrollers[0] <= JOYPAD7))) + { + S9xSetInfoString("Cannot swap pads: port 1 is not a joypad"); + break; + } + + if ((curcontrollers[1] != NONE && !(curcontrollers[1] >= JOYPAD0 && curcontrollers[1] <= JOYPAD7))) + { + S9xSetInfoString("Cannot swap pads: port 2 is not a joypad"); + break; + } + + newcontrollers[1] = curcontrollers[0]; + newcontrollers[0] = curcontrollers[1]; + + strcpy(buf, "Swap pads: P1="); + i = 14; + if (newcontrollers[0] == NONE) + { + strcpy(buf + i, "<none>"); + i += 6; + } + else + { + sprintf(buf + i, "Joypad%d", newcontrollers[0] - JOYPAD0 + 1); + i += 7; + } + + strcpy(buf + i, " P2="); + i += 4; + if (newcontrollers[1] == NONE) + strcpy(buf + i, "<none>"); + else + sprintf(buf + i, "Joypad%d", newcontrollers[1] - JOYPAD0 + 1); + + S9xSetInfoString(buf); + break; + + case SeekToFrame: + if (S9xMovieActive()) + { + sprintf(buf, "Select frame number (current: %d)", S9xMovieGetFrameCounter()); + const char *frameno = S9xStringInput(buf); + if (!frameno) + return; + + int frameDest = atoi(frameno); + if (frameDest > 0 && frameDest > (int) S9xMovieGetFrameCounter()) + { + int distance = frameDest - S9xMovieGetFrameCounter(); + Settings.HighSpeedSeek = distance; + } + } + + break; + + case LAST_COMMAND: + break; + } + } + + return; + + case S9xPointer: + if (cmd.pointer.aim_mouse0) + { + mouse[0].cur_x = data1; + mouse[0].cur_y = data2; + } + + if (cmd.pointer.aim_mouse1) + { + mouse[1].cur_x = data1; + mouse[1].cur_y = data2; + } + + if (cmd.pointer.aim_scope) + { + superscope.x = data1; + superscope.y = data2; + } + + if (cmd.pointer.aim_justifier0) + { + justifier.x[0] = data1; + justifier.y[0] = data2; + } + + if (cmd.pointer.aim_justifier1) + { + justifier.x[1] = data1; + justifier.y[1] = data2; + } + + return; + + case S9xButtonPseudopointer: + if (data1) + { + if (cmd.button.pointer.UD) + { + if (!pseudopointer[cmd.button.pointer.idx].V_adj) + pseudopointer[cmd.button.pointer.idx].V_adj = cmd.button.pointer.UD * ptrspeeds[cmd.button.pointer.speed_type]; + pseudopointer[cmd.button.pointer.idx].V_var = (cmd.button.pointer.speed_type == 0); + } + + if (cmd.button.pointer.LR) + { + if (!pseudopointer[cmd.button.pointer.idx].H_adj) + pseudopointer[cmd.button.pointer.idx].H_adj = cmd.button.pointer.LR * ptrspeeds[cmd.button.pointer.speed_type]; + pseudopointer[cmd.button.pointer.idx].H_var = (cmd.button.pointer.speed_type == 0); + } + } + else + { + if (cmd.button.pointer.UD) + { + pseudopointer[cmd.button.pointer.idx].V_adj = 0; + pseudopointer[cmd.button.pointer.idx].V_var = false; + } + + if (cmd.button.pointer.LR) + { + pseudopointer[cmd.button.pointer.idx].H_adj = 0; + pseudopointer[cmd.button.pointer.idx].H_var = false; + } + } + + return; + + case S9xAxisJoypad: + { + uint16 pos, neg; + + switch (cmd.axis.joypad.axis) + { + case 0: neg = SNES_LEFT_MASK; pos = SNES_RIGHT_MASK; break; + case 1: neg = SNES_UP_MASK; pos = SNES_DOWN_MASK; break; + case 2: neg = SNES_Y_MASK; pos = SNES_A_MASK; break; + case 3: neg = SNES_X_MASK; pos = SNES_B_MASK; break; + case 4: neg = SNES_TL_MASK; pos = SNES_TR_MASK; break; + default: return; + } + + if (cmd.axis.joypad.invert) + data1 = -data1; + + uint16 p, r; + + p = r = 0; + if (data1 > ((cmd.axis.joypad.threshold + 1) * 127)) + p |= pos; + else + r |= pos; + + if (data1 <= ((cmd.axis.joypad.threshold + 1) * -127)) + p |= neg; + else + r |= neg; + + joypad[cmd.axis.joypad.idx].buttons |= p; + joypad[cmd.axis.joypad.idx].buttons &= ~r; + joypad[cmd.axis.joypad.idx].turbos &= ~(p | r); + + return; + } + + case S9xAxisPseudopointer: + if (data1 == 0) + { + if (cmd.axis.pointer.HV) + { + pseudopointer[cmd.axis.pointer.idx].V_adj = 0; + pseudopointer[cmd.axis.pointer.idx].V_var = false; + } + else + { + pseudopointer[cmd.axis.pointer.idx].H_adj = 0; + pseudopointer[cmd.axis.pointer.idx].H_var = false; + } + } + else + { + if (cmd.axis.pointer.invert) + data1 = -data1; + + if (cmd.axis.pointer.HV) + { + if (!pseudopointer[cmd.axis.pointer.idx].V_adj) + pseudopointer[cmd.axis.pointer.idx].V_adj = (int16) ((int32) data1 * ptrspeeds[cmd.axis.pointer.speed_type] / 32767); + pseudopointer[cmd.axis.pointer.idx].V_var = (cmd.axis.pointer.speed_type == 0); + } + else + { + if (!pseudopointer[cmd.axis.pointer.idx].H_adj) + pseudopointer[cmd.axis.pointer.idx].H_adj = (int16) ((int32) data1 * ptrspeeds[cmd.axis.pointer.speed_type] / 32767); + pseudopointer[cmd.axis.pointer.idx].H_var = (cmd.axis.pointer.speed_type == 0); + } + } + + return; + + case S9xAxisPseudobuttons: + if (data1 > ((cmd.axis.button.threshold + 1) * 127)) + { + if (!pseudobuttons[cmd.axis.button.posbutton]) + { + pseudobuttons[cmd.axis.button.posbutton] = 1; + S9xReportButton(PseudoButtonBase + cmd.axis.button.posbutton, true); + } + } + else + { + if (pseudobuttons[cmd.axis.button.posbutton]) + { + pseudobuttons[cmd.axis.button.posbutton] = 0; + S9xReportButton(PseudoButtonBase + cmd.axis.button.posbutton, false); + } + } + + if (data1 <= ((cmd.axis.button.threshold + 1) * -127)) + { + if (!pseudobuttons[cmd.axis.button.negbutton]) + { + pseudobuttons[cmd.axis.button.negbutton] = 1; + S9xReportButton(PseudoButtonBase + cmd.axis.button.negbutton, true); + } + } + else + { + if (pseudobuttons[cmd.axis.button.negbutton]) + { + pseudobuttons[cmd.axis.button.negbutton] = 0; + S9xReportButton(PseudoButtonBase + cmd.axis.button.negbutton, false); + } + } + + return; + + case S9xButtonPort: + case S9xAxisPort: + case S9xPointerPort: + S9xHandlePortCommand(cmd, data1, data2); + return; + + case S9xButtonMulti: + if (cmd.button.multi_idx >= (int) multis.size()) + return; + + if (multis[cmd.button.multi_idx]->multi_press && !data1) + return; + + i = ApplyMulti(multis[cmd.button.multi_idx], 0, data1); + if (i >= 0) + { + struct exemulti *e = new struct exemulti; + e->pos = i; + e->data1 = data1 != 0; + e->script = multis[cmd.button.multi_idx]; + exemultis.insert(e); + } + + return; + + default: + fprintf(stderr, "WARNING: Unknown command type %d\n", cmd.type); + return; + } +} + +static void do_polling (int mp) +{ + set<uint32>::iterator itr; + + if (S9xMoviePlaying()) + return; + + if (pollmap[mp].empty()) + return; + + for (itr = pollmap[mp].begin(); itr != pollmap[mp].end(); itr++) + { + switch (maptype(keymap[*itr].type)) + { + case MAP_BUTTON: + { + bool pressed; + if (S9xPollButton(*itr, &pressed)) + S9xReportButton(*itr, pressed); + break; + } + + case MAP_AXIS: + { + int16 value; + if (S9xPollAxis(*itr, &value)) + S9xReportAxis(*itr, value); + break; + } + + case MAP_POINTER: + { + int16 x, y; + if (S9xPollPointer(*itr, &x, &y)) + S9xReportPointer(*itr, x, y); + break; + } + + default: + break; + } + } +} + +static void UpdatePolledMouse (int i) +{ + int16 j; + + j = mouse[i - MOUSE0].cur_x - mouse[i - MOUSE0].old_x; + + if (j < -127) + { + mouse[i - MOUSE0].delta_x = 0xff; + mouse[i - MOUSE0].old_x -= 127; + } + else + if (j < 0) + { + mouse[i - MOUSE0].delta_x = 0x80 | -j; + mouse[i - MOUSE0].old_x = mouse[i - MOUSE0].cur_x; + } + else + if (j > 127) + { + mouse[i - MOUSE0].delta_x = 0x7f; + mouse[i - MOUSE0].old_x += 127; + } + else + { + mouse[i - MOUSE0].delta_x = (uint8) j; + mouse[i - MOUSE0].old_x = mouse[i - MOUSE0].cur_x; + } + + j = mouse[i - MOUSE0].cur_y - mouse[i - MOUSE0].old_y; + + if (j < -127) + { + mouse[i - MOUSE0].delta_y = 0xff; + mouse[i - MOUSE0].old_y -= 127; + } + else + if (j < 0) + { + mouse[i - MOUSE0].delta_y = 0x80 | -j; + mouse[i - MOUSE0].old_y = mouse[i - MOUSE0].cur_y; + } + else + if (j > 127) + { + mouse[i - MOUSE0].delta_y = 0x7f; + mouse[i - MOUSE0].old_y += 127; + } + else + { + mouse[i - MOUSE0].delta_y = (uint8) j; + mouse[i - MOUSE0].old_y = mouse[i - MOUSE0].cur_y; + } +} + +void S9xSetJoypadLatch (bool latch) +{ + if (!latch && FLAG_LATCH) + { + // 1 written, 'plug in' new controllers now + curcontrollers[0] = newcontrollers[0]; + curcontrollers[1] = newcontrollers[1]; + } + + if (latch && !FLAG_LATCH) + { + int i; + + for (int n = 0; n < 2; n++) + { + for (int j = 0; j < 2; j++) + read_idx[n][j] = 0; + + switch (i = curcontrollers[n]) + { + case MP5: + for (int j = 0, k = mp5[n].pads[j]; j < 4; k = mp5[n].pads[++j]) + { + if (k == NONE) + continue; + do_polling(k); + } + + break; + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + do_polling(i); + break; + + case MOUSE0: + case MOUSE1: + do_polling(i); + if (!S9xMoviePlaying()) + UpdatePolledMouse(i); + break; + + case SUPERSCOPE: + if (superscope.next_buttons & SUPERSCOPE_FIRE) + { + superscope.next_buttons &= ~SUPERSCOPE_TURBO; + superscope.next_buttons |= superscope.phys_buttons & SUPERSCOPE_TURBO; + } + + if (superscope.next_buttons & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR)) + { + superscope.next_buttons &= ~SUPERSCOPE_OFFSCREEN; + superscope.next_buttons |= superscope.phys_buttons & SUPERSCOPE_OFFSCREEN; + } + + superscope.read_buttons = superscope.next_buttons; + + superscope.next_buttons &= ~SUPERSCOPE_PAUSE; + if (!(superscope.phys_buttons & SUPERSCOPE_TURBO)) + superscope.next_buttons &= ~(SUPERSCOPE_CURSOR | SUPERSCOPE_FIRE); + + do_polling(i); + break; + + case TWO_JUSTIFIERS: + do_polling(TWO_JUSTIFIERS); + // fall through + + case ONE_JUSTIFIER: + justifier.buttons ^= JUSTIFIER_SELECT; + do_polling(ONE_JUSTIFIER); + break; + + default: + break; + } + } + } + + FLAG_LATCH = latch; +} + +uint8 S9xReadJOYSERn (int n) +{ + int i, j, r; + + if (n > 1) + n -= 0x4016; + assert(n == 0 || n == 1); + + uint8 bits = (OpenBus & ~3) | ((n == 1) ? 0x1c : 0); + + if (FLAG_LATCH) + { + switch (i = curcontrollers[n]) + { + case MP5: + return (bits | 2); + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + return (bits | ((joypad[i - JOYPAD0].buttons & 0x8000) ? 1 : 0)); + + case MOUSE0: + case MOUSE1: + mouse[i - MOUSE0].buttons += 0x10; + if ((mouse[i - MOUSE0].buttons & 0x30) == 0x30) + mouse[i - MOUSE0].buttons &= 0xcf; + return (bits); + + case SUPERSCOPE: + return (bits | ((superscope.read_buttons & 0x80) ? 1 : 0)); + + case ONE_JUSTIFIER: + case TWO_JUSTIFIERS: + return (bits); + + default: + return (bits); + } + } + else + { + switch (i = curcontrollers[n]) + { + case MP5: + r = read_idx[n][FLAG_IOBIT(n) ? 0 : 1]++; + j = FLAG_IOBIT(n) ? 0 : 2; + + for (i = 0; i < 2; i++, j++) + { + if (mp5[n].pads[j] == NONE) + continue; + if (r >= 16) + bits |= 1 << i; + else + bits |= ((joypad[mp5[n].pads[j] - JOYPAD0].buttons & (0x8000 >> r)) ? 1 : 0) << i; + } + + return (bits); + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + if (read_idx[n][0] >= 16) + { + read_idx[n][0]++; + return (bits | 1); + } + else + return (bits | ((joypad[i - JOYPAD0].buttons & (0x8000 >> read_idx[n][0]++)) ? 1 : 0)); + + case MOUSE0: + case MOUSE1: + if (read_idx[n][0] < 8) + { + read_idx[n][0]++; + return (bits); + } + else + if (read_idx[n][0] < 16) + return (bits | ((mouse[i - MOUSE0].buttons & (0x8000 >> read_idx[n][0]++)) ? 1 : 0)); + else + if (read_idx[n][0] < 24) + return (bits | ((mouse[i - MOUSE0].delta_y & (0x800000 >> read_idx[n][0]++)) ? 1 : 0)); + else + if (read_idx[n][0] < 32) + return (bits | ((mouse[i - MOUSE0].delta_x & (0x80000000 >> read_idx[n][0]++)) ? 1 : 0)); + else + { + read_idx[n][0]++; + return (bits | 1); + } + + case SUPERSCOPE: + if (read_idx[n][0] < 8) + return (bits | ((superscope.read_buttons & (0x80 >> read_idx[n][0]++)) ? 1 : 0)); + else + { + read_idx[n][0]++; + return (bits | 1); + } + + case ONE_JUSTIFIER: + if (read_idx[n][0] < 24) + return (bits | ((0xaa7000 >> read_idx[n][0]++) & 1)); + else + if (read_idx[n][0] < 32) + return (bits | ((justifier.buttons & (JUSTIFIER_TRIGGER | JUSTIFIER_START | JUSTIFIER_SELECT) & (0x80000000 >> read_idx[n][0]++)) ? 1 : 0)); + else + { + read_idx[n][0]++; + return (bits | 1); + } + + case TWO_JUSTIFIERS: + if (read_idx[n][0] < 24) + return (bits | ((0xaa7000 >> read_idx[n][0]++) & 1)); + else + if (read_idx[n][0] < 32) + return (bits | ((justifier.buttons & (0x80000000 >> read_idx[n][0]++)) ? 1 : 0)); + else + { + read_idx[n][0]++; + return (bits | 1); + } + + default: + read_idx[n][0]++; + return (bits); + } + } +} + +void S9xDoAutoJoypad (void) +{ + int i, j; + + S9xSetJoypadLatch(1); + S9xSetJoypadLatch(0); + + S9xMovieUpdate(false); + + for (int n = 0; n < 2; n++) + { + switch (i = curcontrollers[n]) + { + case MP5: + j = FLAG_IOBIT(n) ? 0 : 2; + for (i = 0; i < 2; i++, j++) + { + if (mp5[n].pads[j] == NONE) + WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2 + i * 4, 0); + else + WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2 + i * 4, joypad[mp5[n].pads[j] - JOYPAD0].buttons); + } + + read_idx[n][FLAG_IOBIT(n) ? 0 : 1] = 16; + break; + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + read_idx[n][0] = 16; + WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2, joypad[i - JOYPAD0].buttons); + WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0); + break; + + case MOUSE0: + case MOUSE1: + read_idx[n][0] = 16; + WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2, mouse[i - MOUSE0].buttons); + WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0); + break; + + case SUPERSCOPE: + read_idx[n][0] = 16; + Memory.FillRAM[0x4218 + n * 2] = 0xff; + Memory.FillRAM[0x4219 + n * 2] = superscope.read_buttons; + WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0); + break; + + case ONE_JUSTIFIER: + case TWO_JUSTIFIERS: + read_idx[n][0] = 16; + WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2, 0x000e); + WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0); + break; + + default: + WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2, 0); + WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0); + break; + } + } +} + +void S9xControlEOF (void) +{ + struct crosshair *c; + int i, j; + + PPU.GunVLatch = 1000; // i.e., never latch + PPU.GunHLatch = 0; + + for (int n = 0; n < 2; n++) + { + switch (i = curcontrollers[n]) + { + case MP5: + for (j = 0, i = mp5[n].pads[j]; j < 4; i = mp5[n].pads[++j]) + { + if (i == NONE) + continue; + + if (++joypad[i - JOYPAD0].turbo_ct >= turbo_time) + { + joypad[i - JOYPAD0].turbo_ct = 0; + joypad[i - JOYPAD0].buttons ^= joypad[i - JOYPAD0].turbos; + } + } + + break; + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + if (++joypad[i - JOYPAD0].turbo_ct >= turbo_time) + { + joypad[i - JOYPAD0].turbo_ct = 0; + joypad[i - JOYPAD0].buttons ^= joypad[i - JOYPAD0].turbos; + } + + break; + + case MOUSE0: + case MOUSE1: + c = &mouse[i - MOUSE0].crosshair; + if (IPPU.RenderThisFrame) + S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, mouse[i - MOUSE0].cur_x, mouse[i - MOUSE0].cur_y); + break; + + case SUPERSCOPE: + if (n == 1 && !(superscope.phys_buttons & SUPERSCOPE_OFFSCREEN)) + { + if (superscope.next_buttons & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR)) + DoGunLatch(superscope.x, superscope.y); + + c = &superscope.crosshair; + #ifdef GEKKO + if(GCSettings.crosshair) + #endif + if (IPPU.RenderThisFrame) + S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, superscope.x, superscope.y); + } + + break; + + case TWO_JUSTIFIERS: + if (n == 1 && !justifier.offscreen[1]) + { + c = &justifier.crosshair[1]; + #ifdef GEKKO + if(GCSettings.crosshair) + #endif + if (IPPU.RenderThisFrame) + S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, justifier.x[1], justifier.y[1]); + } + + i = (justifier.buttons & JUSTIFIER_SELECT) ? 1 : 0; + goto do_justifier; + + case ONE_JUSTIFIER: + i = (justifier.buttons & JUSTIFIER_SELECT) ? -1 : 0; + + do_justifier: + if (n == 1) + { + if (i >= 0 && !justifier.offscreen[i]) + DoGunLatch(justifier.x[i], justifier.y[i]); + + if (!justifier.offscreen[0]) + { + c = &justifier.crosshair[0]; + #ifdef GEKKO + if(GCSettings.crosshair) + #endif + if (IPPU.RenderThisFrame) + S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, justifier.x[0], justifier.y[0]); + } + } + + break; + + default: + break; + } + } + + for (int n = 0; n < 8; n++) + { + if (!pseudopointer[n].mapped) + continue; + + if (pseudopointer[n].H_adj) + { + pseudopointer[n].x += pseudopointer[n].H_adj; + if (pseudopointer[n].x < 0) + pseudopointer[n].x = 0; + else + if (pseudopointer[n].x > 255) + pseudopointer[n].x = 255; + + if (pseudopointer[n].H_var) + { + if (pseudopointer[n].H_adj < 0) + { + if (pseudopointer[n].H_adj > -ptrspeeds[3]) + pseudopointer[n].H_adj--; + } + else + { + if (pseudopointer[n].H_adj < ptrspeeds[3]) + pseudopointer[n].H_adj++; + } + } + } + + if (pseudopointer[n].V_adj) + { + pseudopointer[n].y += pseudopointer[n].V_adj; + if (pseudopointer[n].y < 0) + pseudopointer[n].y = 0; + else + if (pseudopointer[n].y > PPU.ScreenHeight - 1) + pseudopointer[n].y = PPU.ScreenHeight - 1; + + if (pseudopointer[n].V_var) + { + if (pseudopointer[n].V_adj < 0) + { + if (pseudopointer[n].V_adj > -ptrspeeds[3]) + pseudopointer[n].V_adj--; + } + else + { + if (pseudopointer[n].V_adj < ptrspeeds[3]) + pseudopointer[n].V_adj++; + } + } + } + + S9xReportPointer(PseudoPointerBase + n, pseudopointer[n].x, pseudopointer[n].y); + } + + set<struct exemulti *>::iterator it, jt; + + for (it = exemultis.begin(); it != exemultis.end(); it++) + { + i = ApplyMulti((*it)->script, (*it)->pos, (*it)->data1); + + if (i >= 0) + (*it)->pos = i; + else + { + jt = it; + it--; + delete *jt; + exemultis.erase(jt); + } + } + + do_polling(POLL_ALL); + + S9xMovieUpdate(); + + pad_read_last = pad_read; + pad_read = false; +} + +void S9xSetControllerCrosshair (enum crosscontrols ctl, int8 idx, const char *fg, const char *bg) +{ + struct crosshair *c; + int8 fgcolor = -1, bgcolor = -1; + int i, j; + + if (idx < -1 || idx > 31) + { + fprintf(stderr, "S9xSetControllerCrosshair() called with invalid index\n"); + return; + } + + switch (ctl) + { + case X_MOUSE1: c = &mouse[0].crosshair; break; + case X_MOUSE2: c = &mouse[1].crosshair; break; + case X_SUPERSCOPE: c = &superscope.crosshair; break; + case X_JUSTIFIER1: c = &justifier.crosshair[0]; break; + case X_JUSTIFIER2: c = &justifier.crosshair[1]; break; + default: + fprintf(stderr, "S9xSetControllerCrosshair() called with an invalid controller ID %d\n", ctl); + return; + } + + if (fg) + { + fgcolor = 0; + if (*fg == 't') + { + fg++; + fgcolor = 16; + } + + for (i = 0; i < 16; i++) + { + for (j = 0; color_names[i][j] && fg[j] == color_names[i][j]; j++) ; + if (isalnum(fg[j])) + continue; + + if (!color_names[i][j]) + break; + } + + fgcolor |= i; + if (i > 15 || fgcolor == 16) + { + fprintf(stderr, "S9xSetControllerCrosshair() called with invalid fgcolor\n"); + return; + } + } + + if (bg) + { + bgcolor = 0; + if (*bg == 't') + { + bg++; + bgcolor = 16; + } + + for (i = 0; i < 16; i++) + { + for (j = 0; color_names[i][j] && bg[j] == color_names[i][j]; j++) ; + if (isalnum(bg[j])) + continue; + + if (!color_names[i][j]) + break; + } + + bgcolor |= i; + if (i > 15 || bgcolor == 16) + { + fprintf(stderr, "S9xSetControllerCrosshair() called with invalid bgcolor\n"); + return; + } + } + + if (idx != -1) + { + c->set |= 1; + c->img = idx; + } + + if (fgcolor != -1) + { + c->set |= 2; + c->fg = fgcolor; + } + + if (bgcolor != -1) + { + c->set |= 4; + c->bg = bgcolor; + } +} + +void S9xGetControllerCrosshair (enum crosscontrols ctl, int8 *idx, const char **fg, const char **bg) +{ + struct crosshair *c; + + switch (ctl) + { + case X_MOUSE1: c = &mouse[0].crosshair; break; + case X_MOUSE2: c = &mouse[1].crosshair; break; + case X_SUPERSCOPE: c = &superscope.crosshair; break; + case X_JUSTIFIER1: c = &justifier.crosshair[0]; break; + case X_JUSTIFIER2: c = &justifier.crosshair[1]; break; + default: + fprintf(stderr, "S9xGetControllerCrosshair() called with an invalid controller ID %d\n", ctl); + return; + } + + if (idx) + *idx = c->img; + + if (fg) + *fg = color_names[c->fg]; + + if (bg) + *bg = color_names[c->bg]; +} + +void S9xControlPreSaveState (struct SControlSnapshot *s) +{ + ZeroMemory(s, sizeof(*s)); + s->ver = 3; + + for (int j = 0; j < 2; j++) + { + s->port1_read_idx[j] = read_idx[0][j]; + s->port2_read_idx[j] = read_idx[1][j]; + } + + for (int j = 0; j < 2; j++) + s->mouse_speed[j] = (mouse[j].buttons & 0x30) >> 4; + + s->justifier_select = ((justifier.buttons & JUSTIFIER_SELECT) ? 1 : 0); + +#define COPY(x) { memcpy((char *) s->internal + i, &(x), sizeof(x)); i += sizeof(x); } + + int i = 0; + + for (int j = 0; j < 8; j++) + COPY(joypad[j].buttons); + + for (int j = 0; j < 2; j++) + { + COPY(mouse[j].delta_x); + COPY(mouse[j].delta_y); + COPY(mouse[j].old_x); + COPY(mouse[j].old_y); + COPY(mouse[j].cur_x); + COPY(mouse[j].cur_y); + COPY(mouse[j].buttons); + } + + COPY(superscope.x); + COPY(superscope.y); + COPY(superscope.phys_buttons); + COPY(superscope.next_buttons); + COPY(superscope.read_buttons); + + for (int j = 0; j < 2; j++) + COPY(justifier.x[j]); + for (int j = 0; j < 2; j++) + COPY(justifier.y[j]); + COPY(justifier.buttons); + for (int j = 0; j < 2; j++) + COPY(justifier.offscreen[j]); + + for (int j = 0; j < 2; j++) + for (int k = 0; k < 2; k++) + COPY(mp5[j].pads[k]); + + assert(i == sizeof(s->internal)); + +#undef COPY + + s->pad_read = pad_read; + s->pad_read_last = pad_read_last; +} + +void S9xControlPostLoadState (struct SControlSnapshot *s) +{ + if (curcontrollers[0] == MP5 && s->ver < 1) + { + // Crap. Old snes9x didn't support this. + S9xMessage(S9X_WARNING, S9X_FREEZE_FILE_INFO, "Old savestate has no support for MP5 in port 1."); + newcontrollers[0] = curcontrollers[0]; + curcontrollers[0] = mp5[0].pads[0]; + } + + for (int j = 0; j < 2; j++) + { + read_idx[0][j] = s->port1_read_idx[j]; + read_idx[1][j] = s->port2_read_idx[j]; + } + + for (int j = 0; j < 2; j++) + mouse[j].buttons |= (s->mouse_speed[j] & 3) << 4; + + if (s->justifier_select & 1) + justifier.buttons |= JUSTIFIER_SELECT; + else + justifier.buttons &= ~JUSTIFIER_SELECT; + + FLAG_LATCH = (Memory.FillRAM[0x4016] & 1) == 1; + + if (s->ver > 1) + { + #define COPY(x) { memcpy(&(x), (char *) s->internal + i, sizeof(x)); i += sizeof(x); } + + int i = 0; + + for (int j = 0; j < 8; j++) + COPY(joypad[j].buttons); + + for (int j = 0; j < 2; j++) + { + COPY(mouse[j].delta_x); + COPY(mouse[j].delta_y); + COPY(mouse[j].old_x); + COPY(mouse[j].old_y); + COPY(mouse[j].cur_x); + COPY(mouse[j].cur_y); + COPY(mouse[j].buttons); + } + + COPY(superscope.x); + COPY(superscope.y); + COPY(superscope.phys_buttons); + COPY(superscope.next_buttons); + COPY(superscope.read_buttons); + + for (int j = 0; j < 2; j++) + COPY(justifier.x[j]); + for (int j = 0; j < 2; j++) + COPY(justifier.y[j]); + COPY(justifier.buttons); + for (int j = 0; j < 2; j++) + COPY(justifier.offscreen[j]); + for (int j = 0; j < 2; j++) + for (int k = 0; k < 2; k++) + COPY(mp5[j].pads[k]); + + assert(i == sizeof(s->internal)); + + #undef COPY + } + + if (s->ver > 2) + { + pad_read = s->pad_read; + pad_read_last = s->pad_read_last; + } +} + +uint16 MovieGetJoypad (int i) +{ + if (i < 0 || i > 7) + return (0); + + return (joypad[i].buttons); +} + +void MovieSetJoypad (int i, uint16 buttons) +{ + if (i < 0 || i > 7) + return; + + joypad[i].buttons = buttons; +} + +bool MovieGetMouse (int i, uint8 out[5]) +{ + if (i < 0 || i > 1 || (curcontrollers[i] != MOUSE0 && curcontrollers[i] != MOUSE1)) + return (false); + + int n = curcontrollers[i] - MOUSE0; + uint8 *ptr = out; + + WRITE_WORD(ptr, mouse[n].cur_x); ptr += 2; + WRITE_WORD(ptr, mouse[n].cur_y); ptr += 2; + *ptr = mouse[n].buttons; + + return (true); +} + +void MovieSetMouse (int i, uint8 in[5], bool inPolling) +{ + if (i < 0 || i > 1 || (curcontrollers[i] != MOUSE0 && curcontrollers[i] != MOUSE1)) + return; + + int n = curcontrollers[i] - MOUSE0; + uint8 *ptr = in; + + mouse[n].cur_x = READ_WORD(ptr); ptr += 2; + mouse[n].cur_y = READ_WORD(ptr); ptr += 2; + mouse[n].buttons = *ptr; + + if (inPolling) + UpdatePolledMouse(curcontrollers[i]); +} + +bool MovieGetScope (int i, uint8 out[6]) +{ + if (i < 0 || i > 1 || curcontrollers[i] != SUPERSCOPE) + return (false); + + uint8 *ptr = out; + + WRITE_WORD(ptr, superscope.x); ptr += 2; + WRITE_WORD(ptr, superscope.y); ptr += 2; + *ptr++ = superscope.phys_buttons; + *ptr = superscope.next_buttons; + + return (true); +} + +void MovieSetScope (int i, uint8 in[6]) +{ + if (i < 0 || i > 1 || curcontrollers[i] != SUPERSCOPE) + return; + + uint8 *ptr = in; + + superscope.x = READ_WORD(ptr); ptr += 2; + superscope.y = READ_WORD(ptr); ptr += 2; + superscope.phys_buttons = *ptr++; + superscope.next_buttons = *ptr; +} + +bool MovieGetJustifier (int i, uint8 out[11]) +{ + if (i < 0 || i > 1 || (curcontrollers[i] != ONE_JUSTIFIER && curcontrollers[i] != TWO_JUSTIFIERS)) + return (false); + + uint8 *ptr = out; + + WRITE_WORD(ptr, justifier.x[0]); ptr += 2; + WRITE_WORD(ptr, justifier.x[1]); ptr += 2; + WRITE_WORD(ptr, justifier.y[0]); ptr += 2; + WRITE_WORD(ptr, justifier.y[1]); ptr += 2; + *ptr++ = justifier.buttons; + *ptr++ = justifier.offscreen[0]; + *ptr = justifier.offscreen[1]; + + return (true); +} + +void MovieSetJustifier (int i, uint8 in[11]) +{ + if (i < 0 || i > 1 || (curcontrollers[i] != ONE_JUSTIFIER && curcontrollers[i] != TWO_JUSTIFIERS)) + return; + + uint8 *ptr = in; + + justifier.x[0] = READ_WORD(ptr); ptr += 2; + justifier.x[1] = READ_WORD(ptr); ptr += 2; + justifier.y[0] = READ_WORD(ptr); ptr += 2; + justifier.y[1] = READ_WORD(ptr); ptr += 2; + justifier.buttons = *ptr++; + justifier.offscreen[0] = *ptr++; + justifier.offscreen[1] = *ptr; +} diff --git a/plugins/snes9x_gx/source/snes9x/controls.h b/plugins/snes9x_gx/source/snes9x/controls.h new file mode 100644 index 00000000..8772f62c --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/controls.h @@ -0,0 +1,453 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _CONTROLS_H_ +#define _CONTROLS_H_ + +#define S9xNoMapping 0 +#define S9xButtonJoypad 1 +#define S9xButtonMouse 2 +#define S9xButtonSuperscope 3 +#define S9xButtonJustifier 4 +#define S9xButtonCommand 5 +#define S9xButtonMulti 6 +#define S9xAxisJoypad 7 +#define S9xPointer 8 + +#define S9xButtonPseudopointer 254 +#define S9xAxisPseudopointer 253 +#define S9xAxisPseudobuttons 252 + +// These are automatically kicked out to the S9xHandlePortCommand function. +// If your port wants to define port-specific commands or whatever, use these values for the s9xcommand_t type field. + +#define S9xButtonPort 251 +#define S9xAxisPort 250 +#define S9xPointerPort 249 + +#define S9xBadMapping 255 +#define InvalidControlID ((uint32) -1) + +// S9xButtonPseudopointer and S9xAxisPseudopointer will report pointer motion using IDs PseudoPointerBase through PseudoPointerBase+7. +// S9xAxisPseudopointer command types. S9xAxisPseudobuttons will report buttons with IDs PseudoButtonBase to PseudoButtonBase+255. + +#define PseudoPointerBase (InvalidControlID - 8) +#define PseudoButtonBase (PseudoPointerBase - 256) + +typedef struct +{ + uint8 type; + uint8 multi_press:2; + uint8 button_norpt:1; + + union + { + union + { + struct + { + uint8 idx:3; // Pad number 0-7 + uint8 toggle:1; // If set, toggle turbo/sticky for the button + uint8 turbo:1; // If set, be a 'turbo' button + uint8 sticky:1; // If set, toggle button state (on/turbo or off) when pressed and do nothing on release + uint16 buttons; // Which buttons to actuate. Use SNES_*_MASK constants from snes9x.h + } joypad; + + struct + { + uint8 idx:1; // Mouse number 0-1 + uint8 left:1; // buttons + uint8 right:1; + } mouse; + + struct + { + uint8 fire:1; + uint8 cursor:1; + uint8 turbo:1; + uint8 pause:1; + uint8 aim_offscreen:1; // Pretend we're pointing the gun offscreen (ignore the pointer) + } scope; + + struct + { + uint8 idx:3; // Pseudo-pointer number 0-7 + uint8 speed_type:2; // 0=variable, 1=slow, 2=med, 3=fast + int8 UD:2; // -1=up, 1=down, 0=no vertical motion + int8 LR:2; // -1=left, 1=right, 0=no horizontal motion + } pointer; + + struct + { + uint8 idx:1; // Justifier number 0-1 + uint8 trigger:1; // buttons + uint8 start:1; + uint8 aim_offscreen:1; // Pretend we're pointing the gun offscreen (ignore the pointer) + } justifier; + + int32 multi_idx; + uint16 command; + } button; + + union + { + struct + { + uint8 idx:3; // Pad number 0-7 + uint8 invert:1; // 1 = positive is Left/Up/Y/X/L + uint8 axis:3; // 0=Left/Right, 1=Up/Down, 2=Y/A, 3=X/B, 4=L/R + uint8 threshold; // (threshold+1)/256% deflection is a button press + } joypad; + + struct + { + uint8 idx:3; // Pseudo-pointer number 0-7 + uint8 speed_type:2; // 0=variable, 1=slow, 2=med, 3=fast + uint8 invert:1; // 1 = invert axis, so positive is up/left + uint8 HV:1; // 0=horizontal, 1=vertical + } pointer; + + struct + { + uint8 threshold; // (threshold+1)/256% deflection is a button press + uint8 negbutton; // Button ID for negative deflection + uint8 posbutton; // Button ID for positive deflection + } button; + } axis; + + struct // Which SNES-pointers to control with this pointer + { + uint16 aim_mouse0:1; + uint16 aim_mouse1:1; + uint16 aim_scope:1; + uint16 aim_justifier0:1; + uint16 aim_justifier1:1; + } pointer; + + uint8 port[4]; + }; +} s9xcommand_t; + +// Starting out... + +void S9xUnmapAllControls (void); + +// Setting which controllers are plugged in. + +enum controllers +{ + CTL_NONE, // all ids ignored + CTL_JOYPAD, // use id1 to specify 0-7 + CTL_MOUSE, // use id1 to specify 0-1 + CTL_SUPERSCOPE, + CTL_JUSTIFIER, // use id1: 0=one justifier, 1=two justifiers + CTL_MP5 // use id1-id4 to specify pad 0-7 (or -1) +}; + +void S9xSetController (int port, enum controllers controller, int8 id1, int8 id2, int8 id3, int8 id4); // port=0-1 +void S9xGetController (int port, enum controllers *controller, int8 *id1, int8 *id2, int8 *id3, int8 *id4); +void S9xReportControllers (void); + +// Call this when you're done with S9xSetController, or if you change any of the controller Settings.*Master flags. +// Returns true if something was disabled. + +bool S9xVerifyControllers (void); + +// Functions for translation s9xcommand_t's into strings, and vice versa. +// free() the returned string after you're done with it. + +char * S9xGetCommandName (s9xcommand_t command); +s9xcommand_t S9xGetCommandT (const char *name); + +// Returns an array of strings naming all the snes9x commands. +// Note that this is only the strings for S9xButtonCommand! +// The idea is that this would be used for a pull-down list in a config GUI. DO NOT free() the returned value. + +const char ** S9xGetAllSnes9xCommands (void); + +// Generic mapping functions + +s9xcommand_t S9xGetMapping (uint32 id); +void S9xUnmapID (uint32 id); + +// Button mapping functions. +// If a button is mapped with poll=TRUE, then S9xPollButton will be called whenever snes9x feels a need for that mapping. +// Otherwise, snes9x will assume you will call S9xReportButton() whenever the button state changes. +// S9xMapButton() will fail and return FALSE if mapping.type isn't an S9xButton* type. + +bool S9xMapButton (uint32 id, s9xcommand_t mapping, bool poll); +void S9xReportButton (uint32 id, bool pressed); + +// Pointer mapping functions. +// If a pointer is mapped with poll=TRUE, then S9xPollPointer will be called whenever snes9x feels a need for that mapping. +// Otherwise, snes9x will assume you will call S9xReportPointer() whenever the pointer position changes. +// S9xMapPointer() will fail and return FALSE if mapping.type isn't an S9xPointer* type. + +// Note that position [0,0] is considered the upper-left corner of the 'screen', +// and either [255,223] or [255,239] is the lower-right. +// Note that the SNES mouse doesn't aim at a particular point, +// so the SNES's idea of where the mouse pointer is will probably differ from your OS's idea. + +bool S9xMapPointer (uint32 id, s9xcommand_t mapping, bool poll); +void S9xReportPointer (uint32 id, int16 x, int16 y); + +// Axis mapping functions. +// If an axis is mapped with poll=TRUE, then S9xPollAxis will be called whenever snes9x feels a need for that mapping. +// Otherwise, snes9x will assume you will call S9xReportAxis() whenever the axis deflection changes. +// S9xMapAxis() will fail and return FALSE if mapping.type isn't an S9xAxis* type. + +// Note that value is linear -32767 through 32767 with 0 being no deflection. +// If your axis reports differently you should transform the value before passing it to S9xReportAxis(). + +bool S9xMapAxis (uint32 id, s9xcommand_t mapping, bool poll); +void S9xReportAxis (uint32 id, int16 value); + +// Do whatever the s9xcommand_t says to do. +// If cmd.type is a button type, data1 should be TRUE (non-0) or FALSE (0) to indicate whether the 'button' is pressed or released. +// If cmd.type is an axis, data1 holds the deflection value. +// If cmd.type is a pointer, data1 and data2 are the positions of the pointer. + +void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2); + +////////// +// These functions are called by snes9x into your port, so each port should implement them. + +// If something was mapped with poll=TRUE, these functions will be called when snes9x needs the button/axis/pointer state. +// Fill in the reference options as appropriate. + +bool S9xPollButton (uint32 id, bool *pressed); +bool S9xPollPointer (uint32 id, int16 *x, int16 *y); +bool S9xPollAxis (uint32 id, int16 *value); + +// These are called when snes9x tries to apply a command with a S9x*Port type. +// data1 and data2 are filled in like S9xApplyCommand. + +void S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2); + +// Called before already-read SNES joypad data is being used by the game if your port defines SNES_JOY_READ_CALLBACKS. + +#ifdef SNES_JOY_READ_CALLBACKS +void S9xOnSNESPadRead (void); +#endif + +// These are for your use. + +s9xcommand_t S9xGetPortCommandT (const char *name); +char * S9xGetPortCommandName (s9xcommand_t command); +void S9xSetupDefaultKeymap (void); +bool8 S9xMapInput (const char *name, s9xcommand_t *cmd); + +////////// +// These functions are called from snes9x into this subsystem. No need to use them from a port. + +// Use when resetting snes9x. + +void S9xControlsReset (void); +void S9xControlsSoftReset (void); + +// Use when writing to $4016. + +void S9xSetJoypadLatch (bool latch); + +// Use when reading $4016/7 (JOYSER0 and JOYSER1). + +uint8 S9xReadJOYSERn (int n); + +// End-Of-Frame processing. Sets gun latch variables and tries to draw crosshairs + +void S9xControlEOF (void); + +// Functions and a structure for snapshot. + +struct SControlSnapshot +{ + uint8 ver; + uint8 port1_read_idx[2]; + uint8 dummy1[4]; // for future expansion + uint8 port2_read_idx[2]; + uint8 dummy2[4]; + uint8 mouse_speed[2]; + uint8 justifier_select; + uint8 dummy3[8]; + bool8 pad_read, pad_read_last; + uint8 internal[60]; // yes, we need to save this! +}; + +void S9xControlPreSaveState (struct SControlSnapshot *s); +void S9xControlPostLoadState (struct SControlSnapshot *s); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/cpu.cpp b/plugins/snes9x_gx/source/snes9x/cpu.cpp new file mode 100644 index 00000000..f2efb4ce --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/cpu.cpp @@ -0,0 +1,338 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "dma.h" +#include "apu/apu.h" +#include "fxemu.h" +#include "sdd1.h" +#include "srtc.h" +#include "snapshot.h" +#include "cheats.h" +#include "logger.h" +#ifdef DEBUGGER +#include "debug.h" +#endif + +static void S9xResetCPU (void); +static void S9xSoftResetCPU (void); + + +static void S9xResetCPU (void) +{ + S9xSoftResetCPU(); + Registers.SL = 0xff; + Registers.P.W = 0; + Registers.A.W = 0; + Registers.X.W = 0; + Registers.Y.W = 0; + SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation); + ClearFlags(Decimal); +} + +static void S9xSoftResetCPU (void) +{ + CPU.Cycles = 182; // Or 188. This is the cycle count just after the jump to the Reset Vector. + CPU.PrevCycles = -1; + CPU.V_Counter = 0; + CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); + CPU.PCBase = NULL; + CPU.IRQActive = FALSE; + CPU.IRQPending = 0; + CPU.MemSpeed = SLOW_ONE_CYCLE; + CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2; + CPU.FastROMSpeed = SLOW_ONE_CYCLE; + CPU.InDMA = FALSE; + CPU.InHDMA = FALSE; + CPU.InDMAorHDMA = FALSE; + CPU.InWRAMDMAorHDMA = FALSE; + CPU.HDMARanInDMA = 0; + CPU.CurrentDMAorHDMAChannel = -1; + CPU.WhichEvent = HC_RENDER_EVENT; + CPU.NextEvent = Timings.RenderPos; + CPU.WaitingForInterrupt = FALSE; + CPU.WaitAddress = 0xffffffff; + CPU.WaitCounter = 0; + CPU.PBPCAtOpcodeStart = 0xffffffff; + CPU.AutoSaveTimer = 0; + CPU.SRAMModified = FALSE; + + Registers.PBPC = 0; + Registers.PB = 0; + Registers.PCw = S9xGetWord(0xfffc); + OpenBus = Registers.PCh; + Registers.D.W = 0; + Registers.DB = 0; + Registers.SH = 1; + Registers.SL -= 3; + Registers.XH = 0; + Registers.YH = 0; + + ICPU.ShiftedPB = 0; + ICPU.ShiftedDB = 0; + SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation); + ClearFlags(Decimal); + + Timings.InterlaceField = FALSE; + Timings.H_Max = Timings.H_Max_Master; + Timings.V_Max = Timings.V_Max_Master; + Timings.NMITriggerPos = 0xffff; + if (Model->_5A22 == 2) + Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2; + else + Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v1; + + S9xSetPCBase(Registers.PBPC); + + ICPU.S9xOpcodes = S9xOpcodesE1; + ICPU.S9xOpLengths = S9xOpLengthsM1X1; + ICPU.CPUExecuting = TRUE; + + S9xUnpackStatus(); +} + +void S9xReset (void) +{ + S9xResetSaveTimer(FALSE); + S9xResetLogger(); + + memset(Memory.RAM, 0x55, 0x20000); + memset(Memory.VRAM, 0x00, 0x10000); + ZeroMemory(Memory.FillRAM, 0x8000); + + if (Settings.BS) + S9xResetBSX(); + + S9xResetCPU(); + S9xResetPPU(); + S9xResetDMA(); + S9xResetAPU(); + + if (Settings.DSP) + S9xResetDSP(); + if (Settings.SuperFX) + S9xResetSuperFX(); + if (Settings.SA1) + S9xSA1Init(); + if (Settings.SDD1) + S9xResetSDD1(); + if (Settings.SPC7110) + S9xResetSPC7110(); + if (Settings.C4) + S9xInitC4(); + if (Settings.OBC1) + S9xResetOBC1(); + if (Settings.SRTC) + S9xResetSRTC(); + + S9xInitCheatData(); +} + +void S9xSoftReset (void) +{ + S9xResetSaveTimer(FALSE); + + ZeroMemory(Memory.FillRAM, 0x8000); + + if (Settings.BS) + S9xResetBSX(); + + S9xSoftResetCPU(); + S9xSoftResetPPU(); + S9xResetDMA(); + S9xSoftResetAPU(); + + if (Settings.DSP) + S9xResetDSP(); + if (Settings.SuperFX) + S9xResetSuperFX(); + if (Settings.SA1) + S9xSA1Init(); + if (Settings.SDD1) + S9xResetSDD1(); + if (Settings.SPC7110) + S9xResetSPC7110(); + if (Settings.C4) + S9xInitC4(); + if (Settings.OBC1) + S9xResetOBC1(); + if (Settings.SRTC) + S9xResetSRTC(); + + S9xInitCheatData(); +} diff --git a/plugins/snes9x_gx/source/snes9x/cpuaddr.h b/plugins/snes9x_gx/source/snes9x/cpuaddr.h new file mode 100644 index 00000000..3ae55c41 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/cpuaddr.h @@ -0,0 +1,690 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _CPUADDR_H_ +#define _CPUADDR_H_ + +typedef enum +{ + NONE = 0, + READ = 1, + WRITE = 2, + MODIFY = 3, + JUMP = 5, + JSR = 8 +} AccessMode; + +static inline uint8 Immediate8Slow (AccessMode a) +{ + uint8 val = S9xGetByte(Registers.PBPC); + if (a & READ) + OpenBus = val; + Registers.PCw++; + + return (val); +} + +static inline uint8 Immediate8 (AccessMode a) +{ + uint8 val = CPU.PCBase[Registers.PCw]; + if (a & READ) + OpenBus = val; + AddCycles(CPU.MemSpeed); + Registers.PCw++; + + return (val); +} + +static inline uint16 Immediate16Slow (AccessMode a) +{ + uint16 val = S9xGetWord(Registers.PBPC, WRAP_BANK); + if (a & READ) + OpenBus = (uint8) (val >> 8); + Registers.PCw += 2; + + return (val); +} + +static inline uint16 Immediate16 (AccessMode a) +{ + uint16 val = READ_WORD(CPU.PCBase + Registers.PCw); + if (a & READ) + OpenBus = (uint8) (val >> 8); + AddCycles(CPU.MemSpeedx2); + Registers.PCw += 2; + + return (val); +} + +static inline uint32 RelativeSlow (AccessMode a) // branch $xx +{ + int8 offset = Immediate8Slow(a); + + return ((int16) Registers.PCw + offset) & 0xffff; +} + +static inline uint32 Relative (AccessMode a) // branch $xx +{ + int8 offset = Immediate8(a); + + return ((int16) Registers.PCw + offset) & 0xffff; +} + +static inline uint32 RelativeLongSlow (AccessMode a) // BRL $xxxx +{ + int16 offset = Immediate16Slow(a); + + return ((int32) Registers.PCw + offset) & 0xffff; +} + +static inline uint32 RelativeLong (AccessMode a) // BRL $xxxx +{ + int16 offset = Immediate16(a); + + return ((int32) Registers.PCw + offset) & 0xffff; +} + +static inline uint32 AbsoluteIndexedIndirectSlow (AccessMode a) // (a,X) +{ + uint16 addr; + + if (a & JSR) + { + // JSR (a,X) pushes the old address in the middle of loading the new. + // OpenBus needs to be set to account for this. + addr = Immediate8Slow(READ); + if (a == JSR) + OpenBus = Registers.PCl; + addr |= Immediate8Slow(READ) << 8; + } + else + addr = Immediate16Slow(READ); + + AddCycles(ONE_CYCLE); + addr += Registers.X.W; + + // Address load wraps within the bank + uint16 addr2 = S9xGetWord(ICPU.ShiftedPB | addr, WRAP_BANK); + OpenBus = addr2 >> 8; + + return (addr2); +} + +static inline uint32 AbsoluteIndexedIndirect (AccessMode a) // (a,X) +{ + uint16 addr = Immediate16Slow(READ); + addr += Registers.X.W; + + // Address load wraps within the bank + uint16 addr2 = S9xGetWord(ICPU.ShiftedPB | addr, WRAP_BANK); + OpenBus = addr2 >> 8; + + return (addr2); +} + +static inline uint32 AbsoluteIndirectLongSlow (AccessMode a) // [a] +{ + uint16 addr = Immediate16Slow(READ); + + // No info on wrapping, but it doesn't matter anyway due to mirroring + uint32 addr2 = S9xGetWord(addr); + OpenBus = addr2 >> 8; + addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16; + + return (addr2); +} + +static inline uint32 AbsoluteIndirectLong (AccessMode a) // [a] +{ + uint16 addr = Immediate16(READ); + + // No info on wrapping, but it doesn't matter anyway due to mirroring + uint32 addr2 = S9xGetWord(addr); + OpenBus = addr2 >> 8; + addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16; + + return (addr2); +} + +static inline uint32 AbsoluteIndirectSlow (AccessMode a) // (a) +{ + // No info on wrapping, but it doesn't matter anyway due to mirroring + uint16 addr2 = S9xGetWord(Immediate16Slow(READ)); + OpenBus = addr2 >> 8; + + return (addr2); +} + +static inline uint32 AbsoluteIndirect (AccessMode a) // (a) +{ + // No info on wrapping, but it doesn't matter anyway due to mirroring + uint16 addr2 = S9xGetWord(Immediate16(READ)); + OpenBus = addr2 >> 8; + + return (addr2); +} + +static inline uint32 AbsoluteSlow (AccessMode a) // a +{ + return (ICPU.ShiftedDB | Immediate16Slow(a)); +} + +static inline uint32 Absolute (AccessMode a) // a +{ + return (ICPU.ShiftedDB | Immediate16(a)); +} + +static inline uint32 AbsoluteLongSlow (AccessMode a) // l +{ + uint32 addr = Immediate16Slow(READ); + + // JSR l pushes the old bank in the middle of loading the new. + // OpenBus needs to be set to account for this. + if (a == JSR) + OpenBus = Registers.PB; + + addr |= Immediate8Slow(a) << 16; + + return (addr); +} + +static inline uint32 AbsoluteLong (AccessMode a) // l +{ + uint32 addr = READ_3WORD(CPU.PCBase + Registers.PCw); + AddCycles(CPU.MemSpeedx2 + CPU.MemSpeed); + if (a & READ) + OpenBus = addr >> 16; + Registers.PCw += 3; + + return (addr); +} + +static inline uint32 DirectSlow (AccessMode a) // d +{ + uint16 addr = Immediate8Slow(a) + Registers.D.W; + if (Registers.DL != 0) + AddCycles(ONE_CYCLE); + + return (addr); +} + +static inline uint32 Direct (AccessMode a) // d +{ + uint16 addr = Immediate8(a) + Registers.D.W; + if (Registers.DL != 0) + AddCycles(ONE_CYCLE); + + return (addr); +} + +static inline uint32 DirectIndirectSlow (AccessMode a) // (d) +{ + uint32 addr = S9xGetWord(DirectSlow(READ), (!CheckEmulation() || Registers.DL) ? WRAP_BANK : WRAP_PAGE); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + addr |= ICPU.ShiftedDB; + + return (addr); +} + +static inline uint32 DirectIndirectE0 (AccessMode a) // (d) +{ + uint32 addr = S9xGetWord(Direct(READ)); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + addr |= ICPU.ShiftedDB; + + return (addr); +} + +static inline uint32 DirectIndirectE1 (AccessMode a) // (d) +{ + uint32 addr = S9xGetWord(DirectSlow(READ), Registers.DL ? WRAP_BANK : WRAP_PAGE); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + addr |= ICPU.ShiftedDB; + + return (addr); +} + +static inline uint32 DirectIndirectIndexedSlow (AccessMode a) // (d),Y +{ + uint32 addr = DirectIndirectSlow(a); + if (a & WRITE || !CheckIndex() || (addr & 0xff) + Registers.YL >= 0x100) + AddCycles(ONE_CYCLE); + + return (addr + Registers.Y.W); +} + +static inline uint32 DirectIndirectIndexedE0X0 (AccessMode a) // (d),Y +{ + uint32 addr = DirectIndirectE0(a); + AddCycles(ONE_CYCLE); + + return (addr + Registers.Y.W); +} + +static inline uint32 DirectIndirectIndexedE0X1 (AccessMode a) // (d),Y +{ + uint32 addr = DirectIndirectE0(a); + if (a & WRITE || (addr & 0xff) + Registers.YL >= 0x100) + AddCycles(ONE_CYCLE); + + return (addr + Registers.Y.W); +} + +static inline uint32 DirectIndirectIndexedE1 (AccessMode a) // (d),Y +{ + uint32 addr = DirectIndirectE1(a); + if (a & WRITE || (addr & 0xff) + Registers.YL >= 0x100) + AddCycles(ONE_CYCLE); + + return (addr + Registers.Y.W); +} + +static inline uint32 DirectIndirectLongSlow (AccessMode a) // [d] +{ + uint16 addr = DirectSlow(READ); + uint32 addr2 = S9xGetWord(addr); + OpenBus = addr2 >> 8; + addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16; + + return (addr2); +} + +static inline uint32 DirectIndirectLong (AccessMode a) // [d] +{ + uint16 addr = Direct(READ); + uint32 addr2 = S9xGetWord(addr); + OpenBus = addr2 >> 8; + addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16; + + return (addr2); +} + +static inline uint32 DirectIndirectIndexedLongSlow (AccessMode a) // [d],Y +{ + return (DirectIndirectLongSlow(a) + Registers.Y.W); +} + +static inline uint32 DirectIndirectIndexedLong (AccessMode a) // [d],Y +{ + return (DirectIndirectLong(a) + Registers.Y.W); +} + +static inline uint32 DirectIndexedXSlow (AccessMode a) // d,X +{ + pair addr; + addr.W = DirectSlow(a); + if (!CheckEmulation() || Registers.DL) + addr.W += Registers.X.W; + else + addr.B.l += Registers.XL; + + AddCycles(ONE_CYCLE); + + return (addr.W); +} + +static inline uint32 DirectIndexedXE0 (AccessMode a) // d,X +{ + uint16 addr = Direct(a) + Registers.X.W; + AddCycles(ONE_CYCLE); + + return (addr); +} + +static inline uint32 DirectIndexedXE1 (AccessMode a) // d,X +{ + if (Registers.DL) + return (DirectIndexedXE0(a)); + else + { + pair addr; + addr.W = Direct(a); + addr.B.l += Registers.XL; + AddCycles(ONE_CYCLE); + + return (addr.W); + } +} + +static inline uint32 DirectIndexedYSlow (AccessMode a) // d,Y +{ + pair addr; + addr.W = DirectSlow(a); + if (!CheckEmulation() || Registers.DL) + addr.W += Registers.Y.W; + else + addr.B.l += Registers.YL; + + AddCycles(ONE_CYCLE); + + return (addr.W); +} + +static inline uint32 DirectIndexedYE0 (AccessMode a) // d,Y +{ + uint16 addr = Direct(a) + Registers.Y.W; + AddCycles(ONE_CYCLE); + + return (addr); +} + +static inline uint32 DirectIndexedYE1 (AccessMode a) // d,Y +{ + if (Registers.DL) + return (DirectIndexedYE0(a)); + else + { + pair addr; + addr.W = Direct(a); + addr.B.l += Registers.YL; + AddCycles(ONE_CYCLE); + + return (addr.W); + } +} + +static inline uint32 DirectIndexedIndirectSlow (AccessMode a) // (d,X) +{ + uint32 addr = S9xGetWord(DirectIndexedXSlow(READ), (!CheckEmulation() || Registers.DL) ? WRAP_BANK : WRAP_PAGE); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + + return (ICPU.ShiftedDB | addr); +} + +static inline uint32 DirectIndexedIndirectE0 (AccessMode a) // (d,X) +{ + uint32 addr = S9xGetWord(DirectIndexedXE0(READ)); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + + return (ICPU.ShiftedDB | addr); +} + +static inline uint32 DirectIndexedIndirectE1 (AccessMode a) // (d,X) +{ + uint32 addr = S9xGetWord(DirectIndexedXE1(READ), Registers.DL ? WRAP_BANK : WRAP_PAGE); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + + return (ICPU.ShiftedDB | addr); +} + +static inline uint32 AbsoluteIndexedXSlow (AccessMode a) // a,X +{ + uint32 addr = AbsoluteSlow(a); + if (a & WRITE || !CheckIndex() || (addr & 0xff) + Registers.XL >= 0x100) + AddCycles(ONE_CYCLE); + + return (addr + Registers.X.W); +} + +static inline uint32 AbsoluteIndexedXX0 (AccessMode a) // a,X +{ + uint32 addr = Absolute(a); + AddCycles(ONE_CYCLE); + + return (addr + Registers.X.W); +} + +static inline uint32 AbsoluteIndexedXX1 (AccessMode a) // a,X +{ + uint32 addr = Absolute(a); + if (a & WRITE || (addr & 0xff) + Registers.XL >= 0x100) + AddCycles(ONE_CYCLE); + + return (addr + Registers.X.W); +} + +static inline uint32 AbsoluteIndexedYSlow (AccessMode a) // a,Y +{ + uint32 addr = AbsoluteSlow(a); + if (a & WRITE || !CheckIndex() || (addr & 0xff) + Registers.YL >= 0x100) + AddCycles(ONE_CYCLE); + + return (addr + Registers.Y.W); +} + +static inline uint32 AbsoluteIndexedYX0 (AccessMode a) // a,Y +{ + uint32 addr = Absolute(a); + AddCycles(ONE_CYCLE); + + return (addr + Registers.Y.W); +} + +static inline uint32 AbsoluteIndexedYX1 (AccessMode a) // a,Y +{ + uint32 addr = Absolute(a); + if (a & WRITE || (addr & 0xff) + Registers.YL >= 0x100) + AddCycles(ONE_CYCLE); + + return (addr + Registers.Y.W); +} + +static inline uint32 AbsoluteLongIndexedXSlow (AccessMode a) // l,X +{ + return (AbsoluteLongSlow(a) + Registers.X.W); +} + +static inline uint32 AbsoluteLongIndexedX (AccessMode a) // l,X +{ + return (AbsoluteLong(a) + Registers.X.W); +} + +static inline uint32 StackRelativeSlow (AccessMode a) // d,S +{ + uint16 addr = Immediate8Slow(a) + Registers.S.W; + AddCycles(ONE_CYCLE); + + return (addr); +} + +static inline uint32 StackRelative (AccessMode a) // d,S +{ + uint16 addr = Immediate8(a) + Registers.S.W; + AddCycles(ONE_CYCLE); + + return (addr); +} + +static inline uint32 StackRelativeIndirectIndexedSlow (AccessMode a) // (d,S),Y +{ + uint32 addr = S9xGetWord(StackRelativeSlow(READ)); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + addr = (addr + Registers.Y.W + ICPU.ShiftedDB) & 0xffffff; + AddCycles(ONE_CYCLE); + + return (addr); +} + +static inline uint32 StackRelativeIndirectIndexed (AccessMode a) // (d,S),Y +{ + uint32 addr = S9xGetWord(StackRelative(READ)); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + addr = (addr + Registers.Y.W + ICPU.ShiftedDB) & 0xffffff; + AddCycles(ONE_CYCLE); + + return (addr); +} + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/cpuexec.cpp b/plugins/snes9x_gx/source/snes9x/cpuexec.cpp new file mode 100644 index 00000000..4bd4c256 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/cpuexec.cpp @@ -0,0 +1,594 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "cpuops.h" +#include "dma.h" +#include "apu/apu.h" +#include "fxemu.h" +#include "snapshot.h" +#ifdef DEBUGGER +#include "debug.h" +#include "missing.h" +#endif + + +void S9xMainLoop (void) +{ + for (;;) + { + if (CPU.Flags) + { + if (CPU.Flags & NMI_FLAG) + { + if (Timings.NMITriggerPos <= CPU.Cycles) + { + CPU.Flags &= ~NMI_FLAG; + Timings.NMITriggerPos = 0xffff; + if (CPU.WaitingForInterrupt) + { + CPU.WaitingForInterrupt = FALSE; + Registers.PCw++; + } + + S9xOpcode_NMI(); + } + } + + #ifdef DEBUGGER + if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG)) + { + for (int Break = 0; Break != 6; Break++) + { + if (S9xBreakpoint[Break].Enabled && + S9xBreakpoint[Break].Bank == Registers.PB && + S9xBreakpoint[Break].Address == Registers.PCw) + { + if (S9xBreakpoint[Break].Enabled == 2) + S9xBreakpoint[Break].Enabled = TRUE; + else + CPU.Flags |= DEBUG_MODE_FLAG; + } + } + } + #endif + + if (CPU.Flags & IRQ_FLAG) + { + if (CPU.IRQPending) + // FIXME: In case of IRQ during WRAM refresh + CPU.IRQPending--; + else + { + if (CPU.WaitingForInterrupt) + { + CPU.WaitingForInterrupt = FALSE; + Registers.PCw++; + } + + if (CPU.IRQActive && !Settings.DisableIRQ) + { + if (!CheckFlag(IRQ)) + // in IRQ handler $4211 is supposed to be read, so IRQ_FLAG should be cleared. + S9xOpcode_IRQ(); + } + else + CPU.Flags &= ~IRQ_FLAG; + } + } + + if (CPU.Flags & SCAN_KEYS_FLAG) + break; + + #ifdef DEBUGGER + if (CPU.Flags & DEBUG_MODE_FLAG) + break; + + if (CPU.Flags & TRACE_FLAG) + S9xTrace(); + + if (CPU.Flags & SINGLE_STEP_FLAG) + { + CPU.Flags &= ~SINGLE_STEP_FLAG; + CPU.Flags |= DEBUG_MODE_FLAG; + } + #endif + } + + #ifdef CPU_SHUTDOWN + CPU.PBPCAtOpcodeStart = Registers.PBPC; + #endif + + register uint8 Op; + register struct SOpcodes *Opcodes; + + CPU.PrevCycles = CPU.Cycles; + + if (CPU.PCBase) + { + Op = CPU.PCBase[Registers.PCw]; + CPU.Cycles += CPU.MemSpeed; + Opcodes = ICPU.S9xOpcodes; + } + else + { + Op = S9xGetByte(Registers.PBPC); + OpenBus = Op; + Opcodes = S9xOpcodesSlow; + } + + if ((Registers.PCw & MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE) + { + uint8 *oldPCBase = CPU.PCBase; + + CPU.PCBase = S9xGetBasePointer(ICPU.ShiftedPB + ((uint16) (Registers.PCw + 4))); + if (oldPCBase != CPU.PCBase || (Registers.PCw & ~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK)) + Opcodes = S9xOpcodesSlow; + } + + Registers.PCw++; + (*Opcodes[Op].S9xOpcode)(); + + if (SA1.Executing) + S9xSA1MainLoop(); + + #if (S9X_ACCURACY_LEVEL <= 2) + while (CPU.Cycles >= CPU.NextEvent) + S9xDoHEventProcessing(); + #endif + } + + S9xPackStatus(); + + if (CPU.Flags & SCAN_KEYS_FLAG) + { + #ifdef DEBUGGER + if (!(CPU.Flags & FRAME_ADVANCE_FLAG)) + #endif + S9xSyncSpeed(); + CPU.Flags &= ~SCAN_KEYS_FLAG; + } +} + +void S9xSetIRQ (uint32 source) +{ + CPU.IRQActive |= source; + CPU.IRQPending = Timings.IRQPendCount; + CPU.Flags |= IRQ_FLAG; + + if (CPU.WaitingForInterrupt) + { + // Force IRQ to trigger immediately after WAI - + // Final Fantasy Mystic Quest crashes without this. + CPU.WaitingForInterrupt = FALSE; + Registers.PCw++; + } + +#ifdef DEBUGGER + S9xTraceMessage("--- /IRQ low"); +#endif +} + +void S9xClearIRQ (uint32 source) +{ + CPU.IRQActive &= ~source; + if (!CPU.IRQActive) + CPU.Flags &= ~IRQ_FLAG; + +#ifdef DEBUGGER + S9xTraceMessage("--- /IRQ high"); +#endif +} + +void S9xDoHEventProcessing (void) +{ +#ifdef DEBUGGER + static char eventname[13][32] = + { + "", + "HC_HBLANK_START_EVENT", + "HC_IRQ_1_3_EVENT ", + "HC_HDMA_START_EVENT ", + "HC_IRQ_3_5_EVENT ", + "HC_HCOUNTER_MAX_EVENT", + "HC_IRQ_5_7_EVENT ", + "HC_HDMA_INIT_EVENT ", + "HC_IRQ_7_9_EVENT ", + "HC_RENDER_EVENT ", + "HC_IRQ_9_A_EVENT ", + "HC_WRAM_REFRESH_EVENT", + "HC_IRQ_A_1_EVENT " + }; +#endif + +#ifdef DEBUGGER + if (Settings.TraceHCEvent) + S9xTraceFormattedMessage("--- HC event processing (%s) expected HC:%04d executed HC:%04d", + eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles); +#endif + +#ifdef CPU_SHUTDOWN + CPU.WaitCounter++; +#endif + + switch (CPU.WhichEvent) + { + case HC_HBLANK_START_EVENT: + S9xCheckMissingHTimerPosition(Timings.HBlankStart); + S9xReschedule(); + break; + + case HC_HDMA_START_EVENT: + S9xCheckMissingHTimerPosition(Timings.HDMAStart); + S9xReschedule(); + + if (PPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) + { + #ifdef DEBUGGER + S9xTraceFormattedMessage("*** HDMA Transfer HC:%04d, Channel:%02x", CPU.Cycles, PPU.HDMA); + #endif + PPU.HDMA = S9xDoHDMA(PPU.HDMA); + } + + break; + + case HC_HCOUNTER_MAX_EVENT: + if (Settings.SuperFX) + { + if (!SuperFX.oneLineDone) + S9xSuperFXExec(); + SuperFX.oneLineDone = FALSE; + } + + S9xAPUEndScanline(); + CPU.Cycles -= Timings.H_Max; + S9xAPUSetReferenceTime(CPU.Cycles); + + if ((Timings.NMITriggerPos != 0xffff) && (Timings.NMITriggerPos >= Timings.H_Max)) + Timings.NMITriggerPos -= Timings.H_Max; + + CPU.V_Counter++; + if (CPU.V_Counter >= Timings.V_Max) // V ranges from 0 to Timings.V_Max - 1 + { + CPU.V_Counter = 0; + Timings.InterlaceField ^= 1; + + // From byuu: + // [NTSC] + // interlace mode has 525 scanlines: 263 on the even frame, and 262 on the odd. + // non-interlace mode has 524 scanlines: 262 scanlines on both even and odd frames. + // [PAL] <PAL info is unverified on hardware> + // interlace mode has 625 scanlines: 313 on the even frame, and 312 on the odd. + // non-interlace mode has 624 scanlines: 312 scanlines on both even and odd frames. + if (IPPU.Interlace && !Timings.InterlaceField) + Timings.V_Max = Timings.V_Max_Master + 1; // 263 (NTSC), 313?(PAL) + else + Timings.V_Max = Timings.V_Max_Master; // 262 (NTSC), 312?(PAL) + + Memory.FillRAM[0x213F] ^= 0x80; + PPU.RangeTimeOver = 0; + + // FIXME: reading $4210 will wait 2 cycles, then perform reading, then wait 4 more cycles. + Memory.FillRAM[0x4210] = Model->_5A22; + CPU.Flags &= ~NMI_FLAG; + Timings.NMITriggerPos = 0xffff; + + ICPU.Frame++; + PPU.HVBeamCounterLatched = 0; + CPU.Flags |= SCAN_KEYS_FLAG; + } + + // From byuu: + // In non-interlace mode, there are 341 dots per scanline, and 262 scanlines per frame. + // On odd frames, scanline 240 is one dot short. + // In interlace mode, there are always 341 dots per scanline. Even frames have 263 scanlines, + // and odd frames have 262 scanlines. + // Interlace mode scanline 240 on odd frames is not missing a dot. + if (CPU.V_Counter == 240 && !IPPU.Interlace && Timings.InterlaceField) // V=240 + Timings.H_Max = Timings.H_Max_Master - ONE_DOT_CYCLE; // HC=1360 + else + Timings.H_Max = Timings.H_Max_Master; // HC=1364 + + if (Model->_5A22 == 2) + { + if (CPU.V_Counter != 240 || IPPU.Interlace || !Timings.InterlaceField) // V=240 + { + if (Timings.WRAMRefreshPos == SNES_WRAM_REFRESH_HC_v2 - ONE_DOT_CYCLE) // HC=534 + Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2; // HC=538 + else + Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2 - ONE_DOT_CYCLE; // HC=534 + } + } + else + Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v1; + + S9xCheckMissingHTimerPosition(0); + + if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) // VBlank starts from V=225(240). + { + S9xEndScreenRefresh(); + PPU.HDMA = 0; + // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU. + #ifdef DEBUGGER + missing.dma_this_frame = 0; + #endif + IPPU.MaxBrightness = PPU.Brightness; + PPU.ForcedBlanking = (Memory.FillRAM[0x2100] >> 7) & 1; + + if (!PPU.ForcedBlanking) + { + PPU.OAMAddr = PPU.SavedOAMAddr; + + uint8 tmp = 0; + + if (PPU.OAMPriorityRotation) + tmp = (PPU.OAMAddr & 0xFE) >> 1; + if ((PPU.OAMFlip & 1) || PPU.FirstSprite != tmp) + { + PPU.FirstSprite = tmp; + IPPU.OBJChanged = TRUE; + } + + PPU.OAMFlip = 0; + } + + // FIXME: writing to $4210 will wait 6 cycles. + Memory.FillRAM[0x4210] = 0x80 | Model->_5A22; + if (Memory.FillRAM[0x4200] & 0x80) + { + // FIXME: triggered at HC=6, checked just before the final CPU cycle, + // then, when to call S9xOpcode_NMI()? + CPU.Flags |= NMI_FLAG; + Timings.NMITriggerPos = 6 + 6; + } + + } + + if (CPU.V_Counter == PPU.ScreenHeight + 3) // FIXME: not true + { + if (Memory.FillRAM[0x4200] & 1) + S9xDoAutoJoypad(); + } + + if (CPU.V_Counter == FIRST_VISIBLE_LINE) // V=1 + S9xStartScreenRefresh(); + + CPU.NextEvent = -1; + S9xReschedule(); + + break; + + case HC_HDMA_INIT_EVENT: + S9xCheckMissingHTimerPosition(Timings.HDMAInit); + S9xReschedule(); + + if (CPU.V_Counter == 0) + { + #ifdef DEBUGGER + S9xTraceFormattedMessage("*** HDMA Init HC:%04d, Channel:%02x", CPU.Cycles, PPU.HDMA); + #endif + S9xStartHDMA(); + } + + break; + + case HC_RENDER_EVENT: + if (CPU.V_Counter >= FIRST_VISIBLE_LINE && CPU.V_Counter <= PPU.ScreenHeight) + RenderLine((uint8) (CPU.V_Counter - FIRST_VISIBLE_LINE)); + + S9xCheckMissingHTimerPosition(Timings.RenderPos); + S9xReschedule(); + + break; + + case HC_WRAM_REFRESH_EVENT: + #ifdef DEBUGGER + S9xTraceFormattedMessage("*** WRAM Refresh HC:%04d", CPU.Cycles); + #endif + + S9xCheckMissingHTimerHalt(Timings.WRAMRefreshPos, SNES_WRAM_REFRESH_CYCLES); + CPU.Cycles += SNES_WRAM_REFRESH_CYCLES; + + S9xCheckMissingHTimerPosition(Timings.WRAMRefreshPos); + S9xReschedule(); + + break; + + case HC_IRQ_1_3_EVENT: + case HC_IRQ_3_5_EVENT: + case HC_IRQ_5_7_EVENT: + case HC_IRQ_7_9_EVENT: + case HC_IRQ_9_A_EVENT: + case HC_IRQ_A_1_EVENT: + if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) + S9xSetIRQ(PPU_IRQ_SOURCE); + else + if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) + S9xSetIRQ(PPU_IRQ_SOURCE); + + S9xReschedule(); + break; + } + +#ifdef DEBUGGER + if (Settings.TraceHCEvent) + S9xTraceFormattedMessage("--- HC event rescheduled (%s) expected HC:%04d current HC:%04d", + eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles); +#endif +} + diff --git a/plugins/snes9x_gx/source/snes9x/cpuexec.h b/plugins/snes9x_gx/source/snes9x/cpuexec.h new file mode 100644 index 00000000..b11cff61 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/cpuexec.h @@ -0,0 +1,353 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _CPUEXEC_H_ +#define _CPUEXEC_H_ + +#include "ppu.h" + +struct SOpcodes +{ + void (*S9xOpcode) (void); +}; + +struct SICPU +{ + struct SOpcodes *S9xOpcodes; + uint8 *S9xOpLengths; + uint8 _Carry; + uint8 _Zero; + uint8 _Negative; + uint8 _Overflow; + bool8 CPUExecuting; + uint32 ShiftedPB; + uint32 ShiftedDB; + uint32 Frame; + uint32 FrameAdvanceCount; +}; + +extern struct SICPU ICPU; + +extern struct SOpcodes S9xOpcodesE1[256]; +extern struct SOpcodes S9xOpcodesM1X1[256]; +extern struct SOpcodes S9xOpcodesM1X0[256]; +extern struct SOpcodes S9xOpcodesM0X1[256]; +extern struct SOpcodes S9xOpcodesM0X0[256]; +extern struct SOpcodes S9xOpcodesSlow[256]; +extern uint8 S9xOpLengthsM1X1[256]; +extern uint8 S9xOpLengthsM1X0[256]; +extern uint8 S9xOpLengthsM0X1[256]; +extern uint8 S9xOpLengthsM0X0[256]; + +void S9xMainLoop (void); +void S9xReset (void); +void S9xSoftReset (void); +void S9xDoHEventProcessing (void); +void S9xClearIRQ (uint32); +void S9xSetIRQ (uint32); + +static inline void S9xUnpackStatus (void) +{ + ICPU._Zero = (Registers.PL & Zero) == 0; + ICPU._Negative = (Registers.PL & Negative); + ICPU._Carry = (Registers.PL & Carry); + ICPU._Overflow = (Registers.PL & Overflow) >> 6; +} + +static inline void S9xPackStatus (void) +{ + Registers.PL &= ~(Zero | Negative | Carry | Overflow); + Registers.PL |= ICPU._Carry | ((ICPU._Zero == 0) << 1) | (ICPU._Negative & 0x80) | (ICPU._Overflow << 6); +} + +static inline void S9xFixCycles (void) +{ + if (CheckEmulation()) + { + ICPU.S9xOpcodes = S9xOpcodesE1; + ICPU.S9xOpLengths = S9xOpLengthsM1X1; + } + else + if (CheckMemory()) + { + if (CheckIndex()) + { + ICPU.S9xOpcodes = S9xOpcodesM1X1; + ICPU.S9xOpLengths = S9xOpLengthsM1X1; + } + else + { + ICPU.S9xOpcodes = S9xOpcodesM1X0; + ICPU.S9xOpLengths = S9xOpLengthsM1X0; + } + } + else + { + if (CheckIndex()) + { + ICPU.S9xOpcodes = S9xOpcodesM0X1; + ICPU.S9xOpLengths = S9xOpLengthsM0X1; + } + else + { + ICPU.S9xOpcodes = S9xOpcodesM0X0; + ICPU.S9xOpLengths = S9xOpLengthsM0X0; + } + } +} + +static inline void S9xReschedule (void) +{ + uint8 next = 0; + int32 hpos = 0; + + switch (CPU.WhichEvent) + { + case HC_HBLANK_START_EVENT: + case HC_IRQ_1_3_EVENT: + next = HC_HDMA_START_EVENT; + hpos = Timings.HDMAStart; + break; + + case HC_HDMA_START_EVENT: + case HC_IRQ_3_5_EVENT: + next = HC_HCOUNTER_MAX_EVENT; + hpos = Timings.H_Max; + break; + + case HC_HCOUNTER_MAX_EVENT: + case HC_IRQ_5_7_EVENT: + next = HC_HDMA_INIT_EVENT; + hpos = Timings.HDMAInit; + break; + + case HC_HDMA_INIT_EVENT: + case HC_IRQ_7_9_EVENT: + next = HC_RENDER_EVENT; + hpos = Timings.RenderPos; + break; + + case HC_RENDER_EVENT: + case HC_IRQ_9_A_EVENT: + next = HC_WRAM_REFRESH_EVENT; + hpos = Timings.WRAMRefreshPos; + break; + + case HC_WRAM_REFRESH_EVENT: + case HC_IRQ_A_1_EVENT: + next = HC_HBLANK_START_EVENT; + hpos = Timings.HBlankStart; + break; + } + + if (((int32) PPU.HTimerPosition > CPU.NextEvent) && ((int32) PPU.HTimerPosition < hpos)) + { + hpos = (int32) PPU.HTimerPosition; + + switch (next) + { + case HC_HDMA_START_EVENT: + next = HC_IRQ_1_3_EVENT; + break; + + case HC_HCOUNTER_MAX_EVENT: + next = HC_IRQ_3_5_EVENT; + break; + + case HC_HDMA_INIT_EVENT: + next = HC_IRQ_5_7_EVENT; + break; + + case HC_RENDER_EVENT: + next = HC_IRQ_7_9_EVENT; + break; + + case HC_WRAM_REFRESH_EVENT: + next = HC_IRQ_9_A_EVENT; + break; + + case HC_HBLANK_START_EVENT: + next = HC_IRQ_A_1_EVENT; + break; + } + } + + CPU.NextEvent = hpos; + CPU.WhichEvent = next; +} + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/cpumacro.h b/plugins/snes9x_gx/source/snes9x/cpumacro.h new file mode 100644 index 00000000..9b1fc4cb --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/cpumacro.h @@ -0,0 +1,904 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _CPUMACRO_H_ +#define _CPUMACRO_H_ + +#define rOP8(OP, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + uint8 val = OpenBus = S9xGetByte(ADDR(READ)); \ + FUNC(val); \ +} + +#define rOP16(OP, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + uint16 val = S9xGetWord(ADDR(READ), WRAP); \ + OpenBus = (uint8) (val >> 8); \ + FUNC(val); \ +} + +#define rOPC(OP, COND, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + if (Check##COND()) \ + { \ + uint8 val = OpenBus = S9xGetByte(ADDR(READ)); \ + FUNC(val); \ + } \ + else \ + { \ + uint16 val = S9xGetWord(ADDR(READ), WRAP); \ + OpenBus = (uint8) (val >> 8); \ + FUNC(val); \ + } \ +} + +#define rOPM(OP, ADDR, WRAP, FUNC) \ +rOPC(OP, Memory, ADDR, WRAP, FUNC) + +#define rOPX(OP, ADDR, WRAP, FUNC) \ +rOPC(OP, Index, ADDR, WRAP, FUNC) + +#define wOP8(OP, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + FUNC##8(ADDR(WRITE)); \ +} + +#define wOP16(OP, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + FUNC##16(ADDR(WRITE), WRAP); \ +} + +#define wOPC(OP, COND, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + if (Check##COND()) \ + FUNC##8(ADDR(WRITE)); \ + else \ + FUNC##16(ADDR(WRITE), WRAP); \ +} + +#define wOPM(OP, ADDR, WRAP, FUNC) \ +wOPC(OP, Memory, ADDR, WRAP, FUNC) + +#define wOPX(OP, ADDR, WRAP, FUNC) \ +wOPC(OP, Index, ADDR, WRAP, FUNC) + +#define mOP8(OP, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + FUNC##8(ADDR(MODIFY)); \ +} + +#define mOP16(OP, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + FUNC##16(ADDR(MODIFY), WRAP); \ +} + +#define mOPC(OP, COND, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + if (Check##COND()) \ + FUNC##8(ADDR(MODIFY)); \ + else \ + FUNC##16(ADDR(MODIFY), WRAP); \ +} + +#define mOPM(OP, ADDR, WRAP, FUNC) \ +mOPC(OP, Memory, ADDR, WRAP, FUNC) + +#define bOP(OP, REL, COND, CHK, E) \ +static void Op##OP (void) \ +{ \ + pair newPC; \ + newPC.W = REL(JUMP); \ + if (COND) \ + { \ + AddCycles(ONE_CYCLE); \ + if (E && Registers.PCh != newPC.B.h) \ + AddCycles(ONE_CYCLE); \ + if ((Registers.PCw & ~MEMMAP_MASK) != (newPC.W & ~MEMMAP_MASK)) \ + S9xSetPCBase(ICPU.ShiftedPB + newPC.W); \ + else \ + Registers.PCw = newPC.W; \ + CPUShutdown(); \ + } \ +} + + +static inline void SetZN (uint16 Work16) +{ + ICPU._Zero = Work16 != 0; + ICPU._Negative = (uint8) (Work16 >> 8); +} + +static inline void SetZN (uint8 Work8) +{ + ICPU._Zero = Work8; + ICPU._Negative = Work8; +} + +static inline void ADC (uint16 Work16) +{ + if (CheckDecimal()) + { + uint16 A1 = Registers.A.W & 0x000F; + uint16 A2 = Registers.A.W & 0x00F0; + uint16 A3 = Registers.A.W & 0x0F00; + uint32 A4 = Registers.A.W & 0xF000; + uint16 W1 = Work16 & 0x000F; + uint16 W2 = Work16 & 0x00F0; + uint16 W3 = Work16 & 0x0F00; + uint16 W4 = Work16 & 0xF000; + + A1 += W1 + CheckCarry(); + if (A1 > 0x0009) + { + A1 -= 0x000A; + A1 &= 0x000F; + A2 += 0x0010; + } + + A2 += W2; + if (A2 > 0x0090) + { + A2 -= 0x00A0; + A2 &= 0x00F0; + A3 += 0x0100; + } + + A3 += W3; + if (A3 > 0x0900) + { + A3 -= 0x0A00; + A3 &= 0x0F00; + A4 += 0x1000; + } + + A4 += W4; + if (A4 > 0x9000) + { + A4 -= 0xA000; + A4 &= 0xF000; + SetCarry(); + } + else + ClearCarry(); + + uint16 Ans16 = A4 | A3 | A2 | A1; + + if (~(Registers.A.W ^ Work16) & (Work16 ^ Ans16) & 0x8000) + SetOverflow(); + else + ClearOverflow(); + + Registers.A.W = Ans16; + SetZN(Registers.A.W); + } + else + { + uint32 Ans32 = Registers.A.W + Work16 + CheckCarry(); + + ICPU._Carry = Ans32 >= 0x10000; + + if (~(Registers.A.W ^ Work16) & (Work16 ^ (uint16) Ans32) & 0x8000) + SetOverflow(); + else + ClearOverflow(); + + Registers.A.W = (uint16) Ans32; + SetZN(Registers.A.W); + } +} + +static inline void ADC (uint8 Work8) +{ + if (CheckDecimal()) + { + uint8 A1 = Registers.A.W & 0x0F; + uint16 A2 = Registers.A.W & 0xF0; + uint8 W1 = Work8 & 0x0F; + uint8 W2 = Work8 & 0xF0; + + A1 += W1 + CheckCarry(); + if (A1 > 0x09) + { + A1 -= 0x0A; + A1 &= 0x0F; + A2 += 0x10; + } + + A2 += W2; + if (A2 > 0x90) + { + A2 -= 0xA0; + A2 &= 0xF0; + SetCarry(); + } + else + ClearCarry(); + + uint8 Ans8 = A2 | A1; + + if (~(Registers.AL ^ Work8) & (Work8 ^ Ans8) & 0x80) + SetOverflow(); + else + ClearOverflow(); + + Registers.AL = Ans8; + SetZN(Registers.AL); + } + else + { + uint16 Ans16 = Registers.AL + Work8 + CheckCarry(); + + ICPU._Carry = Ans16 >= 0x100; + + if (~(Registers.AL ^ Work8) & (Work8 ^ (uint8) Ans16) & 0x80) + SetOverflow(); + else + ClearOverflow(); + + Registers.AL = (uint8) Ans16; + SetZN(Registers.AL); + } +} + +static inline void AND (uint16 Work16) +{ + Registers.A.W &= Work16; + SetZN(Registers.A.W); +} + +static inline void AND (uint8 Work8) +{ + Registers.AL &= Work8; + SetZN(Registers.AL); +} + +static inline void ASL16 (uint32 OpAddress, s9xwrap_t w) +{ + uint16 Work16 = S9xGetWord(OpAddress, w); + ICPU._Carry = (Work16 & 0x8000) != 0; + Work16 <<= 1; + AddCycles(ONE_CYCLE); + S9xSetWord(Work16, OpAddress, w, WRITE_10); + OpenBus = Work16 & 0xff; + SetZN(Work16); +} + +static inline void ASL8 (uint32 OpAddress) +{ + uint8 Work8 = S9xGetByte(OpAddress); + ICPU._Carry = (Work8 & 0x80) != 0; + Work8 <<= 1; + AddCycles(ONE_CYCLE); + S9xSetByte(Work8, OpAddress); + OpenBus = Work8; + SetZN(Work8); +} + +static inline void BIT (uint16 Work16) +{ + ICPU._Overflow = (Work16 & 0x4000) != 0; + ICPU._Negative = (uint8) (Work16 >> 8); + ICPU._Zero = (Work16 & Registers.A.W) != 0; +} + +static inline void BIT (uint8 Work8) +{ + ICPU._Overflow = (Work8 & 0x40) != 0; + ICPU._Negative = Work8; + ICPU._Zero = Work8 & Registers.AL; +} + +static inline void CMP (uint16 val) +{ + int32 Int32 = (int32) Registers.A.W - (int32) val; + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); +} + +static inline void CMP (uint8 val) +{ + int16 Int16 = (int16) Registers.AL - (int16) val; + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); +} + +static inline void CPX (uint16 val) +{ + int32 Int32 = (int32) Registers.X.W - (int32) val; + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); +} + +static inline void CPX (uint8 val) +{ + int16 Int16 = (int16) Registers.XL - (int16) val; + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); +} + +static inline void CPY (uint16 val) +{ + int32 Int32 = (int32) Registers.Y.W - (int32) val; + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); +} + +static inline void CPY (uint8 val) +{ + int16 Int16 = (int16) Registers.YL - (int16) val; + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); +} + +static inline void DEC16 (uint32 OpAddress, s9xwrap_t w) +{ +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + uint16 Work16 = S9xGetWord(OpAddress, w) - 1; + AddCycles(ONE_CYCLE); + S9xSetWord(Work16, OpAddress, w, WRITE_10); + OpenBus = Work16 & 0xff; + SetZN(Work16); +} + +static inline void DEC8 (uint32 OpAddress) +{ +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + uint8 Work8 = S9xGetByte(OpAddress) - 1; + AddCycles(ONE_CYCLE); + S9xSetByte(Work8, OpAddress); + OpenBus = Work8; + SetZN(Work8); +} + +static inline void EOR (uint16 val) +{ + Registers.A.W ^= val; + SetZN(Registers.A.W); +} + +static inline void EOR (uint8 val) +{ + Registers.AL ^= val; + SetZN(Registers.AL); +} + +static inline void INC16 (uint32 OpAddress, s9xwrap_t w) +{ +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + uint16 Work16 = S9xGetWord(OpAddress, w) + 1; + AddCycles(ONE_CYCLE); + S9xSetWord(Work16, OpAddress, w, WRITE_10); + OpenBus = Work16 & 0xff; + SetZN(Work16); +} + +static inline void INC8 (uint32 OpAddress) +{ +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + uint8 Work8 = S9xGetByte(OpAddress) + 1; + AddCycles(ONE_CYCLE); + S9xSetByte(Work8, OpAddress); + OpenBus = Work8; + SetZN(Work8); +} + +static inline void LDA (uint16 val) +{ + Registers.A.W = val; + SetZN(Registers.A.W); +} + +static inline void LDA (uint8 val) +{ + Registers.AL = val; + SetZN(Registers.AL); +} + +static inline void LDX (uint16 val) +{ + Registers.X.W = val; + SetZN(Registers.X.W); +} + +static inline void LDX (uint8 val) +{ + Registers.XL = val; + SetZN(Registers.XL); +} + +static inline void LDY (uint16 val) +{ + Registers.Y.W = val; + SetZN(Registers.Y.W); +} + +static inline void LDY (uint8 val) +{ + Registers.YL = val; + SetZN(Registers.YL); +} + +static inline void LSR16 (uint32 OpAddress, s9xwrap_t w) +{ + uint16 Work16 = S9xGetWord(OpAddress, w); + ICPU._Carry = Work16 & 1; + Work16 >>= 1; + AddCycles(ONE_CYCLE); + S9xSetWord(Work16, OpAddress, w, WRITE_10); + OpenBus = Work16 & 0xff; + SetZN(Work16); +} + +static inline void LSR8 (uint32 OpAddress) +{ + uint8 Work8 = S9xGetByte(OpAddress); + ICPU._Carry = Work8 & 1; + Work8 >>= 1; + AddCycles(ONE_CYCLE); + S9xSetByte(Work8, OpAddress); + OpenBus = Work8; + SetZN(Work8); +} + +static inline void ORA (uint16 val) +{ + Registers.A.W |= val; + SetZN(Registers.A.W); +} + +static inline void ORA (uint8 val) +{ + Registers.AL |= val; + SetZN(Registers.AL); +} + +static inline void ROL16 (uint32 OpAddress, s9xwrap_t w) +{ + uint32 Work32 = (((uint32) S9xGetWord(OpAddress, w)) << 1) | CheckCarry(); + ICPU._Carry = Work32 >= 0x10000; + AddCycles(ONE_CYCLE); + S9xSetWord((uint16) Work32, OpAddress, w, WRITE_10); + OpenBus = Work32 & 0xff; + SetZN((uint16) Work32); +} + +static inline void ROL8 (uint32 OpAddress) +{ + uint16 Work16 = (((uint16) S9xGetByte(OpAddress)) << 1) | CheckCarry(); + ICPU._Carry = Work16 >= 0x100; + AddCycles(ONE_CYCLE); + S9xSetByte((uint8) Work16, OpAddress); + OpenBus = Work16 & 0xff; + SetZN((uint8) Work16); +} + +static inline void ROR16 (uint32 OpAddress, s9xwrap_t w) +{ + uint32 Work32 = ((uint32) S9xGetWord(OpAddress, w)) | (((uint32) CheckCarry()) << 16); + ICPU._Carry = Work32 & 1; + Work32 >>= 1; + AddCycles(ONE_CYCLE); + S9xSetWord((uint16) Work32, OpAddress, w, WRITE_10); + OpenBus = Work32 & 0xff; + SetZN((uint16) Work32); +} + +static inline void ROR8 (uint32 OpAddress) +{ + uint16 Work16 = ((uint16) S9xGetByte(OpAddress)) | (((uint16) CheckCarry()) << 8); + ICPU._Carry = Work16 & 1; + Work16 >>= 1; + AddCycles(ONE_CYCLE); + S9xSetByte((uint8) Work16, OpAddress); + OpenBus = Work16 & 0xff; + SetZN((uint8) Work16); +} + +static inline void SBC (uint16 Work16) +{ + if (CheckDecimal()) + { + uint16 A1 = Registers.A.W & 0x000F; + uint16 A2 = Registers.A.W & 0x00F0; + uint16 A3 = Registers.A.W & 0x0F00; + uint32 A4 = Registers.A.W & 0xF000; + uint16 W1 = Work16 & 0x000F; + uint16 W2 = Work16 & 0x00F0; + uint16 W3 = Work16 & 0x0F00; + uint16 W4 = Work16 & 0xF000; + + A1 -= W1 + !CheckCarry(); + A2 -= W2; + A3 -= W3; + A4 -= W4; + + if (A1 > 0x000F) + { + A1 += 0x000A; + A1 &= 0x000F; + A2 -= 0x0010; + } + + if (A2 > 0x00F0) + { + A2 += 0x00A0; + A2 &= 0x00F0; + A3 -= 0x0100; + } + + if (A3 > 0x0F00) + { + A3 += 0x0A00; + A3 &= 0x0F00; + A4 -= 0x1000; + } + + if (A4 > 0xF000) + { + A4 += 0xA000; + A4 &= 0xF000; + ClearCarry(); + } + else + SetCarry(); + + uint16 Ans16 = A4 | A3 | A2 | A1; + + if ((Registers.A.W ^ Work16) & (Registers.A.W ^ Ans16) & 0x8000) + SetOverflow(); + else + ClearOverflow(); + + Registers.A.W = Ans16; + SetZN(Registers.A.W); + } + else + { + int32 Int32 = (int32) Registers.A.W - (int32) Work16 + (int32) CheckCarry() - 1; + + ICPU._Carry = Int32 >= 0; + + if ((Registers.A.W ^ Work16) & (Registers.A.W ^ (uint16) Int32) & 0x8000) + SetOverflow(); + else + ClearOverflow(); + + Registers.A.W = (uint16) Int32; + SetZN(Registers.A.W); + } +} + +static inline void SBC (uint8 Work8) +{ + if (CheckDecimal()) + { + uint8 A1 = Registers.A.W & 0x0F; + uint16 A2 = Registers.A.W & 0xF0; + uint8 W1 = Work8 & 0x0F; + uint8 W2 = Work8 & 0xF0; + + A1 -= W1 + !CheckCarry(); + A2 -= W2; + + if (A1 > 0x0F) + { + A1 += 0x0A; + A1 &= 0x0F; + A2 -= 0x10; + } + + if (A2 > 0xF0) + { + A2 += 0xA0; + A2 &= 0xF0; + ClearCarry(); + } + else + SetCarry(); + + uint8 Ans8 = A2 | A1; + + if ((Registers.AL ^ Work8) & (Registers.AL ^ Ans8) & 0x80) + SetOverflow(); + else + ClearOverflow(); + + Registers.AL = Ans8; + SetZN(Registers.AL); + } + else + { + int16 Int16 = (int16) Registers.AL - (int16) Work8 + (int16) CheckCarry() - 1; + + ICPU._Carry = Int16 >= 0; + + if ((Registers.AL ^ Work8) & (Registers.AL ^ (uint8) Int16) & 0x80) + SetOverflow(); + else + ClearOverflow(); + + Registers.AL = (uint8) Int16; + SetZN(Registers.AL); + } +} + +static inline void STA16 (uint32 OpAddress, enum s9xwrap_t w) +{ + S9xSetWord(Registers.A.W, OpAddress, w); + OpenBus = Registers.AH; +} + +static inline void STA8 (uint32 OpAddress) +{ + S9xSetByte(Registers.AL, OpAddress); + OpenBus = Registers.AL; +} + +static inline void STX16 (uint32 OpAddress, enum s9xwrap_t w) +{ + S9xSetWord(Registers.X.W, OpAddress, w); + OpenBus = Registers.XH; +} + +static inline void STX8 (uint32 OpAddress) +{ + S9xSetByte(Registers.XL, OpAddress); + OpenBus = Registers.XL; +} + +static inline void STY16 (uint32 OpAddress, enum s9xwrap_t w) +{ + S9xSetWord(Registers.Y.W, OpAddress, w); + OpenBus = Registers.YH; +} + +static inline void STY8 (uint32 OpAddress) +{ + S9xSetByte(Registers.YL, OpAddress); + OpenBus = Registers.YL; +} + +static inline void STZ16 (uint32 OpAddress, enum s9xwrap_t w) +{ + S9xSetWord(0, OpAddress, w); + OpenBus = 0; +} + +static inline void STZ8 (uint32 OpAddress) +{ + S9xSetByte(0, OpAddress); + OpenBus = 0; +} + +static inline void TSB16 (uint32 OpAddress, enum s9xwrap_t w) +{ + uint16 Work16 = S9xGetWord(OpAddress, w); + ICPU._Zero = (Work16 & Registers.A.W) != 0; + Work16 |= Registers.A.W; + AddCycles(ONE_CYCLE); + S9xSetWord(Work16, OpAddress, w, WRITE_10); + OpenBus = Work16 & 0xff; +} + +static inline void TSB8 (uint32 OpAddress) +{ + uint8 Work8 = S9xGetByte(OpAddress); + ICPU._Zero = Work8 & Registers.AL; + Work8 |= Registers.AL; + AddCycles(ONE_CYCLE); + S9xSetByte(Work8, OpAddress); + OpenBus = Work8; +} + +static inline void TRB16 (uint32 OpAddress, enum s9xwrap_t w) +{ + uint16 Work16 = S9xGetWord(OpAddress, w); + ICPU._Zero = (Work16 & Registers.A.W) != 0; + Work16 &= ~Registers.A.W; + AddCycles(ONE_CYCLE); + S9xSetWord(Work16, OpAddress, w, WRITE_10); + OpenBus = Work16 & 0xff; +} + +static inline void TRB8 (uint32 OpAddress) +{ + uint8 Work8 = S9xGetByte(OpAddress); + ICPU._Zero = Work8 & Registers.AL; + Work8 &= ~Registers.AL; + AddCycles(ONE_CYCLE); + S9xSetByte(Work8, OpAddress); + OpenBus = Work8; +} + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/cpuops.cpp b/plugins/snes9x_gx/source/snes9x/cpuops.cpp new file mode 100644 index 00000000..5d1cee24 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/cpuops.cpp @@ -0,0 +1,4027 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "apu/apu.h" + +// for "Magic WDM" features +#ifdef DEBUGGER +#include "snapshot.h" +#include "display.h" +#include "debug.h" +#include "missing.h" +#endif + +#ifdef SA1_OPCODES +#define AddCycles(n) { } +#else +#if (S9X_ACCURACY_LEVEL >= 3) +#define AddCycles(n) { CPU.Cycles += (n); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); } +#else +#define AddCycles(n) { CPU.Cycles += (n); } +#endif +#endif + +#include "cpuaddr.h" +#include "cpuops.h" +#include "cpumacro.h" + + +/* ADC ********************************************************************* */ + +static void Op69M1 (void) +{ + ADC(Immediate8(READ)); +} + +static void Op69M0 (void) +{ + ADC(Immediate16(READ)); +} + +static void Op69Slow (void) +{ + if (CheckMemory()) + ADC(Immediate8Slow(READ)); + else + ADC(Immediate16Slow(READ)); +} + +rOP8 (65M1, Direct, WRAP_BANK, ADC) +rOP16(65M0, Direct, WRAP_BANK, ADC) +rOPM (65Slow, DirectSlow, WRAP_BANK, ADC) + +rOP8 (75E1, DirectIndexedXE1, WRAP_BANK, ADC) +rOP8 (75E0M1, DirectIndexedXE0, WRAP_BANK, ADC) +rOP16(75E0M0, DirectIndexedXE0, WRAP_BANK, ADC) +rOPM (75Slow, DirectIndexedXSlow, WRAP_BANK, ADC) + +rOP8 (72E1, DirectIndirectE1, WRAP_NONE, ADC) +rOP8 (72E0M1, DirectIndirectE0, WRAP_NONE, ADC) +rOP16(72E0M0, DirectIndirectE0, WRAP_NONE, ADC) +rOPM (72Slow, DirectIndirectSlow, WRAP_NONE, ADC) + +rOP8 (61E1, DirectIndexedIndirectE1, WRAP_NONE, ADC) +rOP8 (61E0M1, DirectIndexedIndirectE0, WRAP_NONE, ADC) +rOP16(61E0M0, DirectIndexedIndirectE0, WRAP_NONE, ADC) +rOPM (61Slow, DirectIndexedIndirectSlow, WRAP_NONE, ADC) + +rOP8 (71E1, DirectIndirectIndexedE1, WRAP_NONE, ADC) +rOP8 (71E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, ADC) +rOP16(71E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, ADC) +rOP8 (71E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, ADC) +rOP16(71E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, ADC) +rOPM (71Slow, DirectIndirectIndexedSlow, WRAP_NONE, ADC) + +rOP8 (67M1, DirectIndirectLong, WRAP_NONE, ADC) +rOP16(67M0, DirectIndirectLong, WRAP_NONE, ADC) +rOPM (67Slow, DirectIndirectLongSlow, WRAP_NONE, ADC) + +rOP8 (77M1, DirectIndirectIndexedLong, WRAP_NONE, ADC) +rOP16(77M0, DirectIndirectIndexedLong, WRAP_NONE, ADC) +rOPM (77Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, ADC) + +rOP8 (6DM1, Absolute, WRAP_NONE, ADC) +rOP16(6DM0, Absolute, WRAP_NONE, ADC) +rOPM (6DSlow, AbsoluteSlow, WRAP_NONE, ADC) + +rOP8 (7DM1X1, AbsoluteIndexedXX1, WRAP_NONE, ADC) +rOP16(7DM0X1, AbsoluteIndexedXX1, WRAP_NONE, ADC) +rOP8 (7DM1X0, AbsoluteIndexedXX0, WRAP_NONE, ADC) +rOP16(7DM0X0, AbsoluteIndexedXX0, WRAP_NONE, ADC) +rOPM (7DSlow, AbsoluteIndexedXSlow, WRAP_NONE, ADC) + +rOP8 (79M1X1, AbsoluteIndexedYX1, WRAP_NONE, ADC) +rOP16(79M0X1, AbsoluteIndexedYX1, WRAP_NONE, ADC) +rOP8 (79M1X0, AbsoluteIndexedYX0, WRAP_NONE, ADC) +rOP16(79M0X0, AbsoluteIndexedYX0, WRAP_NONE, ADC) +rOPM (79Slow, AbsoluteIndexedYSlow, WRAP_NONE, ADC) + +rOP8 (6FM1, AbsoluteLong, WRAP_NONE, ADC) +rOP16(6FM0, AbsoluteLong, WRAP_NONE, ADC) +rOPM (6FSlow, AbsoluteLongSlow, WRAP_NONE, ADC) + +rOP8 (7FM1, AbsoluteLongIndexedX, WRAP_NONE, ADC) +rOP16(7FM0, AbsoluteLongIndexedX, WRAP_NONE, ADC) +rOPM (7FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, ADC) + +rOP8 (63M1, StackRelative, WRAP_NONE, ADC) +rOP16(63M0, StackRelative, WRAP_NONE, ADC) +rOPM (63Slow, StackRelativeSlow, WRAP_NONE, ADC) + +rOP8 (73M1, StackRelativeIndirectIndexed, WRAP_NONE, ADC) +rOP16(73M0, StackRelativeIndirectIndexed, WRAP_NONE, ADC) +rOPM (73Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, ADC) + +/* AND ********************************************************************* */ + +static void Op29M1 (void) +{ + Registers.AL &= Immediate8(READ); + SetZN(Registers.AL); +} + +static void Op29M0 (void) +{ + Registers.A.W &= Immediate16(READ); + SetZN(Registers.A.W); +} + +static void Op29Slow (void) +{ + if (CheckMemory()) + { + Registers.AL &= Immediate8Slow(READ); + SetZN(Registers.AL); + } + else + { + Registers.A.W &= Immediate16Slow(READ); + SetZN(Registers.A.W); + } +} + +rOP8 (25M1, Direct, WRAP_BANK, AND) +rOP16(25M0, Direct, WRAP_BANK, AND) +rOPM (25Slow, DirectSlow, WRAP_BANK, AND) + +rOP8 (35E1, DirectIndexedXE1, WRAP_BANK, AND) +rOP8 (35E0M1, DirectIndexedXE0, WRAP_BANK, AND) +rOP16(35E0M0, DirectIndexedXE0, WRAP_BANK, AND) +rOPM (35Slow, DirectIndexedXSlow, WRAP_BANK, AND) + +rOP8 (32E1, DirectIndirectE1, WRAP_NONE, AND) +rOP8 (32E0M1, DirectIndirectE0, WRAP_NONE, AND) +rOP16(32E0M0, DirectIndirectE0, WRAP_NONE, AND) +rOPM (32Slow, DirectIndirectSlow, WRAP_NONE, AND) + +rOP8 (21E1, DirectIndexedIndirectE1, WRAP_NONE, AND) +rOP8 (21E0M1, DirectIndexedIndirectE0, WRAP_NONE, AND) +rOP16(21E0M0, DirectIndexedIndirectE0, WRAP_NONE, AND) +rOPM (21Slow, DirectIndexedIndirectSlow, WRAP_NONE, AND) + +rOP8 (31E1, DirectIndirectIndexedE1, WRAP_NONE, AND) +rOP8 (31E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, AND) +rOP16(31E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, AND) +rOP8 (31E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, AND) +rOP16(31E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, AND) +rOPM (31Slow, DirectIndirectIndexedSlow, WRAP_NONE, AND) + +rOP8 (27M1, DirectIndirectLong, WRAP_NONE, AND) +rOP16(27M0, DirectIndirectLong, WRAP_NONE, AND) +rOPM (27Slow, DirectIndirectLongSlow, WRAP_NONE, AND) + +rOP8 (37M1, DirectIndirectIndexedLong, WRAP_NONE, AND) +rOP16(37M0, DirectIndirectIndexedLong, WRAP_NONE, AND) +rOPM (37Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, AND) + +rOP8 (2DM1, Absolute, WRAP_NONE, AND) +rOP16(2DM0, Absolute, WRAP_NONE, AND) +rOPM (2DSlow, AbsoluteSlow, WRAP_NONE, AND) + +rOP8 (3DM1X1, AbsoluteIndexedXX1, WRAP_NONE, AND) +rOP16(3DM0X1, AbsoluteIndexedXX1, WRAP_NONE, AND) +rOP8 (3DM1X0, AbsoluteIndexedXX0, WRAP_NONE, AND) +rOP16(3DM0X0, AbsoluteIndexedXX0, WRAP_NONE, AND) +rOPM (3DSlow, AbsoluteIndexedXSlow, WRAP_NONE, AND) + +rOP8 (39M1X1, AbsoluteIndexedYX1, WRAP_NONE, AND) +rOP16(39M0X1, AbsoluteIndexedYX1, WRAP_NONE, AND) +rOP8 (39M1X0, AbsoluteIndexedYX0, WRAP_NONE, AND) +rOP16(39M0X0, AbsoluteIndexedYX0, WRAP_NONE, AND) +rOPM (39Slow, AbsoluteIndexedYSlow, WRAP_NONE, AND) + +rOP8 (2FM1, AbsoluteLong, WRAP_NONE, AND) +rOP16(2FM0, AbsoluteLong, WRAP_NONE, AND) +rOPM (2FSlow, AbsoluteLongSlow, WRAP_NONE, AND) + +rOP8 (3FM1, AbsoluteLongIndexedX, WRAP_NONE, AND) +rOP16(3FM0, AbsoluteLongIndexedX, WRAP_NONE, AND) +rOPM (3FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, AND) + +rOP8 (23M1, StackRelative, WRAP_NONE, AND) +rOP16(23M0, StackRelative, WRAP_NONE, AND) +rOPM (23Slow, StackRelativeSlow, WRAP_NONE, AND) + +rOP8 (33M1, StackRelativeIndirectIndexed, WRAP_NONE, AND) +rOP16(33M0, StackRelativeIndirectIndexed, WRAP_NONE, AND) +rOPM (33Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, AND) + +/* ASL ********************************************************************* */ + +static void Op0AM1 (void) +{ + AddCycles(ONE_CYCLE); + ICPU._Carry = (Registers.AL & 0x80) != 0; + Registers.AL <<= 1; + SetZN(Registers.AL); +} + +static void Op0AM0 (void) +{ + AddCycles(ONE_CYCLE); + ICPU._Carry = (Registers.AH & 0x80) != 0; + Registers.A.W <<= 1; + SetZN(Registers.A.W); +} + +static void Op0ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + ICPU._Carry = (Registers.AL & 0x80) != 0; + Registers.AL <<= 1; + SetZN(Registers.AL); + } + else + { + ICPU._Carry = (Registers.AH & 0x80) != 0; + Registers.A.W <<= 1; + SetZN(Registers.A.W); + } +} + +mOP8 (06M1, Direct, WRAP_BANK, ASL) +mOP16(06M0, Direct, WRAP_BANK, ASL) +mOPM (06Slow, DirectSlow, WRAP_BANK, ASL) + +mOP8 (16E1, DirectIndexedXE1, WRAP_BANK, ASL) +mOP8 (16E0M1, DirectIndexedXE0, WRAP_BANK, ASL) +mOP16(16E0M0, DirectIndexedXE0, WRAP_BANK, ASL) +mOPM (16Slow, DirectIndexedXSlow, WRAP_BANK, ASL) + +mOP8 (0EM1, Absolute, WRAP_NONE, ASL) +mOP16(0EM0, Absolute, WRAP_NONE, ASL) +mOPM (0ESlow, AbsoluteSlow, WRAP_NONE, ASL) + +mOP8 (1EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ASL) +mOP16(1EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ASL) +mOP8 (1EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ASL) +mOP16(1EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ASL) +mOPM (1ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ASL) + +/* BIT ********************************************************************* */ + +static void Op89M1 (void) +{ + ICPU._Zero = Registers.AL & Immediate8(READ); +} + +static void Op89M0 (void) +{ + ICPU._Zero = (Registers.A.W & Immediate16(READ)) != 0; +} + +static void Op89Slow (void) +{ + if (CheckMemory()) + ICPU._Zero = Registers.AL & Immediate8Slow(READ); + else + ICPU._Zero = (Registers.A.W & Immediate16Slow(READ)) != 0; +} + +rOP8 (24M1, Direct, WRAP_BANK, BIT) +rOP16(24M0, Direct, WRAP_BANK, BIT) +rOPM (24Slow, DirectSlow, WRAP_BANK, BIT) + +rOP8 (34E1, DirectIndexedXE1, WRAP_BANK, BIT) +rOP8 (34E0M1, DirectIndexedXE0, WRAP_BANK, BIT) +rOP16(34E0M0, DirectIndexedXE0, WRAP_BANK, BIT) +rOPM (34Slow, DirectIndexedXSlow, WRAP_BANK, BIT) + +rOP8 (2CM1, Absolute, WRAP_NONE, BIT) +rOP16(2CM0, Absolute, WRAP_NONE, BIT) +rOPM (2CSlow, AbsoluteSlow, WRAP_NONE, BIT) + +rOP8 (3CM1X1, AbsoluteIndexedXX1, WRAP_NONE, BIT) +rOP16(3CM0X1, AbsoluteIndexedXX1, WRAP_NONE, BIT) +rOP8 (3CM1X0, AbsoluteIndexedXX0, WRAP_NONE, BIT) +rOP16(3CM0X0, AbsoluteIndexedXX0, WRAP_NONE, BIT) +rOPM (3CSlow, AbsoluteIndexedXSlow, WRAP_NONE, BIT) + +/* CMP ********************************************************************* */ + +static void OpC9M1 (void) +{ + int16 Int16 = (int16) Registers.AL - (int16) Immediate8(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); +} + +static void OpC9M0 (void) +{ + int32 Int32 = (int32) Registers.A.W - (int32) Immediate16(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); +} + +static void OpC9Slow (void) +{ + if (CheckMemory()) + { + int16 Int16 = (int16) Registers.AL - (int16) Immediate8Slow(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); + } + else + { + int32 Int32 = (int32) Registers.A.W - (int32) Immediate16Slow(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); + } +} + +rOP8 (C5M1, Direct, WRAP_BANK, CMP) +rOP16(C5M0, Direct, WRAP_BANK, CMP) +rOPM (C5Slow, DirectSlow, WRAP_BANK, CMP) + +rOP8 (D5E1, DirectIndexedXE1, WRAP_BANK, CMP) +rOP8 (D5E0M1, DirectIndexedXE0, WRAP_BANK, CMP) +rOP16(D5E0M0, DirectIndexedXE0, WRAP_BANK, CMP) +rOPM (D5Slow, DirectIndexedXSlow, WRAP_BANK, CMP) + +rOP8 (D2E1, DirectIndirectE1, WRAP_NONE, CMP) +rOP8 (D2E0M1, DirectIndirectE0, WRAP_NONE, CMP) +rOP16(D2E0M0, DirectIndirectE0, WRAP_NONE, CMP) +rOPM (D2Slow, DirectIndirectSlow, WRAP_NONE, CMP) + +rOP8 (C1E1, DirectIndexedIndirectE1, WRAP_NONE, CMP) +rOP8 (C1E0M1, DirectIndexedIndirectE0, WRAP_NONE, CMP) +rOP16(C1E0M0, DirectIndexedIndirectE0, WRAP_NONE, CMP) +rOPM (C1Slow, DirectIndexedIndirectSlow, WRAP_NONE, CMP) + +rOP8 (D1E1, DirectIndirectIndexedE1, WRAP_NONE, CMP) +rOP8 (D1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, CMP) +rOP16(D1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, CMP) +rOP8 (D1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, CMP) +rOP16(D1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, CMP) +rOPM (D1Slow, DirectIndirectIndexedSlow, WRAP_NONE, CMP) + +rOP8 (C7M1, DirectIndirectLong, WRAP_NONE, CMP) +rOP16(C7M0, DirectIndirectLong, WRAP_NONE, CMP) +rOPM (C7Slow, DirectIndirectLongSlow, WRAP_NONE, CMP) + +rOP8 (D7M1, DirectIndirectIndexedLong, WRAP_NONE, CMP) +rOP16(D7M0, DirectIndirectIndexedLong, WRAP_NONE, CMP) +rOPM (D7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, CMP) + +rOP8 (CDM1, Absolute, WRAP_NONE, CMP) +rOP16(CDM0, Absolute, WRAP_NONE, CMP) +rOPM (CDSlow, AbsoluteSlow, WRAP_NONE, CMP) + +rOP8 (DDM1X1, AbsoluteIndexedXX1, WRAP_NONE, CMP) +rOP16(DDM0X1, AbsoluteIndexedXX1, WRAP_NONE, CMP) +rOP8 (DDM1X0, AbsoluteIndexedXX0, WRAP_NONE, CMP) +rOP16(DDM0X0, AbsoluteIndexedXX0, WRAP_NONE, CMP) +rOPM (DDSlow, AbsoluteIndexedXSlow, WRAP_NONE, CMP) + +rOP8 (D9M1X1, AbsoluteIndexedYX1, WRAP_NONE, CMP) +rOP16(D9M0X1, AbsoluteIndexedYX1, WRAP_NONE, CMP) +rOP8 (D9M1X0, AbsoluteIndexedYX0, WRAP_NONE, CMP) +rOP16(D9M0X0, AbsoluteIndexedYX0, WRAP_NONE, CMP) +rOPM (D9Slow, AbsoluteIndexedYSlow, WRAP_NONE, CMP) + +rOP8 (CFM1, AbsoluteLong, WRAP_NONE, CMP) +rOP16(CFM0, AbsoluteLong, WRAP_NONE, CMP) +rOPM (CFSlow, AbsoluteLongSlow, WRAP_NONE, CMP) + +rOP8 (DFM1, AbsoluteLongIndexedX, WRAP_NONE, CMP) +rOP16(DFM0, AbsoluteLongIndexedX, WRAP_NONE, CMP) +rOPM (DFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, CMP) + +rOP8 (C3M1, StackRelative, WRAP_NONE, CMP) +rOP16(C3M0, StackRelative, WRAP_NONE, CMP) +rOPM (C3Slow, StackRelativeSlow, WRAP_NONE, CMP) + +rOP8 (D3M1, StackRelativeIndirectIndexed, WRAP_NONE, CMP) +rOP16(D3M0, StackRelativeIndirectIndexed, WRAP_NONE, CMP) +rOPM (D3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, CMP) + +/* CPX ********************************************************************* */ + +static void OpE0X1 (void) +{ + int16 Int16 = (int16) Registers.XL - (int16) Immediate8(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); +} + +static void OpE0X0 (void) +{ + int32 Int32 = (int32) Registers.X.W - (int32) Immediate16(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); +} + +static void OpE0Slow (void) +{ + if (CheckIndex()) + { + int16 Int16 = (int16) Registers.XL - (int16) Immediate8Slow(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); + } + else + { + int32 Int32 = (int32) Registers.X.W - (int32) Immediate16Slow(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); + } +} + +rOP8 (E4X1, Direct, WRAP_BANK, CPX) +rOP16(E4X0, Direct, WRAP_BANK, CPX) +rOPX (E4Slow, DirectSlow, WRAP_BANK, CPX) + +rOP8 (ECX1, Absolute, WRAP_NONE, CPX) +rOP16(ECX0, Absolute, WRAP_NONE, CPX) +rOPX (ECSlow, AbsoluteSlow, WRAP_NONE, CPX) + +/* CPY ********************************************************************* */ + +static void OpC0X1 (void) +{ + int16 Int16 = (int16) Registers.YL - (int16) Immediate8(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); +} + +static void OpC0X0 (void) +{ + int32 Int32 = (int32) Registers.Y.W - (int32) Immediate16(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); +} + +static void OpC0Slow (void) +{ + if (CheckIndex()) + { + int16 Int16 = (int16) Registers.YL - (int16) Immediate8Slow(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); + } + else + { + int32 Int32 = (int32) Registers.Y.W - (int32) Immediate16Slow(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); + } +} + +rOP8 (C4X1, Direct, WRAP_BANK, CPY) +rOP16(C4X0, Direct, WRAP_BANK, CPY) +rOPX (C4Slow, DirectSlow, WRAP_BANK, CPY) + +rOP8 (CCX1, Absolute, WRAP_NONE, CPY) +rOP16(CCX0, Absolute, WRAP_NONE, CPY) +rOPX (CCSlow, AbsoluteSlow, WRAP_NONE, CPY) + +/* DEC ********************************************************************* */ + +static void Op3AM1 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.AL--; + SetZN(Registers.AL); +} + +static void Op3AM0 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.A.W--; + SetZN(Registers.A.W); +} + +static void Op3ASlow (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + if (CheckMemory()) + { + Registers.AL--; + SetZN(Registers.AL); + } + else + { + Registers.A.W--; + SetZN(Registers.A.W); + } +} + +mOP8 (C6M1, Direct, WRAP_BANK, DEC) +mOP16(C6M0, Direct, WRAP_BANK, DEC) +mOPM (C6Slow, DirectSlow, WRAP_BANK, DEC) + +mOP8 (D6E1, DirectIndexedXE1, WRAP_BANK, DEC) +mOP8 (D6E0M1, DirectIndexedXE0, WRAP_BANK, DEC) +mOP16(D6E0M0, DirectIndexedXE0, WRAP_BANK, DEC) +mOPM (D6Slow, DirectIndexedXSlow, WRAP_BANK, DEC) + +mOP8 (CEM1, Absolute, WRAP_NONE, DEC) +mOP16(CEM0, Absolute, WRAP_NONE, DEC) +mOPM (CESlow, AbsoluteSlow, WRAP_NONE, DEC) + +mOP8 (DEM1X1, AbsoluteIndexedXX1, WRAP_NONE, DEC) +mOP16(DEM0X1, AbsoluteIndexedXX1, WRAP_NONE, DEC) +mOP8 (DEM1X0, AbsoluteIndexedXX0, WRAP_NONE, DEC) +mOP16(DEM0X0, AbsoluteIndexedXX0, WRAP_NONE, DEC) +mOPM (DESlow, AbsoluteIndexedXSlow, WRAP_NONE, DEC) + +/* EOR ********************************************************************* */ + +static void Op49M1 (void) +{ + Registers.AL ^= Immediate8(READ); + SetZN(Registers.AL); +} + +static void Op49M0 (void) +{ + Registers.A.W ^= Immediate16(READ); + SetZN(Registers.A.W); +} + +static void Op49Slow (void) +{ + if (CheckMemory()) + { + Registers.AL ^= Immediate8Slow(READ); + SetZN(Registers.AL); + } + else + { + Registers.A.W ^= Immediate16Slow(READ); + SetZN(Registers.A.W); + } +} + +rOP8 (45M1, Direct, WRAP_BANK, EOR) +rOP16(45M0, Direct, WRAP_BANK, EOR) +rOPM (45Slow, DirectSlow, WRAP_BANK, EOR) + +rOP8 (55E1, DirectIndexedXE1, WRAP_BANK, EOR) +rOP8 (55E0M1, DirectIndexedXE0, WRAP_BANK, EOR) +rOP16(55E0M0, DirectIndexedXE0, WRAP_BANK, EOR) +rOPM (55Slow, DirectIndexedXSlow, WRAP_BANK, EOR) + +rOP8 (52E1, DirectIndirectE1, WRAP_NONE, EOR) +rOP8 (52E0M1, DirectIndirectE0, WRAP_NONE, EOR) +rOP16(52E0M0, DirectIndirectE0, WRAP_NONE, EOR) +rOPM (52Slow, DirectIndirectSlow, WRAP_NONE, EOR) + +rOP8 (41E1, DirectIndexedIndirectE1, WRAP_NONE, EOR) +rOP8 (41E0M1, DirectIndexedIndirectE0, WRAP_NONE, EOR) +rOP16(41E0M0, DirectIndexedIndirectE0, WRAP_NONE, EOR) +rOPM (41Slow, DirectIndexedIndirectSlow, WRAP_NONE, EOR) + +rOP8 (51E1, DirectIndirectIndexedE1, WRAP_NONE, EOR) +rOP8 (51E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, EOR) +rOP16(51E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, EOR) +rOP8 (51E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, EOR) +rOP16(51E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, EOR) +rOPM (51Slow, DirectIndirectIndexedSlow, WRAP_NONE, EOR) + +rOP8 (47M1, DirectIndirectLong, WRAP_NONE, EOR) +rOP16(47M0, DirectIndirectLong, WRAP_NONE, EOR) +rOPM (47Slow, DirectIndirectLongSlow, WRAP_NONE, EOR) + +rOP8 (57M1, DirectIndirectIndexedLong, WRAP_NONE, EOR) +rOP16(57M0, DirectIndirectIndexedLong, WRAP_NONE, EOR) +rOPM (57Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, EOR) + +rOP8 (4DM1, Absolute, WRAP_NONE, EOR) +rOP16(4DM0, Absolute, WRAP_NONE, EOR) +rOPM (4DSlow, AbsoluteSlow, WRAP_NONE, EOR) + +rOP8 (5DM1X1, AbsoluteIndexedXX1, WRAP_NONE, EOR) +rOP16(5DM0X1, AbsoluteIndexedXX1, WRAP_NONE, EOR) +rOP8 (5DM1X0, AbsoluteIndexedXX0, WRAP_NONE, EOR) +rOP16(5DM0X0, AbsoluteIndexedXX0, WRAP_NONE, EOR) +rOPM (5DSlow, AbsoluteIndexedXSlow, WRAP_NONE, EOR) + +rOP8 (59M1X1, AbsoluteIndexedYX1, WRAP_NONE, EOR) +rOP16(59M0X1, AbsoluteIndexedYX1, WRAP_NONE, EOR) +rOP8 (59M1X0, AbsoluteIndexedYX0, WRAP_NONE, EOR) +rOP16(59M0X0, AbsoluteIndexedYX0, WRAP_NONE, EOR) +rOPM (59Slow, AbsoluteIndexedYSlow, WRAP_NONE, EOR) + +rOP8 (4FM1, AbsoluteLong, WRAP_NONE, EOR) +rOP16(4FM0, AbsoluteLong, WRAP_NONE, EOR) +rOPM (4FSlow, AbsoluteLongSlow, WRAP_NONE, EOR) + +rOP8 (5FM1, AbsoluteLongIndexedX, WRAP_NONE, EOR) +rOP16(5FM0, AbsoluteLongIndexedX, WRAP_NONE, EOR) +rOPM (5FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, EOR) + +rOP8 (43M1, StackRelative, WRAP_NONE, EOR) +rOP16(43M0, StackRelative, WRAP_NONE, EOR) +rOPM (43Slow, StackRelativeSlow, WRAP_NONE, EOR) + +rOP8 (53M1, StackRelativeIndirectIndexed, WRAP_NONE, EOR) +rOP16(53M0, StackRelativeIndirectIndexed, WRAP_NONE, EOR) +rOPM (53Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, EOR) + +/* INC ********************************************************************* */ + +static void Op1AM1 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.AL++; + SetZN(Registers.AL); +} + +static void Op1AM0 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.A.W++; + SetZN(Registers.A.W); +} + +static void Op1ASlow (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + if (CheckMemory()) + { + Registers.AL++; + SetZN(Registers.AL); + } + else + { + Registers.A.W++; + SetZN(Registers.A.W); + } +} + +mOP8 (E6M1, Direct, WRAP_BANK, INC) +mOP16(E6M0, Direct, WRAP_BANK, INC) +mOPM (E6Slow, DirectSlow, WRAP_BANK, INC) + +mOP8 (F6E1, DirectIndexedXE1, WRAP_BANK, INC) +mOP8 (F6E0M1, DirectIndexedXE0, WRAP_BANK, INC) +mOP16(F6E0M0, DirectIndexedXE0, WRAP_BANK, INC) +mOPM (F6Slow, DirectIndexedXSlow, WRAP_BANK, INC) + +mOP8 (EEM1, Absolute, WRAP_NONE, INC) +mOP16(EEM0, Absolute, WRAP_NONE, INC) +mOPM (EESlow, AbsoluteSlow, WRAP_NONE, INC) + +mOP8 (FEM1X1, AbsoluteIndexedXX1, WRAP_NONE, INC) +mOP16(FEM0X1, AbsoluteIndexedXX1, WRAP_NONE, INC) +mOP8 (FEM1X0, AbsoluteIndexedXX0, WRAP_NONE, INC) +mOP16(FEM0X0, AbsoluteIndexedXX0, WRAP_NONE, INC) +mOPM (FESlow, AbsoluteIndexedXSlow, WRAP_NONE, INC) + +/* LDA ********************************************************************* */ + +static void OpA9M1 (void) +{ + Registers.AL = Immediate8(READ); + SetZN(Registers.AL); +} + +static void OpA9M0 (void) +{ + Registers.A.W = Immediate16(READ); + SetZN(Registers.A.W); +} + +static void OpA9Slow (void) +{ + if (CheckMemory()) + { + Registers.AL = Immediate8Slow(READ); + SetZN(Registers.AL); + } + else + { + Registers.A.W = Immediate16Slow(READ); + SetZN(Registers.A.W); + } +} + +rOP8 (A5M1, Direct, WRAP_BANK, LDA) +rOP16(A5M0, Direct, WRAP_BANK, LDA) +rOPM (A5Slow, DirectSlow, WRAP_BANK, LDA) + +rOP8 (B5E1, DirectIndexedXE1, WRAP_BANK, LDA) +rOP8 (B5E0M1, DirectIndexedXE0, WRAP_BANK, LDA) +rOP16(B5E0M0, DirectIndexedXE0, WRAP_BANK, LDA) +rOPM (B5Slow, DirectIndexedXSlow, WRAP_BANK, LDA) + +rOP8 (B2E1, DirectIndirectE1, WRAP_NONE, LDA) +rOP8 (B2E0M1, DirectIndirectE0, WRAP_NONE, LDA) +rOP16(B2E0M0, DirectIndirectE0, WRAP_NONE, LDA) +rOPM (B2Slow, DirectIndirectSlow, WRAP_NONE, LDA) + +rOP8 (A1E1, DirectIndexedIndirectE1, WRAP_NONE, LDA) +rOP8 (A1E0M1, DirectIndexedIndirectE0, WRAP_NONE, LDA) +rOP16(A1E0M0, DirectIndexedIndirectE0, WRAP_NONE, LDA) +rOPM (A1Slow, DirectIndexedIndirectSlow, WRAP_NONE, LDA) + +rOP8 (B1E1, DirectIndirectIndexedE1, WRAP_NONE, LDA) +rOP8 (B1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, LDA) +rOP16(B1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, LDA) +rOP8 (B1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, LDA) +rOP16(B1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, LDA) +rOPM (B1Slow, DirectIndirectIndexedSlow, WRAP_NONE, LDA) + +rOP8 (A7M1, DirectIndirectLong, WRAP_NONE, LDA) +rOP16(A7M0, DirectIndirectLong, WRAP_NONE, LDA) +rOPM (A7Slow, DirectIndirectLongSlow, WRAP_NONE, LDA) + +rOP8 (B7M1, DirectIndirectIndexedLong, WRAP_NONE, LDA) +rOP16(B7M0, DirectIndirectIndexedLong, WRAP_NONE, LDA) +rOPM (B7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, LDA) + +rOP8 (ADM1, Absolute, WRAP_NONE, LDA) +rOP16(ADM0, Absolute, WRAP_NONE, LDA) +rOPM (ADSlow, AbsoluteSlow, WRAP_NONE, LDA) + +rOP8 (BDM1X1, AbsoluteIndexedXX1, WRAP_NONE, LDA) +rOP16(BDM0X1, AbsoluteIndexedXX1, WRAP_NONE, LDA) +rOP8 (BDM1X0, AbsoluteIndexedXX0, WRAP_NONE, LDA) +rOP16(BDM0X0, AbsoluteIndexedXX0, WRAP_NONE, LDA) +rOPM (BDSlow, AbsoluteIndexedXSlow, WRAP_NONE, LDA) + +rOP8 (B9M1X1, AbsoluteIndexedYX1, WRAP_NONE, LDA) +rOP16(B9M0X1, AbsoluteIndexedYX1, WRAP_NONE, LDA) +rOP8 (B9M1X0, AbsoluteIndexedYX0, WRAP_NONE, LDA) +rOP16(B9M0X0, AbsoluteIndexedYX0, WRAP_NONE, LDA) +rOPM (B9Slow, AbsoluteIndexedYSlow, WRAP_NONE, LDA) + +rOP8 (AFM1, AbsoluteLong, WRAP_NONE, LDA) +rOP16(AFM0, AbsoluteLong, WRAP_NONE, LDA) +rOPM (AFSlow, AbsoluteLongSlow, WRAP_NONE, LDA) + +rOP8 (BFM1, AbsoluteLongIndexedX, WRAP_NONE, LDA) +rOP16(BFM0, AbsoluteLongIndexedX, WRAP_NONE, LDA) +rOPM (BFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, LDA) + +rOP8 (A3M1, StackRelative, WRAP_NONE, LDA) +rOP16(A3M0, StackRelative, WRAP_NONE, LDA) +rOPM (A3Slow, StackRelativeSlow, WRAP_NONE, LDA) + +rOP8 (B3M1, StackRelativeIndirectIndexed, WRAP_NONE, LDA) +rOP16(B3M0, StackRelativeIndirectIndexed, WRAP_NONE, LDA) +rOPM (B3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, LDA) + +/* LDX ********************************************************************* */ + +static void OpA2X1 (void) +{ + Registers.XL = Immediate8(READ); + SetZN(Registers.XL); +} + +static void OpA2X0 (void) +{ + Registers.X.W = Immediate16(READ); + SetZN(Registers.X.W); +} + +static void OpA2Slow (void) +{ + if (CheckIndex()) + { + Registers.XL = Immediate8Slow(READ); + SetZN(Registers.XL); + } + else + { + Registers.X.W = Immediate16Slow(READ); + SetZN(Registers.X.W); + } +} + +rOP8 (A6X1, Direct, WRAP_BANK, LDX) +rOP16(A6X0, Direct, WRAP_BANK, LDX) +rOPX (A6Slow, DirectSlow, WRAP_BANK, LDX) + +rOP8 (B6E1, DirectIndexedYE1, WRAP_BANK, LDX) +rOP8 (B6E0X1, DirectIndexedYE0, WRAP_BANK, LDX) +rOP16(B6E0X0, DirectIndexedYE0, WRAP_BANK, LDX) +rOPX (B6Slow, DirectIndexedYSlow, WRAP_BANK, LDX) + +rOP8 (AEX1, Absolute, WRAP_BANK, LDX) +rOP16(AEX0, Absolute, WRAP_BANK, LDX) +rOPX (AESlow, AbsoluteSlow, WRAP_BANK, LDX) + +rOP8 (BEX1, AbsoluteIndexedYX1, WRAP_BANK, LDX) +rOP16(BEX0, AbsoluteIndexedYX0, WRAP_BANK, LDX) +rOPX (BESlow, AbsoluteIndexedYSlow, WRAP_BANK, LDX) + +/* LDY ********************************************************************* */ + +static void OpA0X1 (void) +{ + Registers.YL = Immediate8(READ); + SetZN(Registers.YL); +} + +static void OpA0X0 (void) +{ + Registers.Y.W = Immediate16(READ); + SetZN(Registers.Y.W); +} + +static void OpA0Slow (void) +{ + if (CheckIndex()) + { + Registers.YL = Immediate8Slow(READ); + SetZN(Registers.YL); + } + else + { + Registers.Y.W = Immediate16Slow(READ); + SetZN(Registers.Y.W); + } +} + +rOP8 (A4X1, Direct, WRAP_BANK, LDY) +rOP16(A4X0, Direct, WRAP_BANK, LDY) +rOPX (A4Slow, DirectSlow, WRAP_BANK, LDY) + +rOP8 (B4E1, DirectIndexedXE1, WRAP_BANK, LDY) +rOP8 (B4E0X1, DirectIndexedXE0, WRAP_BANK, LDY) +rOP16(B4E0X0, DirectIndexedXE0, WRAP_BANK, LDY) +rOPX (B4Slow, DirectIndexedXSlow, WRAP_BANK, LDY) + +rOP8 (ACX1, Absolute, WRAP_BANK, LDY) +rOP16(ACX0, Absolute, WRAP_BANK, LDY) +rOPX (ACSlow, AbsoluteSlow, WRAP_BANK, LDY) + +rOP8 (BCX1, AbsoluteIndexedXX1, WRAP_BANK, LDY) +rOP16(BCX0, AbsoluteIndexedXX0, WRAP_BANK, LDY) +rOPX (BCSlow, AbsoluteIndexedXSlow, WRAP_BANK, LDY) + +/* LSR ********************************************************************* */ + +static void Op4AM1 (void) +{ + AddCycles(ONE_CYCLE); + ICPU._Carry = Registers.AL & 1; + Registers.AL >>= 1; + SetZN(Registers.AL); +} + +static void Op4AM0 (void) +{ + AddCycles(ONE_CYCLE); + ICPU._Carry = Registers.A.W & 1; + Registers.A.W >>= 1; + SetZN(Registers.A.W); +} + +static void Op4ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + ICPU._Carry = Registers.AL & 1; + Registers.AL >>= 1; + SetZN(Registers.AL); + } + else + { + ICPU._Carry = Registers.A.W & 1; + Registers.A.W >>= 1; + SetZN(Registers.A.W); + } +} + +mOP8 (46M1, Direct, WRAP_BANK, LSR) +mOP16(46M0, Direct, WRAP_BANK, LSR) +mOPM (46Slow, DirectSlow, WRAP_BANK, LSR) + +mOP8 (56E1, DirectIndexedXE1, WRAP_BANK, LSR) +mOP8 (56E0M1, DirectIndexedXE0, WRAP_BANK, LSR) +mOP16(56E0M0, DirectIndexedXE0, WRAP_BANK, LSR) +mOPM (56Slow, DirectIndexedXSlow, WRAP_BANK, LSR) + +mOP8 (4EM1, Absolute, WRAP_NONE, LSR) +mOP16(4EM0, Absolute, WRAP_NONE, LSR) +mOPM (4ESlow, AbsoluteSlow, WRAP_NONE, LSR) + +mOP8 (5EM1X1, AbsoluteIndexedXX1, WRAP_NONE, LSR) +mOP16(5EM0X1, AbsoluteIndexedXX1, WRAP_NONE, LSR) +mOP8 (5EM1X0, AbsoluteIndexedXX0, WRAP_NONE, LSR) +mOP16(5EM0X0, AbsoluteIndexedXX0, WRAP_NONE, LSR) +mOPM (5ESlow, AbsoluteIndexedXSlow, WRAP_NONE, LSR) + +/* ORA ********************************************************************* */ + +static void Op09M1 (void) +{ + Registers.AL |= Immediate8(READ); + SetZN(Registers.AL); +} + +static void Op09M0 (void) +{ + Registers.A.W |= Immediate16(READ); + SetZN(Registers.A.W); +} + +static void Op09Slow (void) +{ + if (CheckMemory()) + { + Registers.AL |= Immediate8Slow(READ); + SetZN(Registers.AL); + } + else + { + Registers.A.W |= Immediate16Slow(READ); + SetZN(Registers.A.W); + } +} + +rOP8 (05M1, Direct, WRAP_BANK, ORA) +rOP16(05M0, Direct, WRAP_BANK, ORA) +rOPM (05Slow, DirectSlow, WRAP_BANK, ORA) + +rOP8 (15E1, DirectIndexedXE1, WRAP_BANK, ORA) +rOP8 (15E0M1, DirectIndexedXE0, WRAP_BANK, ORA) +rOP16(15E0M0, DirectIndexedXE0, WRAP_BANK, ORA) +rOPM (15Slow, DirectIndexedXSlow, WRAP_BANK, ORA) + +rOP8 (12E1, DirectIndirectE1, WRAP_NONE, ORA) +rOP8 (12E0M1, DirectIndirectE0, WRAP_NONE, ORA) +rOP16(12E0M0, DirectIndirectE0, WRAP_NONE, ORA) +rOPM (12Slow, DirectIndirectSlow, WRAP_NONE, ORA) + +rOP8 (01E1, DirectIndexedIndirectE1, WRAP_NONE, ORA) +rOP8 (01E0M1, DirectIndexedIndirectE0, WRAP_NONE, ORA) +rOP16(01E0M0, DirectIndexedIndirectE0, WRAP_NONE, ORA) +rOPM (01Slow, DirectIndexedIndirectSlow, WRAP_NONE, ORA) + +rOP8 (11E1, DirectIndirectIndexedE1, WRAP_NONE, ORA) +rOP8 (11E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, ORA) +rOP16(11E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, ORA) +rOP8 (11E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, ORA) +rOP16(11E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, ORA) +rOPM (11Slow, DirectIndirectIndexedSlow, WRAP_NONE, ORA) + +rOP8 (07M1, DirectIndirectLong, WRAP_NONE, ORA) +rOP16(07M0, DirectIndirectLong, WRAP_NONE, ORA) +rOPM (07Slow, DirectIndirectLongSlow, WRAP_NONE, ORA) + +rOP8 (17M1, DirectIndirectIndexedLong, WRAP_NONE, ORA) +rOP16(17M0, DirectIndirectIndexedLong, WRAP_NONE, ORA) +rOPM (17Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, ORA) + +rOP8 (0DM1, Absolute, WRAP_NONE, ORA) +rOP16(0DM0, Absolute, WRAP_NONE, ORA) +rOPM (0DSlow, AbsoluteSlow, WRAP_NONE, ORA) + +rOP8 (1DM1X1, AbsoluteIndexedXX1, WRAP_NONE, ORA) +rOP16(1DM0X1, AbsoluteIndexedXX1, WRAP_NONE, ORA) +rOP8 (1DM1X0, AbsoluteIndexedXX0, WRAP_NONE, ORA) +rOP16(1DM0X0, AbsoluteIndexedXX0, WRAP_NONE, ORA) +rOPM (1DSlow, AbsoluteIndexedXSlow, WRAP_NONE, ORA) + +rOP8 (19M1X1, AbsoluteIndexedYX1, WRAP_NONE, ORA) +rOP16(19M0X1, AbsoluteIndexedYX1, WRAP_NONE, ORA) +rOP8 (19M1X0, AbsoluteIndexedYX0, WRAP_NONE, ORA) +rOP16(19M0X0, AbsoluteIndexedYX0, WRAP_NONE, ORA) +rOPM (19Slow, AbsoluteIndexedYSlow, WRAP_NONE, ORA) + +rOP8 (0FM1, AbsoluteLong, WRAP_NONE, ORA) +rOP16(0FM0, AbsoluteLong, WRAP_NONE, ORA) +rOPM (0FSlow, AbsoluteLongSlow, WRAP_NONE, ORA) + +rOP8 (1FM1, AbsoluteLongIndexedX, WRAP_NONE, ORA) +rOP16(1FM0, AbsoluteLongIndexedX, WRAP_NONE, ORA) +rOPM (1FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, ORA) + +rOP8 (03M1, StackRelative, WRAP_NONE, ORA) +rOP16(03M0, StackRelative, WRAP_NONE, ORA) +rOPM (03Slow, StackRelativeSlow, WRAP_NONE, ORA) + +rOP8 (13M1, StackRelativeIndirectIndexed, WRAP_NONE, ORA) +rOP16(13M0, StackRelativeIndirectIndexed, WRAP_NONE, ORA) +rOPM (13Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, ORA) + +/* ROL ********************************************************************* */ + +static void Op2AM1 (void) +{ + AddCycles(ONE_CYCLE); + uint16 w = (((uint16) Registers.AL) << 1) | CheckCarry(); + ICPU._Carry = w >= 0x100; + Registers.AL = (uint8) w; + SetZN(Registers.AL); +} + +static void Op2AM0 (void) +{ + AddCycles(ONE_CYCLE); + uint32 w = (((uint32) Registers.A.W) << 1) | CheckCarry(); + ICPU._Carry = w >= 0x10000; + Registers.A.W = (uint16) w; + SetZN(Registers.A.W); +} + +static void Op2ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + uint16 w = (((uint16) Registers.AL) << 1) | CheckCarry(); + ICPU._Carry = w >= 0x100; + Registers.AL = (uint8) w; + SetZN(Registers.AL); + } + else + { + uint32 w = (((uint32) Registers.A.W) << 1) | CheckCarry(); + ICPU._Carry = w >= 0x10000; + Registers.A.W = (uint16) w; + SetZN(Registers.A.W); + } +} + +mOP8 (26M1, Direct, WRAP_BANK, ROL) +mOP16(26M0, Direct, WRAP_BANK, ROL) +mOPM (26Slow, DirectSlow, WRAP_BANK, ROL) + +mOP8 (36E1, DirectIndexedXE1, WRAP_BANK, ROL) +mOP8 (36E0M1, DirectIndexedXE0, WRAP_BANK, ROL) +mOP16(36E0M0, DirectIndexedXE0, WRAP_BANK, ROL) +mOPM (36Slow, DirectIndexedXSlow, WRAP_BANK, ROL) + +mOP8 (2EM1, Absolute, WRAP_NONE, ROL) +mOP16(2EM0, Absolute, WRAP_NONE, ROL) +mOPM (2ESlow, AbsoluteSlow, WRAP_NONE, ROL) + +mOP8 (3EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ROL) +mOP16(3EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ROL) +mOP8 (3EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ROL) +mOP16(3EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ROL) +mOPM (3ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ROL) + +/* ROR ********************************************************************* */ + +static void Op6AM1 (void) +{ + AddCycles(ONE_CYCLE); + uint16 w = ((uint16) Registers.AL) | (((uint16) CheckCarry()) << 8); + ICPU._Carry = w & 1; + w >>= 1; + Registers.AL = (uint8) w; + SetZN(Registers.AL); +} + +static void Op6AM0 (void) +{ + AddCycles(ONE_CYCLE); + uint32 w = ((uint32) Registers.A.W) | (((uint32) CheckCarry()) << 16); + ICPU._Carry = w & 1; + w >>= 1; + Registers.A.W = (uint16) w; + SetZN(Registers.A.W); +} + +static void Op6ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + uint16 w = ((uint16) Registers.AL) | (((uint16) CheckCarry()) << 8); + ICPU._Carry = w & 1; + w >>= 1; + Registers.AL = (uint8) w; + SetZN(Registers.AL); + } + else + { + uint32 w = ((uint32) Registers.A.W) | (((uint32) CheckCarry()) << 16); + ICPU._Carry = w & 1; + w >>= 1; + Registers.A.W = (uint16) w; + SetZN(Registers.A.W); + } +} + +mOP8 (66M1, Direct, WRAP_BANK, ROR) +mOP16(66M0, Direct, WRAP_BANK, ROR) +mOPM (66Slow, DirectSlow, WRAP_BANK, ROR) + +mOP8 (76E1, DirectIndexedXE1, WRAP_BANK, ROR) +mOP8 (76E0M1, DirectIndexedXE0, WRAP_BANK, ROR) +mOP16(76E0M0, DirectIndexedXE0, WRAP_BANK, ROR) +mOPM (76Slow, DirectIndexedXSlow, WRAP_BANK, ROR) + +mOP8 (6EM1, Absolute, WRAP_NONE, ROR) +mOP16(6EM0, Absolute, WRAP_NONE, ROR) +mOPM (6ESlow, AbsoluteSlow, WRAP_NONE, ROR) + +mOP8 (7EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ROR) +mOP16(7EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ROR) +mOP8 (7EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ROR) +mOP16(7EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ROR) +mOPM (7ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ROR) + +/* SBC ********************************************************************* */ + +static void OpE9M1 (void) +{ + SBC(Immediate8(READ)); +} + +static void OpE9M0 (void) +{ + SBC(Immediate16(READ)); +} + +static void OpE9Slow (void) +{ + if (CheckMemory()) + SBC(Immediate8Slow(READ)); + else + SBC(Immediate16Slow(READ)); +} + +rOP8 (E5M1, Direct, WRAP_BANK, SBC) +rOP16(E5M0, Direct, WRAP_BANK, SBC) +rOPM (E5Slow, DirectSlow, WRAP_BANK, SBC) + +rOP8 (F5E1, DirectIndexedXE1, WRAP_BANK, SBC) +rOP8 (F5E0M1, DirectIndexedXE0, WRAP_BANK, SBC) +rOP16(F5E0M0, DirectIndexedXE0, WRAP_BANK, SBC) +rOPM (F5Slow, DirectIndexedXSlow, WRAP_BANK, SBC) + +rOP8 (F2E1, DirectIndirectE1, WRAP_NONE, SBC) +rOP8 (F2E0M1, DirectIndirectE0, WRAP_NONE, SBC) +rOP16(F2E0M0, DirectIndirectE0, WRAP_NONE, SBC) +rOPM (F2Slow, DirectIndirectSlow, WRAP_NONE, SBC) + +rOP8 (E1E1, DirectIndexedIndirectE1, WRAP_NONE, SBC) +rOP8 (E1E0M1, DirectIndexedIndirectE0, WRAP_NONE, SBC) +rOP16(E1E0M0, DirectIndexedIndirectE0, WRAP_NONE, SBC) +rOPM (E1Slow, DirectIndexedIndirectSlow, WRAP_NONE, SBC) + +rOP8 (F1E1, DirectIndirectIndexedE1, WRAP_NONE, SBC) +rOP8 (F1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, SBC) +rOP16(F1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, SBC) +rOP8 (F1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, SBC) +rOP16(F1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, SBC) +rOPM (F1Slow, DirectIndirectIndexedSlow, WRAP_NONE, SBC) + +rOP8 (E7M1, DirectIndirectLong, WRAP_NONE, SBC) +rOP16(E7M0, DirectIndirectLong, WRAP_NONE, SBC) +rOPM (E7Slow, DirectIndirectLongSlow, WRAP_NONE, SBC) + +rOP8 (F7M1, DirectIndirectIndexedLong, WRAP_NONE, SBC) +rOP16(F7M0, DirectIndirectIndexedLong, WRAP_NONE, SBC) +rOPM (F7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, SBC) + +rOP8 (EDM1, Absolute, WRAP_NONE, SBC) +rOP16(EDM0, Absolute, WRAP_NONE, SBC) +rOPM (EDSlow, AbsoluteSlow, WRAP_NONE, SBC) + +rOP8 (FDM1X1, AbsoluteIndexedXX1, WRAP_NONE, SBC) +rOP16(FDM0X1, AbsoluteIndexedXX1, WRAP_NONE, SBC) +rOP8 (FDM1X0, AbsoluteIndexedXX0, WRAP_NONE, SBC) +rOP16(FDM0X0, AbsoluteIndexedXX0, WRAP_NONE, SBC) +rOPM (FDSlow, AbsoluteIndexedXSlow, WRAP_NONE, SBC) + +rOP8 (F9M1X1, AbsoluteIndexedYX1, WRAP_NONE, SBC) +rOP16(F9M0X1, AbsoluteIndexedYX1, WRAP_NONE, SBC) +rOP8 (F9M1X0, AbsoluteIndexedYX0, WRAP_NONE, SBC) +rOP16(F9M0X0, AbsoluteIndexedYX0, WRAP_NONE, SBC) +rOPM (F9Slow, AbsoluteIndexedYSlow, WRAP_NONE, SBC) + +rOP8 (EFM1, AbsoluteLong, WRAP_NONE, SBC) +rOP16(EFM0, AbsoluteLong, WRAP_NONE, SBC) +rOPM (EFSlow, AbsoluteLongSlow, WRAP_NONE, SBC) + +rOP8 (FFM1, AbsoluteLongIndexedX, WRAP_NONE, SBC) +rOP16(FFM0, AbsoluteLongIndexedX, WRAP_NONE, SBC) +rOPM (FFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, SBC) + +rOP8 (E3M1, StackRelative, WRAP_NONE, SBC) +rOP16(E3M0, StackRelative, WRAP_NONE, SBC) +rOPM (E3Slow, StackRelativeSlow, WRAP_NONE, SBC) + +rOP8 (F3M1, StackRelativeIndirectIndexed, WRAP_NONE, SBC) +rOP16(F3M0, StackRelativeIndirectIndexed, WRAP_NONE, SBC) +rOPM (F3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, SBC) + +/* STA ********************************************************************* */ + +wOP8 (85M1, Direct, WRAP_BANK, STA) +wOP16(85M0, Direct, WRAP_BANK, STA) +wOPM (85Slow, DirectSlow, WRAP_BANK, STA) + +wOP8 (95E1, DirectIndexedXE1, WRAP_BANK, STA) +wOP8 (95E0M1, DirectIndexedXE0, WRAP_BANK, STA) +wOP16(95E0M0, DirectIndexedXE0, WRAP_BANK, STA) +wOPM (95Slow, DirectIndexedXSlow, WRAP_BANK, STA) + +wOP8 (92E1, DirectIndirectE1, WRAP_NONE, STA) +wOP8 (92E0M1, DirectIndirectE0, WRAP_NONE, STA) +wOP16(92E0M0, DirectIndirectE0, WRAP_NONE, STA) +wOPM (92Slow, DirectIndirectSlow, WRAP_NONE, STA) + +wOP8 (81E1, DirectIndexedIndirectE1, WRAP_NONE, STA) +wOP8 (81E0M1, DirectIndexedIndirectE0, WRAP_NONE, STA) +wOP16(81E0M0, DirectIndexedIndirectE0, WRAP_NONE, STA) +wOPM (81Slow, DirectIndexedIndirectSlow, WRAP_NONE, STA) + +wOP8 (91E1, DirectIndirectIndexedE1, WRAP_NONE, STA) +wOP8 (91E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, STA) +wOP16(91E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, STA) +wOP8 (91E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, STA) +wOP16(91E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, STA) +wOPM (91Slow, DirectIndirectIndexedSlow, WRAP_NONE, STA) + +wOP8 (87M1, DirectIndirectLong, WRAP_NONE, STA) +wOP16(87M0, DirectIndirectLong, WRAP_NONE, STA) +wOPM (87Slow, DirectIndirectLongSlow, WRAP_NONE, STA) + +wOP8 (97M1, DirectIndirectIndexedLong, WRAP_NONE, STA) +wOP16(97M0, DirectIndirectIndexedLong, WRAP_NONE, STA) +wOPM (97Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, STA) + +wOP8 (8DM1, Absolute, WRAP_NONE, STA) +wOP16(8DM0, Absolute, WRAP_NONE, STA) +wOPM (8DSlow, AbsoluteSlow, WRAP_NONE, STA) + +wOP8 (9DM1X1, AbsoluteIndexedXX1, WRAP_NONE, STA) +wOP16(9DM0X1, AbsoluteIndexedXX1, WRAP_NONE, STA) +wOP8 (9DM1X0, AbsoluteIndexedXX0, WRAP_NONE, STA) +wOP16(9DM0X0, AbsoluteIndexedXX0, WRAP_NONE, STA) +wOPM (9DSlow, AbsoluteIndexedXSlow, WRAP_NONE, STA) + +wOP8 (99M1X1, AbsoluteIndexedYX1, WRAP_NONE, STA) +wOP16(99M0X1, AbsoluteIndexedYX1, WRAP_NONE, STA) +wOP8 (99M1X0, AbsoluteIndexedYX0, WRAP_NONE, STA) +wOP16(99M0X0, AbsoluteIndexedYX0, WRAP_NONE, STA) +wOPM (99Slow, AbsoluteIndexedYSlow, WRAP_NONE, STA) + +wOP8 (8FM1, AbsoluteLong, WRAP_NONE, STA) +wOP16(8FM0, AbsoluteLong, WRAP_NONE, STA) +wOPM (8FSlow, AbsoluteLongSlow, WRAP_NONE, STA) + +wOP8 (9FM1, AbsoluteLongIndexedX, WRAP_NONE, STA) +wOP16(9FM0, AbsoluteLongIndexedX, WRAP_NONE, STA) +wOPM (9FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, STA) + +wOP8 (83M1, StackRelative, WRAP_NONE, STA) +wOP16(83M0, StackRelative, WRAP_NONE, STA) +wOPM (83Slow, StackRelativeSlow, WRAP_NONE, STA) + +wOP8 (93M1, StackRelativeIndirectIndexed, WRAP_NONE, STA) +wOP16(93M0, StackRelativeIndirectIndexed, WRAP_NONE, STA) +wOPM (93Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, STA) + +/* STX ********************************************************************* */ + +wOP8 (86X1, Direct, WRAP_BANK, STX) +wOP16(86X0, Direct, WRAP_BANK, STX) +wOPX (86Slow, DirectSlow, WRAP_BANK, STX) + +wOP8 (96E1, DirectIndexedYE1, WRAP_BANK, STX) +wOP8 (96E0X1, DirectIndexedYE0, WRAP_BANK, STX) +wOP16(96E0X0, DirectIndexedYE0, WRAP_BANK, STX) +wOPX (96Slow, DirectIndexedYSlow, WRAP_BANK, STX) + +wOP8 (8EX1, Absolute, WRAP_BANK, STX) +wOP16(8EX0, Absolute, WRAP_BANK, STX) +wOPX (8ESlow, AbsoluteSlow, WRAP_BANK, STX) + +/* STY ********************************************************************* */ + +wOP8 (84X1, Direct, WRAP_BANK, STY) +wOP16(84X0, Direct, WRAP_BANK, STY) +wOPX (84Slow, DirectSlow, WRAP_BANK, STY) + +wOP8 (94E1, DirectIndexedXE1, WRAP_BANK, STY) +wOP8 (94E0X1, DirectIndexedXE0, WRAP_BANK, STY) +wOP16(94E0X0, DirectIndexedXE0, WRAP_BANK, STY) +wOPX (94Slow, DirectIndexedXSlow, WRAP_BANK, STY) + +wOP8 (8CX1, Absolute, WRAP_BANK, STY) +wOP16(8CX0, Absolute, WRAP_BANK, STY) +wOPX (8CSlow, AbsoluteSlow, WRAP_BANK, STY) + +/* STZ ********************************************************************* */ + +wOP8 (64M1, Direct, WRAP_BANK, STZ) +wOP16(64M0, Direct, WRAP_BANK, STZ) +wOPM (64Slow, DirectSlow, WRAP_BANK, STZ) + +wOP8 (74E1, DirectIndexedXE1, WRAP_BANK, STZ) +wOP8 (74E0M1, DirectIndexedXE0, WRAP_BANK, STZ) +wOP16(74E0M0, DirectIndexedXE0, WRAP_BANK, STZ) +wOPM (74Slow, DirectIndexedXSlow, WRAP_BANK, STZ) + +wOP8 (9CM1, Absolute, WRAP_NONE, STZ) +wOP16(9CM0, Absolute, WRAP_NONE, STZ) +wOPM (9CSlow, AbsoluteSlow, WRAP_NONE, STZ) + +wOP8 (9EM1X1, AbsoluteIndexedXX1, WRAP_NONE, STZ) +wOP16(9EM0X1, AbsoluteIndexedXX1, WRAP_NONE, STZ) +wOP8 (9EM1X0, AbsoluteIndexedXX0, WRAP_NONE, STZ) +wOP16(9EM0X0, AbsoluteIndexedXX0, WRAP_NONE, STZ) +wOPM (9ESlow, AbsoluteIndexedXSlow, WRAP_NONE, STZ) + +/* TRB ********************************************************************* */ + +mOP8 (14M1, Direct, WRAP_BANK, TRB) +mOP16(14M0, Direct, WRAP_BANK, TRB) +mOPM (14Slow, DirectSlow, WRAP_BANK, TRB) + +mOP8 (1CM1, Absolute, WRAP_BANK, TRB) +mOP16(1CM0, Absolute, WRAP_BANK, TRB) +mOPM (1CSlow, AbsoluteSlow, WRAP_BANK, TRB) + +/* TSB ********************************************************************* */ + +mOP8 (04M1, Direct, WRAP_BANK, TSB) +mOP16(04M0, Direct, WRAP_BANK, TSB) +mOPM (04Slow, DirectSlow, WRAP_BANK, TSB) + +mOP8 (0CM1, Absolute, WRAP_BANK, TSB) +mOP16(0CM0, Absolute, WRAP_BANK, TSB) +mOPM (0CSlow, AbsoluteSlow, WRAP_BANK, TSB) + +/* Branch Instructions ***************************************************** */ + +#ifdef CPU_SHUTDOWN + +#ifndef SA1_OPCODES + +inline void CPUShutdown (void) +{ + if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress) + { + // Don't skip cycles with a pending NMI or IRQ - could cause delayed interrupt. + if (CPU.WaitCounter == 0 && !(CPU.Flags & (IRQ_FLAG | NMI_FLAG))) + { + CPU.WaitAddress = 0xffffffff; + if (Settings.SA1) + S9xSA1ExecuteDuringSleep(); + CPU.Cycles = CPU.NextEvent; + ICPU.CPUExecuting = FALSE; + S9xAPUExecute(); + ICPU.CPUExecuting = TRUE; + } + else + if (CPU.WaitCounter >= 2) + CPU.WaitCounter = 1; + else + CPU.WaitCounter--; + } +} + +#else + +inline void CPUShutdown (void) +{ + if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress) + { + if (CPU.WaitCounter >= 1) + SA1.Executing = FALSE; + else + CPU.WaitCounter++; + } +} + +#endif + +#else + +#define CPUShutdown() + +#endif + +// BCC +bOP(90E0, Relative, !CheckCarry(), 0, 0) +bOP(90E1, Relative, !CheckCarry(), 0, 1) +bOP(90Slow, RelativeSlow, !CheckCarry(), 0, CheckEmulation()) + +// BCS +bOP(B0E0, Relative, CheckCarry(), 0, 0) +bOP(B0E1, Relative, CheckCarry(), 0, 1) +bOP(B0Slow, RelativeSlow, CheckCarry(), 0, CheckEmulation()) + +// BEQ +bOP(F0E0, Relative, CheckZero(), 2, 0) +bOP(F0E1, Relative, CheckZero(), 2, 1) +bOP(F0Slow, RelativeSlow, CheckZero(), 2, CheckEmulation()) + +// BMI +bOP(30E0, Relative, CheckNegative(), 1, 0) +bOP(30E1, Relative, CheckNegative(), 1, 1) +bOP(30Slow, RelativeSlow, CheckNegative(), 1, CheckEmulation()) + +// BNE +bOP(D0E0, Relative, !CheckZero(), 1, 0) +bOP(D0E1, Relative, !CheckZero(), 1, 1) +bOP(D0Slow, RelativeSlow, !CheckZero(), 1, CheckEmulation()) + +// BPL +bOP(10E0, Relative, !CheckNegative(), 1, 0) +bOP(10E1, Relative, !CheckNegative(), 1, 1) +bOP(10Slow, RelativeSlow, !CheckNegative(), 1, CheckEmulation()) + +// BRA +bOP(80E0, Relative, 1, X, 0) +bOP(80E1, Relative, 1, X, 1) +bOP(80Slow, RelativeSlow, 1, X, CheckEmulation()) + +// BVC +bOP(50E0, Relative, !CheckOverflow(), 0, 0) +bOP(50E1, Relative, !CheckOverflow(), 0, 1) +bOP(50Slow, RelativeSlow, !CheckOverflow(), 0, CheckEmulation()) + +// BVS +bOP(70E0, Relative, CheckOverflow(), 0, 0) +bOP(70E1, Relative, CheckOverflow(), 0, 1) +bOP(70Slow, RelativeSlow, CheckOverflow(), 0, CheckEmulation()) + +// BRL +static void Op82 (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + RelativeLong(JUMP)); +} + +static void Op82Slow (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + RelativeLongSlow(JUMP)); +} + +/* Flag Instructions ******************************************************* */ + +// CLC +static void Op18 (void) +{ + ClearCarry(); + AddCycles(ONE_CYCLE); +} + +// SEC +static void Op38 (void) +{ + SetCarry(); + AddCycles(ONE_CYCLE); +} + +// CLD +static void OpD8 (void) +{ + ClearDecimal(); + AddCycles(ONE_CYCLE); +} + +// SED +static void OpF8 (void) +{ + SetDecimal(); + AddCycles(ONE_CYCLE); +#ifdef DEBUGGER + missing.decimal_mode = 1; +#endif +} + +// CLI +static void Op58 (void) +{ + ClearIRQ(); + AddCycles(ONE_CYCLE); + //CHECK_FOR_IRQ(); +} + +// SEI +static void Op78 (void) +{ + SetIRQ(); + AddCycles(ONE_CYCLE); +} + +// CLV +static void OpB8 (void) +{ + ClearOverflow(); + AddCycles(ONE_CYCLE); +} + +/* DEX/DEY ***************************************************************** */ + +static void OpCAX1 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.XL--; + SetZN(Registers.XL); +} + +static void OpCAX0 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.X.W--; + SetZN(Registers.X.W); +} + +static void OpCASlow (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + if (CheckIndex()) + { + Registers.XL--; + SetZN(Registers.XL); + } + else + { + Registers.X.W--; + SetZN(Registers.X.W); + } +} + +static void Op88X1 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.YL--; + SetZN(Registers.YL); +} + +static void Op88X0 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.Y.W--; + SetZN(Registers.Y.W); +} + +static void Op88Slow (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + if (CheckIndex()) + { + Registers.YL--; + SetZN(Registers.YL); + } + else + { + Registers.Y.W--; + SetZN(Registers.Y.W); + } +} + +/* INX/INY ***************************************************************** */ + +static void OpE8X1 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.XL++; + SetZN(Registers.XL); +} + +static void OpE8X0 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.X.W++; + SetZN(Registers.X.W); +} + +static void OpE8Slow (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + if (CheckIndex()) + { + Registers.XL++; + SetZN(Registers.XL); + } + else + { + Registers.X.W++; + SetZN(Registers.X.W); + } +} + +static void OpC8X1 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.YL++; + SetZN(Registers.YL); +} + +static void OpC8X0 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.Y.W++; + SetZN(Registers.Y.W); +} + +static void OpC8Slow (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + if (CheckIndex()) + { + Registers.YL--; + SetZN(Registers.YL); + } + else + { + Registers.Y.W--; + SetZN(Registers.Y.W); + } +} + +/* NOP ********************************************************************* */ + +static void OpEA (void) +{ + AddCycles(ONE_CYCLE); +} + +/* PUSH Instructions ******************************************************* */ + +#define PushW(w) \ + S9xSetWord(w, Registers.S.W - 1, WRAP_BANK, WRITE_10); \ + Registers.S.W -= 2; + +#define PushWE(w) \ + Registers.SL--; \ + S9xSetWord(w, Registers.S.W, WRAP_PAGE, WRITE_10); \ + Registers.SL--; + +#define PushB(b) \ + S9xSetByte(b, Registers.S.W--); + +#define PushBE(b) \ + S9xSetByte(b, Registers.S.W); \ + Registers.SL--; + +// PEA +static void OpF4E0 (void) +{ + uint16 val = (uint16) Absolute(NONE); + PushW(val); + OpenBus = val & 0xff; +} + +static void OpF4E1 (void) +{ + // Note: PEA is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + uint16 val = (uint16) Absolute(NONE); + PushW(val); + OpenBus = val & 0xff; + Registers.SH = 1; +} + +static void OpF4Slow (void) +{ + uint16 val = (uint16) AbsoluteSlow(NONE); + PushW(val); + OpenBus = val & 0xff; + if (CheckEmulation()) + Registers.SH = 1; +} + +// PEI +static void OpD4E0 (void) +{ + uint16 val = (uint16) DirectIndirectE0(NONE); + PushW(val); + OpenBus = val & 0xff; +} + +static void OpD4E1 (void) +{ + // Note: PEI is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + uint16 val = (uint16) DirectIndirectE1(NONE); + PushW(val); + OpenBus = val & 0xff; + Registers.SH = 1; +} + +static void OpD4Slow (void) +{ + uint16 val = (uint16) DirectIndirectSlow(NONE); + PushW(val); + OpenBus = val & 0xff; + if (CheckEmulation()) + Registers.SH = 1; +} + +// PER +static void Op62E0 (void) +{ + uint16 val = (uint16) RelativeLong(NONE); + PushW(val); + OpenBus = val & 0xff; +} + +static void Op62E1 (void) +{ + // Note: PER is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + uint16 val = (uint16) RelativeLong(NONE); + PushW(val); + OpenBus = val & 0xff; + Registers.SH = 1; +} + +static void Op62Slow (void) +{ + uint16 val = (uint16) RelativeLongSlow(NONE); + PushW(val); + OpenBus = val & 0xff; + if (CheckEmulation()) + Registers.SH = 1; +} + +// PHA +static void Op48E1 (void) +{ + AddCycles(ONE_CYCLE); + PushBE(Registers.AL); + OpenBus = Registers.AL; +} + +static void Op48E0M1 (void) +{ + AddCycles(ONE_CYCLE); + PushB(Registers.AL); + OpenBus = Registers.AL; +} + +static void Op48E0M0 (void) +{ + AddCycles(ONE_CYCLE); + PushW(Registers.A.W); + OpenBus = Registers.AL; +} + +static void Op48Slow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.AL); + } + else + if (CheckMemory()) + { + PushB(Registers.AL); + } + else + { + PushW(Registers.A.W); + } + + OpenBus = Registers.AL; +} + +// PHB +static void Op8BE1 (void) +{ + AddCycles(ONE_CYCLE); + PushBE(Registers.DB); + OpenBus = Registers.DB; +} + +static void Op8BE0 (void) +{ + AddCycles(ONE_CYCLE); + PushB(Registers.DB); + OpenBus = Registers.DB; +} + +static void Op8BSlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.DB); + } + else + { + PushB(Registers.DB); + } + + OpenBus = Registers.DB; +} + +// PHD +static void Op0BE0 (void) +{ + AddCycles(ONE_CYCLE); + PushW(Registers.D.W); + OpenBus = Registers.DL; +} + +static void Op0BE1 (void) +{ + // Note: PHD is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + AddCycles(ONE_CYCLE); + PushW(Registers.D.W); + OpenBus = Registers.DL; + Registers.SH = 1; +} + +static void Op0BSlow (void) +{ + AddCycles(ONE_CYCLE); + PushW(Registers.D.W); + OpenBus = Registers.DL; + if (CheckEmulation()) + Registers.SH = 1; +} + +// PHK +static void Op4BE1 (void) +{ + AddCycles(ONE_CYCLE); + PushBE(Registers.PB); + OpenBus = Registers.PB; +} + +static void Op4BE0 (void) +{ + AddCycles(ONE_CYCLE); + PushB(Registers.PB); + OpenBus = Registers.PB; +} + +static void Op4BSlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.PB); + } + else + { + PushB(Registers.PB); + } + + OpenBus = Registers.PB; +} + +// PHP +static void Op08E0 (void) +{ + S9xPackStatus(); + AddCycles(ONE_CYCLE); + PushB(Registers.PL); + OpenBus = Registers.PL; +} + +static void Op08E1 (void) +{ + S9xPackStatus(); + AddCycles(ONE_CYCLE); + PushBE(Registers.PL); + OpenBus = Registers.PL; +} + +static void Op08Slow (void) +{ + S9xPackStatus(); + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.PL); + } + else + { + PushB(Registers.PL); + } + + OpenBus = Registers.PL; +} + +// PHX +static void OpDAE1 (void) +{ + AddCycles(ONE_CYCLE); + PushBE(Registers.XL); + OpenBus = Registers.XL; +} + +static void OpDAE0X1 (void) +{ + AddCycles(ONE_CYCLE); + PushB(Registers.XL); + OpenBus = Registers.XL; +} + +static void OpDAE0X0 (void) +{ + AddCycles(ONE_CYCLE); + PushW(Registers.X.W); + OpenBus = Registers.XL; +} + +static void OpDASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.XL); + } + else + if (CheckIndex()) + { + PushB(Registers.XL); + } + else + { + PushW(Registers.X.W); + } + + OpenBus = Registers.XL; +} + +// PHY +static void Op5AE1 (void) +{ + AddCycles(ONE_CYCLE); + PushBE(Registers.YL); + OpenBus = Registers.YL; +} + +static void Op5AE0X1 (void) +{ + AddCycles(ONE_CYCLE); + PushB(Registers.YL); + OpenBus = Registers.YL; +} + +static void Op5AE0X0 (void) +{ + AddCycles(ONE_CYCLE); + PushW(Registers.Y.W); + OpenBus = Registers.YL; +} + +static void Op5ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.YL); + } + else + if (CheckIndex()) + { + PushB(Registers.YL); + } + else + { + PushW(Registers.Y.W); + } + + OpenBus = Registers.YL; +} + +/* PULL Instructions ******************************************************* */ + +#define PullW(w) \ + w = S9xGetWord(Registers.S.W + 1, WRAP_BANK); \ + Registers.S.W += 2; + +#define PullWE(w) \ + Registers.SL++; \ + w = S9xGetWord(Registers.S.W, WRAP_PAGE); \ + Registers.SL++; + +#define PullB(b) \ + b = S9xGetByte(++Registers.S.W); + +#define PullBE(b) \ + Registers.SL++; \ + b = S9xGetByte(Registers.S.W); + +// PLA +static void Op68E1 (void) +{ + AddCycles(TWO_CYCLES); + PullBE(Registers.AL); + SetZN(Registers.AL); + OpenBus = Registers.AL; +} + +static void Op68E0M1 (void) +{ + AddCycles(TWO_CYCLES); + PullB(Registers.AL); + SetZN(Registers.AL); + OpenBus = Registers.AL; +} + +static void Op68E0M0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.A.W); + SetZN(Registers.A.W); + OpenBus = Registers.AH; +} + +static void Op68Slow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullBE(Registers.AL); + SetZN(Registers.AL); + OpenBus = Registers.AL; + } + else + if (CheckMemory()) + { + PullB(Registers.AL); + SetZN(Registers.AL); + OpenBus = Registers.AL; + } + else + { + PullW(Registers.A.W); + SetZN(Registers.A.W); + OpenBus = Registers.AH; + } +} + +// PLB +static void OpABE1 (void) +{ + AddCycles(TWO_CYCLES); + PullBE(Registers.DB); + SetZN(Registers.DB); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = Registers.DB; +} + +static void OpABE0 (void) +{ + AddCycles(TWO_CYCLES); + PullB(Registers.DB); + SetZN(Registers.DB); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = Registers.DB; +} + +static void OpABSlow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullBE(Registers.DB); + } + else + { + PullB(Registers.DB); + } + + SetZN(Registers.DB); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = Registers.DB; +} + +// PLD +static void Op2BE0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.D.W); + SetZN(Registers.D.W); + OpenBus = Registers.DH; +} + +static void Op2BE1 (void) +{ + // Note: PLD is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + AddCycles(TWO_CYCLES); + PullW(Registers.D.W); + SetZN(Registers.D.W); + OpenBus = Registers.DH; + Registers.SH = 1; +} + +static void Op2BSlow (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.D.W); + SetZN(Registers.D.W); + OpenBus = Registers.DH; + if (CheckEmulation()) + Registers.SH = 1; +} + +// PLP +static void Op28E1 (void) +{ + AddCycles(TWO_CYCLES); + PullBE(Registers.PL); + OpenBus = Registers.PL; + SetFlags(MemoryFlag | IndexFlag); + S9xUnpackStatus(); + S9xFixCycles(); + //CHECK_FOR_IRQ(); +} + +static void Op28E0 (void) +{ + AddCycles(TWO_CYCLES); + PullB(Registers.PL); + OpenBus = Registers.PL; + S9xUnpackStatus(); + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); + //CHECK_FOR_IRQ(); +} + +static void Op28Slow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullBE(Registers.PL); + OpenBus = Registers.PL; + SetFlags(MemoryFlag | IndexFlag); + } + else + { + PullB(Registers.PL); + OpenBus = Registers.PL; + } + + S9xUnpackStatus(); + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); + //CHECK_FOR_IRQ(); +} + +// PLX +static void OpFAE1 (void) +{ + AddCycles(TWO_CYCLES); + PullBE(Registers.XL); + SetZN(Registers.XL); + OpenBus = Registers.XL; +} + +static void OpFAE0X1 (void) +{ + AddCycles(TWO_CYCLES); + PullB(Registers.XL); + SetZN(Registers.XL); + OpenBus = Registers.XL; +} + +static void OpFAE0X0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.X.W); + SetZN(Registers.X.W); + OpenBus = Registers.XH; +} + +static void OpFASlow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullBE(Registers.XL); + SetZN(Registers.XL); + OpenBus = Registers.XL; + } + else + if (CheckIndex()) + { + PullB(Registers.XL); + SetZN(Registers.XL); + OpenBus = Registers.XL; + } + else + { + PullW(Registers.X.W); + SetZN(Registers.X.W); + OpenBus = Registers.XH; + } +} + +// PLY +static void Op7AE1 (void) +{ + AddCycles(TWO_CYCLES); + PullBE(Registers.YL); + SetZN(Registers.YL); + OpenBus = Registers.YL; +} + +static void Op7AE0X1 (void) +{ + AddCycles(TWO_CYCLES); + PullB(Registers.YL); + SetZN(Registers.YL); + OpenBus = Registers.YL; +} + +static void Op7AE0X0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.Y.W); + SetZN(Registers.Y.W); + OpenBus = Registers.YH; +} + +static void Op7ASlow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullBE(Registers.YL); + SetZN(Registers.YL); + OpenBus = Registers.YL; + } + else + if (CheckIndex()) + { + PullB(Registers.YL); + SetZN(Registers.YL); + OpenBus = Registers.YL; + } + else + { + PullW(Registers.Y.W); + SetZN(Registers.Y.W); + OpenBus = Registers.YH; + } +} + +/* Transfer Instructions *************************************************** */ + +// TAX +static void OpAAX1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.XL = Registers.AL; + SetZN(Registers.XL); +} + +static void OpAAX0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.X.W = Registers.A.W; + SetZN(Registers.X.W); +} + +static void OpAASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.XL = Registers.AL; + SetZN(Registers.XL); + } + else + { + Registers.X.W = Registers.A.W; + SetZN(Registers.X.W); + } +} + +// TAY +static void OpA8X1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.YL = Registers.AL; + SetZN(Registers.YL); +} + +static void OpA8X0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.Y.W = Registers.A.W; + SetZN(Registers.Y.W); +} + +static void OpA8Slow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.YL = Registers.AL; + SetZN(Registers.YL); + } + else + { + Registers.Y.W = Registers.A.W; + SetZN(Registers.Y.W); + } +} + +// TCD +static void Op5B (void) +{ + AddCycles(ONE_CYCLE); + Registers.D.W = Registers.A.W; + SetZN(Registers.D.W); +} + +// TCS +static void Op1B (void) +{ + AddCycles(ONE_CYCLE); + Registers.S.W = Registers.A.W; + if (CheckEmulation()) + Registers.SH = 1; +} + +// TDC +static void Op7B (void) +{ + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.D.W; + SetZN(Registers.A.W); +} + +// TSC +static void Op3B (void) +{ + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.S.W; + SetZN(Registers.A.W); +} + +// TSX +static void OpBAX1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.XL = Registers.SL; + SetZN(Registers.XL); +} + +static void OpBAX0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.X.W = Registers.S.W; + SetZN(Registers.X.W); +} + +static void OpBASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.XL = Registers.SL; + SetZN(Registers.XL); + } + else + { + Registers.X.W = Registers.S.W; + SetZN(Registers.X.W); + } +} + +// TXA +static void Op8AM1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.AL = Registers.XL; + SetZN(Registers.AL); +} + +static void Op8AM0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.X.W; + SetZN(Registers.A.W); +} + +static void Op8ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + Registers.AL = Registers.XL; + SetZN(Registers.AL); + } + else + { + Registers.A.W = Registers.X.W; + SetZN(Registers.A.W); + } +} + +// TXS +static void Op9A (void) +{ + AddCycles(ONE_CYCLE); + Registers.S.W = Registers.X.W; + if (CheckEmulation()) + Registers.SH = 1; +} + +// TXY +static void Op9BX1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.YL = Registers.XL; + SetZN(Registers.YL); +} + +static void Op9BX0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.Y.W = Registers.X.W; + SetZN(Registers.Y.W); +} + +static void Op9BSlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.YL = Registers.XL; + SetZN(Registers.YL); + } + else + { + Registers.Y.W = Registers.X.W; + SetZN(Registers.Y.W); + } +} + +// TYA +static void Op98M1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.AL = Registers.YL; + SetZN(Registers.AL); +} + +static void Op98M0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.Y.W; + SetZN(Registers.A.W); +} + +static void Op98Slow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + Registers.AL = Registers.YL; + SetZN(Registers.AL); + } + else + { + Registers.A.W = Registers.Y.W; + SetZN(Registers.A.W); + } +} + +// TYX +static void OpBBX1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.XL = Registers.YL; + SetZN(Registers.XL); +} + +static void OpBBX0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.X.W = Registers.Y.W; + SetZN(Registers.X.W); +} + +static void OpBBSlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.XL = Registers.YL; + SetZN(Registers.XL); + } + else + { + Registers.X.W = Registers.Y.W; + SetZN(Registers.X.W); + } +} + +/* XCE ********************************************************************* */ + +static void OpFB (void) +{ + AddCycles(ONE_CYCLE); + + uint8 A1 = ICPU._Carry; + uint8 A2 = Registers.PH; + + ICPU._Carry = A2 & 1; + Registers.PH = A1; + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + Registers.SH = 1; + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); +} + +/* BRK ********************************************************************* */ + +static void Op00 (void) +{ +#ifdef DEBUGGER + if (CPU.Flags & TRACE_FLAG) + S9xTraceMessage("*** BRK"); +#endif + + AddCycles(CPU.MemSpeed); + + uint16 addr; + + if (!CheckEmulation()) + { + PushB(Registers.PB); + PushW(Registers.PCw + 1); + S9xPackStatus(); + PushB(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + addr = S9xGetWord(0xFFE6); + } + else + { + PushWE(Registers.PCw + 1); + S9xPackStatus(); + PushBE(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + addr = S9xGetWord(0xFFFE); + } + + S9xSetPCBase(addr); + OpenBus = addr >> 8; +} + +/* IRQ ********************************************************************* */ + +void S9xOpcode_IRQ (void) +{ +#ifdef DEBUGGER + if (CPU.Flags & TRACE_FLAG) + #ifdef SA1_OPCODES + S9xTraceMessage("*** SA1 IRQ"); + #else + S9xTraceMessage("*** IRQ"); + #endif +#endif + + // IRQ and NMI do an opcode fetch as their first "IO" cycle. + AddCycles(CPU.MemSpeed + ONE_CYCLE); + + if (!CheckEmulation()) + { + PushB(Registers.PB); + PushW(Registers.PCw); + S9xPackStatus(); + PushB(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + #ifdef SA1_OPCODES + OpenBus = Memory.FillRAM[0x2208]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSA1SetPCBase(Memory.FillRAM[0x2207] | (Memory.FillRAM[0x2208] << 8)); + #else + if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x40)) + { + OpenBus = Memory.FillRAM[0x220f]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSetPCBase(Memory.FillRAM[0x220e] | (Memory.FillRAM[0x220f] << 8)); + } + else + { + uint16 addr = S9xGetWord(0xFFEE); + OpenBus = addr >> 8; + S9xSetPCBase(addr); + } + #endif + } + else + { + PushWE(Registers.PCw); + S9xPackStatus(); + PushBE(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + #ifdef SA1_OPCODES + OpenBus = Memory.FillRAM[0x2208]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSA1SetPCBase(Memory.FillRAM[0x2207] | (Memory.FillRAM[0x2208] << 8)); + #else + if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x40)) + { + OpenBus = Memory.FillRAM[0x220f]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSetPCBase(Memory.FillRAM[0x220e] | (Memory.FillRAM[0x220f] << 8)); + } + else + { + uint16 addr = S9xGetWord(0xFFFE); + OpenBus = addr >> 8; + S9xSetPCBase(addr); + } + #endif + } +} + +/* NMI ********************************************************************* */ + +void S9xOpcode_NMI (void) +{ +#ifdef DEBUGGER + if (CPU.Flags & TRACE_FLAG) + #ifdef SA1_OPCODES + S9xTraceMessage("*** SA1 NMI"); + #else + S9xTraceMessage("*** NMI"); + #endif +#endif + + // IRQ and NMI do an opcode fetch as their first "IO" cycle. + AddCycles(CPU.MemSpeed + ONE_CYCLE); + + if (!CheckEmulation()) + { + PushB(Registers.PB); + PushW(Registers.PCw); + S9xPackStatus(); + PushB(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + #ifdef SA1_OPCODES + OpenBus = Memory.FillRAM[0x2206]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSA1SetPCBase(Memory.FillRAM[0x2205] | (Memory.FillRAM[0x2206] << 8)); + #else + if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x10)) + { + OpenBus = Memory.FillRAM[0x220d]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSetPCBase(Memory.FillRAM[0x220c] | (Memory.FillRAM[0x220d] << 8)); + } + else + { + uint16 addr = S9xGetWord(0xFFEA); + OpenBus = addr >> 8; + S9xSetPCBase(addr); + } + #endif + } + else + { + PushWE(Registers.PCw); + S9xPackStatus(); + PushBE(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + #ifdef SA1_OPCODES + OpenBus = Memory.FillRAM[0x2206]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSA1SetPCBase(Memory.FillRAM[0x2205] | (Memory.FillRAM[0x2206] << 8)); + #else + if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x20)) + { + OpenBus = Memory.FillRAM[0x220d]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSetPCBase(Memory.FillRAM[0x220c] | (Memory.FillRAM[0x220d] << 8)); + } + else + { + uint16 addr = S9xGetWord(0xFFFA); + OpenBus = addr >> 8; + S9xSetPCBase(addr); + } + #endif + } +} + +/* COP ********************************************************************* */ + +static void Op02 (void) +{ +#ifdef DEBUGGER + if (CPU.Flags & TRACE_FLAG) + S9xTraceMessage("*** COP"); +#endif + + AddCycles(CPU.MemSpeed); + + uint16 addr; + + if (!CheckEmulation()) + { + PushB(Registers.PB); + PushW(Registers.PCw + 1); + S9xPackStatus(); + PushB(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + addr = S9xGetWord(0xFFE4); + } + else + { + PushWE(Registers.PCw + 1); + S9xPackStatus(); + PushBE(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + addr = S9xGetWord(0xFFF4); + } + + S9xSetPCBase(addr); + OpenBus = addr >> 8; +} + +/* JML ********************************************************************* */ + +static void OpDC (void) +{ + S9xSetPCBase(AbsoluteIndirectLong(JUMP)); +} + +static void OpDCSlow (void) +{ + S9xSetPCBase(AbsoluteIndirectLongSlow(JUMP)); +} + +static void Op5C (void) +{ + S9xSetPCBase(AbsoluteLong(JUMP)); +} + +static void Op5CSlow (void) +{ + S9xSetPCBase(AbsoluteLongSlow(JUMP)); +} + +/* JMP ********************************************************************* */ + +static void Op4C (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) Absolute(JUMP))); +#if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES) + CPUShutdown(); +#endif +} + +static void Op4CSlow (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteSlow(JUMP))); +#if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES) + CPUShutdown(); +#endif +} + +static void Op6C (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndirect(JUMP))); +} + +static void Op6CSlow (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndirectSlow(JUMP))); +} + +static void Op7C (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndexedIndirect(JUMP))); +} + +static void Op7CSlow (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndexedIndirectSlow(JUMP))); +} + +/* JSL/RTL ***************************************************************** */ + +static void Op22E1 (void) +{ + // Note: JSL is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + uint32 addr = AbsoluteLong(JSR); + PushB(Registers.PB); + PushW(Registers.PCw - 1); + Registers.SH = 1; + S9xSetPCBase(addr); +} + +static void Op22E0 (void) +{ + uint32 addr = AbsoluteLong(JSR); + PushB(Registers.PB); + PushW(Registers.PCw - 1); + S9xSetPCBase(addr); +} + +static void Op22Slow (void) +{ + uint32 addr = AbsoluteLongSlow(JSR); + PushB(Registers.PB); + PushW(Registers.PCw - 1); + if (CheckEmulation()) + Registers.SH = 1; + S9xSetPCBase(addr); +} + +static void Op6BE1 (void) +{ + // Note: RTL is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + AddCycles(TWO_CYCLES); + PullW(Registers.PCw); + PullB(Registers.PB); + Registers.SH = 1; + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +static void Op6BE0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.PCw); + PullB(Registers.PB); + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +static void Op6BSlow (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.PCw); + PullB(Registers.PB); + if (CheckEmulation()) + Registers.SH = 1; + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +/* JSR/RTS ***************************************************************** */ + +static void Op20E1 (void) +{ + uint16 addr = Absolute(JSR); + AddCycles(ONE_CYCLE); + PushWE(Registers.PCw - 1); + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void Op20E0 (void) +{ + uint16 addr = Absolute(JSR); + AddCycles(ONE_CYCLE); + PushW(Registers.PCw - 1); + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void Op20Slow (void) +{ + uint16 addr = AbsoluteSlow(JSR); + + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushWE(Registers.PCw - 1); + } + else + { + PushW(Registers.PCw - 1); + } + + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void OpFCE1 (void) +{ + // Note: JSR (a,X) is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + uint16 addr = AbsoluteIndexedIndirect(JSR); + PushW(Registers.PCw - 1); + Registers.SH = 1; + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void OpFCE0 (void) +{ + uint16 addr = AbsoluteIndexedIndirect(JSR); + PushW(Registers.PCw - 1); + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void OpFCSlow (void) +{ + uint16 addr = AbsoluteIndexedIndirectSlow(JSR); + PushW(Registers.PCw - 1); + if (CheckEmulation()) + Registers.SH = 1; + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void Op60E1 (void) +{ + AddCycles(TWO_CYCLES); + PullWE(Registers.PCw); + AddCycles(ONE_CYCLE); + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +static void Op60E0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.PCw); + AddCycles(ONE_CYCLE); + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +static void Op60Slow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullWE(Registers.PCw); + } + else + { + PullW(Registers.PCw); + } + + AddCycles(ONE_CYCLE); + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +/* MVN/MVP ***************************************************************** */ + +static void Op54X1 (void) +{ + uint32 SrcBank; + + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + Registers.XL++; + Registers.YL++; + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +static void Op54X0 (void) +{ + uint32 SrcBank; + + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + Registers.X.W++; + Registers.Y.W++; + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +static void Op54Slow (void) +{ + uint32 SrcBank; + + OpenBus = Registers.DB = Immediate8Slow(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8Slow(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + if (CheckIndex()) + { + Registers.XL++; + Registers.YL++; + } + else + { + Registers.X.W++; + Registers.Y.W++; + } + + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +static void Op44X1 (void) +{ + uint32 SrcBank; + + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + Registers.XL--; + Registers.YL--; + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +static void Op44X0 (void) +{ + uint32 SrcBank; + + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + Registers.X.W--; + Registers.Y.W--; + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +static void Op44Slow (void) +{ + uint32 SrcBank; + + OpenBus = Registers.DB = Immediate8Slow(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8Slow(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + if (CheckIndex()) + { + Registers.XL--; + Registers.YL--; + } + else + { + Registers.X.W--; + Registers.Y.W--; + } + + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +/* REP/SEP ***************************************************************** */ + +static void OpC2 (void) +{ + uint8 Work8 = ~Immediate8(READ); + Registers.PL &= Work8; + ICPU._Carry &= Work8; + ICPU._Overflow &= (Work8 >> 6); + ICPU._Negative &= Work8; + ICPU._Zero |= ~Work8 & Zero; + + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); + //CHECK_FOR_IRQ(); +} + +static void OpC2Slow (void) +{ + uint8 Work8 = ~Immediate8Slow(READ); + Registers.PL &= Work8; + ICPU._Carry &= Work8; + ICPU._Overflow &= (Work8 >> 6); + ICPU._Negative &= Work8; + ICPU._Zero |= ~Work8 & Zero; + + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); + //CHECK_FOR_IRQ(); +} + +static void OpE2 (void) +{ + uint8 Work8 = Immediate8(READ); + Registers.PL |= Work8; + ICPU._Carry |= Work8 & 1; + ICPU._Overflow |= (Work8 >> 6) & 1; + ICPU._Negative |= Work8; + if (Work8 & Zero) + ICPU._Zero = 0; + + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); +} + +static void OpE2Slow (void) +{ + uint8 Work8 = Immediate8Slow(READ); + Registers.PL |= Work8; + ICPU._Carry |= Work8 & 1; + ICPU._Overflow |= (Work8 >> 6) & 1; + ICPU._Negative |= Work8; + if (Work8 & Zero) + ICPU._Zero = 0; + + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); +} + +/* XBA ********************************************************************* */ + +static void OpEB (void) +{ + uint8 Work8 = Registers.AL; + Registers.AL = Registers.AH; + Registers.AH = Work8; + SetZN(Registers.AL); + AddCycles(TWO_CYCLES); +} + +/* RTI ********************************************************************* */ + +static void Op40Slow (void) +{ + AddCycles(TWO_CYCLES); + + if (!CheckEmulation()) + { + PullB(Registers.PL); + S9xUnpackStatus(); + PullW(Registers.PCw); + PullB(Registers.PB); + OpenBus = Registers.PB; + ICPU.ShiftedPB = Registers.PB << 16; + } + else + { + PullBE(Registers.PL); + S9xUnpackStatus(); + PullWE(Registers.PCw); + OpenBus = Registers.PCh; + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + S9xSetPCBase(Registers.PBPC); + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); + //CHECK_FOR_IRQ(); +} + +/* STP/WAI ***************************************************************** */ + +// WAI +static void OpCB (void) +{ + // Ok, let's just C-ify the ASM versions separately. +#ifdef SA1_OPCODES + SA1.WaitingForInterrupt = TRUE; + Registers.PCw--; +#if 0 + // XXX: FIXME + if (Settings.Shutdown) + { + SA1.Cycles = SA1.NextEvent; + SA1.Executing = FALSE; + //S9xAPUExecute(); // FIXME + SA1.Executing = TRUE; + } +#endif +#else // SA1_OPCODES +#if 0 + if (CPU.IRQActive) + AddCycles(TWO_CYCLES); + else +#endif + { + CPU.WaitingForInterrupt = TRUE; + Registers.PCw--; + #ifdef CPU_SHUTDOWN + if (Settings.Shutdown) + { + CPU.Cycles = CPU.NextEvent; + ICPU.CPUExecuting = FALSE; + S9xAPUExecute(); + ICPU.CPUExecuting = TRUE; + } + else + AddCycles(TWO_CYCLES); + #else + AddCycles(TWO_CYCLES); +#endif + } +#endif // SA1_OPCODES +} + +// STP +static void OpDB (void) +{ + Registers.PCw--; + CPU.Flags |= DEBUG_MODE_FLAG | HALTED_FLAG; +} + +/* WDM (Reserved S9xOpcode) ************************************************ */ + +#ifdef DEBUGGER +extern FILE *trace, *trace2; +#endif + +static void Op42 (void) +{ +#ifdef DEBUGGER + uint8 byte = (uint8) S9xGetWord(Registers.PBPC); +#else + S9xGetWord(Registers.PBPC); +#endif + Registers.PCw++; + +#ifdef DEBUGGER + // Hey, let's use this to trigger debug modes. + switch (byte) + { + case 0xdb: // "STP" = Enter debug mode + CPU.Flags |= DEBUG_MODE_FLAG; + break; + + #ifndef SA1_OPCODES + case 0xe2: // "SEP" = Trace on + if (!(CPU.Flags & TRACE_FLAG)) + { + char buf[25]; + CPU.Flags |= TRACE_FLAG; + snprintf(buf, 25, "WDM trace on at $%02X:%04X", Registers.PB, Registers.PCw); + S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf); + if (trace != NULL) + fclose(trace); + trace = fopen("WDMtrace.log", "ab"); + } + + break; + + case 0xc2: // "REP" = Trace off + if (CPU.Flags & TRACE_FLAG) + { + char buf[26]; + CPU.Flags &= ~TRACE_FLAG; + snprintf(buf, 26, "WDM trace off at $%02X:%04X", Registers.PB, Registers.PCw); + S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf); + if (trace != NULL) + fclose(trace); + trace = NULL; + } + + break; + #endif + + case 0x42: // "WDM" = Snapshot + char filename[PATH_MAX + 1], drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[PATH_MAX + 1], ext[_MAX_EXT + 1]; + + _splitpath(Memory.ROMFilename, drive, dir, def, ext); + snprintf(filename, PATH_MAX, "%s%s%s-%06X.wdm", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, Registers.PBPC & 0xffffff); + sprintf(def, "WDM Snapshot at $%02X:%04X: %s", Registers.PB, Registers.PCw, filename); + S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, def); + S9xFreezeGame(filename); + + break; + + default: + break; + } +#endif +} + +/* CPU-S9xOpcodes Definitions ************************************************/ + +struct SOpcodes S9xOpcodesM1X1[256] = +{ + { Op00 }, { Op01E0M1 }, { Op02 }, { Op03M1 }, { Op04M1 }, + { Op05M1 }, { Op06M1 }, { Op07M1 }, { Op08E0 }, { Op09M1 }, + { Op0AM1 }, { Op0BE0 }, { Op0CM1 }, { Op0DM1 }, { Op0EM1 }, + { Op0FM1 }, { Op10E0 }, { Op11E0M1X1 }, { Op12E0M1 }, { Op13M1 }, + { Op14M1 }, { Op15E0M1 }, { Op16E0M1 }, { Op17M1 }, { Op18 }, + { Op19M1X1 }, { Op1AM1 }, { Op1B }, { Op1CM1 }, { Op1DM1X1 }, + { Op1EM1X1 }, { Op1FM1 }, { Op20E0 }, { Op21E0M1 }, { Op22E0 }, + { Op23M1 }, { Op24M1 }, { Op25M1 }, { Op26M1 }, { Op27M1 }, + { Op28E0 }, { Op29M1 }, { Op2AM1 }, { Op2BE0 }, { Op2CM1 }, + { Op2DM1 }, { Op2EM1 }, { Op2FM1 }, { Op30E0 }, { Op31E0M1X1 }, + { Op32E0M1 }, { Op33M1 }, { Op34E0M1 }, { Op35E0M1 }, { Op36E0M1 }, + { Op37M1 }, { Op38 }, { Op39M1X1 }, { Op3AM1 }, { Op3B }, + { Op3CM1X1 }, { Op3DM1X1 }, { Op3EM1X1 }, { Op3FM1 }, { Op40Slow }, + { Op41E0M1 }, { Op42 }, { Op43M1 }, { Op44X1 }, { Op45M1 }, + { Op46M1 }, { Op47M1 }, { Op48E0M1 }, { Op49M1 }, { Op4AM1 }, + { Op4BE0 }, { Op4C }, { Op4DM1 }, { Op4EM1 }, { Op4FM1 }, + { Op50E0 }, { Op51E0M1X1 }, { Op52E0M1 }, { Op53M1 }, { Op54X1 }, + { Op55E0M1 }, { Op56E0M1 }, { Op57M1 }, { Op58 }, { Op59M1X1 }, + { Op5AE0X1 }, { Op5B }, { Op5C }, { Op5DM1X1 }, { Op5EM1X1 }, + { Op5FM1 }, { Op60E0 }, { Op61E0M1 }, { Op62E0 }, { Op63M1 }, + { Op64M1 }, { Op65M1 }, { Op66M1 }, { Op67M1 }, { Op68E0M1 }, + { Op69M1 }, { Op6AM1 }, { Op6BE0 }, { Op6C }, { Op6DM1 }, + { Op6EM1 }, { Op6FM1 }, { Op70E0 }, { Op71E0M1X1 }, { Op72E0M1 }, + { Op73M1 }, { Op74E0M1 }, { Op75E0M1 }, { Op76E0M1 }, { Op77M1 }, + { Op78 }, { Op79M1X1 }, { Op7AE0X1 }, { Op7B }, { Op7C }, + { Op7DM1X1 }, { Op7EM1X1 }, { Op7FM1 }, { Op80E0 }, { Op81E0M1 }, + { Op82 }, { Op83M1 }, { Op84X1 }, { Op85M1 }, { Op86X1 }, + { Op87M1 }, { Op88X1 }, { Op89M1 }, { Op8AM1 }, { Op8BE0 }, + { Op8CX1 }, { Op8DM1 }, { Op8EX1 }, { Op8FM1 }, { Op90E0 }, + { Op91E0M1X1 }, { Op92E0M1 }, { Op93M1 }, { Op94E0X1 }, { Op95E0M1 }, + { Op96E0X1 }, { Op97M1 }, { Op98M1 }, { Op99M1X1 }, { Op9A }, + { Op9BX1 }, { Op9CM1 }, { Op9DM1X1 }, { Op9EM1X1 }, { Op9FM1 }, + { OpA0X1 }, { OpA1E0M1 }, { OpA2X1 }, { OpA3M1 }, { OpA4X1 }, + { OpA5M1 }, { OpA6X1 }, { OpA7M1 }, { OpA8X1 }, { OpA9M1 }, + { OpAAX1 }, { OpABE0 }, { OpACX1 }, { OpADM1 }, { OpAEX1 }, + { OpAFM1 }, { OpB0E0 }, { OpB1E0M1X1 }, { OpB2E0M1 }, { OpB3M1 }, + { OpB4E0X1 }, { OpB5E0M1 }, { OpB6E0X1 }, { OpB7M1 }, { OpB8 }, + { OpB9M1X1 }, { OpBAX1 }, { OpBBX1 }, { OpBCX1 }, { OpBDM1X1 }, + { OpBEX1 }, { OpBFM1 }, { OpC0X1 }, { OpC1E0M1 }, { OpC2 }, + { OpC3M1 }, { OpC4X1 }, { OpC5M1 }, { OpC6M1 }, { OpC7M1 }, + { OpC8X1 }, { OpC9M1 }, { OpCAX1 }, { OpCB }, { OpCCX1 }, + { OpCDM1 }, { OpCEM1 }, { OpCFM1 }, { OpD0E0 }, { OpD1E0M1X1 }, + { OpD2E0M1 }, { OpD3M1 }, { OpD4E0 }, { OpD5E0M1 }, { OpD6E0M1 }, + { OpD7M1 }, { OpD8 }, { OpD9M1X1 }, { OpDAE0X1 }, { OpDB }, + { OpDC }, { OpDDM1X1 }, { OpDEM1X1 }, { OpDFM1 }, { OpE0X1 }, + { OpE1E0M1 }, { OpE2 }, { OpE3M1 }, { OpE4X1 }, { OpE5M1 }, + { OpE6M1 }, { OpE7M1 }, { OpE8X1 }, { OpE9M1 }, { OpEA }, + { OpEB }, { OpECX1 }, { OpEDM1 }, { OpEEM1 }, { OpEFM1 }, + { OpF0E0 }, { OpF1E0M1X1 }, { OpF2E0M1 }, { OpF3M1 }, { OpF4E0 }, + { OpF5E0M1 }, { OpF6E0M1 }, { OpF7M1 }, { OpF8 }, { OpF9M1X1 }, + { OpFAE0X1 }, { OpFB }, { OpFCE0 }, { OpFDM1X1 }, { OpFEM1X1 }, + { OpFFM1 } +}; + +struct SOpcodes S9xOpcodesE1[256] = +{ + { Op00 }, { Op01E1 }, { Op02 }, { Op03M1 }, { Op04M1 }, + { Op05M1 }, { Op06M1 }, { Op07M1 }, { Op08E1 }, { Op09M1 }, + { Op0AM1 }, { Op0BE1 }, { Op0CM1 }, { Op0DM1 }, { Op0EM1 }, + { Op0FM1 }, { Op10E1 }, { Op11E1 }, { Op12E1 }, { Op13M1 }, + { Op14M1 }, { Op15E1 }, { Op16E1 }, { Op17M1 }, { Op18 }, + { Op19M1X1 }, { Op1AM1 }, { Op1B }, { Op1CM1 }, { Op1DM1X1 }, + { Op1EM1X1 }, { Op1FM1 }, { Op20E1 }, { Op21E1 }, { Op22E1 }, + { Op23M1 }, { Op24M1 }, { Op25M1 }, { Op26M1 }, { Op27M1 }, + { Op28E1 }, { Op29M1 }, { Op2AM1 }, { Op2BE1 }, { Op2CM1 }, + { Op2DM1 }, { Op2EM1 }, { Op2FM1 }, { Op30E1 }, { Op31E1 }, + { Op32E1 }, { Op33M1 }, { Op34E1 }, { Op35E1 }, { Op36E1 }, + { Op37M1 }, { Op38 }, { Op39M1X1 }, { Op3AM1 }, { Op3B }, + { Op3CM1X1 }, { Op3DM1X1 }, { Op3EM1X1 }, { Op3FM1 }, { Op40Slow }, + { Op41E1 }, { Op42 }, { Op43M1 }, { Op44X1 }, { Op45M1 }, + { Op46M1 }, { Op47M1 }, { Op48E1 }, { Op49M1 }, { Op4AM1 }, + { Op4BE1 }, { Op4C }, { Op4DM1 }, { Op4EM1 }, { Op4FM1 }, + { Op50E1 }, { Op51E1 }, { Op52E1 }, { Op53M1 }, { Op54X1 }, + { Op55E1 }, { Op56E1 }, { Op57M1 }, { Op58 }, { Op59M1X1 }, + { Op5AE1 }, { Op5B }, { Op5C }, { Op5DM1X1 }, { Op5EM1X1 }, + { Op5FM1 }, { Op60E1 }, { Op61E1 }, { Op62E1 }, { Op63M1 }, + { Op64M1 }, { Op65M1 }, { Op66M1 }, { Op67M1 }, { Op68E1 }, + { Op69M1 }, { Op6AM1 }, { Op6BE1 }, { Op6C }, { Op6DM1 }, + { Op6EM1 }, { Op6FM1 }, { Op70E1 }, { Op71E1 }, { Op72E1 }, + { Op73M1 }, { Op74E1 }, { Op75E1 }, { Op76E1 }, { Op77M1 }, + { Op78 }, { Op79M1X1 }, { Op7AE1 }, { Op7B }, { Op7C }, + { Op7DM1X1 }, { Op7EM1X1 }, { Op7FM1 }, { Op80E1 }, { Op81E1 }, + { Op82 }, { Op83M1 }, { Op84X1 }, { Op85M1 }, { Op86X1 }, + { Op87M1 }, { Op88X1 }, { Op89M1 }, { Op8AM1 }, { Op8BE1 }, + { Op8CX1 }, { Op8DM1 }, { Op8EX1 }, { Op8FM1 }, { Op90E1 }, + { Op91E1 }, { Op92E1 }, { Op93M1 }, { Op94E1 }, { Op95E1 }, + { Op96E1 }, { Op97M1 }, { Op98M1 }, { Op99M1X1 }, { Op9A }, + { Op9BX1 }, { Op9CM1 }, { Op9DM1X1 }, { Op9EM1X1 }, { Op9FM1 }, + { OpA0X1 }, { OpA1E1 }, { OpA2X1 }, { OpA3M1 }, { OpA4X1 }, + { OpA5M1 }, { OpA6X1 }, { OpA7M1 }, { OpA8X1 }, { OpA9M1 }, + { OpAAX1 }, { OpABE1 }, { OpACX1 }, { OpADM1 }, { OpAEX1 }, + { OpAFM1 }, { OpB0E1 }, { OpB1E1 }, { OpB2E1 }, { OpB3M1 }, + { OpB4E1 }, { OpB5E1 }, { OpB6E1 }, { OpB7M1 }, { OpB8 }, + { OpB9M1X1 }, { OpBAX1 }, { OpBBX1 }, { OpBCX1 }, { OpBDM1X1 }, + { OpBEX1 }, { OpBFM1 }, { OpC0X1 }, { OpC1E1 }, { OpC2 }, + { OpC3M1 }, { OpC4X1 }, { OpC5M1 }, { OpC6M1 }, { OpC7M1 }, + { OpC8X1 }, { OpC9M1 }, { OpCAX1 }, { OpCB }, { OpCCX1 }, + { OpCDM1 }, { OpCEM1 }, { OpCFM1 }, { OpD0E1 }, { OpD1E1 }, + { OpD2E1 }, { OpD3M1 }, { OpD4E1 }, { OpD5E1 }, { OpD6E1 }, + { OpD7M1 }, { OpD8 }, { OpD9M1X1 }, { OpDAE1 }, { OpDB }, + { OpDC }, { OpDDM1X1 }, { OpDEM1X1 }, { OpDFM1 }, { OpE0X1 }, + { OpE1E1 }, { OpE2 }, { OpE3M1 }, { OpE4X1 }, { OpE5M1 }, + { OpE6M1 }, { OpE7M1 }, { OpE8X1 }, { OpE9M1 }, { OpEA }, + { OpEB }, { OpECX1 }, { OpEDM1 }, { OpEEM1 }, { OpEFM1 }, + { OpF0E1 }, { OpF1E1 }, { OpF2E1 }, { OpF3M1 }, { OpF4E1 }, + { OpF5E1 }, { OpF6E1 }, { OpF7M1 }, { OpF8 }, { OpF9M1X1 }, + { OpFAE1 }, { OpFB }, { OpFCE1 }, { OpFDM1X1 }, { OpFEM1X1 }, + { OpFFM1 } +}; + +struct SOpcodes S9xOpcodesM1X0[256] = +{ + { Op00 }, { Op01E0M1 }, { Op02 }, { Op03M1 }, { Op04M1 }, + { Op05M1 }, { Op06M1 }, { Op07M1 }, { Op08E0 }, { Op09M1 }, + { Op0AM1 }, { Op0BE0 }, { Op0CM1 }, { Op0DM1 }, { Op0EM1 }, + { Op0FM1 }, { Op10E0 }, { Op11E0M1X0 }, { Op12E0M1 }, { Op13M1 }, + { Op14M1 }, { Op15E0M1 }, { Op16E0M1 }, { Op17M1 }, { Op18 }, + { Op19M1X0 }, { Op1AM1 }, { Op1B }, { Op1CM1 }, { Op1DM1X0 }, + { Op1EM1X0 }, { Op1FM1 }, { Op20E0 }, { Op21E0M1 }, { Op22E0 }, + { Op23M1 }, { Op24M1 }, { Op25M1 }, { Op26M1 }, { Op27M1 }, + { Op28E0 }, { Op29M1 }, { Op2AM1 }, { Op2BE0 }, { Op2CM1 }, + { Op2DM1 }, { Op2EM1 }, { Op2FM1 }, { Op30E0 }, { Op31E0M1X0 }, + { Op32E0M1 }, { Op33M1 }, { Op34E0M1 }, { Op35E0M1 }, { Op36E0M1 }, + { Op37M1 }, { Op38 }, { Op39M1X0 }, { Op3AM1 }, { Op3B }, + { Op3CM1X0 }, { Op3DM1X0 }, { Op3EM1X0 }, { Op3FM1 }, { Op40Slow }, + { Op41E0M1 }, { Op42 }, { Op43M1 }, { Op44X0 }, { Op45M1 }, + { Op46M1 }, { Op47M1 }, { Op48E0M1 }, { Op49M1 }, { Op4AM1 }, + { Op4BE0 }, { Op4C }, { Op4DM1 }, { Op4EM1 }, { Op4FM1 }, + { Op50E0 }, { Op51E0M1X0 }, { Op52E0M1 }, { Op53M1 }, { Op54X0 }, + { Op55E0M1 }, { Op56E0M1 }, { Op57M1 }, { Op58 }, { Op59M1X0 }, + { Op5AE0X0 }, { Op5B }, { Op5C }, { Op5DM1X0 }, { Op5EM1X0 }, + { Op5FM1 }, { Op60E0 }, { Op61E0M1 }, { Op62E0 }, { Op63M1 }, + { Op64M1 }, { Op65M1 }, { Op66M1 }, { Op67M1 }, { Op68E0M1 }, + { Op69M1 }, { Op6AM1 }, { Op6BE0 }, { Op6C }, { Op6DM1 }, + { Op6EM1 }, { Op6FM1 }, { Op70E0 }, { Op71E0M1X0 }, { Op72E0M1 }, + { Op73M1 }, { Op74E0M1 }, { Op75E0M1 }, { Op76E0M1 }, { Op77M1 }, + { Op78 }, { Op79M1X0 }, { Op7AE0X0 }, { Op7B }, { Op7C }, + { Op7DM1X0 }, { Op7EM1X0 }, { Op7FM1 }, { Op80E0 }, { Op81E0M1 }, + { Op82 }, { Op83M1 }, { Op84X0 }, { Op85M1 }, { Op86X0 }, + { Op87M1 }, { Op88X0 }, { Op89M1 }, { Op8AM1 }, { Op8BE0 }, + { Op8CX0 }, { Op8DM1 }, { Op8EX0 }, { Op8FM1 }, { Op90E0 }, + { Op91E0M1X0 }, { Op92E0M1 }, { Op93M1 }, { Op94E0X0 }, { Op95E0M1 }, + { Op96E0X0 }, { Op97M1 }, { Op98M1 }, { Op99M1X0 }, { Op9A }, + { Op9BX0 }, { Op9CM1 }, { Op9DM1X0 }, { Op9EM1X0 }, { Op9FM1 }, + { OpA0X0 }, { OpA1E0M1 }, { OpA2X0 }, { OpA3M1 }, { OpA4X0 }, + { OpA5M1 }, { OpA6X0 }, { OpA7M1 }, { OpA8X0 }, { OpA9M1 }, + { OpAAX0 }, { OpABE0 }, { OpACX0 }, { OpADM1 }, { OpAEX0 }, + { OpAFM1 }, { OpB0E0 }, { OpB1E0M1X0 }, { OpB2E0M1 }, { OpB3M1 }, + { OpB4E0X0 }, { OpB5E0M1 }, { OpB6E0X0 }, { OpB7M1 }, { OpB8 }, + { OpB9M1X0 }, { OpBAX0 }, { OpBBX0 }, { OpBCX0 }, { OpBDM1X0 }, + { OpBEX0 }, { OpBFM1 }, { OpC0X0 }, { OpC1E0M1 }, { OpC2 }, + { OpC3M1 }, { OpC4X0 }, { OpC5M1 }, { OpC6M1 }, { OpC7M1 }, + { OpC8X0 }, { OpC9M1 }, { OpCAX0 }, { OpCB }, { OpCCX0 }, + { OpCDM1 }, { OpCEM1 }, { OpCFM1 }, { OpD0E0 }, { OpD1E0M1X0 }, + { OpD2E0M1 }, { OpD3M1 }, { OpD4E0 }, { OpD5E0M1 }, { OpD6E0M1 }, + { OpD7M1 }, { OpD8 }, { OpD9M1X0 }, { OpDAE0X0 }, { OpDB }, + { OpDC }, { OpDDM1X0 }, { OpDEM1X0 }, { OpDFM1 }, { OpE0X0 }, + { OpE1E0M1 }, { OpE2 }, { OpE3M1 }, { OpE4X0 }, { OpE5M1 }, + { OpE6M1 }, { OpE7M1 }, { OpE8X0 }, { OpE9M1 }, { OpEA }, + { OpEB }, { OpECX0 }, { OpEDM1 }, { OpEEM1 }, { OpEFM1 }, + { OpF0E0 }, { OpF1E0M1X0 }, { OpF2E0M1 }, { OpF3M1 }, { OpF4E0 }, + { OpF5E0M1 }, { OpF6E0M1 }, { OpF7M1 }, { OpF8 }, { OpF9M1X0 }, + { OpFAE0X0 }, { OpFB }, { OpFCE0 }, { OpFDM1X0 }, { OpFEM1X0 }, + { OpFFM1 } +}; + +struct SOpcodes S9xOpcodesM0X0[256] = +{ + { Op00 }, { Op01E0M0 }, { Op02 }, { Op03M0 }, { Op04M0 }, + { Op05M0 }, { Op06M0 }, { Op07M0 }, { Op08E0 }, { Op09M0 }, + { Op0AM0 }, { Op0BE0 }, { Op0CM0 }, { Op0DM0 }, { Op0EM0 }, + { Op0FM0 }, { Op10E0 }, { Op11E0M0X0 }, { Op12E0M0 }, { Op13M0 }, + { Op14M0 }, { Op15E0M0 }, { Op16E0M0 }, { Op17M0 }, { Op18 }, + { Op19M0X0 }, { Op1AM0 }, { Op1B }, { Op1CM0 }, { Op1DM0X0 }, + { Op1EM0X0 }, { Op1FM0 }, { Op20E0 }, { Op21E0M0 }, { Op22E0 }, + { Op23M0 }, { Op24M0 }, { Op25M0 }, { Op26M0 }, { Op27M0 }, + { Op28E0 }, { Op29M0 }, { Op2AM0 }, { Op2BE0 }, { Op2CM0 }, + { Op2DM0 }, { Op2EM0 }, { Op2FM0 }, { Op30E0 }, { Op31E0M0X0 }, + { Op32E0M0 }, { Op33M0 }, { Op34E0M0 }, { Op35E0M0 }, { Op36E0M0 }, + { Op37M0 }, { Op38 }, { Op39M0X0 }, { Op3AM0 }, { Op3B }, + { Op3CM0X0 }, { Op3DM0X0 }, { Op3EM0X0 }, { Op3FM0 }, { Op40Slow }, + { Op41E0M0 }, { Op42 }, { Op43M0 }, { Op44X0 }, { Op45M0 }, + { Op46M0 }, { Op47M0 }, { Op48E0M0 }, { Op49M0 }, { Op4AM0 }, + { Op4BE0 }, { Op4C }, { Op4DM0 }, { Op4EM0 }, { Op4FM0 }, + { Op50E0 }, { Op51E0M0X0 }, { Op52E0M0 }, { Op53M0 }, { Op54X0 }, + { Op55E0M0 }, { Op56E0M0 }, { Op57M0 }, { Op58 }, { Op59M0X0 }, + { Op5AE0X0 }, { Op5B }, { Op5C }, { Op5DM0X0 }, { Op5EM0X0 }, + { Op5FM0 }, { Op60E0 }, { Op61E0M0 }, { Op62E0 }, { Op63M0 }, + { Op64M0 }, { Op65M0 }, { Op66M0 }, { Op67M0 }, { Op68E0M0 }, + { Op69M0 }, { Op6AM0 }, { Op6BE0 }, { Op6C }, { Op6DM0 }, + { Op6EM0 }, { Op6FM0 }, { Op70E0 }, { Op71E0M0X0 }, { Op72E0M0 }, + { Op73M0 }, { Op74E0M0 }, { Op75E0M0 }, { Op76E0M0 }, { Op77M0 }, + { Op78 }, { Op79M0X0 }, { Op7AE0X0 }, { Op7B }, { Op7C }, + { Op7DM0X0 }, { Op7EM0X0 }, { Op7FM0 }, { Op80E0 }, { Op81E0M0 }, + { Op82 }, { Op83M0 }, { Op84X0 }, { Op85M0 }, { Op86X0 }, + { Op87M0 }, { Op88X0 }, { Op89M0 }, { Op8AM0 }, { Op8BE0 }, + { Op8CX0 }, { Op8DM0 }, { Op8EX0 }, { Op8FM0 }, { Op90E0 }, + { Op91E0M0X0 }, { Op92E0M0 }, { Op93M0 }, { Op94E0X0 }, { Op95E0M0 }, + { Op96E0X0 }, { Op97M0 }, { Op98M0 }, { Op99M0X0 }, { Op9A }, + { Op9BX0 }, { Op9CM0 }, { Op9DM0X0 }, { Op9EM0X0 }, { Op9FM0 }, + { OpA0X0 }, { OpA1E0M0 }, { OpA2X0 }, { OpA3M0 }, { OpA4X0 }, + { OpA5M0 }, { OpA6X0 }, { OpA7M0 }, { OpA8X0 }, { OpA9M0 }, + { OpAAX0 }, { OpABE0 }, { OpACX0 }, { OpADM0 }, { OpAEX0 }, + { OpAFM0 }, { OpB0E0 }, { OpB1E0M0X0 }, { OpB2E0M0 }, { OpB3M0 }, + { OpB4E0X0 }, { OpB5E0M0 }, { OpB6E0X0 }, { OpB7M0 }, { OpB8 }, + { OpB9M0X0 }, { OpBAX0 }, { OpBBX0 }, { OpBCX0 }, { OpBDM0X0 }, + { OpBEX0 }, { OpBFM0 }, { OpC0X0 }, { OpC1E0M0 }, { OpC2 }, + { OpC3M0 }, { OpC4X0 }, { OpC5M0 }, { OpC6M0 }, { OpC7M0 }, + { OpC8X0 }, { OpC9M0 }, { OpCAX0 }, { OpCB }, { OpCCX0 }, + { OpCDM0 }, { OpCEM0 }, { OpCFM0 }, { OpD0E0 }, { OpD1E0M0X0 }, + { OpD2E0M0 }, { OpD3M0 }, { OpD4E0 }, { OpD5E0M0 }, { OpD6E0M0 }, + { OpD7M0 }, { OpD8 }, { OpD9M0X0 }, { OpDAE0X0 }, { OpDB }, + { OpDC }, { OpDDM0X0 }, { OpDEM0X0 }, { OpDFM0 }, { OpE0X0 }, + { OpE1E0M0 }, { OpE2 }, { OpE3M0 }, { OpE4X0 }, { OpE5M0 }, + { OpE6M0 }, { OpE7M0 }, { OpE8X0 }, { OpE9M0 }, { OpEA }, + { OpEB }, { OpECX0 }, { OpEDM0 }, { OpEEM0 }, { OpEFM0 }, + { OpF0E0 }, { OpF1E0M0X0 }, { OpF2E0M0 }, { OpF3M0 }, { OpF4E0 }, + { OpF5E0M0 }, { OpF6E0M0 }, { OpF7M0 }, { OpF8 }, { OpF9M0X0 }, + { OpFAE0X0 }, { OpFB }, { OpFCE0 }, { OpFDM0X0 }, { OpFEM0X0 }, + { OpFFM0 } +}; + +struct SOpcodes S9xOpcodesM0X1[256] = +{ + { Op00 }, { Op01E0M0 }, { Op02 }, { Op03M0 }, { Op04M0 }, + { Op05M0 }, { Op06M0 }, { Op07M0 }, { Op08E0 }, { Op09M0 }, + { Op0AM0 }, { Op0BE0 }, { Op0CM0 }, { Op0DM0 }, { Op0EM0 }, + { Op0FM0 }, { Op10E0 }, { Op11E0M0X1 }, { Op12E0M0 }, { Op13M0 }, + { Op14M0 }, { Op15E0M0 }, { Op16E0M0 }, { Op17M0 }, { Op18 }, + { Op19M0X1 }, { Op1AM0 }, { Op1B }, { Op1CM0 }, { Op1DM0X1 }, + { Op1EM0X1 }, { Op1FM0 }, { Op20E0 }, { Op21E0M0 }, { Op22E0 }, + { Op23M0 }, { Op24M0 }, { Op25M0 }, { Op26M0 }, { Op27M0 }, + { Op28E0 }, { Op29M0 }, { Op2AM0 }, { Op2BE0 }, { Op2CM0 }, + { Op2DM0 }, { Op2EM0 }, { Op2FM0 }, { Op30E0 }, { Op31E0M0X1 }, + { Op32E0M0 }, { Op33M0 }, { Op34E0M0 }, { Op35E0M0 }, { Op36E0M0 }, + { Op37M0 }, { Op38 }, { Op39M0X1 }, { Op3AM0 }, { Op3B }, + { Op3CM0X1 }, { Op3DM0X1 }, { Op3EM0X1 }, { Op3FM0 }, { Op40Slow }, + { Op41E0M0 }, { Op42 }, { Op43M0 }, { Op44X1 }, { Op45M0 }, + { Op46M0 }, { Op47M0 }, { Op48E0M0 }, { Op49M0 }, { Op4AM0 }, + { Op4BE0 }, { Op4C }, { Op4DM0 }, { Op4EM0 }, { Op4FM0 }, + { Op50E0 }, { Op51E0M0X1 }, { Op52E0M0 }, { Op53M0 }, { Op54X1 }, + { Op55E0M0 }, { Op56E0M0 }, { Op57M0 }, { Op58 }, { Op59M0X1 }, + { Op5AE0X1 }, { Op5B }, { Op5C }, { Op5DM0X1 }, { Op5EM0X1 }, + { Op5FM0 }, { Op60E0 }, { Op61E0M0 }, { Op62E0 }, { Op63M0 }, + { Op64M0 }, { Op65M0 }, { Op66M0 }, { Op67M0 }, { Op68E0M0 }, + { Op69M0 }, { Op6AM0 }, { Op6BE0 }, { Op6C }, { Op6DM0 }, + { Op6EM0 }, { Op6FM0 }, { Op70E0 }, { Op71E0M0X1 }, { Op72E0M0 }, + { Op73M0 }, { Op74E0M0 }, { Op75E0M0 }, { Op76E0M0 }, { Op77M0 }, + { Op78 }, { Op79M0X1 }, { Op7AE0X1 }, { Op7B }, { Op7C }, + { Op7DM0X1 }, { Op7EM0X1 }, { Op7FM0 }, { Op80E0 }, { Op81E0M0 }, + { Op82 }, { Op83M0 }, { Op84X1 }, { Op85M0 }, { Op86X1 }, + { Op87M0 }, { Op88X1 }, { Op89M0 }, { Op8AM0 }, { Op8BE0 }, + { Op8CX1 }, { Op8DM0 }, { Op8EX1 }, { Op8FM0 }, { Op90E0 }, + { Op91E0M0X1 }, { Op92E0M0 }, { Op93M0 }, { Op94E0X1 }, { Op95E0M0 }, + { Op96E0X1 }, { Op97M0 }, { Op98M0 }, { Op99M0X1 }, { Op9A }, + { Op9BX1 }, { Op9CM0 }, { Op9DM0X1 }, { Op9EM0X1 }, { Op9FM0 }, + { OpA0X1 }, { OpA1E0M0 }, { OpA2X1 }, { OpA3M0 }, { OpA4X1 }, + { OpA5M0 }, { OpA6X1 }, { OpA7M0 }, { OpA8X1 }, { OpA9M0 }, + { OpAAX1 }, { OpABE0 }, { OpACX1 }, { OpADM0 }, { OpAEX1 }, + { OpAFM0 }, { OpB0E0 }, { OpB1E0M0X1 }, { OpB2E0M0 }, { OpB3M0 }, + { OpB4E0X1 }, { OpB5E0M0 }, { OpB6E0X1 }, { OpB7M0 }, { OpB8 }, + { OpB9M0X1 }, { OpBAX1 }, { OpBBX1 }, { OpBCX1 }, { OpBDM0X1 }, + { OpBEX1 }, { OpBFM0 }, { OpC0X1 }, { OpC1E0M0 }, { OpC2 }, + { OpC3M0 }, { OpC4X1 }, { OpC5M0 }, { OpC6M0 }, { OpC7M0 }, + { OpC8X1 }, { OpC9M0 }, { OpCAX1 }, { OpCB }, { OpCCX1 }, + { OpCDM0 }, { OpCEM0 }, { OpCFM0 }, { OpD0E0 }, { OpD1E0M0X1 }, + { OpD2E0M0 }, { OpD3M0 }, { OpD4E0 }, { OpD5E0M0 }, { OpD6E0M0 }, + { OpD7M0 }, { OpD8 }, { OpD9M0X1 }, { OpDAE0X1 }, { OpDB }, + { OpDC }, { OpDDM0X1 }, { OpDEM0X1 }, { OpDFM0 }, { OpE0X1 }, + { OpE1E0M0 }, { OpE2 }, { OpE3M0 }, { OpE4X1 }, { OpE5M0 }, + { OpE6M0 }, { OpE7M0 }, { OpE8X1 }, { OpE9M0 }, { OpEA }, + { OpEB }, { OpECX1 }, { OpEDM0 }, { OpEEM0 }, { OpEFM0 }, + { OpF0E0 }, { OpF1E0M0X1 }, { OpF2E0M0 }, { OpF3M0 }, { OpF4E0 }, + { OpF5E0M0 }, { OpF6E0M0 }, { OpF7M0 }, { OpF8 }, { OpF9M0X1 }, + { OpFAE0X1 }, { OpFB }, { OpFCE0 }, { OpFDM0X1 }, { OpFEM0X1 }, + { OpFFM0 } +}; + +struct SOpcodes S9xOpcodesSlow[256] = +{ + { Op00 }, { Op01Slow }, { Op02 }, { Op03Slow }, { Op04Slow }, + { Op05Slow }, { Op06Slow }, { Op07Slow }, { Op08Slow }, { Op09Slow }, + { Op0ASlow }, { Op0BSlow }, { Op0CSlow }, { Op0DSlow }, { Op0ESlow }, + { Op0FSlow }, { Op10Slow }, { Op11Slow }, { Op12Slow }, { Op13Slow }, + { Op14Slow }, { Op15Slow }, { Op16Slow }, { Op17Slow }, { Op18 }, + { Op19Slow }, { Op1ASlow }, { Op1B }, { Op1CSlow }, { Op1DSlow }, + { Op1ESlow }, { Op1FSlow }, { Op20Slow }, { Op21Slow }, { Op22Slow }, + { Op23Slow }, { Op24Slow }, { Op25Slow }, { Op26Slow }, { Op27Slow }, + { Op28Slow }, { Op29Slow }, { Op2ASlow }, { Op2BSlow }, { Op2CSlow }, + { Op2DSlow }, { Op2ESlow }, { Op2FSlow }, { Op30Slow }, { Op31Slow }, + { Op32Slow }, { Op33Slow }, { Op34Slow }, { Op35Slow }, { Op36Slow }, + { Op37Slow }, { Op38 }, { Op39Slow }, { Op3ASlow }, { Op3B }, + { Op3CSlow }, { Op3DSlow }, { Op3ESlow }, { Op3FSlow }, { Op40Slow }, + { Op41Slow }, { Op42 }, { Op43Slow }, { Op44Slow }, { Op45Slow }, + { Op46Slow }, { Op47Slow }, { Op48Slow }, { Op49Slow }, { Op4ASlow }, + { Op4BSlow }, { Op4CSlow }, { Op4DSlow }, { Op4ESlow }, { Op4FSlow }, + { Op50Slow }, { Op51Slow }, { Op52Slow }, { Op53Slow }, { Op54Slow }, + { Op55Slow }, { Op56Slow }, { Op57Slow }, { Op58 }, { Op59Slow }, + { Op5ASlow }, { Op5B }, { Op5CSlow }, { Op5DSlow }, { Op5ESlow }, + { Op5FSlow }, { Op60Slow }, { Op61Slow }, { Op62Slow }, { Op63Slow }, + { Op64Slow }, { Op65Slow }, { Op66Slow }, { Op67Slow }, { Op68Slow }, + { Op69Slow }, { Op6ASlow }, { Op6BSlow }, { Op6CSlow }, { Op6DSlow }, + { Op6ESlow }, { Op6FSlow }, { Op70Slow }, { Op71Slow }, { Op72Slow }, + { Op73Slow }, { Op74Slow }, { Op75Slow }, { Op76Slow }, { Op77Slow }, + { Op78 }, { Op79Slow }, { Op7ASlow }, { Op7B }, { Op7CSlow }, + { Op7DSlow }, { Op7ESlow }, { Op7FSlow }, { Op80Slow }, { Op81Slow }, + { Op82Slow }, { Op83Slow }, { Op84Slow }, { Op85Slow }, { Op86Slow }, + { Op87Slow }, { Op88Slow }, { Op89Slow }, { Op8ASlow }, { Op8BSlow }, + { Op8CSlow }, { Op8DSlow }, { Op8ESlow }, { Op8FSlow }, { Op90Slow }, + { Op91Slow }, { Op92Slow }, { Op93Slow }, { Op94Slow }, { Op95Slow }, + { Op96Slow }, { Op97Slow }, { Op98Slow }, { Op99Slow }, { Op9A }, + { Op9BSlow }, { Op9CSlow }, { Op9DSlow }, { Op9ESlow }, { Op9FSlow }, + { OpA0Slow }, { OpA1Slow }, { OpA2Slow }, { OpA3Slow }, { OpA4Slow }, + { OpA5Slow }, { OpA6Slow }, { OpA7Slow }, { OpA8Slow }, { OpA9Slow }, + { OpAASlow }, { OpABSlow }, { OpACSlow }, { OpADSlow }, { OpAESlow }, + { OpAFSlow }, { OpB0Slow }, { OpB1Slow }, { OpB2Slow }, { OpB3Slow }, + { OpB4Slow }, { OpB5Slow }, { OpB6Slow }, { OpB7Slow }, { OpB8 }, + { OpB9Slow }, { OpBASlow }, { OpBBSlow }, { OpBCSlow }, { OpBDSlow }, + { OpBESlow }, { OpBFSlow }, { OpC0Slow }, { OpC1Slow }, { OpC2Slow }, + { OpC3Slow }, { OpC4Slow }, { OpC5Slow }, { OpC6Slow }, { OpC7Slow }, + { OpC8Slow }, { OpC9Slow }, { OpCASlow }, { OpCB }, { OpCCSlow }, + { OpCDSlow }, { OpCESlow }, { OpCFSlow }, { OpD0Slow }, { OpD1Slow }, + { OpD2Slow }, { OpD3Slow }, { OpD4Slow }, { OpD5Slow }, { OpD6Slow }, + { OpD7Slow }, { OpD8 }, { OpD9Slow }, { OpDASlow }, { OpDB }, + { OpDCSlow }, { OpDDSlow }, { OpDESlow }, { OpDFSlow }, { OpE0Slow }, + { OpE1Slow }, { OpE2Slow }, { OpE3Slow }, { OpE4Slow }, { OpE5Slow }, + { OpE6Slow }, { OpE7Slow }, { OpE8Slow }, { OpE9Slow }, { OpEA }, + { OpEB }, { OpECSlow }, { OpEDSlow }, { OpEESlow }, { OpEFSlow }, + { OpF0Slow }, { OpF1Slow }, { OpF2Slow }, { OpF3Slow }, { OpF4Slow }, + { OpF5Slow }, { OpF6Slow }, { OpF7Slow }, { OpF8 }, { OpF9Slow }, + { OpFASlow }, { OpFB }, { OpFCSlow }, { OpFDSlow }, { OpFESlow }, + { OpFFSlow } +}; + diff --git a/plugins/snes9x_gx/source/snes9x/cpuops.h b/plugins/snes9x_gx/source/snes9x/cpuops.h new file mode 100644 index 00000000..acb34060 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/cpuops.h @@ -0,0 +1,188 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _CPUOPS_H_ +#define _CPUOPS_H_ + +void S9xOpcode_NMI (void); +void S9xOpcode_IRQ (void); + +#define CHECK_FOR_IRQ() \ +if (CPU.IRQActive && !CheckFlag(IRQ) && !Settings.DisableIRQ) \ + S9xOpcode_IRQ() + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/crosshairs.cpp b/plugins/snes9x_gx/source/snes9x/crosshairs.cpp new file mode 100644 index 00000000..7c3f3851 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/crosshairs.cpp @@ -0,0 +1,682 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifdef HAVE_LIBPNG +#include <png.h> +#endif +#include "port.h" +#include "crosshairs.h" + +static const char *crosshairs[32] = +{ + "` " // Crosshair 0 (no image) + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " ", + + "` " // Crosshair 1 (the classic small dot) + " " + " " + " " + " " + " " + " " + " #. " + " " + " " + " " + " " + " " + " " + " ", + + "` " // Crosshair 2 (a standard cross) + " " + " " + " " + " .#. " + " .#. " + " ...#... " + " ####### " + " ...#... " + " .#. " + " .#. " + " " + " " + " " + " ", + + "` .#. " // Crosshair 3 (a standard cross) + " .#. " + " .#. " + " .#. " + " .#. " + " .#. " + ".......#......." + "###############" + ".......#......." + " .#. " + " .#. " + " .#. " + " .#. " + " .#. " + " .#. ", + + "` " // Crosshair 4 (an X) + " " + " " + " . . " + " .#. .#. " + " .#. .#. " + " .#.#. " + " .#. " + " .#.#. " + " .#. .#. " + " .#. .#. " + " . . " + " " + " " + " ", + + "`. . " // Crosshair 5 (an X) + ".#. .#." + " .#. .#. " + " .#. .#. " + " .#. .#. " + " .#. .#. " + " .#.#. " + " .#. " + " .#.#. " + " .#. .#. " + " .#. .#. " + " .#. .#. " + " .#. .#. " + ".#. .#." + " . . ", + + "` " // Crosshair 6 (a combo) + " " + " " + " " + " # . # " + " # . # " + " #.# " + " ...#... " + " #.# " + " # . # " + " # . # " + " " + " " + " " + " ", + + "` . " // Crosshair 7 (a combo) + " # . # " + " # . # " + " # . # " + " # . # " + " # . # " + " #.# " + ".......#......." + " #.# " + " # . # " + " # . # " + " # . # " + " # . # " + " # . # " + " . ", + + "` # " // Crosshair 8 (a diamond cross) + " #.# " + " # . # " + " # . # " + " # . # " + " # . # " + " # . # " + "#......#......#" + " # . # " + " # . # " + " # . # " + " # . # " + " # . # " + " #.# " + " # ", + + "` ### " // Crosshair 9 (a circle cross) + " ## . ## " + " # . # " + " # . # " + " # . # " + " # . # " + "# . #" + "#......#......#" + "# . #" + " # . # " + " # . # " + " # . # " + " # . # " + " ## . ## " + " ### ", + + "` .#. " // Crosshair 10 (a square cross) + " .#. " + " .#. " + " ....#.... " + " .#######. " + " .# #. " + "....# #...." + "##### #####" + "....# #...." + " .# #. " + " .#######. " + " ....#.... " + " .#. " + " .#. " + " .#. ", + + "` .#. " // Crosshair 11 (an interrupted cross) + " .#. " + " .#. " + " .#. " + " .#. " + " " + "..... ....." + "##### #####" + "..... ....." + " " + " .#. " + " .#. " + " .#. " + " .#. " + " .#. ", + + "`. . " // Crosshair 12 (an interrupted X) + ".#. .#." + " .#. .#. " + " .#. .#. " + " .#. .#. " + " " + " " + " " + " " + " " + " .#. .#. " + " .#. .#. " + " .#. .#. " + ".#. .#." + " . . ", + + "` . " // Crosshair 13 (an interrupted combo) + " # . # " + " # . # " + " # . # " + " # . # " + " " + " " + "..... ....." + " " + " " + " # . # " + " # . # " + " # . # " + " # . # " + " . ", + + "`#### #### " // Crosshair 14 + "#.... ....#" + "#. .#" + "#. .#" + "#. .#" + " # " + " # " + " ##### " + " # " + " # " + "#. .#" + "#. .#" + "#. .#" + "#.... ....#" + " #### #### ", + + "` .# #. " // Crosshair 15 + " .# #. " + " .# #. " + "....# #...." + "##### #####" + " " + " " + " " + " " + " " + "##### #####" + "....# #...." + " .# #. " + " .# #. " + " .# #. ", + + "` # " // Crosshair 16 + " # " + " # " + " ....#.... " + " . # . " + " . # . " + " . # . " + "###############" + " . # . " + " . # . " + " . # . " + " ....#.... " + " # " + " # " + " # ", + + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + + +bool S9xLoadCrosshairFile (int idx, const char *filename) +{ + if (idx < 1 || idx > 31) + return (false); + + char *s = (char *) calloc(15 * 15 + 1, sizeof(char)); + if (s == NULL) + { + fprintf(stderr, "S9xLoadCrosshairFile: malloc error while reading "); + perror(filename); + return (false); + } + + FILE *fp = fopen(filename, "rb"); + if (fp == NULL) + { + fprintf(stderr, "S9xLoadCrosshairFile: Couldn't open "); + perror(filename); + free(s); + return (false); + } + + size_t l = fread(s, 1, 8, fp); + if (l != 8) + { + fprintf(stderr, "S9xLoadCrosshairFile: File is too short!\n"); + free(s); + fclose(fp); + return (false); + } + +#ifdef HAVE_LIBPNG + png_structp png_ptr; + png_infop info_ptr; + + if (!png_sig_cmp((png_byte *) s, 0, 8)) + { + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + { + free(s); + fclose(fp); + return (false); + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); + free(s); + fclose(fp); + return (false); + } + + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); + png_read_info(png_ptr, info_ptr); + + png_uint_32 width, height; + int bit_depth, color_type; + + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); + if (color_type != PNG_COLOR_TYPE_PALETTE) + { + fprintf(stderr, "S9xLoadCrosshairFile: Input PNG is not a palettized image!\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + free(s); + fclose(fp); + return (false); + } + + if (bit_depth == 16) + png_set_strip_16(png_ptr); + + if (width != 15 || height != 15) + { + fprintf(stderr, "S9xLoadCrosshairFile: Expecting a 15x15 PNG\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + free(s); + fclose(fp); + return (false); + } + + png_color *pngpal; + png_byte *trans; + int num_palette = 0, num_trans = 0; + int transcol = -1, fgcol = -1, bgcol = -1; + + png_get_PLTE(png_ptr, info_ptr, &pngpal, &num_palette); + png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); + + if (num_palette != 3 || num_trans != 1) + { + fprintf(stderr, "S9xLoadCrosshairFile: Expecting a 3-color PNG with 1 trasnparent color\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + free(s); + fclose(fp); + return (false); + } + + for (int i = 0; i < 3; i++) + { + if (trans[0] == i) + transcol = i; + else + if (pngpal[i].red == 0 && pngpal[i].green == 0 && pngpal[i].blue == 0) + bgcol = i; + else + if (pngpal[i].red == 255 && pngpal[i].green == 255 && pngpal[i].blue == 255) + fgcol = i; + } + + if (transcol < 0 || fgcol < 0 || bgcol < 0) + { + fprintf(stderr, "S9xLoadCrosshairFile: PNG must have 3 colors: white (fg), black (bg), and transparent.\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + free(s); + fclose(fp); + return (false); + } + + png_set_packing(png_ptr); + png_read_update_info(png_ptr, info_ptr); + png_byte *row_pointer = new png_byte[png_get_rowbytes(png_ptr, info_ptr)]; + + for (int r = 0; r < 15 * 15; r += 15) + { + png_read_row(png_ptr, row_pointer, NULL); + + for (int i = 0; i < 15; i++) + { + if (row_pointer[i] == transcol) + s[r + i] = ' '; + else + if (row_pointer[i] == fgcol) + s[r + i] = '#'; + else + if (row_pointer[i] == bgcol) + s[r + i] = '.'; + else + { + fprintf(stderr, "S9xLoadCrosshairFile: WTF? This was supposed to be a 3-color PNG!\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + free(s); + fclose(fp); + return (false); + } + } + } + + s[15 * 15] = 0; + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + } + else +#endif + { + l = fread(s + 8, 1, 15 - 8, fp); + if (l != 15 - 8) + { + fprintf(stderr, "S9xLoadCrosshairFile: File is too short!\n"); + free(s); + fclose(fp); + return (false); + } + + if (getc(fp) != '\n') + { + fprintf(stderr, "S9xLoadCrosshairFile: Invalid file format! (note: PNG support is not available)\n"); + free(s); + fclose(fp); + return (false); + } + + for (int r = 1; r < 15; r++) + { + l = fread(s + r * 15, 1, 15, fp); + if (l != 15) + { + fprintf(stderr, "S9xLoadCrosshairFile: File is too short! (note: PNG support is not available)\n"); + free(s); + fclose(fp); + return (false); + } + + if (getc(fp) != '\n') + { + fprintf(stderr, "S9xLoadCrosshairFile: Invalid file format! (note: PNG support is not available)\n"); + free(s); + fclose(fp); + return (false); + } + } + + for (int i = 0; i < 15 * 15; i++) + { + if (s[i] != ' ' && s[i] != '#' && s[i] != '.') + { + fprintf(stderr, "S9xLoadCrosshairFile: Invalid file format! (note: PNG support is not available)\n"); + free(s); + fclose(fp); + return (false); + } + } + } + + fclose(fp); + + if (crosshairs[idx] != NULL && crosshairs[idx][0] != '`') + free((void *) crosshairs[idx]); + crosshairs[idx] = s; + + return (true); +} + +const char * S9xGetCrosshair (int idx) +{ + if (idx < 0 || idx > 31) + return (NULL); + + return (crosshairs[idx]); +} diff --git a/plugins/snes9x_gx/source/snes9x/crosshairs.h b/plugins/snes9x_gx/source/snes9x/crosshairs.h new file mode 100644 index 00000000..16c3811d --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/crosshairs.h @@ -0,0 +1,233 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _CROSSHAIRS_H_ +#define _CROSSHAIRS_H_ + +// Read in the specified crosshair file, replacing whatever data might be in that slot. +// Available slots are 1-31. +// The input file must be a PNG or a text file. +// PNG: 15x15 pixels, palettized, with 3 colors (white, black, and transparent). +// text: 15 lines of 16 characters (counting the \n), consisting of ' ', '#', or '.'. + +bool S9xLoadCrosshairFile (int idx, const char *filename); + +// Return the specified crosshair. Woo-hoo. +// char * to a 225-byte string, with '#' marking foreground, '.' marking background, +// and anything else transparent. + +const char * S9xGetCrosshair (int idx); + +// In controls.cpp. Sets the crosshair for the specified device. Defaults are: +// cross fgcolor bgcolor +// Mouse 1: 1 White Black +// Mouse 2: 1 Purple White +// Superscope: 2 White Black +// Justifier 1: 4 Blue Black +// Justifier 2: 4 MagicPink Black +// +// Available colors are: Trans, Black, 25Grey, 50Grey, 75Grey, White, Red, Orange, +// Yellow, Green, Cyan, Sky, Blue, Violet, MagicPink, and Purple. +// You may also prefix a 't' (e.g. tBlue) for a 50%-transparent version. +// Use idx = -1 or fg/bg = NULL to keep the current setting. + +enum crosscontrols +{ + X_MOUSE1, + X_MOUSE2, + X_SUPERSCOPE, + X_JUSTIFIER1, + X_JUSTIFIER2 +}; + +void S9xSetControllerCrosshair (enum crosscontrols ctl, int8 idx, const char *fg, const char *bg); +void S9xGetControllerCrosshair (enum crosscontrols ctl, int8 *idx, const char **fg, const char **bg); + +// In gfx.cpp, much like S9xDisplayChar() except it takes the parameters +// listed and looks up GFX.Screen. +// The 'crosshair' arg is a 15x15 image, with '#' meaning fgcolor, +// '.' meaning bgcolor, and anything else meaning transparent. +// Color values should be (RGB): +// 0 = transparent 4 = 23 23 23 8 = 31 31 0 12 = 0 0 31 +// 1 = 0 0 0 5 = 31 31 31 9 = 0 31 0 13 = 23 0 31 +// 2 = 8 8 8 6 = 31 0 0 10 = 0 31 31 14 = 31 0 31 +// 3 = 16 16 16 7 = 31 16 0 11 = 0 23 31 15 = 31 0 16 +// 16-31 are 50% transparent versions of 0-15. + +void S9xDrawCrosshair (const char *crosshair, uint8 fgcolor, uint8 bgcolor, int16 x, int16 y); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/display.h b/plugins/snes9x_gx/source/snes9x/display.h new file mode 100644 index 00000000..fa784088 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/display.h @@ -0,0 +1,235 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _DISPLAY_H_ +#define _DISPLAY_H_ + +enum s9x_getdirtype +{ + DEFAULT_DIR = 0, + HOME_DIR, + ROMFILENAME_DIR, + ROM_DIR, + SRAM_DIR, + SNAPSHOT_DIR, + SCREENSHOT_DIR, + SPC_DIR, + CHEAT_DIR, + IPS_DIR, + BIOS_DIR, + LOG_DIR, + LAST_DIR +}; + +void S9xUsage (void); +char * S9xParseArgs (char **, int); +void S9xLoadConfigFiles (char **, int); +void S9xSetInfoString (const char *); + +// Routines the port has to implement even if it doesn't use them + +void S9xPutImage (int, int); +void S9xInitDisplay (int, char **); +void S9xDeinitDisplay (void); +void S9xTextMode (void); +void S9xGraphicsMode (void); +void S9xSetPalette (void); +void S9xToggleSoundChannel (int); +bool8 S9xOpenSnapshotFile (const char *, bool8, STREAM *); +void S9xCloseSnapshotFile (STREAM); +const char * S9xStringInput (const char *); +const char * S9xGetDirectory (enum s9x_getdirtype); +const char * S9xGetFilename (const char *, enum s9x_getdirtype); +const char * S9xGetFilenameInc (const char *, enum s9x_getdirtype); +const char * S9xChooseFilename (bool8); +const char * S9xBasename (const char *); + +// Routines the port has to implement if it uses command-line + +void S9xExtraUsage (void); +void S9xParseArg (char **, int &, int); + +// Routines the port may implement as needed + +void S9xExtraDisplayUsage (void); +void S9xParseDisplayArg (char **, int &, int); +void S9xSetTitle (const char *); +void S9xInitInputDevices (void); +void S9xProcessEvents (bool8); +const char * S9xSelectFilename (const char *, const char *, const char *, const char *); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/dma.cpp b/plugins/snes9x_gx/source/snes9x/dma.cpp new file mode 100644 index 00000000..bd2c6f22 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/dma.cpp @@ -0,0 +1,1808 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "dma.h" +#include "apu/apu.h" +#include "sdd1emu.h" +#include "spc7110emu.h" +#ifdef DEBUGGER +#include "missing.h" +#endif + +#define ADD_CYCLES(n) CPU.Cycles += (n) + +extern uint8 *HDMAMemPointers[8]; +extern int HDMA_ModeByteCounts[8]; +extern SPC7110 s7emu; + +static uint8 sdd1_decode_buffer[0x10000]; + +static inline bool8 addCyclesInDMA (uint8); +static inline bool8 HDMAReadLineCount (int); + + +static inline bool8 addCyclesInDMA (uint8 dma_channel) +{ + // Add 8 cycles per byte, sync APU, and do HC related events. + // If HDMA was done in S9xDoHEventProcessing(), check if it used the same channel as DMA. + ADD_CYCLES(SLOW_ONE_CYCLE); + while (CPU.Cycles >= CPU.NextEvent) + S9xDoHEventProcessing(); + + if (CPU.HDMARanInDMA & (1 << dma_channel)) + { + CPU.HDMARanInDMA = 0; + #ifdef DEBUGGER + printf("HDMA and DMA use the same channel %d!\n", dma_channel); + #endif + // If HDMA triggers in the middle of DMA transfer and it uses the same channel, + // it kills the DMA transfer immediately. $43x2 and $43x5 stop updating. + return (FALSE); + } + + CPU.HDMARanInDMA = 0; + return (TRUE); +} + +bool8 S9xDoDMA (uint8 Channel) +{ + CPU.InDMA = TRUE; + CPU.InDMAorHDMA = TRUE; + CPU.CurrentDMAorHDMAChannel = Channel; + + SDMA *d = &DMA[Channel]; + + // Check invalid DMA first + if ((d->ABank == 0x7E || d->ABank == 0x7F) && d->BAddress == 0x80 && !d->ReverseTransfer) + { + // Attempting a DMA from WRAM to $2180 will not work, WRAM will not be written. + // Attempting a DMA from $2180 to WRAM will similarly not work, + // the value written is (initially) the OpenBus value. + // In either case, the address in $2181-3 is not incremented. + + // Does an invalid DMA actually take time? + // I'd say yes, since 'invalid' is probably just the WRAM chip + // not being able to read and write itself at the same time + // And no, PPU.WRAM should not be updated. + + int32 c = d->TransferBytes; + // Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0. + if (c == 0) + c = 0x10000; + + // 8 cycles per channel + ADD_CYCLES(SLOW_ONE_CYCLE); + // 8 cycles per byte + while (c) + { + d->TransferBytes--; + d->AAddress++; + c--; + if (!addCyclesInDMA(Channel)) + { + CPU.InDMA = FALSE; + CPU.InDMAorHDMA = FALSE; + CPU.CurrentDMAorHDMAChannel = -1; + return (FALSE); + } + } + + #ifdef DEBUGGER + if (Settings.TraceDMA) + { + sprintf(String, "DMA[%d]: WRAM Bank:%02X->$2180", Channel, d->ABank); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + } + #endif + + CPU.InDMA = FALSE; + CPU.InDMAorHDMA = FALSE; + CPU.CurrentDMAorHDMAChannel = -1; + return (TRUE); + } + + // Prepare for accessing $2118-2119 + switch (d->BAddress) + { + case 0x18: + case 0x19: + if (IPPU.RenderThisFrame) + FLUSH_REDRAW(); + break; + } + + int32 inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1); + int32 count = d->TransferBytes; + // Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0. + if (count == 0) + count = 0x10000; + + // Prepare for custom chip DMA + + // S-DD1 + + uint8 *in_sdd1_dma = NULL; + + if (Settings.SDD1) + { + if (d->AAddressFixed && Memory.FillRAM[0x4801] > 0) + { + // XXX: Should probably verify that we're DMAing from ROM? + // And somewhere we should make sure we're not running across a mapping boundary too. + // Hacky support for pre-decompressed S-DD1 data + inc = !d->AAddressDecrement ? 1 : -1; + + uint8 *in_ptr = S9xGetBasePointer(((d->ABank << 16) | d->AAddress)); + if (in_ptr) + { + in_ptr += d->AAddress; + SDD1_decompress(sdd1_decode_buffer, in_ptr, d->TransferBytes); + } + #ifdef DEBUGGER + else + { + sprintf(String, "S-DD1: DMA from non-block address $%02X:%04X", d->ABank, d->AAddress); + S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String); + } + #endif + + in_sdd1_dma = sdd1_decode_buffer; + } + + Memory.FillRAM[0x4801] = 0; + } + + // SPC7110 + + uint8 *spc7110_dma = NULL; + + if (Settings.SPC7110) + { + if (d->AAddress == 0x4800 || d->ABank == 0x50) + { + spc7110_dma = new uint8[d->TransferBytes]; + for (int i = 0; i < d->TransferBytes; i++) + spc7110_dma[i] = s7emu.decomp.read(); + + int32 icount = s7emu.r4809 | (s7emu.r480a << 8); + icount -= d->TransferBytes; + s7emu.r4809 = icount & 0x00ff; + s7emu.r480a = (icount & 0xff00) >> 8; + + inc = 1; + d->AAddress -= count; + } + } + + // SA-1 + + bool8 in_sa1_dma = FALSE; + + if (Settings.SA1) + { + if (SA1.in_char_dma && d->BAddress == 0x18 && (d->ABank & 0xf0) == 0x40) + { + // Perform packed bitmap to PPU character format conversion on the data + // before transmitting it to V-RAM via-DMA. + int32 num_chars = 1 << ((Memory.FillRAM[0x2231] >> 2) & 7); + int32 depth = (Memory.FillRAM[0x2231] & 3) == 0 ? 8 : (Memory.FillRAM[0x2231] & 3) == 1 ? 4 : 2; + int32 bytes_per_char = 8 * depth; + int32 bytes_per_line = depth * num_chars; + int32 char_line_bytes = bytes_per_char * num_chars; + uint32 addr = (d->AAddress / char_line_bytes) * char_line_bytes; + + uint8 *base = S9xGetBasePointer((d->ABank << 16) + addr); + if (!base) + { + sprintf(String, "SA-1: DMA from non-block address $%02X:%04X", d->ABank, addr); + S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String); + base = Memory.ROM; + } + + base += addr; + + uint8 *buffer = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000]; + uint8 *p = buffer; + uint32 inc_sa1 = char_line_bytes - (d->AAddress % char_line_bytes); + uint32 char_count = inc_sa1 / bytes_per_char; + + in_sa1_dma = TRUE; + + #if 0 + printf("SA-1 DMA: %08x,", base); + printf("depth = %d, count = %d, bytes_per_char = %d, bytes_per_line = %d, num_chars = %d, char_line_bytes = %d\n", + depth, count, bytes_per_char, bytes_per_line, num_chars, char_line_bytes); + #endif + + switch (depth) + { + case 2: + for (int32 i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) + { + uint8 *line = base + (num_chars - char_count) * 2; + for (uint32 j = 0; j < char_count && p - buffer < count; j++, line += 2) + { + uint8 *q = line; + for (int32 l = 0; l < 8; l++, q += bytes_per_line) + { + for (int32 b = 0; b < 2; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 2) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 3) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 6) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 7) & 1); + } + + p += 2; + } + } + } + + break; + + case 4: + for (int32 i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) + { + uint8 *line = base + (num_chars - char_count) * 4; + for (uint32 j = 0; j < char_count && p - buffer < count; j++, line += 4) + { + uint8 *q = line; + for (int32 l = 0; l < 8; l++, q += bytes_per_line) + { + for (int32 b = 0; b < 4; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 6) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 7) & 1); + } + + p += 2; + } + + p += 32 - 16; + } + } + + break; + + case 8: + for (int32 i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) + { + uint8 *line = base + (num_chars - char_count) * 8; + for (uint32 j = 0; j < char_count && p - buffer < count; j++, line += 8) + { + uint8 *q = line; + for (int32 l = 0; l < 8; l++, q += bytes_per_line) + { + for (int32 b = 0; b < 8; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); + *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); + *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); + *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); + *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); + } + + p += 2; + } + + p += 64 - 16; + } + } + + break; + } + } + } + +#ifdef DEBUGGER + if (Settings.TraceDMA) + { + sprintf(String, "DMA[%d]: %s Mode:%d 0x%02X%04X->0x21%02X Bytes:%d (%s) V:%03d", + Channel, d->ReverseTransfer ? "PPU->CPU" : "CPU->PPU", d->TransferMode, d->ABank, d->AAddress, d->BAddress, + d->TransferBytes, d->AAddressFixed ? "fixed" : (d->AAddressDecrement ? "dec" : "inc"), CPU.V_Counter); + + if (d->BAddress == 0x18 || d->BAddress == 0x19 || d->BAddress == 0x39 || d->BAddress == 0x3a) + sprintf(String, "%s VRAM: %04X (%d,%d) %s", String, + PPU.VMA.Address, PPU.VMA.Increment, PPU.VMA.FullGraphicCount, PPU.VMA.High ? "word" : "byte"); + else + if (d->BAddress == 0x22 || d->BAddress == 0x3b) + sprintf(String, "%s CGRAM: %02X (%x)", String, PPU.CGADD, PPU.CGFLIP); + else + if (d->BAddress == 0x04 || d->BAddress == 0x38) + sprintf(String, "%s OBJADDR: %04X", String, PPU.OAMAddr); + + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + } +#endif + + // Do Transfer + + uint8 Work; + + // 8 cycles per channel + ADD_CYCLES(SLOW_ONE_CYCLE); + + if (!d->ReverseTransfer) + { + // CPU -> PPU + int32 b = 0; + uint16 p = d->AAddress; + uint8 *base = S9xGetBasePointer((d->ABank << 16) + d->AAddress); + bool8 inWRAM_DMA; + + int32 rem = count; + // Transfer per block if d->AAdressFixed is FALSE + count = d->AAddressFixed ? rem : (d->AAddressDecrement ? ((p & MEMMAP_MASK) + 1) : (MEMMAP_BLOCK_SIZE - (p & MEMMAP_MASK))); + + // Settings for custom chip DMA + if (in_sa1_dma) + { + base = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000]; + p = 0; + count = rem; + } + else + if (in_sdd1_dma) + { + base = in_sdd1_dma; + p = 0; + count = rem; + } + else + if (spc7110_dma) + { + base = spc7110_dma; + p = 0; + count = rem; + } + + inWRAM_DMA = ((!in_sa1_dma && !in_sdd1_dma && !spc7110_dma) && + (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000))); + + // 8 cycles per byte + #define UPDATE_COUNTERS \ + d->TransferBytes--; \ + d->AAddress += inc; \ + p += inc; \ + if (!addCyclesInDMA(Channel)) \ + { \ + CPU.InDMA = FALSE; \ + CPU.InDMAorHDMA = FALSE; \ + CPU.InWRAMDMAorHDMA = FALSE; \ + CPU.CurrentDMAorHDMAChannel = -1; \ + return (FALSE); \ + } + + while (1) + { + if (count > rem) + count = rem; + rem -= count; + + CPU.InWRAMDMAorHDMA = inWRAM_DMA; + + if (!base) + { + // DMA SLOW PATH + if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6) + { + do + { + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + } while (--count > 0); + } + else + if (d->TransferMode == 1 || d->TransferMode == 5) + { + // This is a variation on Duff's Device. It is legal C/C++. + switch (b) + { + default: + while (count > 1) + { + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + count--; + + case 1: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + count--; + } + } + + if (count == 1) + { + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + b = 1; + } + else + b = 0; + } + else + if (d->TransferMode == 3 || d->TransferMode == 7) + { + switch (b) + { + default: + do + { + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 1; + break; + } + + case 1: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 2; + break; + } + + case 2: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 3; + break; + } + + case 3: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 0; + break; + } + } while (1); + } + } + else + if (d->TransferMode == 4) + { + switch (b) + { + default: + do + { + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 1; + break; + } + + case 1: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 2; + break; + } + + case 2: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2102 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 3; + break; + } + + case 3: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2103 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 0; + break; + } + } while (1); + } + } + #ifdef DEBUGGER + else + { + sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + } + #endif + } + else + { + // DMA FAST PATH + if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6) + { + switch (d->BAddress) + { + case 0x04: // OAMDATA + do + { + Work = *(base + p); + REGISTER_2104(Work); + UPDATE_COUNTERS; + } while (--count > 0); + + break; + + case 0x18: // VMDATAL + #ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; + #endif + if (!PPU.VMA.FullGraphicCount) + { + do + { + Work = *(base + p); + REGISTER_2118_linear(Work); + UPDATE_COUNTERS; + } while (--count > 0); + } + else + { + do + { + Work = *(base + p); + REGISTER_2118_tile(Work); + UPDATE_COUNTERS; + } while (--count > 0); + } + + break; + + case 0x19: // VMDATAH + #ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; + #endif + if (!PPU.VMA.FullGraphicCount) + { + do + { + Work = *(base + p); + REGISTER_2119_linear(Work); + UPDATE_COUNTERS; + } while (--count > 0); + } + else + { + do + { + Work = *(base + p); + REGISTER_2119_tile(Work); + UPDATE_COUNTERS; + } while (--count > 0); + } + + break; + + case 0x22: // CGDATA + do + { + Work = *(base + p); + REGISTER_2122(Work); + UPDATE_COUNTERS; + } while (--count > 0); + + break; + + case 0x80: // WMDATA + if (!CPU.InWRAMDMAorHDMA) + { + do + { + Work = *(base + p); + REGISTER_2180(Work); + UPDATE_COUNTERS; + } while (--count > 0); + } + else + { + do + { + UPDATE_COUNTERS; + } while (--count > 0); + } + + break; + + default: + do + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + } while (--count > 0); + + break; + } + } + else + if (d->TransferMode == 1 || d->TransferMode == 5) + { + if (d->BAddress == 0x18) + { + // VMDATAL + #ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; + #endif + if (!PPU.VMA.FullGraphicCount) + { + switch (b) + { + default: + while (count > 1) + { + Work = *(base + p); + REGISTER_2118_linear(Work); + UPDATE_COUNTERS; + count--; + + case 1: + Work = *(base + p); + REGISTER_2119_linear(Work); + UPDATE_COUNTERS; + count--; + } + } + + if (count == 1) + { + Work = *(base + p); + REGISTER_2118_linear(Work); + UPDATE_COUNTERS; + b = 1; + } + else + b = 0; + } + else + { + switch (b) + { + default: + while (count > 1) + { + Work = *(base + p); + REGISTER_2118_tile(Work); + UPDATE_COUNTERS; + count--; + + case 1: + Work = *(base + p); + REGISTER_2119_tile(Work); + UPDATE_COUNTERS; + count--; + } + } + + if (count == 1) + { + Work = *(base + p); + REGISTER_2118_tile(Work); + UPDATE_COUNTERS; + b = 1; + } + else + b = 0; + } + } + else + { + // DMA mode 1 general case + switch (b) + { + default: + while (count > 1) + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + count--; + + case 1: + Work = *(base + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + count--; + } + } + + if (count == 1) + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + b = 1; + } + else + b = 0; + } + } + else + if (d->TransferMode == 3 || d->TransferMode == 7) + { + switch (b) + { + default: + do + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 1; + break; + } + + case 1: + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 2; + break; + } + + case 2: + Work = *(base + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 3; + break; + } + + case 3: + Work = *(base + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 0; + break; + } + } while (1); + } + } + else + if (d->TransferMode == 4) + { + switch (b) + { + default: + do + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 1; + break; + } + + case 1: + Work = *(base + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 2; + break; + } + + case 2: + Work = *(base + p); + S9xSetPPU(Work, 0x2102 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 3; + break; + } + + case 3: + Work = *(base + p); + S9xSetPPU(Work, 0x2103 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 0; + break; + } + } while (1); + } + } + #ifdef DEBUGGER + else + { + sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + } + #endif + } + + if (rem <= 0) + break; + + base = S9xGetBasePointer((d->ABank << 16) + d->AAddress); + count = MEMMAP_BLOCK_SIZE; + inWRAM_DMA = ((!in_sa1_dma && !in_sdd1_dma && !spc7110_dma) && + (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000))); + } + + #undef UPDATE_COUNTERS + } + else + { + // PPU -> CPU + + // 8 cycles per byte + #define UPDATE_COUNTERS \ + d->TransferBytes--; \ + d->AAddress += inc; \ + if (!addCyclesInDMA(Channel)) \ + { \ + CPU.InDMA = FALSE; \ + CPU.InDMAorHDMA = FALSE; \ + CPU.InWRAMDMAorHDMA = FALSE; \ + CPU.CurrentDMAorHDMAChannel = -1; \ + return (FALSE); \ + } + + if (d->BAddress > 0x80 - 4 && d->BAddress <= 0x83 && !(d->ABank & 0x40)) + { + // REVERSE-DMA REALLY-SLOW PATH + do + { + switch (d->TransferMode) + { + case 0: + case 2: + case 6: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 1: + case 5: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 3: + case 7: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 4: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2102 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2103 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + default: + #ifdef DEBUGGER + sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + #endif + while (count) + { + UPDATE_COUNTERS; + count--; + } + + break; + } + } while (count); + } + else + { + // REVERSE-DMA FASTER PATH + CPU.InWRAMDMAorHDMA = (d->ABank == 0x7e || d->ABank == 0x7f); + do + { + switch (d->TransferMode) + { + case 0: + case 2: + case 6: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 1: + case 5: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 3: + case 7: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 4: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2102 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2103 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + default: + #ifdef DEBUGGER + sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + #endif + while (count) + { + UPDATE_COUNTERS; + count--; + } + + break; + } + } while (count); + } + } + + if ((CPU.Flags & NMI_FLAG) && (Timings.NMITriggerPos != 0xffff)) + { + Timings.NMITriggerPos = CPU.Cycles + Timings.NMIDMADelay; + if (Timings.NMITriggerPos >= Timings.H_Max) + Timings.NMITriggerPos -= Timings.H_Max; + } + + // Release the memory used in SPC7110 DMA + if (Settings.SPC7110) + { + if (spc7110_dma) + delete [] spc7110_dma; + } + +#if 0 + // sanity check + if (d->TransferBytes != 0) + fprintf(stderr,"DMA[%d] TransferBytes not 0! $21%02x Reverse:%d %04x\n", Channel, d->BAddress, d->ReverseTransfer, d->TransferBytes); +#endif + + CPU.InDMA = FALSE; + CPU.InDMAorHDMA = FALSE; + CPU.InWRAMDMAorHDMA = FALSE; + CPU.CurrentDMAorHDMAChannel = -1; + + return (TRUE); +} + +static inline bool8 HDMAReadLineCount (int d) +{ + // CPU.InDMA is set, so S9xGetXXX() / S9xSetXXX() incur no charges. + + uint8 line; + + line = S9xGetByte((DMA[d].ABank << 16) + DMA[d].Address); + ADD_CYCLES(SLOW_ONE_CYCLE); + + if (!line) + { + DMA[d].Repeat = FALSE; + DMA[d].LineCount = 128; + + if (DMA[d].HDMAIndirectAddressing) + { + if (PPU.HDMA & (0xfe << d)) + { + DMA[d].Address++; + ADD_CYCLES(SLOW_ONE_CYCLE << 1); + } + else + ADD_CYCLES(SLOW_ONE_CYCLE); + + DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address); + DMA[d].Address++; + } + + DMA[d].Address++; + HDMAMemPointers[d] = NULL; + + return (FALSE); + } + else + if (line == 0x80) + { + DMA[d].Repeat = TRUE; + DMA[d].LineCount = 128; + } + else + { + DMA[d].Repeat = !(line & 0x80); + DMA[d].LineCount = line & 0x7f; + } + + DMA[d].Address++; + DMA[d].DoTransfer = TRUE; + + if (DMA[d].HDMAIndirectAddressing) + { + ADD_CYCLES(SLOW_ONE_CYCLE << 1); + DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address); + DMA[d].Address += 2; + HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].IndirectBank << 16) + DMA[d].IndirectAddress); + } + else + HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].ABank << 16) + DMA[d].Address); + + return (TRUE); +} + +void S9xStartHDMA (void) +{ + if (Settings.DisableHDMA) + PPU.HDMA = 0; + else + PPU.HDMA = Memory.FillRAM[0x420c]; + +#ifdef DEBUGGER + missing.hdma_this_frame = PPU.HDMA; +#endif + + PPU.HDMAEnded = 0; + + int32 tmpch; + + CPU.InHDMA = TRUE; + CPU.InDMAorHDMA = TRUE; + tmpch = CPU.CurrentDMAorHDMAChannel; + + // XXX: Not quite right... + if (PPU.HDMA != 0) + ADD_CYCLES(Timings.DMACPUSync); + + for (uint8 i = 0; i < 8; i++) + { + if (PPU.HDMA & (1 << i)) + { + CPU.CurrentDMAorHDMAChannel = i; + + DMA[i].Address = DMA[i].AAddress; + + if (!HDMAReadLineCount(i)) + { + PPU.HDMA &= ~(1 << i); + PPU.HDMAEnded |= (1 << i); + } + } + else + DMA[i].DoTransfer = FALSE; + } + + CPU.InHDMA = FALSE; + CPU.InDMAorHDMA = CPU.InDMA; + CPU.HDMARanInDMA = CPU.InDMA ? PPU.HDMA : 0; + CPU.CurrentDMAorHDMAChannel = tmpch; +} + +uint8 S9xDoHDMA (uint8 byte) +{ + struct SDMA *p = &DMA[0]; + + uint32 ShiftedIBank; + uint16 IAddr; + bool8 temp; + int32 tmpch; + int d = 0; + + CPU.InHDMA = TRUE; + CPU.InDMAorHDMA = TRUE; + CPU.HDMARanInDMA = CPU.InDMA ? byte : 0; + temp = CPU.InWRAMDMAorHDMA; + tmpch = CPU.CurrentDMAorHDMAChannel; + + // XXX: Not quite right... + ADD_CYCLES(Timings.DMACPUSync); + + for (uint8 mask = 1; mask; mask <<= 1, p++, d++) + { + if (byte & mask) + { + CPU.InWRAMDMAorHDMA = FALSE; + CPU.CurrentDMAorHDMAChannel = d; + + if (p->HDMAIndirectAddressing) + { + ShiftedIBank = (p->IndirectBank << 16); + IAddr = p->IndirectAddress; + } + else + { + ShiftedIBank = (p->ABank << 16); + IAddr = p->Address; + } + + if (!HDMAMemPointers[d]) + HDMAMemPointers[d] = S9xGetMemPointer(ShiftedIBank + IAddr); + + if (p->DoTransfer) + { + // XXX: Hack for Uniracers, because we don't understand + // OAM Address Invalidation + if (p->BAddress == 0x04) + { + if (SNESGameFixes.Uniracers) + { + PPU.OAMAddr = 0x10c; + PPU.OAMFlip = 0; + } + } + + #ifdef DEBUGGER + if (Settings.TraceHDMA && p->DoTransfer) + { + sprintf(String, "H-DMA[%d] %s (%d) 0x%06X->0x21%02X %s, Count: %3d, Rep: %s, V-LINE: %3ld %02X%04X", + p-DMA, p->ReverseTransfer? "read" : "write", + p->TransferMode, ShiftedIBank+IAddr, p->BAddress, + p->HDMAIndirectAddressing ? "ind" : "abs", + p->LineCount, + p->Repeat ? "yes" : "no ", (long) CPU.V_Counter, + p->ABank, p->Address); + S9xMessage(S9X_TRACE, S9X_HDMA_TRACE, String); + } + #endif + + if (!p->ReverseTransfer) + { + if ((IAddr & MEMMAP_MASK) + HDMA_ModeByteCounts[p->TransferMode] >= MEMMAP_BLOCK_SIZE) + { + // HDMA REALLY-SLOW PATH + HDMAMemPointers[d] = NULL; + + #define DOBYTE(Addr, RegOff) \ + CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || \ + (!(ShiftedIBank & 0x400000) && ((uint16) (Addr)) < 0x2000)); \ + S9xSetPPU(S9xGetByte(ShiftedIBank + ((uint16) (Addr))), 0x2100 + p->BAddress + (RegOff)); + + switch (p->TransferMode) + { + case 0: + DOBYTE(IAddr, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + + case 5: + DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 1, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 2, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 3, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + + case 1: + DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 1, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + + case 2: + case 6: + DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 1, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + + case 3: + case 7: + DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 1, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 2, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 3, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + + case 4: + DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 1, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 2, 2); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 3, 3); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + } + + #undef DOBYTE + } + else + { + CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || + (!(ShiftedIBank & 0x400000) && IAddr < 0x2000)); + + if (!HDMAMemPointers[d]) + { + // HDMA SLOW PATH + uint32 Addr = ShiftedIBank + IAddr; + + switch (p->TransferMode) + { + case 0: + S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + + case 5: + S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + Addr += 2; + /* fall through */ + case 1: + S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + + case 2: + case 6: + S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + + case 3: + case 7: + S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(S9xGetByte(Addr + 2), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(S9xGetByte(Addr + 3), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + + case 4: + S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(S9xGetByte(Addr + 2), 0x2102 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(S9xGetByte(Addr + 3), 0x2103 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + } + } + else + { + // HDMA FAST PATH + switch (p->TransferMode) + { + case 0: + S9xSetPPU(*HDMAMemPointers[d]++, 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + + case 5: + S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + HDMAMemPointers[d] += 2; + /* fall through */ + case 1: + S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + HDMAMemPointers[d] += 2; + break; + + case 2: + case 6: + S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + HDMAMemPointers[d] += 2; + break; + + case 3: + case 7: + S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + HDMAMemPointers[d] += 4; + break; + + case 4: + S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2102 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2103 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); + HDMAMemPointers[d] += 4; + break; + } + } + } + } + else + { + // REVERSE HDMA REALLY-SLOW PATH + // anomie says: Since this is apparently never used + // (otherwise we would have noticed before now), let's not bother with faster paths. + HDMAMemPointers[d] = NULL; + + #define DOBYTE(Addr, RegOff) \ + CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || \ + (!(ShiftedIBank & 0x400000) && ((uint16) (Addr)) < 0x2000)); \ + S9xSetByte(S9xGetPPU(0x2100 + p->BAddress + (RegOff)), ShiftedIBank + ((uint16) (Addr))); + + switch (p->TransferMode) + { + case 0: + DOBYTE(IAddr, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + + case 5: + DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 1, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 2, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 3, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + + case 1: + DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 1, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + + case 2: + case 6: + DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 1, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + + case 3: + case 7: + DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 1, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 2, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 3, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + + case 4: + DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 1, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 2, 2); + ADD_CYCLES(SLOW_ONE_CYCLE); + DOBYTE(IAddr + 3, 3); + ADD_CYCLES(SLOW_ONE_CYCLE); + break; + } + + #undef DOBYTE + } + + if (p->HDMAIndirectAddressing) + p->IndirectAddress += HDMA_ModeByteCounts[p->TransferMode]; + else + p->Address += HDMA_ModeByteCounts[p->TransferMode]; + } + + p->DoTransfer = !p->Repeat; + + if (!--p->LineCount) + { + if (!HDMAReadLineCount(d)) + { + byte &= ~mask; + PPU.HDMAEnded |= mask; + p->DoTransfer = FALSE; + continue; + } + } + else + ADD_CYCLES(SLOW_ONE_CYCLE); + } + } + + CPU.InHDMA = FALSE; + CPU.InDMAorHDMA = CPU.InDMA; + CPU.InWRAMDMAorHDMA = temp; + CPU.CurrentDMAorHDMAChannel = tmpch; + + return (byte); +} + +void S9xResetDMA (void) +{ + for (int d = 0; d < 8; d++) + { + DMA[d].ReverseTransfer = TRUE; + DMA[d].HDMAIndirectAddressing = TRUE; + DMA[d].AAddressFixed = TRUE; + DMA[d].AAddressDecrement = TRUE; + DMA[d].TransferMode = 7; + DMA[d].BAddress = 0xff; + DMA[d].AAddress = 0xffff; + DMA[d].ABank = 0xff; + DMA[d].DMACount_Or_HDMAIndirectAddress = 0xffff; + DMA[d].IndirectBank = 0xff; + DMA[d].Address = 0xffff; + DMA[d].Repeat = FALSE; + DMA[d].LineCount = 0x7f; + DMA[d].UnknownByte = 0xff; + DMA[d].DoTransfer = FALSE; + DMA[d].UnusedBit43x0 = 1; + } +} diff --git a/plugins/snes9x_gx/source/snes9x/dma.h b/plugins/snes9x_gx/source/snes9x/dma.h new file mode 100644 index 00000000..c779a798 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/dma.h @@ -0,0 +1,211 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _DMA_H_ +#define _DMA_H_ + +struct SDMA +{ + bool8 ReverseTransfer; + bool8 HDMAIndirectAddressing; + bool8 UnusedBit43x0; + bool8 AAddressFixed; + bool8 AAddressDecrement; + uint8 TransferMode; + uint8 BAddress; + uint16 AAddress; + uint8 ABank; + uint16 DMACount_Or_HDMAIndirectAddress; + uint8 IndirectBank; + uint16 Address; + uint8 Repeat; + uint8 LineCount; + uint8 UnknownByte; + uint8 DoTransfer; +}; + +#define TransferBytes DMACount_Or_HDMAIndirectAddress +#define IndirectAddress DMACount_Or_HDMAIndirectAddress + +extern struct SDMA DMA[8]; + +bool8 S9xDoDMA (uint8); +void S9xStartHDMA (void); +uint8 S9xDoHDMA (uint8); +void S9xResetDMA (void); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/dsp.cpp b/plugins/snes9x_gx/source/snes9x/dsp.cpp new file mode 100644 index 00000000..b6e23ff1 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/dsp.cpp @@ -0,0 +1,229 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#ifdef DEBUGGER +#include "missing.h" +#endif + +uint8 (*GetDSP) (uint16) = NULL; +void (*SetDSP) (uint8, uint16) = NULL; + + +void S9xResetDSP (void) +{ + memset(&DSP1, 0, sizeof(DSP1)); + DSP1.waiting4command = TRUE; + DSP1.first_parameter = TRUE; + + memset(&DSP2, 0, sizeof(DSP2)); + DSP2.waiting4command = TRUE; + + memset(&DSP3, 0, sizeof(DSP3)); + DSP3_Reset(); + + memset(&DSP4, 0, sizeof(DSP4)); + DSP4.waiting4command = TRUE; +} + +uint8 S9xGetDSP (uint16 address) +{ +#ifdef DEBUGGER + if (Settings.TraceDSP) + { + sprintf(String, "DSP read: 0x%04X", address); + S9xMessage(S9X_TRACE, S9X_TRACE_DSP1, String); + } +#endif + + return ((*GetDSP)(address)); +} + +void S9xSetDSP (uint8 byte, uint16 address) +{ +#ifdef DEBUGGER + missing.unknowndsp_write = address; + if (Settings.TraceDSP) + { + sprintf(String, "DSP write: 0x%04X=0x%02X", address, byte); + S9xMessage(S9X_TRACE, S9X_TRACE_DSP1, String); + } +#endif + + (*SetDSP)(byte, address); +} diff --git a/plugins/snes9x_gx/source/snes9x/dsp.h b/plugins/snes9x_gx/source/snes9x/dsp.h new file mode 100644 index 00000000..be4d073f --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/dsp.h @@ -0,0 +1,618 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _DSP1_H_ +#define _DSP1_H_ + +enum +{ + M_DSP1_LOROM_S, + M_DSP1_LOROM_L, + M_DSP1_HIROM, + M_DSP2_LOROM, + M_DSP3_LOROM, + M_DSP4_LOROM +}; + +struct SDSP0 +{ + uint32 maptype; + uint32 boundary; +}; + +struct SDSP1 +{ + bool8 waiting4command; + bool8 first_parameter; + uint8 command; + uint32 in_count; + uint32 in_index; + uint32 out_count; + uint32 out_index; + uint8 parameters[512]; + uint8 output[512]; + + int16 CentreX; + int16 CentreY; + int16 VOffset; + + int16 VPlane_C; + int16 VPlane_E; + + // Azimuth and Zenith angles + int16 SinAas; + int16 CosAas; + int16 SinAzs; + int16 CosAzs; + + // Clipped Zenith angle + int16 SinAZS; + int16 CosAZS; + int16 SecAZS_C1; + int16 SecAZS_E1; + int16 SecAZS_C2; + int16 SecAZS_E2; + + int16 Nx; + int16 Ny; + int16 Nz; + int16 Gx; + int16 Gy; + int16 Gz; + int16 C_Les; + int16 E_Les; + int16 G_Les; + + int16 matrixA[3][3]; + int16 matrixB[3][3]; + int16 matrixC[3][3]; + + int16 Op00Multiplicand; + int16 Op00Multiplier; + int16 Op00Result; + + int16 Op20Multiplicand; + int16 Op20Multiplier; + int16 Op20Result; + + int16 Op10Coefficient; + int16 Op10Exponent; + int16 Op10CoefficientR; + int16 Op10ExponentR; + + int16 Op04Angle; + int16 Op04Radius; + int16 Op04Sin; + int16 Op04Cos; + + int16 Op0CA; + int16 Op0CX1; + int16 Op0CY1; + int16 Op0CX2; + int16 Op0CY2; + + int16 Op02FX; + int16 Op02FY; + int16 Op02FZ; + int16 Op02LFE; + int16 Op02LES; + int16 Op02AAS; + int16 Op02AZS; + int16 Op02VOF; + int16 Op02VVA; + int16 Op02CX; + int16 Op02CY; + + int16 Op0AVS; + int16 Op0AA; + int16 Op0AB; + int16 Op0AC; + int16 Op0AD; + + int16 Op06X; + int16 Op06Y; + int16 Op06Z; + int16 Op06H; + int16 Op06V; + int16 Op06M; + + int16 Op01m; + int16 Op01Zr; + int16 Op01Xr; + int16 Op01Yr; + + int16 Op11m; + int16 Op11Zr; + int16 Op11Xr; + int16 Op11Yr; + + int16 Op21m; + int16 Op21Zr; + int16 Op21Xr; + int16 Op21Yr; + + int16 Op0DX; + int16 Op0DY; + int16 Op0DZ; + int16 Op0DF; + int16 Op0DL; + int16 Op0DU; + + int16 Op1DX; + int16 Op1DY; + int16 Op1DZ; + int16 Op1DF; + int16 Op1DL; + int16 Op1DU; + + int16 Op2DX; + int16 Op2DY; + int16 Op2DZ; + int16 Op2DF; + int16 Op2DL; + int16 Op2DU; + + int16 Op03F; + int16 Op03L; + int16 Op03U; + int16 Op03X; + int16 Op03Y; + int16 Op03Z; + + int16 Op13F; + int16 Op13L; + int16 Op13U; + int16 Op13X; + int16 Op13Y; + int16 Op13Z; + + int16 Op23F; + int16 Op23L; + int16 Op23U; + int16 Op23X; + int16 Op23Y; + int16 Op23Z; + + int16 Op14Zr; + int16 Op14Xr; + int16 Op14Yr; + int16 Op14U; + int16 Op14F; + int16 Op14L; + int16 Op14Zrr; + int16 Op14Xrr; + int16 Op14Yrr; + + int16 Op0EH; + int16 Op0EV; + int16 Op0EX; + int16 Op0EY; + + int16 Op0BX; + int16 Op0BY; + int16 Op0BZ; + int16 Op0BS; + + int16 Op1BX; + int16 Op1BY; + int16 Op1BZ; + int16 Op1BS; + + int16 Op2BX; + int16 Op2BY; + int16 Op2BZ; + int16 Op2BS; + + int16 Op28X; + int16 Op28Y; + int16 Op28Z; + int16 Op28R; + + int16 Op1CX; + int16 Op1CY; + int16 Op1CZ; + int16 Op1CXBR; + int16 Op1CYBR; + int16 Op1CZBR; + int16 Op1CXAR; + int16 Op1CYAR; + int16 Op1CZAR; + int16 Op1CX1; + int16 Op1CY1; + int16 Op1CZ1; + int16 Op1CX2; + int16 Op1CY2; + int16 Op1CZ2; + + uint16 Op0FRamsize; + uint16 Op0FPass; + + int16 Op2FUnknown; + int16 Op2FSize; + + int16 Op08X; + int16 Op08Y; + int16 Op08Z; + int16 Op08Ll; + int16 Op08Lh; + + int16 Op18X; + int16 Op18Y; + int16 Op18Z; + int16 Op18R; + int16 Op18D; + + int16 Op38X; + int16 Op38Y; + int16 Op38Z; + int16 Op38R; + int16 Op38D; +}; + +struct SDSP2 +{ + bool8 waiting4command; + uint8 command; + uint32 in_count; + uint32 in_index; + uint32 out_count; + uint32 out_index; + uint8 parameters[512]; + uint8 output[512]; + + bool8 Op05HasLen; + int32 Op05Len; + uint8 Op05Transparent; + + bool8 Op06HasLen; + int32 Op06Len; + + uint16 Op09Word1; + uint16 Op09Word2; + + bool8 Op0DHasLen; + int32 Op0DOutLen; + int32 Op0DInLen; +}; + +struct SDSP3 +{ + uint16 DR; + uint16 SR; + uint16 MemoryIndex; + + int16 WinLo; + int16 WinHi; + int16 AddLo; + int16 AddHi; + + uint16 Codewords; + uint16 Outwords; + uint16 Symbol; + uint16 BitCount; + uint16 Index; + uint16 Codes[512]; + uint16 BitsLeft; + uint16 ReqBits; + uint16 ReqData; + uint16 BitCommand; + uint8 BaseLength; + uint16 BaseCodes; + uint16 BaseCode; + uint8 CodeLengths[8]; + uint16 CodeOffsets[8]; + uint16 LZCode; + uint8 LZLength; + + uint16 X; + uint16 Y; + + uint8 Bitmap[8]; + uint8 Bitplane[8]; + uint16 BMIndex; + uint16 BPIndex; + uint16 Count; + + int16 op3e_x; + int16 op3e_y; + + int16 op1e_terrain[0x2000]; + int16 op1e_cost[0x2000]; + int16 op1e_weight[0x2000]; + + int16 op1e_cell; + int16 op1e_turn; + int16 op1e_search; + + int16 op1e_x; + int16 op1e_y; + + int16 op1e_min_radius; + int16 op1e_max_radius; + + int16 op1e_max_search_radius; + int16 op1e_max_path_radius; + + int16 op1e_lcv_radius; + int16 op1e_lcv_steps; + int16 op1e_lcv_turns; +}; + +struct SDSP4 +{ + bool8 waiting4command; + bool8 half_command; + uint16 command; + uint32 in_count; + uint32 in_index; + uint32 out_count; + uint32 out_index; + uint8 parameters[512]; + uint8 output[512]; + uint8 byte; + uint16 address; + + // op control + int8 Logic; // controls op flow + + // projection format + int16 lcv; // loop-control variable + int16 distance; // z-position into virtual world + int16 raster; // current raster line + int16 segments; // number of raster lines drawn + + // 1.15.16 or 1.15.0 [sign, integer, fraction] + int32 world_x; // line of x-projection in world + int32 world_y; // line of y-projection in world + int32 world_dx; // projection line x-delta + int32 world_dy; // projection line y-delta + int16 world_ddx; // x-delta increment + int16 world_ddy; // y-delta increment + int32 world_xenv; // world x-shaping factor + int16 world_yofs; // world y-vertical scroll + int16 view_x1; // current viewer-x + int16 view_y1; // current viewer-y + int16 view_x2; // future viewer-x + int16 view_y2; // future viewer-y + int16 view_dx; // view x-delta factor + int16 view_dy; // view y-delta factor + int16 view_xofs1; // current viewer x-vertical scroll + int16 view_yofs1; // current viewer y-vertical scroll + int16 view_xofs2; // future viewer x-vertical scroll + int16 view_yofs2; // future viewer y-vertical scroll + int16 view_yofsenv; // y-scroll shaping factor + int16 view_turnoff_x; // road turnoff data + int16 view_turnoff_dx; // road turnoff delta factor + + // drawing area + int16 viewport_cx; // x-center of viewport window + int16 viewport_cy; // y-center of render window + int16 viewport_left; // x-left of viewport + int16 viewport_right; // x-right of viewport + int16 viewport_top; // y-top of viewport + int16 viewport_bottom; // y-bottom of viewport + + // sprite structure + int16 sprite_x; // projected x-pos of sprite + int16 sprite_y; // projected y-pos of sprite + int16 sprite_attr; // obj attributes + bool8 sprite_size; // sprite size: 8x8 or 16x16 + int16 sprite_clipy; // visible line to clip pixels off + int16 sprite_count; + + // generic projection variables designed for two solid polygons + two polygon sides + int16 poly_clipLf[2][2]; // left clip boundary + int16 poly_clipRt[2][2]; // right clip boundary + int16 poly_ptr[2][2]; // HDMA structure pointers + int16 poly_raster[2][2]; // current raster line below horizon + int16 poly_top[2][2]; // top clip boundary + int16 poly_bottom[2][2]; // bottom clip boundary + int16 poly_cx[2][2]; // center for left/right points + int16 poly_start[2]; // current projection points + int16 poly_plane[2]; // previous z-plane distance + + // OAM + int16 OAM_attr[16]; // OAM (size, MSB) data + int16 OAM_index; // index into OAM table + int16 OAM_bits; // offset into OAM table + int16 OAM_RowMax; // maximum number of tiles per 8 aligned pixels (row) + int16 OAM_Row[32]; // current number of tiles per row +}; + +extern struct SDSP0 DSP0; +extern struct SDSP1 DSP1; +extern struct SDSP2 DSP2; +extern struct SDSP3 DSP3; +extern struct SDSP4 DSP4; + +uint8 S9xGetDSP (uint16); +void S9xSetDSP (uint8, uint16); +void S9xResetDSP (void); +uint8 DSP1GetByte (uint16); +void DSP1SetByte (uint8, uint16); +uint8 DSP2GetByte (uint16); +void DSP2SetByte (uint8, uint16); +uint8 DSP3GetByte (uint16); +void DSP3SetByte (uint8, uint16); +uint8 DSP4GetByte (uint16); +void DSP4SetByte (uint8, uint16); +void DSP3_Reset (void); + +extern uint8 (*GetDSP) (uint16); +extern void (*SetDSP) (uint8, uint16); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/dsp1.cpp b/plugins/snes9x_gx/source/snes9x/dsp1.cpp new file mode 100644 index 00000000..85f95123 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/dsp1.cpp @@ -0,0 +1,1894 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + +/* +Copyright (C) 1997-2006 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach ) + +http://www.zsnes.com +http://sourceforge.net/projects/zsnes + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 2 as published by the Free Software Foundation. + +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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include "snes9x.h" +#include "memmap.h" + +#ifdef DEBUGGER +//#define DebugDSP1 +#endif + +#ifdef DebugDSP1 +#include <stdarg.h> +static FILE *LogFile = NULL; +#endif + +static const uint16 DSP1ROM[1024] = +{ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, + 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, + 0x4000, 0x7fff, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, + 0x0100, 0x0080, 0x0040, 0x0020, 0x0001, 0x0008, 0x0004, 0x0002, + 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8000, 0xffe5, 0x0100, 0x7fff, 0x7f02, 0x7e08, + 0x7d12, 0x7c1f, 0x7b30, 0x7a45, 0x795d, 0x7878, 0x7797, 0x76ba, + 0x75df, 0x7507, 0x7433, 0x7361, 0x7293, 0x71c7, 0x70fe, 0x7038, + 0x6f75, 0x6eb4, 0x6df6, 0x6d3a, 0x6c81, 0x6bca, 0x6b16, 0x6a64, + 0x69b4, 0x6907, 0x685b, 0x67b2, 0x670b, 0x6666, 0x65c4, 0x6523, + 0x6484, 0x63e7, 0x634c, 0x62b3, 0x621c, 0x6186, 0x60f2, 0x6060, + 0x5fd0, 0x5f41, 0x5eb5, 0x5e29, 0x5d9f, 0x5d17, 0x5c91, 0x5c0c, + 0x5b88, 0x5b06, 0x5a85, 0x5a06, 0x5988, 0x590b, 0x5890, 0x5816, + 0x579d, 0x5726, 0x56b0, 0x563b, 0x55c8, 0x5555, 0x54e4, 0x5474, + 0x5405, 0x5398, 0x532b, 0x52bf, 0x5255, 0x51ec, 0x5183, 0x511c, + 0x50b6, 0x5050, 0x4fec, 0x4f89, 0x4f26, 0x4ec5, 0x4e64, 0x4e05, + 0x4da6, 0x4d48, 0x4cec, 0x4c90, 0x4c34, 0x4bda, 0x4b81, 0x4b28, + 0x4ad0, 0x4a79, 0x4a23, 0x49cd, 0x4979, 0x4925, 0x48d1, 0x487f, + 0x482d, 0x47dc, 0x478c, 0x473c, 0x46ed, 0x469f, 0x4651, 0x4604, + 0x45b8, 0x456c, 0x4521, 0x44d7, 0x448d, 0x4444, 0x43fc, 0x43b4, + 0x436d, 0x4326, 0x42e0, 0x429a, 0x4255, 0x4211, 0x41cd, 0x4189, + 0x4146, 0x4104, 0x40c2, 0x4081, 0x4040, 0x3fff, 0x41f7, 0x43e1, + 0x45bd, 0x478d, 0x4951, 0x4b0b, 0x4cbb, 0x4e61, 0x4fff, 0x5194, + 0x5322, 0x54a9, 0x5628, 0x57a2, 0x5914, 0x5a81, 0x5be9, 0x5d4a, + 0x5ea7, 0x5fff, 0x6152, 0x62a0, 0x63ea, 0x6530, 0x6672, 0x67b0, + 0x68ea, 0x6a20, 0x6b53, 0x6c83, 0x6daf, 0x6ed9, 0x6fff, 0x7122, + 0x7242, 0x735f, 0x747a, 0x7592, 0x76a7, 0x77ba, 0x78cb, 0x79d9, + 0x7ae5, 0x7bee, 0x7cf5, 0x7dfa, 0x7efe, 0x7fff, 0x0000, 0x0324, + 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, 0x18f8, 0x1c0b, + 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, 0x30fb, 0x33de, + 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, 0x471c, 0x49b4, + 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, 0x5a82, 0x5cb4, + 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, 0x6a6d, 0x6c24, + 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, 0x7641, 0x776c, + 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, 0x7d8a, 0x7e1d, + 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, 0x7fff, 0x7ff6, + 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3, + 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504, + 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6, + 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842, + 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a, + 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11, + 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2, + 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x7fff, 0x7ff6, + 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3, + 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504, + 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6, + 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842, + 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a, + 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11, + 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2, + 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x0000, 0xfcdc, + 0xf9b9, 0xf696, 0xf375, 0xf055, 0xed38, 0xea1e, 0xe708, 0xe3f5, + 0xe0e7, 0xdddd, 0xdad8, 0xd7da, 0xd4e1, 0xd1ef, 0xcf05, 0xcc22, + 0xc946, 0xc674, 0xc3aa, 0xc0e9, 0xbe32, 0xbb86, 0xb8e4, 0xb64c, + 0xb3c1, 0xb141, 0xaecd, 0xac65, 0xaa0b, 0xa7be, 0xa57e, 0xa34c, + 0xa129, 0x9f14, 0x9d0e, 0x9b18, 0x9931, 0x975a, 0x9593, 0x93dc, + 0x9236, 0x90a1, 0x8f1e, 0x8dab, 0x8c4b, 0x8afc, 0x89bf, 0x8894, + 0x877c, 0x8676, 0x8583, 0x84a3, 0x83d7, 0x831d, 0x8276, 0x81e3, + 0x8163, 0x80f7, 0x809e, 0x8059, 0x8028, 0x800a, 0x6488, 0x0080, + 0x03ff, 0x0116, 0x0002, 0x0080, 0x4000, 0x3fd7, 0x3faf, 0x3f86, + 0x3f5d, 0x3f34, 0x3f0c, 0x3ee3, 0x3eba, 0x3e91, 0x3e68, 0x3e40, + 0x3e17, 0x3dee, 0x3dc5, 0x3d9c, 0x3d74, 0x3d4b, 0x3d22, 0x3cf9, + 0x3cd0, 0x3ca7, 0x3c7f, 0x3c56, 0x3c2d, 0x3c04, 0x3bdb, 0x3bb2, + 0x3b89, 0x3b60, 0x3b37, 0x3b0e, 0x3ae5, 0x3abc, 0x3a93, 0x3a69, + 0x3a40, 0x3a17, 0x39ee, 0x39c5, 0x399c, 0x3972, 0x3949, 0x3920, + 0x38f6, 0x38cd, 0x38a4, 0x387a, 0x3851, 0x3827, 0x37fe, 0x37d4, + 0x37aa, 0x3781, 0x3757, 0x372d, 0x3704, 0x36da, 0x36b0, 0x3686, + 0x365c, 0x3632, 0x3609, 0x35df, 0x35b4, 0x358a, 0x3560, 0x3536, + 0x350c, 0x34e1, 0x34b7, 0x348d, 0x3462, 0x3438, 0x340d, 0x33e3, + 0x33b8, 0x338d, 0x3363, 0x3338, 0x330d, 0x32e2, 0x32b7, 0x328c, + 0x3261, 0x3236, 0x320b, 0x31df, 0x31b4, 0x3188, 0x315d, 0x3131, + 0x3106, 0x30da, 0x30ae, 0x3083, 0x3057, 0x302b, 0x2fff, 0x2fd2, + 0x2fa6, 0x2f7a, 0x2f4d, 0x2f21, 0x2ef4, 0x2ec8, 0x2e9b, 0x2e6e, + 0x2e41, 0x2e14, 0x2de7, 0x2dba, 0x2d8d, 0x2d60, 0x2d32, 0x2d05, + 0x2cd7, 0x2ca9, 0x2c7b, 0x2c4d, 0x2c1f, 0x2bf1, 0x2bc3, 0x2b94, + 0x2b66, 0x2b37, 0x2b09, 0x2ada, 0x2aab, 0x2a7c, 0x2a4c, 0x2a1d, + 0x29ed, 0x29be, 0x298e, 0x295e, 0x292e, 0x28fe, 0x28ce, 0x289d, + 0x286d, 0x283c, 0x280b, 0x27da, 0x27a9, 0x2777, 0x2746, 0x2714, + 0x26e2, 0x26b0, 0x267e, 0x264c, 0x2619, 0x25e7, 0x25b4, 0x2581, + 0x254d, 0x251a, 0x24e6, 0x24b2, 0x247e, 0x244a, 0x2415, 0x23e1, + 0x23ac, 0x2376, 0x2341, 0x230b, 0x22d6, 0x229f, 0x2269, 0x2232, + 0x21fc, 0x21c4, 0x218d, 0x2155, 0x211d, 0x20e5, 0x20ad, 0x2074, + 0x203b, 0x2001, 0x1fc7, 0x1f8d, 0x1f53, 0x1f18, 0x1edd, 0x1ea1, + 0x1e66, 0x1e29, 0x1ded, 0x1db0, 0x1d72, 0x1d35, 0x1cf6, 0x1cb8, + 0x1c79, 0x1c39, 0x1bf9, 0x1bb8, 0x1b77, 0x1b36, 0x1af4, 0x1ab1, + 0x1a6e, 0x1a2a, 0x19e6, 0x19a1, 0x195c, 0x1915, 0x18ce, 0x1887, + 0x183f, 0x17f5, 0x17ac, 0x1761, 0x1715, 0x16c9, 0x167c, 0x162e, + 0x15df, 0x158e, 0x153d, 0x14eb, 0x1497, 0x1442, 0x13ec, 0x1395, + 0x133c, 0x12e2, 0x1286, 0x1228, 0x11c9, 0x1167, 0x1104, 0x109e, + 0x1036, 0x0fcc, 0x0f5f, 0x0eef, 0x0e7b, 0x0e04, 0x0d89, 0x0d0a, + 0x0c86, 0x0bfd, 0x0b6d, 0x0ad6, 0x0a36, 0x098d, 0x08d7, 0x0811, + 0x0736, 0x063e, 0x0519, 0x039a, 0x0000, 0x7fff, 0x0100, 0x0080, + 0x021d, 0x00c8, 0x00ce, 0x0048, 0x0a26, 0x277a, 0x00ce, 0x6488, + 0x14ac, 0x0001, 0x00f9, 0x00fc, 0x00ff, 0x00fc, 0x00f9, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff +}; + +static const int16 DSP1_MulTable[256] = +{ + 0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015, + 0x0019, 0x001c, 0x001f, 0x0022, 0x0025, 0x0028, 0x002b, 0x002f, + 0x0032, 0x0035, 0x0038, 0x003b, 0x003e, 0x0041, 0x0045, 0x0048, + 0x004b, 0x004e, 0x0051, 0x0054, 0x0057, 0x005b, 0x005e, 0x0061, + 0x0064, 0x0067, 0x006a, 0x006d, 0x0071, 0x0074, 0x0077, 0x007a, + 0x007d, 0x0080, 0x0083, 0x0087, 0x008a, 0x008d, 0x0090, 0x0093, + 0x0096, 0x0099, 0x009d, 0x00a0, 0x00a3, 0x00a6, 0x00a9, 0x00ac, + 0x00af, 0x00b3, 0x00b6, 0x00b9, 0x00bc, 0x00bf, 0x00c2, 0x00c5, + 0x00c9, 0x00cc, 0x00cf, 0x00d2, 0x00d5, 0x00d8, 0x00db, 0x00df, + 0x00e2, 0x00e5, 0x00e8, 0x00eb, 0x00ee, 0x00f1, 0x00f5, 0x00f8, + 0x00fb, 0x00fe, 0x0101, 0x0104, 0x0107, 0x010b, 0x010e, 0x0111, + 0x0114, 0x0117, 0x011a, 0x011d, 0x0121, 0x0124, 0x0127, 0x012a, + 0x012d, 0x0130, 0x0133, 0x0137, 0x013a, 0x013d, 0x0140, 0x0143, + 0x0146, 0x0149, 0x014d, 0x0150, 0x0153, 0x0156, 0x0159, 0x015c, + 0x015f, 0x0163, 0x0166, 0x0169, 0x016c, 0x016f, 0x0172, 0x0175, + 0x0178, 0x017c, 0x017f, 0x0182, 0x0185, 0x0188, 0x018b, 0x018e, + 0x0192, 0x0195, 0x0198, 0x019b, 0x019e, 0x01a1, 0x01a4, 0x01a8, + 0x01ab, 0x01ae, 0x01b1, 0x01b4, 0x01b7, 0x01ba, 0x01be, 0x01c1, + 0x01c4, 0x01c7, 0x01ca, 0x01cd, 0x01d0, 0x01d4, 0x01d7, 0x01da, + 0x01dd, 0x01e0, 0x01e3, 0x01e6, 0x01ea, 0x01ed, 0x01f0, 0x01f3, + 0x01f6, 0x01f9, 0x01fc, 0x0200, 0x0203, 0x0206, 0x0209, 0x020c, + 0x020f, 0x0212, 0x0216, 0x0219, 0x021c, 0x021f, 0x0222, 0x0225, + 0x0228, 0x022c, 0x022f, 0x0232, 0x0235, 0x0238, 0x023b, 0x023e, + 0x0242, 0x0245, 0x0248, 0x024b, 0x024e, 0x0251, 0x0254, 0x0258, + 0x025b, 0x025e, 0x0261, 0x0264, 0x0267, 0x026a, 0x026e, 0x0271, + 0x0274, 0x0277, 0x027a, 0x027d, 0x0280, 0x0284, 0x0287, 0x028a, + 0x028d, 0x0290, 0x0293, 0x0296, 0x029a, 0x029d, 0x02a0, 0x02a3, + 0x02a6, 0x02a9, 0x02ac, 0x02b0, 0x02b3, 0x02b6, 0x02b9, 0x02bc, + 0x02bf, 0x02c2, 0x02c6, 0x02c9, 0x02cc, 0x02cf, 0x02d2, 0x02d5, + 0x02d8, 0x02db, 0x02df, 0x02e2, 0x02e5, 0x02e8, 0x02eb, 0x02ee, + 0x02f1, 0x02f5, 0x02f8, 0x02fb, 0x02fe, 0x0301, 0x0304, 0x0307, + 0x030b, 0x030e, 0x0311, 0x0314, 0x0317, 0x031a, 0x031d, 0x0321 +}; + +static const int16 DSP1_SinTable[256] = +{ + 0x0000, 0x0324, 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, + 0x18f8, 0x1c0b, 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, + 0x30fb, 0x33de, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, + 0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, + 0x5a82, 0x5cb4, 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, + 0x6a6d, 0x6c24, 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, + 0x7641, 0x776c, 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, + 0x7d8a, 0x7e1d, 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, + 0x7fff, 0x7ff6, 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, + 0x7d8a, 0x7ce3, 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, + 0x7641, 0x7504, 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, + 0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, + 0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, + 0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, + 0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, + 0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, + -0x0000, -0x0324, -0x0647, -0x096a, -0x0c8b, -0x0fab, -0x12c8, -0x15e2, + -0x18f8, -0x1c0b, -0x1f19, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11, + -0x30fb, -0x33de, -0x36ba, -0x398c, -0x3c56, -0x3f17, -0x41ce, -0x447a, + -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842, + -0x5a82, -0x5cb4, -0x5ed7, -0x60ec, -0x62f2, -0x64e8, -0x66cf, -0x68a6, + -0x6a6d, -0x6c24, -0x6dca, -0x6f5f, -0x70e2, -0x7255, -0x73b5, -0x7504, + -0x7641, -0x776c, -0x7884, -0x798a, -0x7a7d, -0x7b5d, -0x7c29, -0x7ce3, + -0x7d8a, -0x7e1d, -0x7e9d, -0x7f09, -0x7f62, -0x7fa7, -0x7fd8, -0x7ff6, + -0x7fff, -0x7ff6, -0x7fd8, -0x7fa7, -0x7f62, -0x7f09, -0x7e9d, -0x7e1d, + -0x7d8a, -0x7ce3, -0x7c29, -0x7b5d, -0x7a7d, -0x798a, -0x7884, -0x776c, + -0x7641, -0x7504, -0x73b5, -0x7255, -0x70e2, -0x6f5f, -0x6dca, -0x6c24, + -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f2, -0x60ec, -0x5ed7, -0x5cb4, + -0x5a82, -0x5842, -0x55f5, -0x539b, -0x5133, -0x4ebf, -0x4c3f, -0x49b4, + -0x471c, -0x447a, -0x41ce, -0x3f17, -0x3c56, -0x398c, -0x36ba, -0x33de, + -0x30fb, -0x2e11, -0x2b1f, -0x2826, -0x2528, -0x2223, -0x1f19, -0x1c0b, + -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324 +}; + + +#ifdef DebugDSP1 + +static void Log_Message (const char *Message, ...) +{ + char Msg[400]; + va_list ap; + size_t ignore; + + va_start(ap, Message); + vsprintf(Msg, Message, ap); + va_end(ap); + + strcat(Msg, "\r\n\0"); + ignore = fwrite(Msg, strlen(Msg), 1, LogFile); + fflush(LogFile); +} + +static void Start_Log (void) +{ + LogFile = fopen("dsp1emu.log", "wb"); +} + +static void Stop_Log (void) +{ + if (LogFile) + { + fclose(LogFile); + LogFile = NULL; + } +} + +#endif + +static void DSP1_Op00 (void) +{ + DSP1.Op00Result = DSP1.Op00Multiplicand * DSP1.Op00Multiplier >> 15; + +#ifdef DebugDSP1 + Log_Message("OP00 MULT %d*%d/32768=%d", DSP1.Op00Multiplicand, DSP1.Op00Multiplier, DSP1.Op00Result); +#endif +} + +static void DSP1_Op20 (void) +{ + DSP1.Op20Result = DSP1.Op20Multiplicand * DSP1.Op20Multiplier >> 15; + DSP1.Op20Result++; + +#ifdef DebugDSP1 + Log_Message("OP20 MULT %d*%d/32768=%d", DSP1.Op20Multiplicand, DSP1.Op20Multiplier, DSP1.Op20Result); +#endif +} + +static void DSP1_Inverse (int16 Coefficient, int16 Exponent, int16 *iCoefficient, int16 *iExponent) +{ + // Step One: Division by Zero + if (Coefficient == 0x0000) + { + *iCoefficient = 0x7fff; + *iExponent = 0x002f; + } + else + { + int16 Sign = 1; + + // Step Two: Remove Sign + if (Coefficient < 0) + { + if (Coefficient < -32767) + Coefficient = -32767; + Coefficient = -Coefficient; + Sign = -1; + } + + // Step Three: Normalize + while (Coefficient < 0x4000) + { + Coefficient <<= 1; + Exponent--; + } + + // Step Four: Special Case + if (Coefficient == 0x4000) + { + if (Sign == 1) + *iCoefficient = 0x7fff; + else + { + *iCoefficient = -0x4000; + Exponent--; + } + } + else + { + // Step Five: Initial Guess + int16 i = DSP1ROM[((Coefficient - 0x4000) >> 7) + 0x0065]; + + // Step Six: Iterate "estimated" Newton's Method + i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; + i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; + + *iCoefficient = i * Sign; + } + + *iExponent = 1 - Exponent; + } +} + +static void DSP1_Op10 (void) +{ + DSP1_Inverse(DSP1.Op10Coefficient, DSP1.Op10Exponent, &DSP1.Op10CoefficientR, &DSP1.Op10ExponentR); + +#ifdef DebugDSP1 + Log_Message("OP10 INV %d*2^%d = %d*2^%d", DSP1.Op10Coefficient, DSP1.Op10Exponent, DSP1.Op10CoefficientR, DSP1.Op10ExponentR); +#endif +} + +static int16 DSP1_Sin (int16 Angle) +{ + int32 S; + + if (Angle < 0) + { + if (Angle == -32768) + return (0); + + return (-DSP1_Sin(-Angle)); + } + + S = DSP1_SinTable[Angle >> 8] + (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[0x40 + (Angle >> 8)] >> 15); + if (S > 32767) + S = 32767; + + return ((int16) S); +} + +static int16 DSP1_Cos (int16 Angle) +{ + int32 S; + + if (Angle < 0) + { + if (Angle == -32768) + return (-32768); + + Angle = -Angle; + } + + S = DSP1_SinTable[0x40 + (Angle >> 8)] - (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[Angle >> 8] >> 15); + if (S < -32768) + S = -32767; + + return ((int16) S); +} + +static void DSP1_Normalize (int16 m, int16 *Coefficient, int16 *Exponent) +{ + int16 i = 0x4000; + int16 e = 0; + + if (m < 0) + { + while ((m & i) && i) + { + i >>= 1; + e++; + } + } + else + { + while (!(m & i) && i) + { + i >>= 1; + e++; + } + } + + if (e > 0) + *Coefficient = m * DSP1ROM[0x21 + e] << 1; + else + *Coefficient = m; + + *Exponent -= e; +} + +static void DSP1_NormalizeDouble (int32 Product, int16 *Coefficient, int16 *Exponent) +{ + int16 n = Product & 0x7fff; + int16 m = Product >> 15; + int16 i = 0x4000; + int16 e = 0; + + if (m < 0) + { + while ((m & i) && i) + { + i >>= 1; + e++; + } + } + else + { + while (!(m & i) && i) + { + i >>= 1; + e++; + } + } + + if (e > 0) + { + *Coefficient = m * DSP1ROM[0x0021 + e] << 1; + + if (e < 15) + *Coefficient += n * DSP1ROM[0x0040 - e] >> 15; + else + { + i = 0x4000; + + if (m < 0) + { + while ((n & i) && i) + { + i >>= 1; + e++; + } + } + else + { + while (!(n & i) && i) + { + i >>= 1; + e++; + } + } + + if (e > 15) + *Coefficient = n * DSP1ROM[0x0012 + e] << 1; + else + *Coefficient += n; + } + } + else + *Coefficient = m; + + *Exponent = e; +} + +static int16 DSP1_Truncate (int16 C, int16 E) +{ + if (E > 0) + { + if (C > 0) + return (32767); + else + if (C < 0) + return (-32767); + } + else + { + if (E < 0) + return (C * DSP1ROM[0x0031 + E] >> 15); + } + + return (C); +} + +static void DSP1_Op04 (void) +{ + DSP1.Op04Sin = DSP1_Sin(DSP1.Op04Angle) * DSP1.Op04Radius >> 15; + DSP1.Op04Cos = DSP1_Cos(DSP1.Op04Angle) * DSP1.Op04Radius >> 15; +} + +static void DSP1_Op0C (void) +{ + DSP1.Op0CX2 = (DSP1.Op0CY1 * DSP1_Sin(DSP1.Op0CA) >> 15) + (DSP1.Op0CX1 * DSP1_Cos(DSP1.Op0CA) >> 15); + DSP1.Op0CY2 = (DSP1.Op0CY1 * DSP1_Cos(DSP1.Op0CA) >> 15) - (DSP1.Op0CX1 * DSP1_Sin(DSP1.Op0CA) >> 15); +} + +static void DSP1_Parameter (int16 Fx, int16 Fy, int16 Fz, int16 Lfe, int16 Les, int16 Aas, int16 Azs, int16 *Vof, int16 *Vva, int16 *Cx, int16 *Cy) +{ + const int16 MaxAZS_Exp[16] = + { + 0x38b4, 0x38b7, 0x38ba, 0x38be, 0x38c0, 0x38c4, 0x38c7, 0x38ca, + 0x38ce, 0x38d0, 0x38d4, 0x38d7, 0x38da, 0x38dd, 0x38e0, 0x38e4 + }; + + int16 CSec, C, E, MaxAZS, Aux; + int16 LfeNx, LfeNy, LfeNz; + int16 LesNx, LesNy, LesNz; + int16 CentreZ; + + // Copy Zenith angle for clipping + int16 AZS = Azs; + + // Store Sine and Cosine of Azimuth and Zenith angle + DSP1.SinAas = DSP1_Sin(Aas); + DSP1.CosAas = DSP1_Cos(Aas); + DSP1.SinAzs = DSP1_Sin(Azs); + DSP1.CosAzs = DSP1_Cos(Azs); + + DSP1.Nx = DSP1.SinAzs * -DSP1.SinAas >> 15; + DSP1.Ny = DSP1.SinAzs * DSP1.CosAas >> 15; + DSP1.Nz = DSP1.CosAzs * 0x7fff >> 15; + + LfeNx = Lfe * DSP1.Nx >> 15; + LfeNy = Lfe * DSP1.Ny >> 15; + LfeNz = Lfe * DSP1.Nz >> 15; + + // Center of Projection + DSP1.CentreX = Fx + LfeNx; + DSP1.CentreY = Fy + LfeNy; + CentreZ = Fz + LfeNz; + + LesNx = Les * DSP1.Nx >> 15; + LesNy = Les * DSP1.Ny >> 15; + LesNz = Les * DSP1.Nz >> 15; + + DSP1.Gx = DSP1.CentreX - LesNx; + DSP1.Gy = DSP1.CentreY - LesNy; + DSP1.Gz = CentreZ - LesNz; + + DSP1.E_Les = 0; + DSP1_Normalize(Les, &DSP1.C_Les, &DSP1.E_Les); + DSP1.G_Les = Les; + + E = 0; + DSP1_Normalize(CentreZ, &C, &E); + + DSP1.VPlane_C = C; + DSP1.VPlane_E = E; + + // Determine clip boundary and clip Zenith angle if necessary + MaxAZS = MaxAZS_Exp[-E]; + + if (AZS < 0) + { + MaxAZS = -MaxAZS; + if (AZS < MaxAZS + 1) + AZS = MaxAZS + 1; + } + else + { + if (AZS > MaxAZS) + AZS = MaxAZS; + } + + // Store Sine and Cosine of clipped Zenith angle + DSP1.SinAZS = DSP1_Sin(AZS); + DSP1.CosAZS = DSP1_Cos(AZS); + + DSP1_Inverse(DSP1.CosAZS, 0, &DSP1.SecAZS_C1, &DSP1.SecAZS_E1); + DSP1_Normalize(C * DSP1.SecAZS_C1 >> 15, &C, &E); + E += DSP1.SecAZS_E1; + + C = DSP1_Truncate(C, E) * DSP1.SinAZS >> 15; + + DSP1.CentreX += C * DSP1.SinAas >> 15; + DSP1.CentreY -= C * DSP1.CosAas >> 15; + + *Cx = DSP1.CentreX; + *Cy = DSP1.CentreY; + + // Raster number of imaginary center and horizontal line + *Vof = 0; + + if ((Azs != AZS) || (Azs == MaxAZS)) + { + if (Azs == -32768) + Azs = -32767; + + C = Azs - MaxAZS; + if (C >= 0) + C--; + Aux = ~(C << 2); + + C = Aux * DSP1ROM[0x0328] >> 15; + C = (C * Aux >> 15) + DSP1ROM[0x0327]; + *Vof -= (C * Aux >> 15) * Les >> 15; + + C = Aux * Aux >> 15; + Aux = (C * DSP1ROM[0x0324] >> 15) + DSP1ROM[0x0325]; + DSP1.CosAZS += (C * Aux >> 15) * DSP1.CosAZS >> 15; + } + + DSP1.VOffset = Les * DSP1.CosAZS >> 15; + + DSP1_Inverse(DSP1.SinAZS, 0, &CSec, &E); + DSP1_Normalize(DSP1.VOffset, &C, &E); + DSP1_Normalize(C * CSec >> 15, &C, &E); + + if (C == -32768) + { + C >>= 1; + E++; + } + + *Vva = DSP1_Truncate(-C, E); + + // Store Secant of clipped Zenith angle + DSP1_Inverse(DSP1.CosAZS, 0, &DSP1.SecAZS_C2, &DSP1.SecAZS_E2); +} + +static void DSP1_Raster (int16 Vs, int16 *An, int16 *Bn, int16 *Cn, int16 *Dn) +{ + int16 C, E, C1, E1; + + DSP1_Inverse((Vs * DSP1.SinAzs >> 15) + DSP1.VOffset, 7, &C, &E); + E += DSP1.VPlane_E; + + C1 = C * DSP1.VPlane_C >> 15; + E1 = E + DSP1.SecAZS_E2; + + DSP1_Normalize(C1, &C, &E); + + C = DSP1_Truncate(C, E); + + *An = C * DSP1.CosAas >> 15; + *Cn = C * DSP1.SinAas >> 15; + + DSP1_Normalize(C1 * DSP1.SecAZS_C2 >> 15, &C, &E1); + + C = DSP1_Truncate(C, E1); + + *Bn = C * -DSP1.SinAas >> 15; + *Dn = C * DSP1.CosAas >> 15; +} + +static void DSP1_Op02 (void) +{ + DSP1_Parameter(DSP1.Op02FX, DSP1.Op02FY, DSP1.Op02FZ, DSP1.Op02LFE, DSP1.Op02LES, DSP1.Op02AAS, DSP1.Op02AZS, &DSP1.Op02VOF, &DSP1.Op02VVA, &DSP1.Op02CX, &DSP1.Op02CY); +} + +static void DSP1_Op0A (void) +{ + DSP1_Raster(DSP1.Op0AVS, &DSP1.Op0AA, &DSP1.Op0AB, &DSP1.Op0AC, &DSP1.Op0AD); + DSP1.Op0AVS++; +} + +static int16 DSP1_ShiftR (int16 C, int16 E) +{ + return (C * DSP1ROM[0x0031 + E] >> 15); +} + +static void DSP1_Project (int16 X, int16 Y, int16 Z, int16 *H, int16 *V, int16 *M) +{ + int32 aux, aux4; + int16 E, E2, E3, E4, E5, refE, E6, E7; + int16 C2, C4, C6, C8, C9, C10, C11, C12, C16, C17, C18, C19, C20, C21, C22, C23, C24, C25, C26; + int16 Px, Py, Pz; + + E4 = E3 = E2 = E = E5 = 0; + + DSP1_NormalizeDouble((int32) X - DSP1.Gx, &Px, &E4); + DSP1_NormalizeDouble((int32) Y - DSP1.Gy, &Py, &E ); + DSP1_NormalizeDouble((int32) Z - DSP1.Gz, &Pz, &E3); + Px >>= 1; // to avoid overflows when calculating the scalar products + E4--; + Py >>= 1; + E--; + Pz >>= 1; + E3--; + + refE = (E < E3) ? E : E3; + refE = (refE < E4) ? refE : E4; + + Px = DSP1_ShiftR(Px, E4 - refE); // normalize them to the same exponent + Py = DSP1_ShiftR(Py, E - refE); + Pz = DSP1_ShiftR(Pz, E3 - refE); + + C11 =- (Px * DSP1.Nx >> 15); + C8 =- (Py * DSP1.Ny >> 15); + C9 =- (Pz * DSP1.Nz >> 15); + C12 = C11 + C8 + C9; // this cannot overflow! + + aux4 = C12; // de-normalization with 32-bits arithmetic + refE = 16 - refE; // refE can be up to 3 + if (refE >= 0) + aux4 <<= (refE); + else + aux4 >>= -(refE); + if (aux4 == -1) + aux4 = 0; // why? + aux4 >>= 1; + + aux = ((uint16) DSP1.G_Les) + aux4; // Les - the scalar product of P with the normal vector of the screen + DSP1_NormalizeDouble(aux, &C10, &E2); + E2 = 15 - E2; + + DSP1_Inverse(C10, 0, &C4, &E4); + C2 = C4 * DSP1.C_Les >> 15; // scale factor + + // H + E7 = 0; + C16 = Px * ( DSP1.CosAas * 0x7fff >> 15) >> 15; + C20 = Py * ( DSP1.SinAas * 0x7fff >> 15) >> 15; + C17 = C16 + C20; // scalar product of P with the normalized horizontal vector of the screen... + + C18 = C17 * C2 >> 15; // ... multiplied by the scale factor + DSP1_Normalize(C18, &C19, &E7); + *H = DSP1_Truncate(C19, DSP1.E_Les - E2 + refE + E7); + + // V + E6 = 0; + C21 = Px * ( DSP1.CosAzs * -DSP1.SinAas >> 15) >> 15; + C22 = Py * ( DSP1.CosAzs * DSP1.CosAas >> 15) >> 15; + C23 = Pz * (-DSP1.SinAzs * 0x7fff >> 15) >> 15; + C24 = C21 + C22 + C23; // scalar product of P with the normalized vertical vector of the screen... + + C26 = C24 * C2 >> 15; // ... multiplied by the scale factor + DSP1_Normalize(C26, &C25, &E6); + *V = DSP1_Truncate(C25, DSP1.E_Les - E2 + refE + E6); + + // M + DSP1_Normalize(C2, &C6, &E4); + *M = DSP1_Truncate(C6, E4 + DSP1.E_Les - E2 - 7); // M is the scale factor divided by 2^7 +} + +static void DSP1_Op06 (void) +{ + DSP1_Project(DSP1.Op06X, DSP1.Op06Y, DSP1.Op06Z, &DSP1.Op06H, &DSP1.Op06V, &DSP1.Op06M); +} + +static void DSP1_Op01 (void) +{ + int16 SinAz = DSP1_Sin(DSP1.Op01Zr); + int16 CosAz = DSP1_Cos(DSP1.Op01Zr); + int16 SinAy = DSP1_Sin(DSP1.Op01Yr); + int16 CosAy = DSP1_Cos(DSP1.Op01Yr); + int16 SinAx = DSP1_Sin(DSP1.Op01Xr); + int16 CosAx = DSP1_Cos(DSP1.Op01Xr); + + DSP1.Op01m >>= 1; + + DSP1.matrixA[0][0] = (DSP1.Op01m * CosAz >> 15) * CosAy >> 15; + DSP1.matrixA[0][1] = -((DSP1.Op01m * SinAz >> 15) * CosAy >> 15); + DSP1.matrixA[0][2] = DSP1.Op01m * SinAy >> 15; + + DSP1.matrixA[1][0] = ((DSP1.Op01m * SinAz >> 15) * CosAx >> 15) + (((DSP1.Op01m * CosAz >> 15) * SinAx >> 15) * SinAy >> 15); + DSP1.matrixA[1][1] = ((DSP1.Op01m * CosAz >> 15) * CosAx >> 15) - (((DSP1.Op01m * SinAz >> 15) * SinAx >> 15) * SinAy >> 15); + DSP1.matrixA[1][2] = -((DSP1.Op01m * SinAx >> 15) * CosAy >> 15); + + DSP1.matrixA[2][0] = ((DSP1.Op01m * SinAz >> 15) * SinAx >> 15) - (((DSP1.Op01m * CosAz >> 15) * CosAx >> 15) * SinAy >> 15); + DSP1.matrixA[2][1] = ((DSP1.Op01m * CosAz >> 15) * SinAx >> 15) + (((DSP1.Op01m * SinAz >> 15) * CosAx >> 15) * SinAy >> 15); + DSP1.matrixA[2][2] = (DSP1.Op01m * CosAx >> 15) * CosAy >> 15; +} + +static void DSP1_Op11 (void) +{ + int16 SinAz = DSP1_Sin(DSP1.Op11Zr); + int16 CosAz = DSP1_Cos(DSP1.Op11Zr); + int16 SinAy = DSP1_Sin(DSP1.Op11Yr); + int16 CosAy = DSP1_Cos(DSP1.Op11Yr); + int16 SinAx = DSP1_Sin(DSP1.Op11Xr); + int16 CosAx = DSP1_Cos(DSP1.Op11Xr); + + DSP1.Op11m >>= 1; + + DSP1.matrixB[0][0] = (DSP1.Op11m * CosAz >> 15) * CosAy >> 15; + DSP1.matrixB[0][1] = -((DSP1.Op11m * SinAz >> 15) * CosAy >> 15); + DSP1.matrixB[0][2] = DSP1.Op11m * SinAy >> 15; + + DSP1.matrixB[1][0] = ((DSP1.Op11m * SinAz >> 15) * CosAx >> 15) + (((DSP1.Op11m * CosAz >> 15) * SinAx >> 15) * SinAy >> 15); + DSP1.matrixB[1][1] = ((DSP1.Op11m * CosAz >> 15) * CosAx >> 15) - (((DSP1.Op11m * SinAz >> 15) * SinAx >> 15) * SinAy >> 15); + DSP1.matrixB[1][2] = -((DSP1.Op11m * SinAx >> 15) * CosAy >> 15); + + DSP1.matrixB[2][0] = ((DSP1.Op11m * SinAz >> 15) * SinAx >> 15) - (((DSP1.Op11m * CosAz >> 15) * CosAx >> 15) * SinAy >> 15); + DSP1.matrixB[2][1] = ((DSP1.Op11m * CosAz >> 15) * SinAx >> 15) + (((DSP1.Op11m * SinAz >> 15) * CosAx >> 15) * SinAy >> 15); + DSP1.matrixB[2][2] = (DSP1.Op11m * CosAx >> 15) * CosAy >> 15; +} + +static void DSP1_Op21 (void) +{ + int16 SinAz = DSP1_Sin(DSP1.Op21Zr); + int16 CosAz = DSP1_Cos(DSP1.Op21Zr); + int16 SinAy = DSP1_Sin(DSP1.Op21Yr); + int16 CosAy = DSP1_Cos(DSP1.Op21Yr); + int16 SinAx = DSP1_Sin(DSP1.Op21Xr); + int16 CosAx = DSP1_Cos(DSP1.Op21Xr); + + DSP1.Op21m >>= 1; + + DSP1.matrixC[0][0] = (DSP1.Op21m * CosAz >> 15) * CosAy >> 15; + DSP1.matrixC[0][1] = -((DSP1.Op21m * SinAz >> 15) * CosAy >> 15); + DSP1.matrixC[0][2] = DSP1.Op21m * SinAy >> 15; + + DSP1.matrixC[1][0] = ((DSP1.Op21m * SinAz >> 15) * CosAx >> 15) + (((DSP1.Op21m * CosAz >> 15) * SinAx >> 15) * SinAy >> 15); + DSP1.matrixC[1][1] = ((DSP1.Op21m * CosAz >> 15) * CosAx >> 15) - (((DSP1.Op21m * SinAz >> 15) * SinAx >> 15) * SinAy >> 15); + DSP1.matrixC[1][2] = -((DSP1.Op21m * SinAx >> 15) * CosAy >> 15); + + DSP1.matrixC[2][0] = ((DSP1.Op21m * SinAz >> 15) * SinAx >> 15) - (((DSP1.Op21m * CosAz >> 15) * CosAx >> 15) * SinAy >> 15); + DSP1.matrixC[2][1] = ((DSP1.Op21m * CosAz >> 15) * SinAx >> 15) + (((DSP1.Op21m * SinAz >> 15) * CosAx >> 15) * SinAy >> 15); + DSP1.matrixC[2][2] = (DSP1.Op21m * CosAx >> 15) * CosAy >> 15; +} + +static void DSP1_Op0D (void) +{ + DSP1.Op0DF = (DSP1.Op0DX * DSP1.matrixA[0][0] >> 15) + (DSP1.Op0DY * DSP1.matrixA[0][1] >> 15) + (DSP1.Op0DZ * DSP1.matrixA[0][2] >> 15); + DSP1.Op0DL = (DSP1.Op0DX * DSP1.matrixA[1][0] >> 15) + (DSP1.Op0DY * DSP1.matrixA[1][1] >> 15) + (DSP1.Op0DZ * DSP1.matrixA[1][2] >> 15); + DSP1.Op0DU = (DSP1.Op0DX * DSP1.matrixA[2][0] >> 15) + (DSP1.Op0DY * DSP1.matrixA[2][1] >> 15) + (DSP1.Op0DZ * DSP1.matrixA[2][2] >> 15); + +#ifdef DebugDSP1 + Log_Message("OP0D X: %d Y: %d Z: %d / F: %d L: %d U: %d", DSP1.Op0DX, DSP1.Op0DY, DSP1.Op0DZ, DSP1.Op0DF, DSP1.Op0DL, DSP1.Op0DU); +#endif +} + +static void DSP1_Op1D (void) +{ + DSP1.Op1DF = (DSP1.Op1DX * DSP1.matrixB[0][0] >> 15) + (DSP1.Op1DY * DSP1.matrixB[0][1] >> 15) + (DSP1.Op1DZ * DSP1.matrixB[0][2] >> 15); + DSP1.Op1DL = (DSP1.Op1DX * DSP1.matrixB[1][0] >> 15) + (DSP1.Op1DY * DSP1.matrixB[1][1] >> 15) + (DSP1.Op1DZ * DSP1.matrixB[1][2] >> 15); + DSP1.Op1DU = (DSP1.Op1DX * DSP1.matrixB[2][0] >> 15) + (DSP1.Op1DY * DSP1.matrixB[2][1] >> 15) + (DSP1.Op1DZ * DSP1.matrixB[2][2] >> 15); + +#ifdef DebugDSP1 + Log_Message("OP1D X: %d Y: %d Z: %d / F: %d L: %d U: %d", DSP1.Op1DX, DSP1.Op1DY, DSP1.Op1DZ, DSP1.Op1DF, DSP1.Op1DL, DSP1.Op1DU); +#endif +} + +static void DSP1_Op2D (void) +{ + DSP1.Op2DF = (DSP1.Op2DX * DSP1.matrixC[0][0] >> 15) + (DSP1.Op2DY * DSP1.matrixC[0][1] >> 15) + (DSP1.Op2DZ * DSP1.matrixC[0][2] >> 15); + DSP1.Op2DL = (DSP1.Op2DX * DSP1.matrixC[1][0] >> 15) + (DSP1.Op2DY * DSP1.matrixC[1][1] >> 15) + (DSP1.Op2DZ * DSP1.matrixC[1][2] >> 15); + DSP1.Op2DU = (DSP1.Op2DX * DSP1.matrixC[2][0] >> 15) + (DSP1.Op2DY * DSP1.matrixC[2][1] >> 15) + (DSP1.Op2DZ * DSP1.matrixC[2][2] >> 15); + +#ifdef DebugDSP1 + Log_Message("OP2D X: %d Y: %d Z: %d / F: %d L: %d U: %d", DSP1.Op2DX, DSP1.Op2DY, DSP1.Op2DZ, DSP1.Op2DF, DSP1.Op2DL, DSP1.Op2DU); +#endif +} + +static void DSP1_Op03 (void) +{ + DSP1.Op03X = (DSP1.Op03F * DSP1.matrixA[0][0] >> 15) + (DSP1.Op03L * DSP1.matrixA[1][0] >> 15) + (DSP1.Op03U * DSP1.matrixA[2][0] >> 15); + DSP1.Op03Y = (DSP1.Op03F * DSP1.matrixA[0][1] >> 15) + (DSP1.Op03L * DSP1.matrixA[1][1] >> 15) + (DSP1.Op03U * DSP1.matrixA[2][1] >> 15); + DSP1.Op03Z = (DSP1.Op03F * DSP1.matrixA[0][2] >> 15) + (DSP1.Op03L * DSP1.matrixA[1][2] >> 15) + (DSP1.Op03U * DSP1.matrixA[2][2] >> 15); + +#ifdef DebugDSP1 + Log_Message("OP03 F: %d L: %d U: %d / X: %d Y: %d Z: %d", DSP1.Op03F, DSP1.Op03L, DSP1.Op03U, DSP1.Op03X, DSP1.Op03Y, DSP1.Op03Z); +#endif +} + +static void DSP1_Op13 (void) +{ + DSP1.Op13X = (DSP1.Op13F * DSP1.matrixB[0][0] >> 15) + (DSP1.Op13L * DSP1.matrixB[1][0] >> 15) + (DSP1.Op13U * DSP1.matrixB[2][0] >> 15); + DSP1.Op13Y = (DSP1.Op13F * DSP1.matrixB[0][1] >> 15) + (DSP1.Op13L * DSP1.matrixB[1][1] >> 15) + (DSP1.Op13U * DSP1.matrixB[2][1] >> 15); + DSP1.Op13Z = (DSP1.Op13F * DSP1.matrixB[0][2] >> 15) + (DSP1.Op13L * DSP1.matrixB[1][2] >> 15) + (DSP1.Op13U * DSP1.matrixB[2][2] >> 15); + +#ifdef DebugDSP1 + Log_Message("OP13 F: %d L: %d U: %d / X: %d Y: %d Z: %d", DSP1.Op13F, DSP1.Op13L, DSP1.Op13U, DSP1.Op13X, DSP1.Op13Y, DSP1.Op13Z); +#endif +} + +static void DSP1_Op23 (void) +{ + DSP1.Op23X = (DSP1.Op23F * DSP1.matrixC[0][0] >> 15) + (DSP1.Op23L * DSP1.matrixC[1][0] >> 15) + (DSP1.Op23U * DSP1.matrixC[2][0] >> 15); + DSP1.Op23Y = (DSP1.Op23F * DSP1.matrixC[0][1] >> 15) + (DSP1.Op23L * DSP1.matrixC[1][1] >> 15) + (DSP1.Op23U * DSP1.matrixC[2][1] >> 15); + DSP1.Op23Z = (DSP1.Op23F * DSP1.matrixC[0][2] >> 15) + (DSP1.Op23L * DSP1.matrixC[1][2] >> 15) + (DSP1.Op23U * DSP1.matrixC[2][2] >> 15); + +#ifdef DebugDSP1 + Log_Message("OP23 F: %d L: %d U: %d / X: %d Y: %d Z: %d", DSP1.Op23F, DSP1.Op23L, DSP1.Op23U, DSP1.Op23X, DSP1.Op23Y, DSP1.Op23Z); +#endif +} + +static void DSP1_Op14 (void) +{ + int16 CSec, ESec, CTan, CSin, C, E; + + DSP1_Inverse(DSP1_Cos(DSP1.Op14Xr), 0, &CSec, &ESec); + + // Rotation Around Z + DSP1_NormalizeDouble(DSP1.Op14U * DSP1_Cos(DSP1.Op14Yr) - DSP1.Op14F * DSP1_Sin(DSP1.Op14Yr), &C, &E); + + E = ESec - E; + + DSP1_Normalize(C * CSec >> 15, &C, &E); + + DSP1.Op14Zrr = DSP1.Op14Zr + DSP1_Truncate(C, E); + + // Rotation Around X + DSP1.Op14Xrr = DSP1.Op14Xr + (DSP1.Op14U * DSP1_Sin(DSP1.Op14Yr) >> 15) + (DSP1.Op14F * DSP1_Cos(DSP1.Op14Yr) >> 15); + + // Rotation Around Y + DSP1_NormalizeDouble(DSP1.Op14U * DSP1_Cos(DSP1.Op14Yr) + DSP1.Op14F * DSP1_Sin(DSP1.Op14Yr), &C, &E); + + E = ESec - E; + + DSP1_Normalize(DSP1_Sin(DSP1.Op14Xr), &CSin, &E); + + CTan = CSec * CSin >> 15; + + DSP1_Normalize(-(C * CTan >> 15), &C, &E); + + DSP1.Op14Yrr = DSP1.Op14Yr + DSP1_Truncate(C, E) + DSP1.Op14L; +} + +static void DSP1_Target (int16 H, int16 V, int16 *X, int16 *Y) +{ + int16 C, E, C1, E1; + + DSP1_Inverse((V * DSP1.SinAzs >> 15) + DSP1.VOffset, 8, &C, &E); + E += DSP1.VPlane_E; + + C1 = C * DSP1.VPlane_C >> 15; + E1 = E + DSP1.SecAZS_E1; + + H <<= 8; + + DSP1_Normalize(C1, &C, &E); + + C = DSP1_Truncate(C, E) * H >> 15; + + *X = DSP1.CentreX + (C * DSP1.CosAas >> 15); + *Y = DSP1.CentreY - (C * DSP1.SinAas >> 15); + + V <<= 8; + + DSP1_Normalize(C1 * DSP1.SecAZS_C1 >> 15, &C, &E1); + + C = DSP1_Truncate(C, E1) * V >> 15; + + *X += C * -DSP1.SinAas >> 15; + *Y += C * DSP1.CosAas >> 15; +} + +static void DSP1_Op0E (void) +{ + DSP1_Target(DSP1.Op0EH, DSP1.Op0EV, &DSP1.Op0EX, &DSP1.Op0EY); +} + +static void DSP1_Op0B (void) +{ + DSP1.Op0BS = (DSP1.Op0BX * DSP1.matrixA[0][0] + DSP1.Op0BY * DSP1.matrixA[0][1] + DSP1.Op0BZ * DSP1.matrixA[0][2]) >> 15; + +#ifdef DebugDSP1 + Log_Message("OP0B"); +#endif +} + +static void DSP1_Op1B (void) +{ + DSP1.Op1BS = (DSP1.Op1BX * DSP1.matrixB[0][0] + DSP1.Op1BY * DSP1.matrixB[0][1] + DSP1.Op1BZ * DSP1.matrixB[0][2]) >> 15; + +#ifdef DebugDSP1 + Log_Message("OP1B X: %d Y: %d Z: %d S: %d", DSP1.Op1BX, DSP1.Op1BY, DSP1.Op1BZ, DSP1.Op1BS); + Log_Message(" MX: %d MY: %d MZ: %d Scale: %d", (int16) (DSP1.matrixB[0][0] * 100), (int16) (DSP1.matrixB[0][1] * 100), (int16) (DSP1.matrixB[0][2] * 100), (int16) (DSP1.Op1BS * 100)); +#endif +} + +static void DSP1_Op2B (void) +{ + DSP1.Op2BS = (DSP1.Op2BX * DSP1.matrixC[0][0] + DSP1.Op2BY * DSP1.matrixC[0][1] + DSP1.Op2BZ * DSP1.matrixC[0][2]) >> 15; + +#ifdef DebugDSP1 + Log_Message("OP2B"); +#endif +} + +static void DSP1_Op08 (void) +{ + int32 op08Size = (DSP1.Op08X * DSP1.Op08X + DSP1.Op08Y * DSP1.Op08Y + DSP1.Op08Z * DSP1.Op08Z) << 1; + DSP1.Op08Ll = op08Size & 0xffff; + DSP1.Op08Lh = (op08Size >> 16) & 0xffff; + +#ifdef DebugDSP1 + Log_Message("OP08 %d,%d,%d", DSP1.Op08X, DSP1.Op08Y, DSP1.Op08Z); + Log_Message("OP08 ((OP08X^2)+(OP08Y^2)+(OP08Z^2))=%x", op08Size); +#endif +} + +static void DSP1_Op18 (void) +{ + DSP1.Op18D = (DSP1.Op18X * DSP1.Op18X + DSP1.Op18Y * DSP1.Op18Y + DSP1.Op18Z * DSP1.Op18Z - DSP1.Op18R * DSP1.Op18R) >> 15; + +#ifdef DebugDSP1 + Log_Message("OP18 X: %d Y: %d Z: %d R: %D DIFF %d", DSP1.Op18X, DSP1.Op18Y, DSP1.Op38Z, DSP1.Op18D); +#endif +} + +static void DSP1_Op38 (void) +{ + DSP1.Op38D = (DSP1.Op38X * DSP1.Op38X + DSP1.Op38Y * DSP1.Op38Y + DSP1.Op38Z * DSP1.Op38Z - DSP1.Op38R * DSP1.Op38R) >> 15; + DSP1.Op38D++; + +#ifdef DebugDSP1 + Log_Message("OP38 X: %d Y: %d Z: %d R: %D DIFF %d", DSP1.Op38X, DSP1.Op38Y, DSP1.Op38Z, DSP1.Op38D); +#endif +} + +static void DSP1_Op28 (void) +{ + int32 Radius = DSP1.Op28X * DSP1.Op28X + DSP1.Op28Y * DSP1.Op28Y + DSP1.Op28Z * DSP1.Op28Z; + + if (Radius == 0) + DSP1.Op28R = 0; + else + { + int16 C, E, Pos, Node1, Node2; + + DSP1_NormalizeDouble(Radius, &C, &E); + if (E & 1) + C = C * 0x4000 >> 15; + + Pos = C * 0x0040 >> 15; + + Node1 = DSP1ROM[0x00d5 + Pos]; + Node2 = DSP1ROM[0x00d6 + Pos]; + + DSP1.Op28R = ((Node2 - Node1) * (C & 0x1ff) >> 9) + Node1; + DSP1.Op28R >>= (E >> 1); + } + +#ifdef DebugDSP1 + Log_Message("OP28 X:%d Y:%d Z:%d", DSP1.Op28X, DSP1.Op28Y, DSP1.Op28Z); + Log_Message("OP28 Vector Length %d", DSP1.Op28R); +#endif +} + +static void DSP1_Op1C (void) +{ + // Rotate Around Op1CZ1 + DSP1.Op1CX1 = (DSP1.Op1CYBR * DSP1_Sin(DSP1.Op1CZ) >> 15) + (DSP1.Op1CXBR * DSP1_Cos(DSP1.Op1CZ) >> 15); + DSP1.Op1CY1 = (DSP1.Op1CYBR * DSP1_Cos(DSP1.Op1CZ) >> 15) - (DSP1.Op1CXBR * DSP1_Sin(DSP1.Op1CZ) >> 15); + DSP1.Op1CXBR = DSP1.Op1CX1; + DSP1.Op1CYBR = DSP1.Op1CY1; + + // Rotate Around Op1CY1 + DSP1.Op1CZ1 = (DSP1.Op1CXBR * DSP1_Sin(DSP1.Op1CY) >> 15) + (DSP1.Op1CZBR * DSP1_Cos(DSP1.Op1CY) >> 15); + DSP1.Op1CX1 = (DSP1.Op1CXBR * DSP1_Cos(DSP1.Op1CY) >> 15) - (DSP1.Op1CZBR * DSP1_Sin(DSP1.Op1CY) >> 15); + DSP1.Op1CXAR = DSP1.Op1CX1; + DSP1.Op1CZBR = DSP1.Op1CZ1; + + // Rotate Around Op1CX1 + DSP1.Op1CY1 = (DSP1.Op1CZBR * DSP1_Sin(DSP1.Op1CX) >> 15) + (DSP1.Op1CYBR * DSP1_Cos(DSP1.Op1CX) >> 15); + DSP1.Op1CZ1 = (DSP1.Op1CZBR * DSP1_Cos(DSP1.Op1CX) >> 15) - (DSP1.Op1CYBR * DSP1_Sin(DSP1.Op1CX) >> 15); + DSP1.Op1CYAR = DSP1.Op1CY1; + DSP1.Op1CZAR = DSP1.Op1CZ1; + +#ifdef DebugDSP1 + Log_Message("OP1C Apply Matrix CX:%d CY:%d CZ", DSP1.Op1CXAR, DSP1.Op1CYAR, DSP1.Op1CZAR); +#endif +} + +static void DSP1_Op0F (void) +{ + DSP1.Op0FPass = 0x0000; + +#ifdef DebugDSP1 + Log_Message("OP0F RAM Test Pass:%d", DSP1.Op0FPass); +#endif +} + +static void DSP1_Op2F (void) +{ + DSP1.Op2FSize = 0x100; +} + +void DSP1SetByte (uint8 byte, uint16 address) +{ + if (address < DSP0.boundary) + { + if ((DSP1.command == 0x0A || DSP1.command == 0x1A) && DSP1.out_count != 0) + { + DSP1.out_count--; + DSP1.out_index++; + return; + } + else + if (DSP1.waiting4command) + { + DSP1.command = byte; + DSP1.in_index = 0; + DSP1.waiting4command = FALSE; + DSP1.first_parameter = TRUE; + #ifdef DEBUGGER + //printf("OP%02X\n",byte); + #endif + + switch (byte) + { + case 0x00: DSP1.in_count = 2; break; + case 0x30: + case 0x10: DSP1.in_count = 2; break; + case 0x20: DSP1.in_count = 2; break; + case 0x24: + case 0x04: DSP1.in_count = 2; break; + case 0x08: DSP1.in_count = 3; break; + case 0x18: DSP1.in_count = 4; break; + case 0x28: DSP1.in_count = 3; break; + case 0x38: DSP1.in_count = 4; break; + case 0x2c: + case 0x0c: DSP1.in_count = 3; break; + case 0x3c: + case 0x1c: DSP1.in_count = 6; break; + case 0x32: + case 0x22: + case 0x12: + case 0x02: DSP1.in_count = 7; break; + case 0x0a: DSP1.in_count = 1; break; + case 0x3a: + case 0x2a: + case 0x1a: + DSP1.command = 0x1a; + DSP1.in_count = 1; + break; + case 0x16: + case 0x26: + case 0x36: + case 0x06: DSP1.in_count = 3; break; + case 0x1e: + case 0x2e: + case 0x3e: + case 0x0e: DSP1.in_count = 2; break; + case 0x05: + case 0x35: + case 0x31: + case 0x01: DSP1.in_count = 4; break; + case 0x15: + case 0x11: DSP1.in_count = 4; break; + case 0x25: + case 0x21: DSP1.in_count = 4; break; + case 0x09: + case 0x39: + case 0x3d: + case 0x0d: DSP1.in_count = 3; break; + case 0x19: + case 0x1d: DSP1.in_count = 3; break; + case 0x29: + case 0x2d: DSP1.in_count = 3; break; + case 0x33: + case 0x03: DSP1.in_count = 3; break; + case 0x13: DSP1.in_count = 3; break; + case 0x23: DSP1.in_count = 3; break; + case 0x3b: + case 0x0b: DSP1.in_count = 3; break; + case 0x1b: DSP1.in_count = 3; break; + case 0x2b: DSP1.in_count = 3; break; + case 0x34: + case 0x14: DSP1.in_count = 6; break; + case 0x07: + case 0x0f: DSP1.in_count = 1; break; + case 0x27: + case 0x2F: DSP1.in_count = 1; break; + case 0x17: + case 0x37: + case 0x3F: + DSP1.command = 0x1f; + case 0x1f: DSP1.in_count = 1; break; + default: + #ifdef DEBUGGER + //printf("OP%02X\n", byte); + #endif + case 0x80: + DSP1.in_count = 0; + DSP1.waiting4command = TRUE; + DSP1.first_parameter = TRUE; + break; + } + + DSP1.in_count <<= 1; + } + else + { + DSP1.parameters[DSP1.in_index] = byte; + DSP1.first_parameter = FALSE; + DSP1.in_index++; + } + + if (DSP1.waiting4command || (DSP1.first_parameter && byte == 0x80)) + { + DSP1.waiting4command = TRUE; + DSP1.first_parameter = FALSE; + } + else + if (DSP1.first_parameter && (DSP1.in_count != 0 || (DSP1.in_count == 0 && DSP1.in_index == 0))) + ; + else + { + if (DSP1.in_count) + { + if (--DSP1.in_count == 0) + { + // Actually execute the command + DSP1.waiting4command = TRUE; + DSP1.out_index = 0; + + switch (DSP1.command) + { + case 0x1f: + DSP1.out_count = 2048; + break; + + case 0x00: // Multiple + DSP1.Op00Multiplicand = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op00Multiplier = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + + DSP1_Op00(); + + DSP1.out_count = 2; + DSP1.output[0] = DSP1.Op00Result & 0xFF; + DSP1.output[1] = (DSP1.Op00Result >> 8) & 0xFF; + break; + + case 0x20: // Multiple + DSP1.Op20Multiplicand = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op20Multiplier = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + + DSP1_Op20(); + + DSP1.out_count = 2; + DSP1.output[0] = DSP1.Op20Result & 0xFF; + DSP1.output[1] = (DSP1.Op20Result >> 8) & 0xFF; + break; + + case 0x30: + case 0x10: // Inverse + DSP1.Op10Coefficient = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op10Exponent = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + + DSP1_Op10(); + + DSP1.out_count = 4; + DSP1.output[0] = (uint8) ( ((int16) DSP1.Op10CoefficientR) & 0xFF); + DSP1.output[1] = (uint8) ((((int16) DSP1.Op10CoefficientR) >> 8) & 0xFF); + DSP1.output[2] = (uint8) ( ((int16) DSP1.Op10ExponentR ) & 0xFF); + DSP1.output[3] = (uint8) ((((int16) DSP1.Op10ExponentR ) >> 8) & 0xFF); + break; + + case 0x24: + case 0x04: // Sin and Cos of angle + DSP1.Op04Angle = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op04Radius = (uint16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + + DSP1_Op04(); + + DSP1.out_count = 4; + DSP1.output[0] = (uint8) (DSP1.Op04Sin & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op04Sin >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op04Cos & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op04Cos >> 8) & 0xFF); + break; + + case 0x08: // Radius + DSP1.Op08X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op08Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op08Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op08(); + + DSP1.out_count = 4; + DSP1.output[0] = (uint8) ( ((int16) DSP1.Op08Ll) & 0xFF); + DSP1.output[1] = (uint8) ((((int16) DSP1.Op08Ll) >> 8) & 0xFF); + DSP1.output[2] = (uint8) ( ((int16) DSP1.Op08Lh) & 0xFF); + DSP1.output[3] = (uint8) ((((int16) DSP1.Op08Lh) >> 8) & 0xFF); + break; + + case 0x18: // Range + + DSP1.Op18X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op18Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op18Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + DSP1.Op18R = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8)); + + DSP1_Op18(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op18D & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op18D >> 8) & 0xFF); + break; + + case 0x38: // Range + + DSP1.Op38X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op38Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op38Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + DSP1.Op38R = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8)); + + DSP1_Op38(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op38D & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op38D >> 8) & 0xFF); + break; + + case 0x28: // Distance (vector length) + DSP1.Op28X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op28Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op28Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op28(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op28R & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op28R >> 8) & 0xFF); + break; + + case 0x2c: + case 0x0c: // Rotate (2D rotate) + DSP1.Op0CA = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op0CX1 = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op0CY1 = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op0C(); + + DSP1.out_count = 4; + DSP1.output[0] = (uint8) (DSP1.Op0CX2 & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op0CX2 >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op0CY2 & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op0CY2 >> 8) & 0xFF); + break; + + case 0x3c: + case 0x1c: // Polar (3D rotate) + DSP1.Op1CZ = (DSP1.parameters[ 0] | (DSP1.parameters[ 1] << 8)); + //MK: reversed X and Y on neviksti and John's advice. + DSP1.Op1CY = (DSP1.parameters[ 2] | (DSP1.parameters[ 3] << 8)); + DSP1.Op1CX = (DSP1.parameters[ 4] | (DSP1.parameters[ 5] << 8)); + DSP1.Op1CXBR = (DSP1.parameters[ 6] | (DSP1.parameters[ 7] << 8)); + DSP1.Op1CYBR = (DSP1.parameters[ 8] | (DSP1.parameters[ 9] << 8)); + DSP1.Op1CZBR = (DSP1.parameters[10] | (DSP1.parameters[11] << 8)); + + DSP1_Op1C(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op1CXAR & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op1CXAR >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op1CYAR & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op1CYAR >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op1CZAR & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op1CZAR >> 8) & 0xFF); + break; + + case 0x32: + case 0x22: + case 0x12: + case 0x02: // Parameter (Projection) + DSP1.Op02FX = (int16) (DSP1.parameters[ 0] | (DSP1.parameters[ 1] << 8)); + DSP1.Op02FY = (int16) (DSP1.parameters[ 2] | (DSP1.parameters[ 3] << 8)); + DSP1.Op02FZ = (int16) (DSP1.parameters[ 4] | (DSP1.parameters[ 5] << 8)); + DSP1.Op02LFE = (int16) (DSP1.parameters[ 6] | (DSP1.parameters[ 7] << 8)); + DSP1.Op02LES = (int16) (DSP1.parameters[ 8] | (DSP1.parameters[ 9] << 8)); + DSP1.Op02AAS = (uint16) (DSP1.parameters[10] | (DSP1.parameters[11] << 8)); + DSP1.Op02AZS = (uint16) (DSP1.parameters[12] | (DSP1.parameters[13] << 8)); + + DSP1_Op02(); + + DSP1.out_count = 8; + DSP1.output[0] = (uint8) (DSP1.Op02VOF & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op02VOF >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op02VVA & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op02VVA >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op02CX & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op02CX >> 8) & 0xFF); + DSP1.output[6] = (uint8) (DSP1.Op02CY & 0xFF); + DSP1.output[7] = (uint8) ((DSP1.Op02CY >> 8) & 0xFF); + break; + + case 0x3a: + case 0x2a: + case 0x1a: // Raster mode 7 matrix data + case 0x0a: + DSP1.Op0AVS = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + + DSP1_Op0A(); + + DSP1.out_count = 8; + DSP1.output[0] = (uint8) (DSP1.Op0AA & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op0AA >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op0AB & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op0AB >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op0AC & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op0AC >> 8) & 0xFF); + DSP1.output[6] = (uint8) (DSP1.Op0AD & 0xFF); + DSP1.output[7] = (uint8) ((DSP1.Op0AD >> 8) & 0xFF); + DSP1.in_index = 0; + break; + + case 0x16: + case 0x26: + case 0x36: + case 0x06: // Project object + DSP1.Op06X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op06Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op06Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op06(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op06H & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op06H >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op06V & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op06V >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op06M & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op06M >> 8) & 0xFF); + break; + + case 0x1e: + case 0x2e: + case 0x3e: + case 0x0e: // Target + DSP1.Op0EH = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op0EV = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + + DSP1_Op0E(); + + DSP1.out_count = 4; + DSP1.output[0] = (uint8) (DSP1.Op0EX & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op0EX >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op0EY & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op0EY >> 8) & 0xFF); + break; + + // Extra commands used by Pilot Wings + case 0x05: + case 0x35: + case 0x31: + case 0x01: // Set attitude matrix A + DSP1.Op01m = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op01Zr = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op01Yr = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + DSP1.Op01Xr = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8)); + + DSP1_Op01(); + break; + + case 0x15: + case 0x11: // Set attitude matrix B + DSP1.Op11m = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op11Zr = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op11Yr = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + DSP1.Op11Xr = (int16) (DSP1.parameters[7] | (DSP1.parameters[7] << 8)); + + DSP1_Op11(); + break; + + case 0x25: + case 0x21: // Set attitude matrix C + DSP1.Op21m = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op21Zr = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op21Yr = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + DSP1.Op21Xr = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8)); + + DSP1_Op21(); + break; + + case 0x09: + case 0x39: + case 0x3d: + case 0x0d: // Objective matrix A + DSP1.Op0DX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op0DY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op0DZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op0D(); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (DSP1.Op0DF & 0xFF); + DSP1.output [1] = (uint8) ((DSP1.Op0DF >> 8) & 0xFF); + DSP1.output [2] = (uint8) (DSP1.Op0DL & 0xFF); + DSP1.output [3] = (uint8) ((DSP1.Op0DL >> 8) & 0xFF); + DSP1.output [4] = (uint8) (DSP1.Op0DU & 0xFF); + DSP1.output [5] = (uint8) ((DSP1.Op0DU >> 8) & 0xFF); + break; + + case 0x19: + case 0x1d: // Objective matrix B + DSP1.Op1DX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op1DY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op1DZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op1D(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op1DF & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op1DF >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op1DL & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op1DL >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op1DU & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op1DU >> 8) & 0xFF); + break; + + case 0x29: + case 0x2d: // Objective matrix C + DSP1.Op2DX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op2DY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op2DZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op2D(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op2DF & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op2DF >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op2DL & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op2DL >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op2DU & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op2DU >> 8) & 0xFF); + break; + + case 0x33: + case 0x03: // Subjective matrix A + DSP1.Op03F = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op03L = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op03U = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op03(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op03X & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op03X >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op03Y & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op03Y >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op03Z & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op03Z >> 8) & 0xFF); + break; + + case 0x13: // Subjective matrix B + DSP1.Op13F = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op13L = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op13U = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op13(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op13X & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op13X >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op13Y & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op13Y >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op13Z & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op13Z >> 8) & 0xFF); + break; + + case 0x23: // Subjective matrix C + DSP1.Op23F = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op23L = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op23U = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op23(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op23X & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op23X >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op23Y & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op23Y >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op23Z & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op23Z >> 8) & 0xFF); + break; + + case 0x3b: + case 0x0b: + DSP1.Op0BX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op0BY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op0BZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op0B(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op0BS & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op0BS >> 8) & 0xFF); + break; + + case 0x1b: + DSP1.Op1BX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op1BY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op1BZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op1B(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op1BS & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op1BS >> 8) & 0xFF); + break; + + case 0x2b: + DSP1.Op2BX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op2BY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op2BZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op2B(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op2BS & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op2BS >> 8) & 0xFF); + break; + + case 0x34: + case 0x14: + DSP1.Op14Zr = (int16) (DSP1.parameters[ 0] | (DSP1.parameters[ 1] << 8)); + DSP1.Op14Xr = (int16) (DSP1.parameters[ 2] | (DSP1.parameters[ 3] << 8)); + DSP1.Op14Yr = (int16) (DSP1.parameters[ 4] | (DSP1.parameters[ 5] << 8)); + DSP1.Op14U = (int16) (DSP1.parameters[ 6] | (DSP1.parameters[ 7] << 8)); + DSP1.Op14F = (int16) (DSP1.parameters[ 8] | (DSP1.parameters[ 9] << 8)); + DSP1.Op14L = (int16) (DSP1.parameters[10] | (DSP1.parameters[11] << 8)); + + DSP1_Op14(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op14Zrr & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op14Zrr >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op14Xrr & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op14Xrr >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op14Yrr & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op14Yrr >> 8) & 0xFF); + break; + + case 0x27: + case 0x2F: + DSP1.Op2FUnknown = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + + DSP1_Op2F(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op2FSize & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op2FSize >> 8) & 0xFF); + break; + + + case 0x07: + case 0x0F: + DSP1.Op0FRamsize = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + + DSP1_Op0F(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op0FPass & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op0FPass >> 8) & 0xFF); + break; + + default: + break; + } + } + } + } + } +} + +uint8 DSP1GetByte (uint16 address) +{ + uint8 t; + + if (address < DSP0.boundary) + { + if (DSP1.out_count) + { + t = (uint8) DSP1.output[DSP1.out_index]; + + DSP1.out_index++; + + if (--DSP1.out_count == 0) + { + if (DSP1.command == 0x1a || DSP1.command == 0x0a) + { + DSP1_Op0A(); + DSP1.out_count = 8; + DSP1.out_index = 0; + DSP1.output[0] = DSP1.Op0AA & 0xFF; + DSP1.output[1] = (DSP1.Op0AA >> 8) & 0xFF; + DSP1.output[2] = DSP1.Op0AB & 0xFF; + DSP1.output[3] = (DSP1.Op0AB >> 8) & 0xFF; + DSP1.output[4] = DSP1.Op0AC & 0xFF; + DSP1.output[5] = (DSP1.Op0AC >> 8) & 0xFF; + DSP1.output[6] = DSP1.Op0AD & 0xFF; + DSP1.output[7] = (DSP1.Op0AD >> 8) & 0xFF; + } + + if (DSP1.command == 0x1f) + { + if ((DSP1.out_index % 2) != 0) + t = (uint8) DSP1ROM[DSP1.out_index >> 1]; + else + t = DSP1ROM[DSP1.out_index >> 1] >> 8; + } + } + + DSP1.waiting4command = TRUE; + } + else + t = 0xff; + } + else + t = 0x80; + + return (t); +} diff --git a/plugins/snes9x_gx/source/snes9x/dsp2.cpp b/plugins/snes9x_gx/source/snes9x/dsp2.cpp new file mode 100644 index 00000000..477209b4 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/dsp2.cpp @@ -0,0 +1,532 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" + +static void DSP2_Op01 (void); +static void DSP2_Op03 (void); +static void DSP2_Op05 (void); +static void DSP2_Op06 (void); +static void DSP2_Op09 (void); +static void DSP2_Op0D (void); + + +// convert bitmap to bitplane tile +static void DSP2_Op01 (void) +{ + // Op01 size is always 32 bytes input and output + // The hardware does strange things if you vary the size + + uint8 c0, c1, c2, c3; + uint8 *p1 = DSP2.parameters; + uint8 *p2a = DSP2.output; + uint8 *p2b = DSP2.output + 16; // halfway + + // Process 8 blocks of 4 bytes each + + for (int j = 0; j < 8; j++) + { + c0 = *p1++; + c1 = *p1++; + c2 = *p1++; + c3 = *p1++; + + *p2a++ = (c0 & 0x10) << 3 | + (c0 & 0x01) << 6 | + (c1 & 0x10) << 1 | + (c1 & 0x01) << 4 | + (c2 & 0x10) >> 1 | + (c2 & 0x01) << 2 | + (c3 & 0x10) >> 3 | + (c3 & 0x01); + + *p2a++ = (c0 & 0x20) << 2 | + (c0 & 0x02) << 5 | + (c1 & 0x20) | + (c1 & 0x02) << 3 | + (c2 & 0x20) >> 2 | + (c2 & 0x02) << 1 | + (c3 & 0x20) >> 4 | + (c3 & 0x02) >> 1; + + *p2b++ = (c0 & 0x40) << 1 | + (c0 & 0x04) << 4 | + (c1 & 0x40) >> 1 | + (c1 & 0x04) << 2 | + (c2 & 0x40) >> 3 | + (c2 & 0x04) | + (c3 & 0x40) >> 5 | + (c3 & 0x04) >> 2; + + *p2b++ = (c0 & 0x80) | + (c0 & 0x08) << 3 | + (c1 & 0x80) >> 2 | + (c1 & 0x08) << 1 | + (c2 & 0x80) >> 4 | + (c2 & 0x08) >> 1 | + (c3 & 0x80) >> 6 | + (c3 & 0x08) >> 3; + } +} + +// set transparent color +static void DSP2_Op03 (void) +{ + DSP2.Op05Transparent = DSP2.parameters[0]; +} + +// replace bitmap using transparent color +static void DSP2_Op05 (void) +{ + // Overlay bitmap with transparency. + // Input: + // + // Bitmap 1: i[0] <=> i[size-1] + // Bitmap 2: i[size] <=> i[2*size-1] + // + // Output: + // + // Bitmap 3: o[0] <=> o[size-1] + // + // Processing: + // + // Process all 4-bit pixels (nibbles) in the bitmap + // + // if ( BM2_pixel == transparent_color ) + // pixelout = BM1_pixel + // else + // pixelout = BM2_pixel + + // The max size bitmap is limited to 255 because the size parameter is a byte + // I think size=0 is an error. The behavior of the chip on size=0 is to + // return the last value written to DR if you read DR on Op05 with + // size = 0. I don't think it's worth implementing this quirk unless it's + // proven necessary. + + uint8 color; + uint8 c1, c2; + uint8 *p1 = DSP2.parameters; + uint8 *p2 = DSP2.parameters + DSP2.Op05Len; + uint8 *p3 = DSP2.output; + + color = DSP2.Op05Transparent & 0x0f; + + for (int32 n = 0; n < DSP2.Op05Len; n++) + { + c1 = *p1++; + c2 = *p2++; + *p3++ = (((c2 >> 4) == color) ? c1 & 0xf0: c2 & 0xf0) | (((c2 & 0x0f) == color) ? c1 & 0x0f: c2 & 0x0f); + } +} + +// reverse bitmap +static void DSP2_Op06 (void) +{ + // Input: + // size + // bitmap + + for (int32 i = 0, j = DSP2.Op06Len - 1; i < DSP2.Op06Len; i++, j--) + DSP2.output[j] = (DSP2.parameters[i] << 4) | (DSP2.parameters[i] >> 4); +} + +// multiply +static void DSP2_Op09 (void) +{ + DSP2.Op09Word1 = DSP2.parameters[0] | (DSP2.parameters[1] << 8); + DSP2.Op09Word2 = DSP2.parameters[2] | (DSP2.parameters[3] << 8); + + uint32 temp = DSP2.Op09Word1 * DSP2.Op09Word2; + DSP2.output[0] = temp & 0xFF; + DSP2.output[1] = (temp >> 8) & 0xFF; + DSP2.output[2] = (temp >> 16) & 0xFF; + DSP2.output[3] = (temp >> 24) & 0xFF; +} + +// scale bitmap +static void DSP2_Op0D (void) +{ + // Bit accurate hardware algorithm - uses fixed point math + // This should match the DSP2 Op0D output exactly + // I wouldn't recommend using this unless you're doing hardware debug. + // In some situations it has small visual artifacts that + // are not readily apparent on a TV screen but show up clearly + // on a monitor. Use Overload's scaling instead. + // This is for hardware verification testing. + // + // One note: the HW can do odd byte scaling but since we divide + // by two to get the count of bytes this won't work well for + // odd byte scaling (in any of the current algorithm implementations). + // So far I haven't seen Dungeon Master use it. + // If it does we can adjust the parameters and code to work with it + + uint32 multiplier; // Any size int >= 32-bits + uint32 pixloc; // match size of multiplier + uint8 pixelarray[512]; + + if (DSP2.Op0DInLen <= DSP2.Op0DOutLen) + multiplier = 0x10000; // In our self defined fixed point 0x10000 == 1 + else + multiplier = (DSP2.Op0DInLen << 17) / ((DSP2.Op0DOutLen << 1) + 1); + + pixloc = 0; + + for (int32 i = 0; i < DSP2.Op0DOutLen * 2; i++) + { + int32 j = pixloc >> 16; + + if (j & 1) + pixelarray[i] = DSP2.parameters[j >> 1] & 0x0f; + else + pixelarray[i] = (DSP2.parameters[j >> 1] & 0xf0) >> 4; + + pixloc += multiplier; + } + + for (int32 i = 0; i < DSP2.Op0DOutLen; i++) + DSP2.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1]; +} + +/* +static void DSP2_Op0D (void) +{ + // Overload's algorithm - use this unless doing hardware testing + + // One note: the HW can do odd byte scaling but since we divide + // by two to get the count of bytes this won't work well for + // odd byte scaling (in any of the current algorithm implementations). + // So far I haven't seen Dungeon Master use it. + // If it does we can adjust the parameters and code to work with it + + int32 pixel_offset; + uint8 pixelarray[512]; + + for (int32 i = 0; i < DSP2.Op0DOutLen * 2; i++) + { + pixel_offset = (i * DSP2.Op0DInLen) / DSP2.Op0DOutLen; + + if ((pixel_offset & 1) == 0) + pixelarray[i] = DSP2.parameters[pixel_offset >> 1] >> 4; + else + pixelarray[i] = DSP2.parameters[pixel_offset >> 1] & 0x0f; + } + + for (int32 i = 0; i < DSP2.Op0DOutLen; i++) + DSP2.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1]; +} +*/ + +void DSP2SetByte (uint8 byte, uint16 address) +{ + if ((address & 0xf000) == 0x6000 || (address >= 0x8000 && address < 0xc000)) + { + if (DSP2.waiting4command) + { + DSP2.command = byte; + DSP2.in_index = 0; + DSP2.waiting4command = FALSE; + + switch (byte) + { + case 0x01: DSP2.in_count = 32; break; + case 0x03: DSP2.in_count = 1; break; + case 0x05: DSP2.in_count = 1; break; + case 0x06: DSP2.in_count = 1; break; + case 0x09: DSP2.in_count = 4; break; + case 0x0D: DSP2.in_count = 2; break; + default: + #ifdef DEBUGGER + //printf("Op%02X\n", byte); + #endif + case 0x0f: DSP2.in_count = 0; break; + } + } + else + { + DSP2.parameters[DSP2.in_index] = byte; + DSP2.in_index++; + } + + if (DSP2.in_count == DSP2.in_index) + { + DSP2.waiting4command = TRUE; + DSP2.out_index = 0; + + switch (DSP2.command) + { + case 0x01: + DSP2.out_count = 32; + DSP2_Op01(); + break; + + case 0x03: + DSP2_Op03(); + break; + + case 0x05: + if (DSP2.Op05HasLen) + { + DSP2.Op05HasLen = FALSE; + DSP2.out_count = DSP2.Op05Len; + DSP2_Op05(); + } + else + { + DSP2.Op05Len = DSP2.parameters[0]; + DSP2.in_index = 0; + DSP2.in_count = 2 * DSP2.Op05Len; + DSP2.Op05HasLen = TRUE; + if (byte) + DSP2.waiting4command = FALSE; + } + + break; + + case 0x06: + if (DSP2.Op06HasLen) + { + DSP2.Op06HasLen = FALSE; + DSP2.out_count = DSP2.Op06Len; + DSP2_Op06(); + } + else + { + DSP2.Op06Len = DSP2.parameters[0]; + DSP2.in_index = 0; + DSP2.in_count = DSP2.Op06Len; + DSP2.Op06HasLen = TRUE; + if (byte) + DSP2.waiting4command = FALSE; + } + + break; + + case 0x09: + DSP2.out_count = 4; + DSP2_Op09(); + break; + + case 0x0D: + if (DSP2.Op0DHasLen) + { + DSP2.Op0DHasLen = FALSE; + DSP2.out_count = DSP2.Op0DOutLen; + DSP2_Op0D(); + } + else + { + DSP2.Op0DInLen = DSP2.parameters[0]; + DSP2.Op0DOutLen = DSP2.parameters[1]; + DSP2.in_index = 0; + DSP2.in_count = (DSP2.Op0DInLen + 1) >> 1; + DSP2.Op0DHasLen = TRUE; + if (byte) + DSP2.waiting4command = FALSE; + } + + break; + + case 0x0f: + default: + break; + } + } + } +} + +uint8 DSP2GetByte (uint16 address) +{ + uint8 t; + + if ((address & 0xf000) == 0x6000 || (address >= 0x8000 && address < 0xc000)) + { + if (DSP2.out_count) + { + t = (uint8) DSP2.output[DSP2.out_index]; + DSP2.out_index++; + if (DSP2.out_count == DSP2.out_index) + DSP2.out_count = 0; + } + else + t = 0xff; + } + else + t = 0x80; + + return (t); +} diff --git a/plugins/snes9x_gx/source/snes9x/dsp3.cpp b/plugins/snes9x_gx/source/snes9x/dsp3.cpp new file mode 100644 index 00000000..5c792403 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/dsp3.cpp @@ -0,0 +1,1268 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" + +static void (*SetDSP3) (void); + +static const uint16 DSP3_DataROM[1024] = +{ + 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100, + 0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001, + 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, + 0x0000, 0x000f, 0x0400, 0x0200, 0x0140, 0x0400, 0x0200, 0x0040, + 0x007d, 0x007e, 0x007e, 0x007b, 0x007c, 0x007d, 0x007b, 0x007c, + 0x0002, 0x0020, 0x0030, 0x0000, 0x000d, 0x0019, 0x0026, 0x0032, + 0x003e, 0x004a, 0x0056, 0x0062, 0x006d, 0x0079, 0x0084, 0x008e, + 0x0098, 0x00a2, 0x00ac, 0x00b5, 0x00be, 0x00c6, 0x00ce, 0x00d5, + 0x00dc, 0x00e2, 0x00e7, 0x00ec, 0x00f1, 0x00f5, 0x00f8, 0x00fb, + 0x00fd, 0x00ff, 0x0100, 0x0100, 0x0100, 0x00ff, 0x00fd, 0x00fb, + 0x00f8, 0x00f5, 0x00f1, 0x00ed, 0x00e7, 0x00e2, 0x00dc, 0x00d5, + 0x00ce, 0x00c6, 0x00be, 0x00b5, 0x00ac, 0x00a2, 0x0099, 0x008e, + 0x0084, 0x0079, 0x006e, 0x0062, 0x0056, 0x004a, 0x003e, 0x0032, + 0x0026, 0x0019, 0x000d, 0x0000, 0xfff3, 0xffe7, 0xffdb, 0xffce, + 0xffc2, 0xffb6, 0xffaa, 0xff9e, 0xff93, 0xff87, 0xff7d, 0xff72, + 0xff68, 0xff5e, 0xff54, 0xff4b, 0xff42, 0xff3a, 0xff32, 0xff2b, + 0xff25, 0xff1e, 0xff19, 0xff14, 0xff0f, 0xff0b, 0xff08, 0xff05, + 0xff03, 0xff01, 0xff00, 0xff00, 0xff00, 0xff01, 0xff03, 0xff05, + 0xff08, 0xff0b, 0xff0f, 0xff13, 0xff18, 0xff1e, 0xff24, 0xff2b, + 0xff32, 0xff3a, 0xff42, 0xff4b, 0xff54, 0xff5d, 0xff67, 0xff72, + 0xff7c, 0xff87, 0xff92, 0xff9e, 0xffa9, 0xffb5, 0xffc2, 0xffce, + 0xffda, 0xffe7, 0xfff3, 0x002b, 0x007f, 0x0020, 0x00ff, 0xff00, + 0xffbe, 0x0000, 0x0044, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffc1, 0x0001, 0x0002, 0x0045, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffc5, 0x0003, 0x0004, 0x0005, 0x0047, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffca, 0x0006, 0x0007, 0x0008, + 0x0009, 0x004a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffd0, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x004e, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffd7, 0x000f, 0x0010, 0x0011, + 0x0012, 0x0013, 0x0014, 0x0053, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffdf, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, + 0x0059, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffe8, 0x001c, 0x001d, 0x001e, + 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0060, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xfff2, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, + 0x002b, 0x002c, 0x0068, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xfffd, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0071, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffc7, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, + 0x003e, 0x003f, 0x0040, 0x0041, 0x007b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffd4, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, + 0x000b, 0x0044, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffe2, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, + 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0050, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xfff1, 0x0019, 0x001a, 0x001b, + 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, + 0x0024, 0x0025, 0x0026, 0x005d, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffcb, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, + 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, + 0x006b, 0x0000, 0x0000, 0x0000, 0xffdc, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, + 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0044, 0x0000, 0x0000, + 0xffee, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, + 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, + 0x001f, 0x0020, 0x0054, 0x0000, 0xffee, 0x0021, 0x0022, 0x0023, + 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, + 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0065, + 0xffbe, 0x0000, 0xfeac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffc1, 0x0001, 0x0002, 0xfead, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffc5, 0x0003, 0x0004, 0x0005, 0xfeaf, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffca, 0x0006, 0x0007, 0x0008, + 0x0009, 0xfeb2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffd0, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0xfeb6, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffd7, 0x000f, 0x0010, 0x0011, + 0x0012, 0x0013, 0x0014, 0xfebb, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffdf, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, + 0xfec1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffe8, 0x001c, 0x001d, 0x001e, + 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0xfec8, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xfff2, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, + 0x002b, 0x002c, 0xfed0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xfffd, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0xfed9, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffc7, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, + 0x003e, 0x003f, 0x0040, 0x0041, 0xfee3, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffd4, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, + 0x000b, 0xfeac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffe2, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, + 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0xfeb8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xfff1, 0x0019, 0x001a, 0x001b, + 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, + 0x0024, 0x0025, 0x0026, 0xfec5, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffcb, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, + 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, + 0xfed3, 0x0000, 0x0000, 0x0000, 0xffdc, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, + 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0xfeac, 0x0000, 0x0000, + 0xffee, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, + 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, + 0x001f, 0x0020, 0xfebc, 0x0000, 0xffee, 0x0021, 0x0022, 0x0023, + 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, + 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0xfecd, + 0x0154, 0x0218, 0x0110, 0x00b0, 0x00cc, 0x00b0, 0x0088, 0x00b0, + 0x0044, 0x00b0, 0x0000, 0x00b0, 0x00fe, 0xff07, 0x0002, 0x00ff, + 0x00f8, 0x0007, 0x00fe, 0x00ee, 0x07ff, 0x0200, 0x00ef, 0xf800, + 0x0700, 0x00ee, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, + 0xffff, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, + 0x0000, 0xffff, 0xffff, 0x0000, 0xffff, 0x0001, 0x0000, 0x0001, + 0x0001, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, + 0xffff, 0x0001, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0xffff, + 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0044, 0x0088, 0x00cc, + 0x0110, 0x0154, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff +}; + +static bool8 DSP3_GetBits (uint8); +//static void DSP3_MemorySize (void); +static void DSP3_TestMemory (void); +static void DSP3_DumpDataROM (void); +static void DSP3_MemoryDump (void); +static void DSP3_Coordinate (void); +static void DSP3_Command (void); +static void DSP3_Decode_Data (void); +static void DSP3_Decode_Tree (void); +static void DSP3_Decode_Symbols (void); +static void DSP3_Decode (void); +static void DSP3_Decode_A (void); +static void DSP3_Convert (void); +static void DSP3_Convert_A (void); +static void DSP3_OP03 (void); +static void DSP3_OP06 (void); +static void DSP3_OP07 (void); +static void DSP3_OP07_A (void); +static void DSP3_OP07_B (void); +static void DSP3_OP0C (void); +//static void DSP3_OP0C_A (void); +static void DSP3_OP10 (void); +static void DSP3_OP1C (void); +static void DSP3_OP1C_A (void); +static void DSP3_OP1C_B (void); +static void DSP3_OP1C_C (void); +static void DSP3_OP1E (void); +static void DSP3_OP1E_A (void); +static void DSP3_OP1E_A1 (void); +static void DSP3_OP1E_A2 (void); +static void DSP3_OP1E_A3 (void); +static void DSP3_OP1E_B (void); +static void DSP3_OP1E_B1 (void); +static void DSP3_OP1E_B2 (void); +static void DSP3_OP1E_C (void); +static void DSP3_OP1E_C1 (void); +static void DSP3_OP1E_C2 (void); +static void DSP3_OP1E_D (int16, int16 *, int16 *); +static void DSP3_OP1E_D1 (int16, int16 *, int16 *); +static void DSP3_OP3E (void); + + +void DSP3_Reset (void) +{ + DSP3.DR = 0x0080; + DSP3.SR = 0x0084; + SetDSP3 = &DSP3_Command; +} + +/* +static void DSP3_MemorySize (void) +{ + DSP3.DR = 0x0300; + SetDSP3 = &DSP3_Reset; +} +*/ + +static void DSP3_TestMemory (void) +{ + DSP3.DR = 0x0000; + SetDSP3 = &DSP3_Reset; +} + +static void DSP3_DumpDataROM (void) +{ + DSP3.DR = DSP3_DataROM[DSP3.MemoryIndex++]; + if (DSP3.MemoryIndex == 1024) + SetDSP3 = &DSP3_Reset; +} + +static void DSP3_MemoryDump (void) +{ + DSP3.MemoryIndex = 0; + SetDSP3 = &DSP3_DumpDataROM; + DSP3_DumpDataROM(); +} + +static void DSP3_OP06 (void) +{ + DSP3.WinLo = (uint8) (DSP3.DR); + DSP3.WinHi = (uint8) (DSP3.DR >> 8); + DSP3_Reset(); +} + +static void DSP3_OP03 (void) +{ + int16 Lo = (uint8) (DSP3.DR); + int16 Hi = (uint8) (DSP3.DR >> 8); + int16 Ofs = (DSP3.WinLo * Hi << 1) + (Lo << 1); + + DSP3.DR = Ofs >> 1; + SetDSP3 = &DSP3_Reset; +} + +static void DSP3_OP07_B (void) +{ + int16 Ofs = (DSP3.WinLo * DSP3.AddHi << 1) + (DSP3.AddLo << 1); + + DSP3.DR = Ofs >> 1; + SetDSP3 = &DSP3_Reset; +} + +static void DSP3_OP07_A (void) +{ + int16 Lo = (uint8) (DSP3.DR); + int16 Hi = (uint8) (DSP3.DR >> 8); + + if (Lo & 1) + Hi += (DSP3.AddLo & 1); + + DSP3.AddLo += Lo; + DSP3.AddHi += Hi; + + if (DSP3.AddLo < 0) + DSP3.AddLo += DSP3.WinLo; + else + if (DSP3.AddLo >= DSP3.WinLo) + DSP3.AddLo -= DSP3.WinLo; + + if (DSP3.AddHi < 0) + DSP3.AddHi += DSP3.WinHi; + else + if (DSP3.AddHi >= DSP3.WinHi) + DSP3.AddHi -= DSP3.WinHi; + + DSP3.DR = DSP3.AddLo | (DSP3.AddHi << 8) | ((DSP3.AddHi >> 8) & 0xff); + SetDSP3 = &DSP3_OP07_B; +} + +static void DSP3_OP07 (void) +{ + uint32 dataOfs = ((DSP3.DR << 1) + 0x03b2) & 0x03ff; + + DSP3.AddHi = DSP3_DataROM[dataOfs]; + DSP3.AddLo = DSP3_DataROM[dataOfs + 1]; + + SetDSP3 = &DSP3_OP07_A; + DSP3.SR = 0x0080; +} + +static void DSP3_Coordinate (void) +{ + DSP3.Index++; + + switch (DSP3.Index) + { + case 3: + if (DSP3.DR == 0xffff) + DSP3_Reset(); + break; + + case 4: + DSP3.X = DSP3.DR; + break; + + case 5: + DSP3.Y = DSP3.DR; + DSP3.DR = 1; + break; + + case 6: + DSP3.DR = DSP3.X; + break; + + case 7: + DSP3.DR = DSP3.Y; + DSP3.Index = 0; + break; + } +} + +static void DSP3_Convert_A (void) +{ + if (DSP3.BMIndex < 8) + { + DSP3.Bitmap[DSP3.BMIndex++] = (uint8) (DSP3.DR); + DSP3.Bitmap[DSP3.BMIndex++] = (uint8) (DSP3.DR >> 8); + + if (DSP3.BMIndex == 8) + { + for (int i = 0; i < 8; i++) + { + for (int j = 0; j < 8; j++) + { + DSP3.Bitplane[j] <<= 1; + DSP3.Bitplane[j] |= (DSP3.Bitmap[i] >> j) & 1; + } + } + + DSP3.BPIndex = 0; + DSP3.Count--; + } + } + + if (DSP3.BMIndex == 8) + { + if (DSP3.BPIndex == 8) + { + if (!DSP3.Count) + DSP3_Reset(); + + DSP3.BMIndex = 0; + } + else + { + DSP3.DR = DSP3.Bitplane[DSP3.BPIndex++]; + DSP3.DR |= DSP3.Bitplane[DSP3.BPIndex++] << 8; + } + } +} + +static void DSP3_Convert (void) +{ + DSP3.Count = DSP3.DR; + DSP3.BMIndex = 0; + SetDSP3 = &DSP3_Convert_A; +} + +static bool8 DSP3_GetBits (uint8 Count) +{ + if (!DSP3.BitsLeft) + { + DSP3.BitsLeft = Count; + DSP3.ReqBits = 0; + } + + do + { + if (!DSP3.BitCount) + { + DSP3.SR = 0xC0; + return (FALSE); + } + + DSP3.ReqBits <<= 1; + if (DSP3.ReqData & 0x8000) + DSP3.ReqBits++; + DSP3.ReqData <<= 1; + + DSP3.BitCount--; + DSP3.BitsLeft--; + + } + while (DSP3.BitsLeft); + + return (TRUE); +} + +static void DSP3_Decode_Data (void) +{ + if (!DSP3.BitCount) + { + if (DSP3.SR & 0x40) + { + DSP3.ReqData = DSP3.DR; + DSP3.BitCount += 16; + } + else + { + DSP3.SR = 0xC0; + return; + } + } + + if (DSP3.LZCode == 1) + { + if (!DSP3_GetBits(1)) + return; + + if (DSP3.ReqBits) + DSP3.LZLength = 12; + else + DSP3.LZLength = 8; + + DSP3.LZCode++; + } + + if (DSP3.LZCode == 2) + { + if (!DSP3_GetBits(DSP3.LZLength)) + return; + + DSP3.LZCode = 0; + DSP3.Outwords--; + if (!DSP3.Outwords) + SetDSP3 = &DSP3_Reset; + + DSP3.SR = 0x80; + DSP3.DR = DSP3.ReqBits; + return; + } + + if (DSP3.BaseCode == 0xffff) + { + if (!DSP3_GetBits(DSP3.BaseLength)) + return; + + DSP3.BaseCode = DSP3.ReqBits; + } + + if (!DSP3_GetBits(DSP3.CodeLengths[DSP3.BaseCode])) + return; + + DSP3.Symbol = DSP3.Codes[DSP3.CodeOffsets[DSP3.BaseCode] + DSP3.ReqBits]; + DSP3.BaseCode = 0xffff; + + if (DSP3.Symbol & 0xff00) + { + DSP3.Symbol += 0x7f02; + DSP3.LZCode++; + } + else + { + DSP3.Outwords--; + if (!DSP3.Outwords) + SetDSP3 = &DSP3_Reset; + } + + DSP3.SR = 0x80; + DSP3.DR = DSP3.Symbol; +} + +static void DSP3_Decode_Tree (void) +{ + if (!DSP3.BitCount) + { + DSP3.ReqData = DSP3.DR; + DSP3.BitCount += 16; + } + + if (!DSP3.BaseCodes) + { + DSP3_GetBits(1); + + if (DSP3.ReqBits) + { + DSP3.BaseLength = 3; + DSP3.BaseCodes = 8; + } + else + { + DSP3.BaseLength = 2; + DSP3.BaseCodes = 4; + } + } + + while (DSP3.BaseCodes) + { + if (!DSP3_GetBits(3)) + return; + + DSP3.ReqBits++; + + DSP3.CodeLengths[DSP3.Index] = (uint8) DSP3.ReqBits; + DSP3.CodeOffsets[DSP3.Index] = DSP3.Symbol; + DSP3.Index++; + + DSP3.Symbol += 1 << DSP3.ReqBits; + DSP3.BaseCodes--; + } + + DSP3.BaseCode = 0xffff; + DSP3.LZCode = 0; + + SetDSP3 = &DSP3_Decode_Data; + if (DSP3.BitCount) + DSP3_Decode_Data(); +} + +static void DSP3_Decode_Symbols (void) +{ + DSP3.ReqData = DSP3.DR; + DSP3.BitCount += 16; + + do + { + if (DSP3.BitCommand == 0xffff) + { + if (!DSP3_GetBits(2)) + return; + + DSP3.BitCommand = DSP3.ReqBits; + } + + switch (DSP3.BitCommand) + { + case 0: + if (!DSP3_GetBits(9)) + return; + DSP3.Symbol = DSP3.ReqBits; + break; + + case 1: + DSP3.Symbol++; + break; + + case 2: + if (!DSP3_GetBits(1)) + return; + DSP3.Symbol += 2 + DSP3.ReqBits; + break; + + case 3: + if (!DSP3_GetBits(4)) + return; + DSP3.Symbol += 4 + DSP3.ReqBits; + break; + } + + DSP3.BitCommand = 0xffff; + + DSP3.Codes[DSP3.Index++] = DSP3.Symbol; + DSP3.Codewords--; + + } + while (DSP3.Codewords); + + DSP3.Index = 0; + DSP3.Symbol = 0; + DSP3.BaseCodes = 0; + + SetDSP3 = &DSP3_Decode_Tree; + if (DSP3.BitCount) + DSP3_Decode_Tree(); +} + +static void DSP3_Decode_A (void) +{ + DSP3.Outwords = DSP3.DR; + SetDSP3 = &DSP3_Decode_Symbols; + DSP3.BitCount = 0; + DSP3.BitsLeft = 0; + DSP3.Symbol = 0; + DSP3.Index = 0; + DSP3.BitCommand = 0xffff; + DSP3.SR = 0xC0; +} + +static void DSP3_Decode (void) +{ + DSP3.Codewords = DSP3.DR; + SetDSP3 = &DSP3_Decode_A; +} + +// Opcodes 1E/3E bit-perfect to 'dsp3-intro' log +// src: adapted from SD Gundam X/G-Next + +static void DSP3_OP3E (void) +{ + DSP3. op3e_x = (uint8) (DSP3.DR & 0x00ff); + DSP3. op3e_y = (uint8) ((DSP3.DR & 0xff00) >> 8); + + DSP3_OP03(); + + DSP3.op1e_terrain[DSP3.DR] = 0x00; + DSP3.op1e_cost[DSP3.DR] = 0xff; + DSP3.op1e_weight[DSP3.DR] = 0; + + DSP3.op1e_max_search_radius = 0; + DSP3.op1e_max_path_radius = 0; +} + +static void DSP3_OP1E (void) +{ + DSP3.op1e_min_radius = (uint8) (DSP3.DR & 0x00ff); + DSP3.op1e_max_radius = (uint8) ((DSP3.DR & 0xff00) >> 8); + + if (DSP3.op1e_min_radius == 0) + DSP3.op1e_min_radius++; + + if (DSP3.op1e_max_search_radius >= DSP3.op1e_min_radius) + DSP3.op1e_min_radius = DSP3.op1e_max_search_radius + 1; + + if (DSP3.op1e_max_radius > DSP3.op1e_max_search_radius) + DSP3.op1e_max_search_radius = DSP3.op1e_max_radius; + + DSP3.op1e_lcv_radius = DSP3.op1e_min_radius; + DSP3.op1e_lcv_steps = DSP3.op1e_min_radius; + + DSP3.op1e_lcv_turns = 6; + DSP3.op1e_turn = 0; + + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; + + for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + + DSP3_OP1E_A(); +} + +static void DSP3_OP1E_A (void) +{ + if (DSP3.op1e_lcv_steps == 0) + { + DSP3.op1e_lcv_radius++; + + DSP3.op1e_lcv_steps = DSP3.op1e_lcv_radius; + + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; + + for (int lcv = 0; lcv < DSP3.op1e_lcv_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + } + + if (DSP3.op1e_lcv_radius > DSP3.op1e_max_radius) + { + DSP3.op1e_turn++; + DSP3.op1e_lcv_turns--; + + DSP3.op1e_lcv_radius = DSP3.op1e_min_radius; + DSP3.op1e_lcv_steps = DSP3.op1e_min_radius; + + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; + + for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + } + + if (DSP3.op1e_lcv_turns == 0) + { + DSP3.DR = 0xffff; + DSP3.SR = 0x0080; + SetDSP3 = &DSP3_OP1E_B; + return; + } + + DSP3.DR = (uint8) (DSP3.op1e_x) | ((uint8) (DSP3.op1e_y) << 8); + DSP3_OP03(); + + DSP3.op1e_cell = DSP3.DR; + + DSP3.SR = 0x0080; + SetDSP3 = &DSP3_OP1E_A1; +} + +static void DSP3_OP1E_A1 (void) +{ + DSP3.SR = 0x0084; + SetDSP3 = &DSP3_OP1E_A2; +} + +static void DSP3_OP1E_A2 (void) +{ + DSP3.op1e_terrain[DSP3.op1e_cell] = (uint8) (DSP3.DR & 0x00ff); + + DSP3.SR = 0x0084; + SetDSP3 = &DSP3_OP1E_A3; +} + +static void DSP3_OP1E_A3 (void) +{ + DSP3.op1e_cost[DSP3.op1e_cell] = (uint8) (DSP3.DR & 0x00ff); + + if (DSP3.op1e_lcv_radius == 1) + { + if (DSP3.op1e_terrain[DSP3.op1e_cell] & 1) + DSP3.op1e_weight[DSP3.op1e_cell] = 0xff; + else + DSP3.op1e_weight[DSP3.op1e_cell] = DSP3.op1e_cost[DSP3.op1e_cell]; + } + else + DSP3.op1e_weight[DSP3.op1e_cell] = 0xff; + + DSP3_OP1E_D((int16) (DSP3.op1e_turn + 2), &DSP3.op1e_x, &DSP3.op1e_y); + DSP3.op1e_lcv_steps--; + + DSP3.SR = 0x0080; + DSP3_OP1E_A(); +} + +static void DSP3_OP1E_B (void) +{ + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; + DSP3.op1e_lcv_radius = 1; + + DSP3.op1e_search = 0; + + DSP3_OP1E_B1(); + + SetDSP3 = &DSP3_OP1E_C; +} + +static void DSP3_OP1E_B1 (void) +{ + while (DSP3.op1e_lcv_radius < DSP3.op1e_max_radius) + { + DSP3.op1e_y--; + + DSP3.op1e_lcv_turns = 6; + DSP3.op1e_turn = 5; + + while (DSP3.op1e_lcv_turns) + { + DSP3.op1e_lcv_steps = DSP3.op1e_lcv_radius; + + while (DSP3.op1e_lcv_steps) + { + DSP3_OP1E_D1(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + + if (0 <= DSP3.op1e_y && DSP3.op1e_y < DSP3.WinHi && 0 <= DSP3.op1e_x && DSP3.op1e_x < DSP3.WinLo) + { + DSP3.DR = (uint8) (DSP3.op1e_x) | ((uint8) (DSP3.op1e_y) << 8); + DSP3_OP03(); + + DSP3.op1e_cell = DSP3.DR; + if (DSP3.op1e_cost[DSP3.op1e_cell] < 0x80 && DSP3.op1e_terrain[DSP3.op1e_cell] < 0x40) + DSP3_OP1E_B2(); // end cell perimeter + } + + DSP3.op1e_lcv_steps--; + } // end search line + + DSP3.op1e_turn--; + if (DSP3.op1e_turn == 0) + DSP3.op1e_turn = 6; + + DSP3.op1e_lcv_turns--; + } // end circle search + + DSP3.op1e_lcv_radius++; + } // end radius search +} + +static void DSP3_OP1E_B2 (void) +{ + int16 cell; + int16 path; + int16 x, y; + int16 lcv_turns; + + path = 0xff; + lcv_turns = 6; + + while (lcv_turns) + { + x = DSP3.op1e_x; + y = DSP3.op1e_y; + + DSP3_OP1E_D1(lcv_turns, &x, &y); + + DSP3.DR = (uint8) (x) | ((uint8) (y) << 8); + DSP3_OP03(); + + cell = DSP3.DR; + + if (0 <= y && y < DSP3.WinHi && 0 <= x && x < DSP3.WinLo) + { + if (DSP3.op1e_terrain[cell] < 0x80 || DSP3.op1e_weight[cell] == 0) + { + if (DSP3.op1e_weight[cell] < path) + path = DSP3.op1e_weight[cell]; + } + } // end step travel + + lcv_turns--; + } // end while turns + + if (path != 0xff) + DSP3.op1e_weight[DSP3.op1e_cell] = path + DSP3.op1e_cost[DSP3.op1e_cell]; +} + +static void DSP3_OP1E_C (void) +{ + DSP3.op1e_min_radius = (uint8) (DSP3.DR & 0x00ff); + DSP3.op1e_max_radius = (uint8) ((DSP3.DR & 0xff00) >> 8); + + if (DSP3.op1e_min_radius == 0) + DSP3.op1e_min_radius++; + + if (DSP3.op1e_max_path_radius >= DSP3.op1e_min_radius) + DSP3.op1e_min_radius = DSP3.op1e_max_path_radius + 1; + + if (DSP3.op1e_max_radius > DSP3.op1e_max_path_radius) + DSP3.op1e_max_path_radius = DSP3.op1e_max_radius; + + DSP3.op1e_lcv_radius = DSP3.op1e_min_radius; + DSP3.op1e_lcv_steps = DSP3.op1e_min_radius; + + DSP3.op1e_lcv_turns = 6; + DSP3.op1e_turn = 0; + + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; + + for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + + DSP3_OP1E_C1(); +} + +static void DSP3_OP1E_C1 (void) +{ + if (DSP3.op1e_lcv_steps == 0) + { + DSP3.op1e_lcv_radius++; + + DSP3.op1e_lcv_steps = DSP3.op1e_lcv_radius; + + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; + + for (int lcv = 0; lcv < DSP3.op1e_lcv_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + } + + if (DSP3.op1e_lcv_radius > DSP3.op1e_max_radius) + { + DSP3.op1e_turn++; + DSP3.op1e_lcv_turns--; + + DSP3.op1e_lcv_radius = DSP3.op1e_min_radius; + DSP3.op1e_lcv_steps = DSP3.op1e_min_radius; + + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; + + for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + } + + if (DSP3.op1e_lcv_turns == 0) + { + DSP3.DR = 0xffff; + DSP3.SR = 0x0080; + SetDSP3 = &DSP3_Reset; + return; + } + + DSP3.DR = (uint8) (DSP3.op1e_x) | ((uint8) (DSP3.op1e_y) << 8); + DSP3_OP03(); + + DSP3.op1e_cell = DSP3.DR; + + DSP3.SR = 0x0080; + SetDSP3 = &DSP3_OP1E_C2; +} + +static void DSP3_OP1E_C2 (void) +{ + DSP3.DR = DSP3.op1e_weight[DSP3.op1e_cell]; + + DSP3_OP1E_D((int16) (DSP3.op1e_turn + 2), &DSP3.op1e_x, &DSP3.op1e_y); + DSP3.op1e_lcv_steps--; + + DSP3.SR = 0x0084; + SetDSP3 = &DSP3_OP1E_C1; +} + +static void DSP3_OP1E_D (int16 move, int16 *lo, int16 *hi) +{ + uint32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff; + int16 Lo; + int16 Hi; + + DSP3.AddHi = DSP3_DataROM[dataOfs]; + DSP3.AddLo = DSP3_DataROM[dataOfs + 1]; + + Lo = (uint8) (*lo); + Hi = (uint8) (*hi); + + if (Lo & 1) + Hi += (DSP3.AddLo & 1); + + DSP3.AddLo += Lo; + DSP3.AddHi += Hi; + + if (DSP3.AddLo < 0) + DSP3.AddLo += DSP3.WinLo; + else + if (DSP3.AddLo >= DSP3.WinLo) + DSP3.AddLo -= DSP3.WinLo; + + if (DSP3.AddHi < 0) + DSP3.AddHi += DSP3.WinHi; + else + if (DSP3.AddHi >= DSP3.WinHi) + DSP3.AddHi -= DSP3.WinHi; + + *lo = DSP3.AddLo; + *hi = DSP3.AddHi; +} + +static void DSP3_OP1E_D1 (int16 move, int16 *lo, int16 *hi) +{ + const uint16 HiAdd[] = + { + 0x00, 0xFF, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xFF, 0x00 + }; + + const uint16 LoAdd[] = + { + 0x00, 0x00, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x00 + }; + + int16 Lo; + int16 Hi; + + if ((*lo) & 1) + DSP3.AddHi = HiAdd[move + 8]; + else + DSP3.AddHi = HiAdd[move + 0]; + + DSP3.AddLo = LoAdd[move]; + + Lo = (uint8) (*lo); + Hi = (uint8) (*hi); + + if (Lo & 1) + Hi += (DSP3.AddLo & 1); + + DSP3.AddLo += Lo; + DSP3.AddHi += Hi; + + *lo = DSP3.AddLo; + *hi = DSP3.AddHi; +} + +static void DSP3_OP10 (void) +{ + if (DSP3.DR == 0xffff) + DSP3_Reset(); + else + // absorb 2 bytes + DSP3.DR = DSP3.DR; +} + +/* +static void DSP3_OP0C_A (void) +{ + // absorb 2 bytes + DSP3.DR = 0; + SetDSP3 = &DSP3_Reset; +} +*/ + +static void DSP3_OP0C (void) +{ + // absorb 2 bytes + DSP3.DR = 0; + //SetDSP3 = &DSP3_OP0C_A; + SetDSP3 = &DSP3_Reset; +} + +static void DSP3_OP1C_C (void) +{ + // return 2 bytes + DSP3.DR = 0; + SetDSP3 = &DSP3_Reset; +} + +static void DSP3_OP1C_B (void) +{ + // return 2 bytes + DSP3.DR = 0; + SetDSP3 = &DSP3_OP1C_C; +} + +static void DSP3_OP1C_A (void) +{ + // absorb 2 bytes + SetDSP3 = &DSP3_OP1C_B; +} + +static void DSP3_OP1C (void) +{ + // absorb 2 bytes + SetDSP3 = &DSP3_OP1C_A; +} + +static void DSP3_Command (void) +{ + if (DSP3.DR < 0x40) + { + switch (DSP3.DR) + { + case 0x02: SetDSP3 = &DSP3_Coordinate; break; + case 0x03: SetDSP3 = &DSP3_OP03; break; + case 0x06: SetDSP3 = &DSP3_OP06; break; + case 0x07: SetDSP3 = &DSP3_OP07; return; + case 0x0c: SetDSP3 = &DSP3_OP0C; break; + case 0x0f: SetDSP3 = &DSP3_TestMemory; break; + case 0x10: SetDSP3 = &DSP3_OP10; break; + case 0x18: SetDSP3 = &DSP3_Convert; break; + case 0x1c: SetDSP3 = &DSP3_OP1C; break; + case 0x1e: SetDSP3 = &DSP3_OP1E; break; + case 0x1f: SetDSP3 = &DSP3_MemoryDump; break; + case 0x38: SetDSP3 = &DSP3_Decode; break; + case 0x3e: SetDSP3 = &DSP3_OP3E; break; + default: + return; + } + + DSP3.SR = 0x0080; + DSP3.Index = 0; + } +} + +void DSP3SetByte (uint8 byte, uint16 address) +{ + if (address < DSP0.boundary) + { + if (DSP3.SR & 0x04) + { + DSP3.DR = (DSP3.DR & 0xff00) + byte; + (*SetDSP3)(); + } + else + { + DSP3.SR ^= 0x10; + + if (DSP3.SR & 0x10) + DSP3.DR = (DSP3.DR & 0xff00) + byte; + else + { + DSP3.DR = (DSP3.DR & 0x00ff) + (byte << 8); + (*SetDSP3)(); + } + } + } +} + +uint8 DSP3GetByte (uint16 address) +{ + if (address < DSP0.boundary) + { + uint8 byte; + + if (DSP3.SR & 0x04) + { + byte = (uint8) DSP3.DR; + (*SetDSP3)(); + } + else + { + DSP3.SR ^= 0x10; + + if (DSP3.SR & 0x10) + byte = (uint8) (DSP3.DR); + else + { + byte = (uint8) (DSP3.DR >> 8); + (*SetDSP3)(); + } + } + + return (byte); + } + + return (uint8) DSP3.SR; +} diff --git a/plugins/snes9x_gx/source/snes9x/dsp4.cpp b/plugins/snes9x_gx/source/snes9x/dsp4.cpp new file mode 100644 index 00000000..9d6f3fd7 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/dsp4.cpp @@ -0,0 +1,2220 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + +/* + Due recognition and credit are given on Overload's DSP website. + Thank those contributors for their hard work on this chip. + + Fixed-point math reminder: + [sign, integer, fraction] + 1.15.00 * 1.15.00 = 2.30.00 -> 1.30.00 (DSP) -> 1.31.00 (LSB is '0') + 1.15.00 * 1.00.15 = 2.15.15 -> 1.15.15 (DSP) -> 1.15.16 (LSB is '0') +*/ + + +#include "snes9x.h" +#include "memmap.h" + +#define DSP4_CLEAR_OUT() \ + { DSP4.out_count = 0; DSP4.out_index = 0; } + +#define DSP4_WRITE_BYTE(d) \ + { WRITE_WORD(DSP4.output + DSP4.out_count, (d)); DSP4.out_count++; } + +#define DSP4_WRITE_WORD(d) \ + { WRITE_WORD(DSP4.output + DSP4.out_count, (d)); DSP4.out_count += 2; } + +#ifndef MSB_FIRST +#define DSP4_WRITE_16_WORD(d) \ + { memcpy(DSP4.output + DSP4.out_count, (d), 32); DSP4.out_count += 32; } +#else +#define DSP4_WRITE_16_WORD(d) \ + { for (int p = 0; p < 16; p++) DSP4_WRITE_WORD((d)[p]); } +#endif + +// used to wait for dsp i/o +#define DSP4_WAIT(x) \ + DSP4.in_index = 0; DSP4.Logic = (x); return + +// 1.7.8 -> 1.15.16 +#define SEX78(a) (((int32) ((int16) (a))) << 8) + +// 1.15.0 -> 1.15.16 +#define SEX16(a) (((int32) ((int16) (a))) << 16) + +static int16 DSP4_READ_WORD (void); +static int32 DSP4_READ_DWORD (void); +static int16 DSP4_Inverse (int16); +static void DSP4_Multiply (int16, int16, int32 *); +static void DSP4_OP01 (void); +static void DSP4_OP03 (void); +static void DSP4_OP05 (void); +static void DSP4_OP06 (void); +static void DSP4_OP07 (void); +static void DSP4_OP08 (void); +static void DSP4_OP09 (void); +static void DSP4_OP0A (int16, int16 *, int16 *, int16 *, int16 *); +static void DSP4_OP0B (bool8 *, int16, int16, int16, bool8, bool8); +static void DSP4_OP0D (void); +static void DSP4_OP0E (void); +static void DSP4_OP0F (void); +static void DSP4_OP10 (void); +static void DSP4_OP11 (int16, int16, int16, int16, int16 *); +static void DSP4_SetByte (void); +static void DSP4_GetByte (void); + + +static int16 DSP4_READ_WORD (void) +{ + int16 out; + + out = READ_WORD(DSP4.parameters + DSP4.in_index); + DSP4.in_index += 2; + + return (out); +} + +static int32 DSP4_READ_DWORD (void) +{ + int32 out; + + out = READ_DWORD(DSP4.parameters + DSP4.in_index); + DSP4.in_index += 4; + + return (out); +} + +static int16 DSP4_Inverse (int16 value) +{ + // Attention: This lookup table is not verified + const uint16 div_lut[64] = + { + 0x0000, 0x8000, 0x4000, 0x2aaa, 0x2000, 0x1999, 0x1555, 0x1249, + 0x1000, 0x0e38, 0x0ccc, 0x0ba2, 0x0aaa, 0x09d8, 0x0924, 0x0888, + 0x0800, 0x0787, 0x071c, 0x06bc, 0x0666, 0x0618, 0x05d1, 0x0590, + 0x0555, 0x051e, 0x04ec, 0x04bd, 0x0492, 0x0469, 0x0444, 0x0421, + 0x0400, 0x03e0, 0x03c3, 0x03a8, 0x038e, 0x0375, 0x035e, 0x0348, + 0x0333, 0x031f, 0x030c, 0x02fa, 0x02e8, 0x02d8, 0x02c8, 0x02b9, + 0x02aa, 0x029c, 0x028f, 0x0282, 0x0276, 0x026a, 0x025e, 0x0253, + 0x0249, 0x023e, 0x0234, 0x022b, 0x0222, 0x0219, 0x0210, 0x0208 + }; + + // saturate bounds + if (value < 0) + value = 0; + if (value > 63) + value = 63; + + return (div_lut[value]); +} + +static void DSP4_Multiply (int16 Multiplicand, int16 Multiplier, int32 *Product) +{ + *Product = (Multiplicand * Multiplier << 1) >> 1; +} + +static void DSP4_OP01 (void) +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4.Logic) + { + case 1: goto resume1; break; + case 2: goto resume2; break; + case 3: goto resume3; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // sort inputs + DSP4.world_y = DSP4_READ_DWORD(); + DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); + DSP4.poly_top[0][0] = DSP4_READ_WORD(); + DSP4.poly_cx[1][0] = DSP4_READ_WORD(); + DSP4.viewport_bottom = DSP4_READ_WORD(); + DSP4.world_x = DSP4_READ_DWORD(); + DSP4.poly_cx[0][0] = DSP4_READ_WORD(); + DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); + DSP4.world_yofs = DSP4_READ_WORD(); + DSP4.world_dy = DSP4_READ_DWORD(); + DSP4.world_dx = DSP4_READ_DWORD(); + DSP4.distance = DSP4_READ_WORD(); + DSP4_READ_WORD(); // 0x0000 + DSP4.world_xenv = DSP4_READ_DWORD(); + DSP4.world_ddy = DSP4_READ_WORD(); + DSP4.world_ddx = DSP4_READ_WORD(); + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // initial (x, y, offset) at starting raster line + DSP4.view_x1 = (DSP4.world_x + DSP4.world_xenv) >> 16; + DSP4.view_y1 = DSP4.world_y >> 16; + DSP4.view_xofs1 = DSP4.world_x >> 16; + DSP4.view_yofs1 = DSP4.world_yofs; + DSP4.view_turnoff_x = 0; + DSP4.view_turnoff_dx = 0; + + // first raster line + DSP4.poly_raster[0][0] = DSP4.poly_bottom[0][0]; + + do + { + //////////////////////////////////////////////////// + // process one iteration of projection + + // perspective projection of world (x, y, scroll) points + // based on the current projection lines + DSP4.view_x2 = (((DSP4.world_x + DSP4.world_xenv) >> 16) * DSP4.distance >> 15) + (DSP4.view_turnoff_x * DSP4.distance >> 15); + DSP4.view_y2 = (DSP4.world_y >> 16) * DSP4.distance >> 15; + DSP4.view_xofs2 = DSP4.view_x2; + DSP4.view_yofs2 = (DSP4.world_yofs * DSP4.distance >> 15) + DSP4.poly_bottom[0][0] - DSP4.view_y2; + + // 1. World x-location before transformation + // 2. Viewer x-position at the next + // 3. World y-location before perspective projection + // 4. Viewer y-position below the horizon + // 5. Number of raster lines drawn in this iteration + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD((DSP4.world_x + DSP4.world_xenv) >> 16); + DSP4_WRITE_WORD(DSP4.view_x2); + DSP4_WRITE_WORD(DSP4.world_y >> 16); + DSP4_WRITE_WORD(DSP4.view_y2); + + ////////////////////////////////////////////////////// + + // SR = 0x00 + + // determine # of raster lines used + DSP4.segments = DSP4.poly_raster[0][0] - DSP4.view_y2; + + // prevent overdraw + if (DSP4.view_y2 >= DSP4.poly_raster[0][0]) + DSP4.segments = 0; + else + DSP4.poly_raster[0][0] = DSP4.view_y2; + + // don't draw outside the window + if (DSP4.view_y2 < DSP4.poly_top[0][0]) + { + DSP4.segments = 0; + + // flush remaining raster lines + if (DSP4.view_y1 >= DSP4.poly_top[0][0]) + DSP4.segments = DSP4.view_y1 - DSP4.poly_top[0][0]; + } + + // SR = 0x80 + + DSP4_WRITE_WORD(DSP4.segments); + + ////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (DSP4.segments) + { + int32 px_dx, py_dy; + int32 x_scroll, y_scroll; + + // SR = 0x00 + + // linear interpolation (lerp) between projected points + px_dx = (DSP4.view_xofs2 - DSP4.view_xofs1) * DSP4_Inverse(DSP4.segments) << 1; + py_dy = (DSP4.view_yofs2 - DSP4.view_yofs1) * DSP4_Inverse(DSP4.segments) << 1; + + // starting step values + x_scroll = SEX16(DSP4.poly_cx[0][0] + DSP4.view_xofs1); + y_scroll = SEX16(-DSP4.viewport_bottom + DSP4.view_yofs1 + DSP4.view_yofsenv + DSP4.poly_cx[1][0] - DSP4.world_yofs); + + // SR = 0x80 + + // rasterize line + for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) + { + // 1. HDMA memory pointer (bg1) + // 2. vertical scroll offset ($210E) + // 3. horizontal scroll offset ($210D) + DSP4_WRITE_WORD(DSP4.poly_ptr[0][0]); + DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); + DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); + + // update memory address + DSP4.poly_ptr[0][0] -= 4; + + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } + + //////////////////////////////////////////////////// + // Post-update + + // update new viewer (x, y, scroll) to last raster line drawn + DSP4.view_x1 = DSP4.view_x2; + DSP4.view_y1 = DSP4.view_y2; + DSP4.view_xofs1 = DSP4.view_xofs2; + DSP4.view_yofs1 = DSP4.view_yofs2; + + // add deltas for projection lines + DSP4.world_dx += SEX78(DSP4.world_ddx); + DSP4.world_dy += SEX78(DSP4.world_ddy); + + // update projection lines + DSP4.world_x += (DSP4.world_dx + DSP4.world_xenv); + DSP4.world_y += DSP4.world_dy; + + // update road turnoff position + DSP4.view_turnoff_x += DSP4.view_turnoff_dx; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(1); + + resume1: + + // check for termination + DSP4.distance = DSP4_READ_WORD(); + if (DSP4.distance == -0x8000) + break; + + // road turnoff + if ((uint16) DSP4.distance == 0x8001) + { + DSP4.in_count = 6; + DSP4_WAIT(2); + + resume2: + + DSP4.distance = DSP4_READ_WORD(); + DSP4.view_turnoff_x = DSP4_READ_WORD(); + DSP4.view_turnoff_dx = DSP4_READ_WORD(); + + // factor in new changes + DSP4.view_x1 += (DSP4.view_turnoff_x * DSP4.distance >> 15); + DSP4.view_xofs1 += (DSP4.view_turnoff_x * DSP4.distance >> 15); + + // update stepping values + DSP4.view_turnoff_x += DSP4.view_turnoff_dx; + + DSP4.in_count = 2; + DSP4_WAIT(1); + } + + // already have 2 bytes read + DSP4.in_count = 6; + DSP4_WAIT(3); + + resume3: + + // inspect inputs + DSP4.world_ddy = DSP4_READ_WORD(); + DSP4.world_ddx = DSP4_READ_WORD(); + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // no envelope here + DSP4.world_xenv = 0; + } + while (1); + + // terminate op + DSP4.waiting4command = TRUE; +} + +static void DSP4_OP03 (void) +{ + DSP4.OAM_RowMax = 33; + memset(DSP4.OAM_Row, 0, 64); +} + +static void DSP4_OP05 (void) +{ + DSP4.OAM_index = 0; + DSP4.OAM_bits = 0; + memset(DSP4.OAM_attr, 0, 32); + DSP4.sprite_count = 0; +} + +static void DSP4_OP06 (void) +{ + DSP4_CLEAR_OUT(); + DSP4_WRITE_16_WORD(DSP4.OAM_attr); +} + +static void DSP4_OP07 (void) +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4.Logic) + { + case 1: goto resume1; break; + case 2: goto resume2; break; + } + + //////////////////////////////////////////////////// + // sort inputs + + DSP4.world_y = DSP4_READ_DWORD(); + DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); + DSP4.poly_top[0][0] = DSP4_READ_WORD(); + DSP4.poly_cx[1][0] = DSP4_READ_WORD(); + DSP4.viewport_bottom = DSP4_READ_WORD(); + DSP4.world_x = DSP4_READ_DWORD(); + DSP4.poly_cx[0][0] = DSP4_READ_WORD(); + DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); + DSP4.world_yofs = DSP4_READ_WORD(); + DSP4.distance = DSP4_READ_WORD(); + DSP4.view_y2 = DSP4_READ_WORD(); + DSP4.view_dy = DSP4_READ_WORD() * DSP4.distance >> 15; + DSP4.view_x2 = DSP4_READ_WORD(); + DSP4.view_dx = DSP4_READ_WORD() * DSP4.distance >> 15; + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // initial (x, y, offset) at starting raster line + DSP4.view_x1 = DSP4.world_x >> 16; + DSP4.view_y1 = DSP4.world_y >> 16; + DSP4.view_xofs1 = DSP4.view_x1; + DSP4.view_yofs1 = DSP4.world_yofs; + + // first raster line + DSP4.poly_raster[0][0] = DSP4.poly_bottom[0][0]; + + do + { + //////////////////////////////////////////////////// + // process one iteration of projection + + // add shaping + DSP4.view_x2 += DSP4.view_dx; + DSP4.view_y2 += DSP4.view_dy; + + // vertical scroll calculation + DSP4.view_xofs2 = DSP4.view_x2; + DSP4.view_yofs2 = (DSP4.world_yofs * DSP4.distance >> 15) + DSP4.poly_bottom[0][0] - DSP4.view_y2; + + // 1. Viewer x-position at the next + // 2. Viewer y-position below the horizon + // 3. Number of raster lines drawn in this iteration + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(DSP4.view_x2); + DSP4_WRITE_WORD(DSP4.view_y2); + + ////////////////////////////////////////////////////// + + // SR = 0x00 + + // determine # of raster lines used + DSP4.segments = DSP4.view_y1 - DSP4.view_y2; + + // prevent overdraw + if (DSP4.view_y2 >= DSP4.poly_raster[0][0]) + DSP4.segments = 0; + else + DSP4.poly_raster[0][0] = DSP4.view_y2; + + // don't draw outside the window + if (DSP4.view_y2 < DSP4.poly_top[0][0]) + { + DSP4.segments = 0; + + // flush remaining raster lines + if (DSP4.view_y1 >= DSP4.poly_top[0][0]) + DSP4.segments = DSP4.view_y1 - DSP4.poly_top[0][0]; + } + + // SR = 0x80 + + DSP4_WRITE_WORD(DSP4.segments); + + ////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (DSP4.segments) + { + int32 px_dx, py_dy; + int32 x_scroll, y_scroll; + + // SR = 0x00 + + // linear interpolation (lerp) between projected points + px_dx = (DSP4.view_xofs2 - DSP4.view_xofs1) * DSP4_Inverse(DSP4.segments) << 1; + py_dy = (DSP4.view_yofs2 - DSP4.view_yofs1) * DSP4_Inverse(DSP4.segments) << 1; + + // starting step values + x_scroll = SEX16(DSP4.poly_cx[0][0] + DSP4.view_xofs1); + y_scroll = SEX16(-DSP4.viewport_bottom + DSP4.view_yofs1 + DSP4.view_yofsenv + DSP4.poly_cx[1][0] - DSP4.world_yofs); + + // SR = 0x80 + + // rasterize line + for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) + { + // 1. HDMA memory pointer (bg2) + // 2. vertical scroll offset ($2110) + // 3. horizontal scroll offset ($210F) + DSP4_WRITE_WORD(DSP4.poly_ptr[0][0]); + DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); + DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); + + // update memory address + DSP4.poly_ptr[0][0] -= 4; + + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } + + ///////////////////////////////////////////////////// + // Post-update + + // update new viewer (x, y, scroll) to last raster line drawn + DSP4.view_x1 = DSP4.view_x2; + DSP4.view_y1 = DSP4.view_y2; + DSP4.view_xofs1 = DSP4.view_xofs2; + DSP4.view_yofs1 = DSP4.view_yofs2; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(1); + + resume1: + + // check for opcode termination + DSP4.distance = DSP4_READ_WORD(); + if (DSP4.distance == -0x8000) + break; + + // already have 2 bytes in queue + DSP4.in_count = 10; + DSP4_WAIT(2); + + resume2: + + // inspect inputs + DSP4.view_y2 = DSP4_READ_WORD(); + DSP4.view_dy = DSP4_READ_WORD() * DSP4.distance >> 15; + DSP4.view_x2 = DSP4_READ_WORD(); + DSP4.view_dx = DSP4_READ_WORD() * DSP4.distance >> 15; + DSP4.view_yofsenv = DSP4_READ_WORD(); + } + while (1); + + DSP4.waiting4command = TRUE; +} + +static void DSP4_OP08 (void) +{ + int16 win_left, win_right; + int16 view_x[2], view_y[2]; + int16 envelope[2][2]; + + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4.Logic) + { + case 1: goto resume1; break; + case 2: goto resume2; break; + } + + //////////////////////////////////////////////////// + // process initial inputs for two polygons + + // clip values + DSP4.poly_clipRt[0][0] = DSP4_READ_WORD(); + DSP4.poly_clipRt[0][1] = DSP4_READ_WORD(); + DSP4.poly_clipRt[1][0] = DSP4_READ_WORD(); + DSP4.poly_clipRt[1][1] = DSP4_READ_WORD(); + + DSP4.poly_clipLf[0][0] = DSP4_READ_WORD(); + DSP4.poly_clipLf[0][1] = DSP4_READ_WORD(); + DSP4.poly_clipLf[1][0] = DSP4_READ_WORD(); + DSP4.poly_clipLf[1][1] = DSP4_READ_WORD(); + + // unknown (constant) (ex. 1P/2P = $00A6, $00A6, $00A6, $00A6) + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + + // unknown (constant) (ex. 1P/2P = $00A5, $00A5, $00A7, $00A7) + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + + // polygon centering (left, right) + DSP4.poly_cx[0][0] = DSP4_READ_WORD(); + DSP4.poly_cx[0][1] = DSP4_READ_WORD(); + DSP4.poly_cx[1][0] = DSP4_READ_WORD(); + DSP4.poly_cx[1][1] = DSP4_READ_WORD(); + + // HDMA pointer locations + DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); + DSP4.poly_ptr[0][1] = DSP4_READ_WORD(); + DSP4.poly_ptr[1][0] = DSP4_READ_WORD(); + DSP4.poly_ptr[1][1] = DSP4_READ_WORD(); + + // starting raster line below the horizon + DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); + DSP4.poly_bottom[0][1] = DSP4_READ_WORD(); + DSP4.poly_bottom[1][0] = DSP4_READ_WORD(); + DSP4.poly_bottom[1][1] = DSP4_READ_WORD(); + + // top boundary line to clip + DSP4.poly_top[0][0] = DSP4_READ_WORD(); + DSP4.poly_top[0][1] = DSP4_READ_WORD(); + DSP4.poly_top[1][0] = DSP4_READ_WORD(); + DSP4.poly_top[1][1] = DSP4_READ_WORD(); + + // unknown + // (ex. 1P = $2FC8, $0034, $FF5C, $0035) + // + // (ex. 2P = $3178, $0034, $FFCC, $0035) + // (ex. 2P = $2FC8, $0034, $FFCC, $0035) + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + + // look at guidelines for both polygon shapes + DSP4.distance = DSP4_READ_WORD(); + view_x[0] = DSP4_READ_WORD(); + view_y[0] = DSP4_READ_WORD(); + view_x[1] = DSP4_READ_WORD(); + view_y[1] = DSP4_READ_WORD(); + + // envelope shaping guidelines (one frame only) + envelope[0][0] = DSP4_READ_WORD(); + envelope[0][1] = DSP4_READ_WORD(); + envelope[1][0] = DSP4_READ_WORD(); + envelope[1][1] = DSP4_READ_WORD(); + + // starting base values to project from + DSP4.poly_start[0] = view_x[0]; + DSP4.poly_start[1] = view_x[1]; + + // starting raster lines to begin drawing + DSP4.poly_raster[0][0] = view_y[0]; + DSP4.poly_raster[0][1] = view_y[0]; + DSP4.poly_raster[1][0] = view_y[1]; + DSP4.poly_raster[1][1] = view_y[1]; + + // starting distances + DSP4.poly_plane[0] = DSP4.distance; + DSP4.poly_plane[1] = DSP4.distance; + + // SR = 0x00 + + // re-center coordinates + win_left = DSP4.poly_cx[0][0] - view_x[0] + envelope[0][0]; + win_right = DSP4.poly_cx[0][1] - view_x[0] + envelope[0][1]; + + // saturate offscreen data for polygon #1 + if (win_left < DSP4.poly_clipLf[0][0]) + win_left = DSP4.poly_clipLf[0][0]; + if (win_left > DSP4.poly_clipRt[0][0]) + win_left = DSP4.poly_clipRt[0][0]; + if (win_right < DSP4.poly_clipLf[0][1]) + win_right = DSP4.poly_clipLf[0][1]; + if (win_right > DSP4.poly_clipRt[0][1]) + win_right = DSP4.poly_clipRt[0][1]; + + // SR = 0x80 + + // initial output for polygon #1 + DSP4_CLEAR_OUT(); + DSP4_WRITE_BYTE(win_left & 0xff); + DSP4_WRITE_BYTE(win_right & 0xff); + + do + { + int16 polygon; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(1); + + resume1: + + // terminate op + DSP4.distance = DSP4_READ_WORD(); + if (DSP4.distance == -0x8000) + break; + + // already have 2 bytes in queue + DSP4.in_count = 16; + DSP4_WAIT(2); + + resume2: + + // look at guidelines for both polygon shapes + view_x[0] = DSP4_READ_WORD(); + view_y[0] = DSP4_READ_WORD(); + view_x[1] = DSP4_READ_WORD(); + view_y[1] = DSP4_READ_WORD(); + + // envelope shaping guidelines (one frame only) + envelope[0][0] = DSP4_READ_WORD(); + envelope[0][1] = DSP4_READ_WORD(); + envelope[1][0] = DSP4_READ_WORD(); + envelope[1][1] = DSP4_READ_WORD(); + + //////////////////////////////////////////////////// + // projection begins + + // init + DSP4_CLEAR_OUT(); + + ////////////////////////////////////////////// + // solid polygon renderer - 2 shapes + + for (polygon = 0; polygon < 2; polygon++) + { + int32 left_inc, right_inc; + int16 x1_final, x2_final; + int16 env[2][2]; + int16 poly; + + // SR = 0x00 + + // # raster lines to draw + DSP4.segments = DSP4.poly_raster[polygon][0] - view_y[polygon]; + + // prevent overdraw + if (DSP4.segments > 0) + { + // bump drawing cursor + DSP4.poly_raster[polygon][0] = view_y[polygon]; + DSP4.poly_raster[polygon][1] = view_y[polygon]; + } + else + DSP4.segments = 0; + + // don't draw outside the window + if (view_y[polygon] < DSP4.poly_top[polygon][0]) + { + DSP4.segments = 0; + + // flush remaining raster lines + if (view_y[polygon] >= DSP4.poly_top[polygon][0]) + DSP4.segments = view_y[polygon] - DSP4.poly_top[polygon][0]; + } + + // SR = 0x80 + + // tell user how many raster structures to read in + DSP4_WRITE_WORD(DSP4.segments); + + // normal parameters + poly = polygon; + + ///////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (DSP4.segments) + { + int32 w_left, w_right; + + // road turnoff selection + if ((uint16) envelope[polygon][0] == (uint16) 0xc001) + poly = 1; + else + if (envelope[polygon][1] == 0x3fff) + poly = 1; + + /////////////////////////////////////////////// + // left side of polygon + + // perspective correction on additional shaping parameters + env[0][0] = envelope[polygon][0] * DSP4.poly_plane[poly] >> 15; + env[0][1] = envelope[polygon][0] * DSP4.distance >> 15; + + // project new shapes (left side) + x1_final = view_x[poly] + env[0][0]; + x2_final = DSP4.poly_start[poly] + env[0][1]; + + // interpolate between projected points with shaping + left_inc = (x2_final - x1_final) * DSP4_Inverse(DSP4.segments) << 1; + if (DSP4.segments == 1) + left_inc = -left_inc; + + /////////////////////////////////////////////// + // right side of polygon + + // perspective correction on additional shaping parameters + env[1][0] = envelope[polygon][1] * DSP4.poly_plane[poly] >> 15; + env[1][1] = envelope[polygon][1] * DSP4.distance >> 15; + + // project new shapes (right side) + x1_final = view_x[poly] + env[1][0]; + x2_final = DSP4.poly_start[poly] + env[1][1]; + + // interpolate between projected points with shaping + right_inc = (x2_final - x1_final) * DSP4_Inverse(DSP4.segments) << 1; + if (DSP4.segments == 1) + right_inc = -right_inc; + + /////////////////////////////////////////////// + // update each point on the line + + w_left = SEX16(DSP4.poly_cx[polygon][0] - DSP4.poly_start[poly] + env[0][0]); + w_right = SEX16(DSP4.poly_cx[polygon][1] - DSP4.poly_start[poly] + env[1][0]); + + // update distance drawn into world + DSP4.poly_plane[polygon] = DSP4.distance; + + // rasterize line + for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) + { + int16 x_left, x_right; + + // project new coordinates + w_left += left_inc; + w_right += right_inc; + + // grab integer portion, drop fraction (no rounding) + x_left = w_left >> 16; + x_right = w_right >> 16; + + // saturate offscreen data + if (x_left < DSP4.poly_clipLf[polygon][0]) + x_left = DSP4.poly_clipLf[polygon][0]; + if (x_left > DSP4.poly_clipRt[polygon][0]) + x_left = DSP4.poly_clipRt[polygon][0]; + if (x_right < DSP4.poly_clipLf[polygon][1]) + x_right = DSP4.poly_clipLf[polygon][1]; + if (x_right > DSP4.poly_clipRt[polygon][1]) + x_right = DSP4.poly_clipRt[polygon][1]; + + // 1. HDMA memory pointer + // 2. Left window position ($2126/$2128) + // 3. Right window position ($2127/$2129) + DSP4_WRITE_WORD(DSP4.poly_ptr[polygon][0]); + DSP4_WRITE_BYTE(x_left & 0xff); + DSP4_WRITE_BYTE(x_right & 0xff); + + // update memory pointers + DSP4.poly_ptr[polygon][0] -= 4; + DSP4.poly_ptr[polygon][1] -= 4; + } // end rasterize line + } + + //////////////////////////////////////////////// + // Post-update + + // new projection spot to continue rasterizing from + DSP4.poly_start[polygon] = view_x[poly]; + } // end polygon rasterizer + } + while (1); + + // unknown output + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(0); + + DSP4.waiting4command = TRUE; +} + +static void DSP4_OP09 (void) +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4.Logic) + { + case 1: goto resume1; break; + case 2: goto resume2; break; + case 3: goto resume3; break; + case 4: goto resume4; break; + case 5: goto resume5; break; + case 6: goto resume6; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // grab screen information + DSP4.viewport_cx = DSP4_READ_WORD(); + DSP4.viewport_cy = DSP4_READ_WORD(); + DSP4_READ_WORD(); // 0x0000 + DSP4.viewport_left = DSP4_READ_WORD(); + DSP4.viewport_right = DSP4_READ_WORD(); + DSP4.viewport_top = DSP4_READ_WORD(); + DSP4.viewport_bottom = DSP4_READ_WORD(); + + // starting raster line below the horizon + DSP4.poly_bottom[0][0] = DSP4.viewport_bottom - DSP4.viewport_cy; + DSP4.poly_raster[0][0] = 0x100; + + do + { + //////////////////////////////////////////////////// + // check for new sprites + + DSP4.in_count = 4; + DSP4_WAIT(1); + + resume1: + + //////////////////////////////////////////////// + // raster overdraw check + + DSP4.raster = DSP4_READ_WORD(); + + // continue updating the raster line where overdraw begins + if (DSP4.raster < DSP4.poly_raster[0][0]) + { + DSP4.sprite_clipy = DSP4.viewport_bottom - (DSP4.poly_bottom[0][0] - DSP4.raster); + DSP4.poly_raster[0][0] = DSP4.raster; + } + + ///////////////////////////////////////////////// + // identify sprite + + // op termination + DSP4.distance = DSP4_READ_WORD(); + if (DSP4.distance == -0x8000) + goto terminate; + + // no sprite + if (DSP4.distance == 0x0000) + continue; + + //////////////////////////////////////////////////// + // process projection information + + // vehicle sprite + if ((uint16) DSP4.distance == 0x9000) + { + int16 car_left, car_right, car_back; + int16 impact_left, impact_back; + int16 world_spx, world_spy; + int16 view_spx, view_spy; + uint16 energy; + + // we already have 4 bytes we want + DSP4.in_count = 14; + DSP4_WAIT(2); + + resume2: + + // filter inputs + energy = DSP4_READ_WORD(); + impact_back = DSP4_READ_WORD(); + car_back = DSP4_READ_WORD(); + impact_left = DSP4_READ_WORD(); + car_left = DSP4_READ_WORD(); + DSP4.distance = DSP4_READ_WORD(); + car_right = DSP4_READ_WORD(); + + // calculate car's world (x, y) values + world_spx = car_right - car_left; + world_spy = car_back; + + // add in collision vector [needs bit-twiddling] + world_spx -= energy * (impact_left - car_left) >> 16; + world_spy -= energy * (car_back - impact_back) >> 16; + + // perspective correction for world (x, y) + view_spx = world_spx * DSP4.distance >> 15; + view_spy = world_spy * DSP4.distance >> 15; + + // convert to screen values + DSP4.sprite_x = DSP4.viewport_cx + view_spx; + DSP4.sprite_y = DSP4.viewport_bottom - (DSP4.poly_bottom[0][0] - view_spy); + + // make the car's (x)-coordinate available + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(world_spx); + + // grab a few remaining vehicle values + DSP4.in_count = 4; + DSP4_WAIT(3); + + resume3: + + // add vertical lift factor + DSP4.sprite_y += DSP4_READ_WORD(); + } + // terrain sprite + else + { + int16 world_spx, world_spy; + int16 view_spx, view_spy; + + // we already have 4 bytes we want + DSP4.in_count = 10; + DSP4_WAIT(4); + + resume4: + + // sort loop inputs + DSP4.poly_cx[0][0] = DSP4_READ_WORD(); + DSP4.poly_raster[0][1] = DSP4_READ_WORD(); + world_spx = DSP4_READ_WORD(); + world_spy = DSP4_READ_WORD(); + + // compute base raster line from the bottom + DSP4.segments = DSP4.poly_bottom[0][0] - DSP4.raster; + + // perspective correction for world (x, y) + view_spx = world_spx * DSP4.distance >> 15; + view_spy = world_spy * DSP4.distance >> 15; + + // convert to screen values + DSP4.sprite_x = DSP4.viewport_cx + view_spx - DSP4.poly_cx[0][0]; + DSP4.sprite_y = DSP4.viewport_bottom - DSP4.segments + view_spy; + } + + // default sprite size: 16x16 + DSP4.sprite_size = 1; + DSP4.sprite_attr = DSP4_READ_WORD(); + + //////////////////////////////////////////////////// + // convert tile data to SNES OAM format + + do + { + int16 sp_x, sp_y, sp_attr, sp_dattr; + int16 sp_dx, sp_dy; + int16 pixels; + uint16 header; + bool8 draw; + + DSP4.in_count = 2; + DSP4_WAIT(5); + + resume5: + + draw = TRUE; + + // opcode termination + DSP4.raster = DSP4_READ_WORD(); + if (DSP4.raster == -0x8000) + goto terminate; + + // stop code + if (DSP4.raster == 0x0000 && !DSP4.sprite_size) + break; + + // toggle sprite size + if (DSP4.raster == 0x0000) + { + DSP4.sprite_size = !DSP4.sprite_size; + continue; + } + + // check for valid sprite header + header = DSP4.raster; + header >>= 8; + if (header != 0x20 && + header != 0x2e && // This is for attractor sprite + header != 0x40 && + header != 0x60 && + header != 0xa0 && + header != 0xc0 && + header != 0xe0) + break; + + // read in rest of sprite data + DSP4.in_count = 4; + DSP4_WAIT(6); + + resume6: + + draw = TRUE; + + ///////////////////////////////////// + // process tile data + + // sprite deltas + sp_dattr = DSP4.raster; + sp_dy = DSP4_READ_WORD(); + sp_dx = DSP4_READ_WORD(); + + // update coordinates to screen space + sp_x = DSP4.sprite_x + sp_dx; + sp_y = DSP4.sprite_y + sp_dy; + + // update sprite nametable/attribute information + sp_attr = DSP4.sprite_attr + sp_dattr; + + // allow partially visibile tiles + pixels = DSP4.sprite_size ? 15 : 7; + + DSP4_CLEAR_OUT(); + + // transparent tile to clip off parts of a sprite (overdraw) + if (DSP4.sprite_clipy - pixels <= sp_y && sp_y <= DSP4.sprite_clipy && sp_x >= DSP4.viewport_left - pixels && sp_x <= DSP4.viewport_right && DSP4.sprite_clipy >= DSP4.viewport_top - pixels && DSP4.sprite_clipy <= DSP4.viewport_bottom) + DSP4_OP0B(&draw, sp_x, DSP4.sprite_clipy, 0x00EE, DSP4.sprite_size, 0); + + // normal sprite tile + if (sp_x >= DSP4.viewport_left - pixels && sp_x <= DSP4.viewport_right && sp_y >= DSP4.viewport_top - pixels && sp_y <= DSP4.viewport_bottom && sp_y <= DSP4.sprite_clipy) + DSP4_OP0B(&draw, sp_x, sp_y, sp_attr, DSP4.sprite_size, 0); + + // no following OAM data + DSP4_OP0B(&draw, 0, 0x0100, 0, 0, 1); + } + while (1); + } + while (1); + + terminate: + DSP4.waiting4command = TRUE; +} + +static void DSP4_OP0A (int16 n2, int16 *o1, int16 *o2, int16 *o3, int16 *o4) +{ + const uint16 OP0A_Values[16] = + { + 0x0000, 0x0030, 0x0060, 0x0090, 0x00c0, 0x00f0, 0x0120, 0x0150, + 0xfe80, 0xfeb0, 0xfee0, 0xff10, 0xff40, 0xff70, 0xffa0, 0xffd0 + }; + + *o4 = OP0A_Values[(n2 & 0x000f)]; + *o3 = OP0A_Values[(n2 & 0x00f0) >> 4]; + *o2 = OP0A_Values[(n2 & 0x0f00) >> 8]; + *o1 = OP0A_Values[(n2 & 0xf000) >> 12]; +} + +static void DSP4_OP0B (bool8 *draw, int16 sp_x, int16 sp_y, int16 sp_attr, bool8 size, bool8 stop) +{ + int16 Row1, Row2; + + // SR = 0x00 + + // align to nearest 8-pixel row + Row1 = (sp_y >> 3) & 0x1f; + Row2 = (Row1 + 1) & 0x1f; + + // check boundaries + if (!((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb))) + *draw = 0; + + if (size) + { + if (DSP4.OAM_Row[Row1] + 1 >= DSP4.OAM_RowMax) + *draw = 0; + if (DSP4.OAM_Row[Row2] + 1 >= DSP4.OAM_RowMax) + *draw = 0; + } + else + { + if (DSP4.OAM_Row[Row1] >= DSP4.OAM_RowMax) + *draw = 0; + } + + // emulator fail-safe (unknown if this really exists) + if (DSP4.sprite_count >= 128) + *draw = 0; + + // SR = 0x80 + + if (*draw) + { + // Row tiles + if (size) + { + DSP4.OAM_Row[Row1] += 2; + DSP4.OAM_Row[Row2] += 2; + } + else + DSP4.OAM_Row[Row1]++; + + // yield OAM output + DSP4_WRITE_WORD(1); + + // pack OAM data: x, y, name, attr + DSP4_WRITE_BYTE(sp_x & 0xff); + DSP4_WRITE_BYTE(sp_y & 0xff); + DSP4_WRITE_WORD(sp_attr); + + DSP4.sprite_count++; + + // OAM: size, msb data + // save post-oam table data for future retrieval + DSP4.OAM_attr[DSP4.OAM_index] |= ((sp_x < 0 || sp_x > 255) << DSP4.OAM_bits); + DSP4.OAM_bits++; + + DSP4.OAM_attr[DSP4.OAM_index] |= (size << DSP4.OAM_bits); + DSP4.OAM_bits++; + + // move to next byte in buffer + if (DSP4.OAM_bits == 16) + { + DSP4.OAM_bits = 0; + DSP4.OAM_index++; + } + } + else + if (stop) + // yield no OAM output + DSP4_WRITE_WORD(0); +} + +static void DSP4_OP0D (void) +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4.Logic) + { + case 1: goto resume1; break; + case 2: goto resume2; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // sort inputs + DSP4.world_y = DSP4_READ_DWORD(); + DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); + DSP4.poly_top[0][0] = DSP4_READ_WORD(); + DSP4.poly_cx[1][0] = DSP4_READ_WORD(); + DSP4.viewport_bottom = DSP4_READ_WORD(); + DSP4.world_x = DSP4_READ_DWORD(); + DSP4.poly_cx[0][0] = DSP4_READ_WORD(); + DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); + DSP4.world_yofs = DSP4_READ_WORD(); + DSP4.world_dy = DSP4_READ_DWORD(); + DSP4.world_dx = DSP4_READ_DWORD(); + DSP4.distance = DSP4_READ_WORD(); + DSP4_READ_WORD(); // 0x0000 + DSP4.world_xenv = SEX78(DSP4_READ_WORD()); + DSP4.world_ddy = DSP4_READ_WORD(); + DSP4.world_ddx = DSP4_READ_WORD(); + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // initial (x, y, offset) at starting raster line + DSP4.view_x1 = (DSP4.world_x + DSP4.world_xenv) >> 16; + DSP4.view_y1 = DSP4.world_y >> 16; + DSP4.view_xofs1 = DSP4.world_x >> 16; + DSP4.view_yofs1 = DSP4.world_yofs; + + // first raster line + DSP4.poly_raster[0][0] = DSP4.poly_bottom[0][0]; + + do + { + //////////////////////////////////////////////////// + // process one iteration of projection + + // perspective projection of world (x, y, scroll) points + // based on the current projection lines + DSP4.view_x2 = (((DSP4.world_x + DSP4.world_xenv) >> 16) * DSP4.distance >> 15) + (DSP4.view_turnoff_x * DSP4.distance >> 15); + DSP4.view_y2 = (DSP4.world_y >> 16) * DSP4.distance >> 15; + DSP4.view_xofs2 = DSP4.view_x2; + DSP4.view_yofs2 = (DSP4.world_yofs * DSP4.distance >> 15) + DSP4.poly_bottom[0][0] - DSP4.view_y2; + + // 1. World x-location before transformation + // 2. Viewer x-position at the current + // 3. World y-location before perspective projection + // 4. Viewer y-position below the horizon + // 5. Number of raster lines drawn in this iteration + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD((DSP4.world_x + DSP4.world_xenv) >> 16); + DSP4_WRITE_WORD(DSP4.view_x2); + DSP4_WRITE_WORD(DSP4.world_y >> 16); + DSP4_WRITE_WORD(DSP4.view_y2); + + ////////////////////////////////////////////////////////// + + // SR = 0x00 + + // determine # of raster lines used + DSP4.segments = DSP4.view_y1 - DSP4.view_y2; + + // prevent overdraw + if (DSP4.view_y2 >= DSP4.poly_raster[0][0]) + DSP4.segments = 0; + else + DSP4.poly_raster[0][0] = DSP4.view_y2; + + // don't draw outside the window + if (DSP4.view_y2 < DSP4.poly_top[0][0]) + { + DSP4.segments = 0; + + // flush remaining raster lines + if (DSP4.view_y1 >= DSP4.poly_top[0][0]) + DSP4.segments = DSP4.view_y1 - DSP4.poly_top[0][0]; + } + + // SR = 0x80 + + DSP4_WRITE_WORD(DSP4.segments); + + ////////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (DSP4.segments) + { + int32 px_dx, py_dy; + int32 x_scroll, y_scroll; + + // SR = 0x00 + + // linear interpolation (lerp) between projected points + px_dx = (DSP4.view_xofs2 - DSP4.view_xofs1) * DSP4_Inverse(DSP4.segments) << 1; + py_dy = (DSP4.view_yofs2 - DSP4.view_yofs1) * DSP4_Inverse(DSP4.segments) << 1; + + // starting step values + x_scroll = SEX16(DSP4.poly_cx[0][0] + DSP4.view_xofs1); + y_scroll = SEX16(-DSP4.viewport_bottom + DSP4.view_yofs1 + DSP4.view_yofsenv + DSP4.poly_cx[1][0] - DSP4.world_yofs); + + // SR = 0x80 + + // rasterize line + for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) + { + // 1. HDMA memory pointer (bg1) + // 2. vertical scroll offset ($210E) + // 3. horizontal scroll offset ($210D) + DSP4_WRITE_WORD(DSP4.poly_ptr[0][0]); + DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); + DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); + + // update memory address + DSP4.poly_ptr[0][0] -= 4; + + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } + + ///////////////////////////////////////////////////// + // Post-update + + // update new viewer (x, y, scroll) to last raster line drawn + DSP4.view_x1 = DSP4.view_x2; + DSP4.view_y1 = DSP4.view_y2; + DSP4.view_xofs1 = DSP4.view_xofs2; + DSP4.view_yofs1 = DSP4.view_yofs2; + + // add deltas for projection lines + DSP4.world_dx += SEX78(DSP4.world_ddx); + DSP4.world_dy += SEX78(DSP4.world_ddy); + + // update projection lines + DSP4.world_x += (DSP4.world_dx + DSP4.world_xenv); + DSP4.world_y += DSP4.world_dy; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(1); + + resume1: + + // inspect input + DSP4.distance = DSP4_READ_WORD(); + + // terminate op + if (DSP4.distance == -0x8000) + break; + + // already have 2 bytes in queue + DSP4.in_count = 6; + DSP4_WAIT(2); + + resume2: + + // inspect inputs + DSP4.world_ddy = DSP4_READ_WORD(); + DSP4.world_ddx = DSP4_READ_WORD(); + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // no envelope here + DSP4.world_xenv = 0; + } + while (1); + + DSP4.waiting4command = TRUE; +} + +static void DSP4_OP0E (void) +{ + DSP4.OAM_RowMax = 16; + memset(DSP4.OAM_Row, 0, 64); +} + +static void DSP4_OP0F (void) +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4.Logic) + { + case 1: goto resume1; break; + case 2: goto resume2; break; + case 3: goto resume3; break; + case 4: goto resume4; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // sort inputs + DSP4_READ_WORD(); // 0x0000 + DSP4.world_y = DSP4_READ_DWORD(); + DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); + DSP4.poly_top[0][0] = DSP4_READ_WORD(); + DSP4.poly_cx[1][0] = DSP4_READ_WORD(); + DSP4.viewport_bottom = DSP4_READ_WORD(); + DSP4.world_x = DSP4_READ_DWORD(); + DSP4.poly_cx[0][0] = DSP4_READ_WORD(); + DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); + DSP4.world_yofs = DSP4_READ_WORD(); + DSP4.world_dy = DSP4_READ_DWORD(); + DSP4.world_dx = DSP4_READ_DWORD(); + DSP4.distance = DSP4_READ_WORD(); + DSP4_READ_WORD(); // 0x0000 + DSP4.world_xenv = DSP4_READ_DWORD(); + DSP4.world_ddy = DSP4_READ_WORD(); + DSP4.world_ddx = DSP4_READ_WORD(); + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // initial (x, y, offset) at starting raster line + DSP4.view_x1 = (DSP4.world_x + DSP4.world_xenv) >> 16; + DSP4.view_y1 = DSP4.world_y >> 16; + DSP4.view_xofs1 = DSP4.world_x >> 16; + DSP4.view_yofs1 = DSP4.world_yofs; + DSP4.view_turnoff_x = 0; + DSP4.view_turnoff_dx = 0; + + // first raster line + DSP4.poly_raster[0][0] = DSP4.poly_bottom[0][0]; + + do + { + //////////////////////////////////////////////////// + // process one iteration of projection + + // perspective projection of world (x, y, scroll) points + // based on the current projection lines + DSP4.view_x2 = ((DSP4.world_x + DSP4.world_xenv) >> 16) * DSP4.distance >> 15; + DSP4.view_y2 = (DSP4.world_y >> 16) * DSP4.distance >> 15; + DSP4.view_xofs2 = DSP4.view_x2; + DSP4.view_yofs2 = (DSP4.world_yofs * DSP4.distance >> 15) + DSP4.poly_bottom[0][0] - DSP4.view_y2; + + // 1. World x-location before transformation + // 2. Viewer x-position at the next + // 3. World y-location before perspective projection + // 4. Viewer y-position below the horizon + // 5. Number of raster lines drawn in this iteration + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD((DSP4.world_x + DSP4.world_xenv) >> 16); + DSP4_WRITE_WORD(DSP4.view_x2); + DSP4_WRITE_WORD(DSP4.world_y >> 16); + DSP4_WRITE_WORD(DSP4.view_y2); + + ////////////////////////////////////////////////////// + + // SR = 0x00 + + // determine # of raster lines used + DSP4.segments = DSP4.poly_raster[0][0] - DSP4.view_y2; + + // prevent overdraw + if (DSP4.view_y2 >= DSP4.poly_raster[0][0]) + DSP4.segments = 0; + else + DSP4.poly_raster[0][0] = DSP4.view_y2; + + // don't draw outside the window + if (DSP4.view_y2 < DSP4.poly_top[0][0]) + { + DSP4.segments = 0; + + // flush remaining raster lines + if (DSP4.view_y1 >= DSP4.poly_top[0][0]) + DSP4.segments = DSP4.view_y1 - DSP4.poly_top[0][0]; + } + + // SR = 0x80 + + DSP4_WRITE_WORD(DSP4.segments); + + ////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (DSP4.segments) + { + int32 px_dx, py_dy; + int32 x_scroll, y_scroll; + + for (DSP4.lcv = 0; DSP4.lcv < 4; DSP4.lcv++) + { + // grab inputs + DSP4.in_count = 4; + DSP4_WAIT(1); + + resume1: + + for (;;) + { + int16 dist; + int16 color, red, green, blue; + + dist = DSP4_READ_WORD(); + color = DSP4_READ_WORD(); + + // U1+B5+G5+R5 + red = color & 0x1f; + green = (color >> 5) & 0x1f; + blue = (color >> 10) & 0x1f; + + // dynamic lighting + red = (red * dist >> 15) & 0x1f; + green = (green * dist >> 15) & 0x1f; + blue = (blue * dist >> 15) & 0x1f; + color = red | (green << 5) | (blue << 10); + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(color); + + break; + } + } + + ////////////////////////////////////////////////////// + + // SR = 0x00 + + // linear interpolation (lerp) between projected points + px_dx = (DSP4.view_xofs2 - DSP4.view_xofs1) * DSP4_Inverse(DSP4.segments) << 1; + py_dy = (DSP4.view_yofs2 - DSP4.view_yofs1) * DSP4_Inverse(DSP4.segments) << 1; + + // starting step values + x_scroll = SEX16(DSP4.poly_cx[0][0] + DSP4.view_xofs1); + y_scroll = SEX16(-DSP4.viewport_bottom + DSP4.view_yofs1 + DSP4.view_yofsenv + DSP4.poly_cx[1][0] - DSP4.world_yofs); + + // SR = 0x80 + + // rasterize line + for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) + { + // 1. HDMA memory pointer + // 2. vertical scroll offset ($210E) + // 3. horizontal scroll offset ($210D) + DSP4_WRITE_WORD(DSP4.poly_ptr[0][0]); + DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); + DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); + + // update memory address + DSP4.poly_ptr[0][0] -= 4; + + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } + + //////////////////////////////////////////////////// + // Post-update + + // update new viewer (x, y, scroll) to last raster line drawn + DSP4.view_x1 = DSP4.view_x2; + DSP4.view_y1 = DSP4.view_y2; + DSP4.view_xofs1 = DSP4.view_xofs2; + DSP4.view_yofs1 = DSP4.view_yofs2; + + // add deltas for projection lines + DSP4.world_dx += SEX78(DSP4.world_ddx); + DSP4.world_dy += SEX78(DSP4.world_ddy); + + // update projection lines + DSP4.world_x += (DSP4.world_dx + DSP4.world_xenv); + DSP4.world_y += DSP4.world_dy; + + // update road turnoff position + DSP4.view_turnoff_x += DSP4.view_turnoff_dx; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(2); + + resume2: + + // check for termination + DSP4.distance = DSP4_READ_WORD(); + if (DSP4.distance == -0x8000) + break; + + // road splice + if ((uint16) DSP4.distance == 0x8001) + { + DSP4.in_count = 6; + DSP4_WAIT(3); + + resume3: + + DSP4.distance = DSP4_READ_WORD(); + DSP4.view_turnoff_x = DSP4_READ_WORD(); + DSP4.view_turnoff_dx = DSP4_READ_WORD(); + + // factor in new changes + DSP4.view_x1 += (DSP4.view_turnoff_x * DSP4.distance >> 15); + DSP4.view_xofs1 += (DSP4.view_turnoff_x * DSP4.distance >> 15); + + // update stepping values + DSP4.view_turnoff_x += DSP4.view_turnoff_dx; + + DSP4.in_count = 2; + DSP4_WAIT(2); + } + + // already have 2 bytes in queue + DSP4.in_count = 6; + DSP4_WAIT(4); + + resume4: + + // inspect inputs + DSP4.world_ddy = DSP4_READ_WORD(); + DSP4.world_ddx = DSP4_READ_WORD(); + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // no envelope here + DSP4.world_xenv = 0; + } + while (1); + + // terminate op + DSP4.waiting4command = TRUE; +} + +static void DSP4_OP10 (void) +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4.Logic) + { + case 1: goto resume1; break; + case 2: goto resume2; break; + case 3: goto resume3; break; + } + + //////////////////////////////////////////////////// + // sort inputs + + DSP4_READ_WORD(); // 0x0000 + DSP4.world_y = DSP4_READ_DWORD(); + DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); + DSP4.poly_top[0][0] = DSP4_READ_WORD(); + DSP4.poly_cx[1][0] = DSP4_READ_WORD(); + DSP4.viewport_bottom = DSP4_READ_WORD(); + DSP4.world_x = DSP4_READ_DWORD(); + DSP4.poly_cx[0][0] = DSP4_READ_WORD(); + DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); + DSP4.world_yofs = DSP4_READ_WORD(); + DSP4.distance = DSP4_READ_WORD(); + DSP4.view_y2 = DSP4_READ_WORD(); + DSP4.view_dy = DSP4_READ_WORD() * DSP4.distance >> 15; + DSP4.view_x2 = DSP4_READ_WORD(); + DSP4.view_dx = DSP4_READ_WORD() * DSP4.distance >> 15; + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // initial (x, y, offset) at starting raster line + DSP4.view_x1 = DSP4.world_x >> 16; + DSP4.view_y1 = DSP4.world_y >> 16; + DSP4.view_xofs1 = DSP4.view_x1; + DSP4.view_yofs1 = DSP4.world_yofs; + + // first raster line + DSP4.poly_raster[0][0] = DSP4.poly_bottom[0][0]; + + do + { + //////////////////////////////////////////////////// + // process one iteration of projection + + // add shaping + DSP4.view_x2 += DSP4.view_dx; + DSP4.view_y2 += DSP4.view_dy; + + // vertical scroll calculation + DSP4.view_xofs2 = DSP4.view_x2; + DSP4.view_yofs2 = (DSP4.world_yofs * DSP4.distance >> 15) + DSP4.poly_bottom[0][0] - DSP4.view_y2; + + // 1. Viewer x-position at the next + // 2. Viewer y-position below the horizon + // 3. Number of raster lines drawn in this iteration + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(DSP4.view_x2); + DSP4_WRITE_WORD(DSP4.view_y2); + + ////////////////////////////////////////////////////// + + // SR = 0x00 + + // determine # of raster lines used + DSP4.segments = DSP4.view_y1 - DSP4.view_y2; + + // prevent overdraw + if (DSP4.view_y2 >= DSP4.poly_raster[0][0]) + DSP4.segments = 0; + else + DSP4.poly_raster[0][0] = DSP4.view_y2; + + // don't draw outside the window + if (DSP4.view_y2 < DSP4.poly_top[0][0]) + { + DSP4.segments = 0; + + // flush remaining raster lines + if (DSP4.view_y1 >= DSP4.poly_top[0][0]) + DSP4.segments = DSP4.view_y1 - DSP4.poly_top[0][0]; + } + + // SR = 0x80 + + DSP4_WRITE_WORD(DSP4.segments); + + ////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (DSP4.segments) + { + for (DSP4.lcv = 0; DSP4.lcv < 4; DSP4.lcv++) + { + // grab inputs + DSP4.in_count = 4; + DSP4_WAIT(1); + + resume1: + + for (;;) + { + int16 dist; + int16 color, red, green, blue; + + dist = DSP4_READ_WORD(); + color = DSP4_READ_WORD(); + + // U1+B5+G5+R5 + red = color & 0x1f; + green = (color >> 5) & 0x1f; + blue = (color >> 10) & 0x1f; + + // dynamic lighting + red = (red * dist >> 15) & 0x1f; + green = (green * dist >> 15) & 0x1f; + blue = (blue * dist >> 15) & 0x1f; + color = red | (green << 5) | (blue << 10); + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(color); + + break; + } + } + } + + ////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (DSP4.segments) + { + int32 px_dx, py_dy; + int32 x_scroll, y_scroll; + + // SR = 0x00 + + // linear interpolation (lerp) between projected points + px_dx = (DSP4.view_xofs2 - DSP4.view_xofs1) * DSP4_Inverse(DSP4.segments) << 1; + py_dy = (DSP4.view_yofs2 - DSP4.view_yofs1) * DSP4_Inverse(DSP4.segments) << 1; + + // starting step values + x_scroll = SEX16(DSP4.poly_cx[0][0] + DSP4.view_xofs1); + y_scroll = SEX16(-DSP4.viewport_bottom + DSP4.view_yofs1 + DSP4.view_yofsenv + DSP4.poly_cx[1][0] - DSP4.world_yofs); + + // SR = 0x80 + + // rasterize line + for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) + { + // 1. HDMA memory pointer (bg2) + // 2. vertical scroll offset ($2110) + // 3. horizontal scroll offset ($210F) + DSP4_WRITE_WORD(DSP4.poly_ptr[0][0]); + DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); + DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); + + // update memory address + DSP4.poly_ptr[0][0] -= 4; + + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } + + ///////////////////////////////////////////////////// + // Post-update + + // update new viewer (x, y, scroll) to last raster line drawn + DSP4.view_x1 = DSP4.view_x2; + DSP4.view_y1 = DSP4.view_y2; + DSP4.view_xofs1 = DSP4.view_xofs2; + DSP4.view_yofs1 = DSP4.view_yofs2; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(2); + + resume2: + + // check for opcode termination + DSP4.distance = DSP4_READ_WORD(); + if (DSP4.distance == -0x8000) + break; + + // already have 2 bytes in queue + DSP4.in_count = 10; + DSP4_WAIT(3); + + resume3: + + // inspect inputs + DSP4.view_y2 = DSP4_READ_WORD(); + DSP4.view_dy = DSP4_READ_WORD() * DSP4.distance >> 15; + DSP4.view_x2 = DSP4_READ_WORD(); + DSP4.view_dx = DSP4_READ_WORD() * DSP4.distance >> 15; + } + while (1); + + DSP4.waiting4command = TRUE; +} + +static void DSP4_OP11 (int16 A, int16 B, int16 C, int16 D, int16 *M) +{ + // 0x155 = 341 = Horizontal Width of the Screen + *M = ((A * 0x0155 >> 2) & 0xf000) | ((B * 0x0155 >> 6) & 0x0f00) | ((C * 0x0155 >> 10) & 0x00f0) | ((D * 0x0155 >> 14) & 0x000f); +} + +static void DSP4_SetByte (void) +{ + // clear pending read + if (DSP4.out_index < DSP4.out_count) + { + DSP4.out_index++; + return; + } + + if (DSP4.waiting4command) + { + if (DSP4.half_command) + { + DSP4.command |= (DSP4.byte << 8); + DSP4.in_index = 0; + DSP4.waiting4command = FALSE; + DSP4.half_command = FALSE; + DSP4.out_count = 0; + DSP4.out_index = 0; + + DSP4.Logic = 0; + + switch (DSP4.command) + { + case 0x0000: DSP4.in_count = 4; break; + case 0x0001: DSP4.in_count = 44; break; + case 0x0003: DSP4.in_count = 0; break; + case 0x0005: DSP4.in_count = 0; break; + case 0x0006: DSP4.in_count = 0; break; + case 0x0007: DSP4.in_count = 34; break; + case 0x0008: DSP4.in_count = 90; break; + case 0x0009: DSP4.in_count = 14; break; + case 0x000a: DSP4.in_count = 6; break; + case 0x000b: DSP4.in_count = 6; break; + case 0x000d: DSP4.in_count = 42; break; + case 0x000e: DSP4.in_count = 0; break; + case 0x000f: DSP4.in_count = 46; break; + case 0x0010: DSP4.in_count = 36; break; + case 0x0011: DSP4.in_count = 8; break; + default: + DSP4.waiting4command = TRUE; + break; + } + } + else + { + DSP4.command = DSP4.byte; + DSP4.half_command = TRUE; + } + } + else + { + DSP4.parameters[DSP4.in_index] = DSP4.byte; + DSP4.in_index++; + } + + if (!DSP4.waiting4command && DSP4.in_count == DSP4.in_index) + { + // Actually execute the command + DSP4.waiting4command = TRUE; + DSP4.out_index = 0; + DSP4.in_index = 0; + + switch (DSP4.command) + { + // 16-bit multiplication + case 0x0000: + { + int16 multiplier, multiplicand; + int32 product; + + multiplier = DSP4_READ_WORD(); + multiplicand = DSP4_READ_WORD(); + + DSP4_Multiply(multiplicand, multiplier, &product); + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(product); + DSP4_WRITE_WORD(product >> 16); + + break; + } + + // single-player track projection + case 0x0001: + DSP4_OP01(); + break; + + // single-player selection + case 0x0003: + DSP4_OP03(); + break; + + // clear OAM + case 0x0005: + DSP4_OP05(); + break; + + // transfer OAM + case 0x0006: + DSP4_OP06(); + break; + + // single-player track turnoff projection + case 0x0007: + DSP4_OP07(); + break; + + // solid polygon projection + case 0x0008: + DSP4_OP08(); + break; + + // sprite projection + case 0x0009: + DSP4_OP09(); + break; + + // unknown + case 0x000A: + { + DSP4_READ_WORD(); + int16 in2a = DSP4_READ_WORD(); + DSP4_READ_WORD(); + int16 out1a, out2a, out3a, out4a; + + DSP4_OP0A(in2a, &out2a, &out1a, &out4a, &out3a); + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(out1a); + DSP4_WRITE_WORD(out2a); + DSP4_WRITE_WORD(out3a); + DSP4_WRITE_WORD(out4a); + + break; + } + + // set OAM + case 0x000B: + { + int16 sp_x = DSP4_READ_WORD(); + int16 sp_y = DSP4_READ_WORD(); + int16 sp_attr = DSP4_READ_WORD(); + bool8 draw = TRUE; + + DSP4_CLEAR_OUT(); + DSP4_OP0B(&draw, sp_x, sp_y, sp_attr, 0, 1); + + break; + } + + // multi-player track projection + case 0x000D: + DSP4_OP0D(); + break; + + // multi-player selection + case 0x000E: + DSP4_OP0E(); + break; + + // single-player track projection with lighting + case 0x000F: + DSP4_OP0F(); + break; + + // single-player track turnoff projection with lighting + case 0x0010: + DSP4_OP10(); + break; + + // unknown: horizontal mapping command + case 0x0011: + { + int16 a, b, c, d, m; + + d = DSP4_READ_WORD(); + c = DSP4_READ_WORD(); + b = DSP4_READ_WORD(); + a = DSP4_READ_WORD(); + + DSP4_OP11(a, b, c, d, &m); + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(m); + + break; + } + + default: + break; + } + } +} + +static void DSP4_GetByte (void) +{ + if (DSP4.out_count) + { + DSP4.byte = (uint8) DSP4.output[DSP4.out_index & 0x1FF]; + + DSP4.out_index++; + if (DSP4.out_count == DSP4.out_index) + DSP4.out_count = 0; + } + else + DSP4.byte = 0xff; +} + +void DSP4SetByte (uint8 byte, uint16 address) +{ + if (address < DSP0.boundary) + { + DSP4.byte = byte; + DSP4.address = address; + DSP4_SetByte(); + } +} + +uint8 DSP4GetByte (uint16 address) +{ + if (address < DSP0.boundary) + { + DSP4.address = address; + DSP4_GetByte(); + return (DSP4.byte); + } + + return (0x80); +} diff --git a/plugins/snes9x_gx/source/snes9x/font.h b/plugins/snes9x_gx/source/snes9x/font.h new file mode 100644 index 00000000..27011f6b --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/font.h @@ -0,0 +1,325 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _FONT_H_ +#define _FONT_H_ + +static const char *font[] = +{ + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " . . . . .. . . ", + " .#. .#.#. . . ... .#. . . .##. .#. .#. . . . . ", + " .#. .#.#. .#.#. .###. .#..#. .#. .#. .#. .#. .#.#. .#. .#. ", + " .#. .#.#. .#####. .#.#. ..#. .#.#. .#. .#. .#. .#. ..#.. .... .#. ", + " .#. . . .#.#. .###. .#.. .#. . .#. .#. .###. .#####. .. .####. .. .#. ", + " . .#####. .#.#. .#..#. .#.#. .#. .#. .#. ..#.. .##. .... .##. .#. ", + " .#. .#.#. .###. . .#. .#.#. .#. .#. .#.#. .#. .#. .##. . ", + " . . . ... . . . . . . . . .#. .. ", + " . ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " . . .. .... . .... .. .... .. .. . ", + " .#. .#. .##. .####. .#. .####. .##. .####. .##. .##. .. .. . . .#. ", + ".#.#. .##. .#..#. ...#. .##. .#... .#.. ...#. .#..#. .#..#. .##. .##. .#. .... .#. .#.#. ", + ".#.#. .#. . .#. .##. .#.#. .###. .###. .#. .##. .#..#. .##. .##. .#. .####. .#. ..#. ", + ".#.#. .#. .#. ...#. .####. ...#. .#..#. .#. .#..#. .###. .. .. .#. .... .#. .#. ", + ".#.#. .#. .#.. .#..#. ..#. .#..#. .#..#. .#. .#..#. ..#. .##. .##. .#. .####. .#. . ", + " .#. .###. .####. .##. .#. .##. .##. .#. .##. .##. .##. .#. .#. .... .#. .#. ", + " . ... .... .. . .. .. . .. .. .. .#. . . . ", + " . ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " .. .. ... .. ... .... .... .. . . ... . . . . . . . . .. ", + " .##. .##. .###. .##. .###. .####. .####. .##. .#..#. .###. .#. .#..#. .#. .#. .#. .#. .#. .##. ", + ".#..#. .#..#. .#..#. .#..#. .#..#. .#... .#... .#..#. .#..#. .#. .#. .#.#. .#. .##.##. .##..#. .#..#. ", + ".#.##. .#..#. .###. .#. . .#..#. .###. .###. .#... .####. .#. .#. .##. .#. .#.#.#. .#.#.#. .#..#. ", + ".#.##. .####. .#..#. .#. . .#..#. .#.. .#.. .#.##. .#..#. .#. . .#. .##. .#. .#...#. .#.#.#. .#..#. ", + ".#... .#..#. .#..#. .#..#. .#..#. .#... .#. .#..#. .#..#. .#. .#..#. .#.#. .#... .#. .#. .#..##. .#..#. ", + " .##. .#..#. .###. .##. .###. .####. .#. .###. .#..#. .###. .##. .#..#. .####. .#. .#. .#. .#. .##. ", + " .. . . ... .. ... .... . ... . . ... .. . . .... . . . . .. ", + " ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " ... .. ... .. ... . . . . . . . . . . .... ... ... . ", + ".###. .##. .###. .##. .###. .#. .#. .#. .#. .#. .#. .#..#. .#.#. .####. .###. . .###. .#. ", + ".#..#. .#..#. .#..#. .#..#. .#. .#. .#. .#. .#. .#...#. .#..#. .#.#. ...#. .#.. .#. ..#. .#.#. ", + ".#..#. .#..#. .#..#. .#.. .#. .#. .#. .#. .#. .#.#.#. .##. .#.#. .#. .#. .#. .#. . . ", + ".###. .#..#. .###. ..#. .#. .#. .#. .#. .#. .#.#.#. .#..#. .#. .#. .#. .#. .#. ", + ".#.. .##.#. .#.#. .#..#. .#. .#...#. .#.#. .##.##. .#..#. .#. .#... .#.. .#. ..#. .... ", + ".#. .##. .#..#. .##. .#. .###. .#. .#. .#. .#..#. .#. .####. .###. . .###. .####. ", + " . ..#. . . .. . ... . . . . . . .... ... ... .... ", + " . ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " .. . . . . . . . .. ", + ".##. .#. .#. .#. .#. .#. .#. .#. .##. ", + " .#. ... .#.. .. ..#. .. .#.#. ... .#.. .. . .#.. .#. .. .. ... .. ", + " .#. .###. .###. .##. .###. .##. .#.. .###. .###. .##. .#. .#.#. .#. .##.##. .###. .##. ", + " . .#..#. .#..#. .#.. .#..#. .#.##. .###. .#..#. .#..#. .#. .#. .##. .#. .#.#.#. .#..#. .#..#. ", + " .#.##. .#..#. .#.. .#..#. .##.. .#. .##. .#..#. .#. ..#. .#.#. .#. .#...#. .#..#. .#..#. ", + " .#.#. .###. .##. .###. .##. .#. .#... .#..#. .###. .#.#. .#..#. .###. .#. .#. .#..#. .##. ", + " . . ... .. ... .. . .###. . . ... .#. . . ... . . . . .. ", + " ... . ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " . . . . . . ", + " .#. .#. .#. .#. .#.#. ", + " ... ... ... ... .#. . . . . . . . . . . .... .#. .#. .#. .#.#. ", + ".###. .###. .###. .###. .###. .#..#. .#.#. .#...#. .#..#. .#..#. .####. .##. .#. .##. . . ", + ".#..#. .#..#. .#..#. .##.. .#. .#..#. .#.#. .#.#.#. .##. .#..#. ..#. .#. .#. .#. ", + ".#..#. .#..#. .#. . ..##. .#.. .#..#. .#.#. .#.#.#. .##. .#.#. .#.. .#. .#. .#. ", + ".###. .###. .#. .###. .##. .###. .#. .#.#. .#..#. .#. .####. .#. .#. .#. ", + ".#.. ..#. . ... .. ... . . . . . .#. .... . . . ", + " . . . ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " .. ..... ", + " .##. .#####. ... . . . . .. ", + " .#. . .. ....#. .###. .#. .#. .#. .#.. .##. . . . ", + " .#. .#. .##. .#####. .#. .#. .###. ... .###. .###. .. .#. .#.#.#. ", + " . .#. .#. . .##. ....#. .#. .##. .#.#. .###. .#. .##.#. .##. .##. .#.#.#. ", + " .#. . .#. .#. .. ...#. .#. .#. ..#. .#. .##. .#.. ..#. .#. ...#. ", + " .#.#. .##. .#. .###. .#. .#. .#. .###. .#. .#. .####. .##. .##. ", + " .#. .. .#. ... . . . ... . . .... .. .. ", + " . . ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " .... . . ... . . . .... . . . .. . ..... . . . ", + " .####. .#. ..#.. .###. ...#. ..#.. ..#.. .####. .#... .... .#.#. .##..#. .#####. .#... .#. .#. ", + " .... ...#. .#. .#####. .#. .#####. .#####. .#####. .#..#. .####. .####. .#####. .. .#. ....#. .#####. .#. .#. ", + ".####. .##. .## .#...#. .#. ...#. ..#.#. ..#.. .# .#. .#..#. ...#. .#.#. .##..#. .#. .#..#. .#..#. ", + " .... .#. .#.# . .#. .#. .##. .#..#. .#####. .#. .#. . .#. .#. ..#. .. .#. .#. .#.#. . .#. ", + " .#. .#. ..#. ..#.. .#.#. .#..#. ..#.. . .#. .#. ...#. .#. ...#. .#.#. .#... ...#. ", + " .#. .#. .##. .#####. .#..#. .#..#. .#. .#. .#. .####. .#. .###. .#. .#. .###. .###. ", + " . . .. ..... . . . . . . . .... . ... . . ... ... ", + " ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " .... .. . . . ... . . ... .... . . . ..... . . ", + " .####. ..##. .#.#.#. .###. .#. ..#.. .###. .####. ..#.. .#. . . .#. .. .#####. .#. ..#.. ..... ", + " .#..#. .###. .#.#.#. ..... .#. .#####. ... ...#. .#####. .#. .#.#. .#..##. ....#. .#.#. .#####. .#####. ", + " .####. ..#. .#.#.#. .#####. .##. ..#.. .#.#. ....#. .#. .#.#. .###.. .#. .#..#. ..#.. .#. ", + ".#...#. .####. . ..#. ..#.. .#.#. .#. .#. .###. .#. .#. .#. .#.. .#. . .#. .#.#.#. .#.#. ", + " . .#. ..#. ...#. .#. .#.. ..#. ..... .#.#. .#.#.#. .#. .#. .#. .#.... ..#. .#. .#.#.#. .#. ", + " .#. .##. .###. .#. .#. .##. .#####. .#. .#. ..#.. .#. .#. .#. .####. .##. .#. ..#.. .#. ", + " . .. ... . . .. ..... . . . . . . .... .. . . . ", + " ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " .. . . ... . .... .... . . . . . ..... . . . . ", + " .##. .#. .#. .###. .#... ... .####. .####. .#..#. .#.#. .#. ..... .#####. ....#. .#.#. .#. ", + " ..#. .#. . .#. .#. .#.##. .###. ...#. ..... .#..#. .#.#. .#. .#####. .#...#. .###.#. .#.#. .#.#. ", + " .##. .#. . .#.#. .#####. .##.#. .#. .###. .#####. .#..#. .#.#. .#. . .#...#. . .#. ....#. . . .#. ", + " ..#. .#..#. .##. ..#.. .#.#. ..#. ..#. ....#. . .#. .#.#. .#..#. .#...#. .#. .#. . ", + " .##. .####. ..#.#. .#.. .#. ...#. ...#. ..#. ..#. .#.#. .#.#. .#####. ..#. ...#. ", + " ..#. ...#. .##. . .###. .#. .#####. .####. .##. .##. .#..##. .##. .#...#. .##. .###. ", + " . . .. ... . ..... .... .. ... . .. .. . . .. ... ", + " ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " +}; + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/fxdbg.cpp b/plugins/snes9x_gx/source/snes9x/fxdbg.cpp new file mode 100644 index 00000000..ed971234 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/fxdbg.cpp @@ -0,0 +1,1425 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifdef DEBUGGER + +#include "snes9x.h" +#include "fxinst.h" +#include "fxemu.h" + +/* + When printing a line from the pipe, it could look like this: + + 01:8006 f4 fb 86 iwt r4, #$86fb + + The values are: + program bank : 01 + adress : 8006 + values at memory address 8006 : f4 fb 86 + instruction in the pipe : iwt r4, #$86fb + + Note! If the instruction has more than one byte (like in 'iwt') and the instruction is in a delay slot, + the second and third byte displayed will not be the same as those used. + Since the instrction is in a delay slot, + the first byte of the instruction will be taken from the pipe at the address after the branch instruction, + and the next one or two bytes will be taken from the address that the branch points to. + This is a bit complicated, but I've taken this into account, in this debug function. + (See the diffrence of how the values vPipe1 and vPipe2 are read, compared to the values vByte1 and vByte2) +*/ + +/* +static const char *fx_apvMnemonicTable[] = +{ + // ALT0 Table + + // 00 - 0f + "stop", + "nop", + "cache", + "lsr", + "rol", + "bra $%04x", + "blt $%04x", + "bge $%04x", + "bne $%04x", + "beq $%04x", + "bpl $%04x", + "bmi $%04x", + "bcc $%04x", + "bcs $%04x", + "bvc $%04x", + "bvs $%04x", + + // 10 - 1f + "to r0", + "to r1", + "to r2", + "to r3", + "to r4", + "to r5", + "to r6", + "to r7", + "to r8", + "to r9", + "to r10", + "to r11", + "to r12", + "to r13", + "to r14", + "to r15", + + // 20 - 2f + "with r0", + "with r1", + "with r2", + "with r3", + "with r4", + "with r5", + "with r6", + "with r7", + "with r8", + "with r9", + "with r10", + "with r11", + "with r12", + "with r13", + "with r14", + "with r15", + + // 30 - 3f + "stw (r0)", + "stw (r1)", + "stw (r2)", + "stw (r3)", + "stw (r4)", + "stw (r5)", + "stw (r6)", + "stw (r7)", + "stw (r8)", + "stw (r9)", + "stw (r10)", + "stw (r11)", + "loop", + "alt1", + "alt2", + "alt3", + + // 40 - 4f + "ldw (r0)", + "ldw (r1)", + "ldw (r2)", + "ldw (r3)", + "ldw (r4)", + "ldw (r5)", + "ldw (r6)", + "ldw (r7)", + "ldw (r8)", + "ldw (r9)", + "ldw (r10)", + "ldw (r11)", + "plot", + "swap", + "color", + "not", + + // 50 - 5f + "add r0", + "add r1", + "add r2", + "add r3", + "add r4", + "add r5", + "add r6", + "add r7", + "add r8", + "add r9", + "add r10", + "add r11", + "add r12", + "add r13", + "add r14", + "add r15", + + // 60 - 6f + "sub r0", + "sub r1", + "sub r2", + "sub r3", + "sub r4", + "sub r5", + "sub r6", + "sub r7", + "sub r8", + "sub r9", + "sub r10", + "sub r11", + "sub r12", + "sub r13", + "sub r14", + "sub r15", + + // 70 - 7f + "merge", + "and r1", + "and r2", + "and r3", + "and r4", + "and r5", + "and r6", + "and r7", + "and r8", + "and r9", + "and r10", + "and r11", + "and r12", + "and r13", + "and r14", + "and r15", + + // 80 - 8f + "mult r0", + "mult r1", + "mult r2", + "mult r3", + "mult r4", + "mult r5", + "mult r6", + "mult r7", + "mult r8", + "mult r9", + "mult r10", + "mult r11", + "mult r12", + "mult r13", + "mult r14", + "mult r15", + + // 90 - 9f + "sbk", + "link #1", + "link #2", + "link #3", + "link #4", + "sex", + "asr", + "ror", + "jmp (r8)", + "jmp (r9)", + "jmp (r10)", + "jmp (r11)", + "jmp (r12)", + "jmp (r13)", + "lob", + "fmult", + + // a0 - af + "ibt r0, #$%02x", + "ibt r1, #$%02x", + "ibt r2, #$%02x", + "ibt r3, #$%02x", + "ibt r4, #$%02x", + "ibt r5, #$%02x", + "ibt r6, #$%02x", + "ibt r7, #$%02x", + "ibt r8, #$%02x", + "ibt r9, #$%02x", + "ibt r10, #$%02x", + "ibt r11, #$%02x", + "ibt r12, #$%02x", + "ibt r13, #$%02x", + "ibt r14, #$%02x", + "ibt r15, #$%02x", + + // b0 - bf + "from r0", + "from r1", + "from r2", + "from r3", + "from r4", + "from r5", + "from r6", + "from r7", + "from r8", + "from r9", + "from r10", + "from r11", + "from r12", + "from r13", + "from r14", + "from r15", + + // c0 - cf + "hib", + "or r1", + "or r2", + "or r3", + "or r4", + "or r5", + "or r6", + "or r7", + "or r8", + "or r9", + "or r10", + "or r11", + "or r12", + "or r13", + "or r14", + "or r15", + + // d0 - df + "inc r0", + "inc r1", + "inc r2", + "inc r3", + "inc r4", + "inc r5", + "inc r6", + "inc r7", + "inc r8", + "inc r9", + "inc r10", + "inc r11", + "inc r12", + "inc r13", + "inc r14", + "getc", + + // e0 - ef + "dec r0", + "dec r1", + "dec r2", + "dec r3", + "dec r4", + "dec r5", + "dec r6", + "dec r7", + "dec r8", + "dec r9", + "dec r10", + "dec r11", + "dec r12", + "dec r13", + "dec r14", + "getb", + + // f0 - ff + "iwt r0, #$%04x", + "iwt r1, #$%04x", + "iwt r2, #$%04x", + "iwt r3, #$%04x", + "iwt r4, #$%04x", + "iwt r5, #$%04x", + "iwt r6, #$%04x", + "iwt r7, #$%04x", + "iwt r8, #$%04x", + "iwt r9, #$%04x", + "iwt r10, #$%04x", + "iwt r11, #$%04x", + "iwt r12, #$%04x", + "iwt r13, #$%04x", + "iwt r14, #$%04x", + "iwt r15, #$%04x", + + // ALT1 Table + + // 00 - 0f + "stop", + "nop", + "cache", + "lsr", + "rol", + "bra $%04x", + "blt $%04x", + "bge $%04x", + "bne $%04x", + "beq $%04x", + "bpl $%04x", + "bmi $%04x", + "bcc $%04x", + "bcs $%04x", + "bvc $%04x", + "bvs $%04x", + + // 10 - 1f + "to r0", + "to r1", + "to r2", + "to r3", + "to r4", + "to r5", + "to r6", + "to r7", + "to r8", + "to r9", + "to r10", + "to r11", + "to r12", + "to r13", + "to r14", + "to r15", + + // 20 - 2f + "with r0", + "with r1", + "with r2", + "with r3", + "with r4", + "with r5", + "with r6", + "with r7", + "with r8", + "with r9", + "with r10", + "with r11", + "with r12", + "with r13", + "with r14", + "with r15", + + // 30 - 3f + "stb (r0)", + "stb (r1)", + "stb (r2)", + "stb (r3)", + "stb (r4)", + "stb (r5)", + "stb (r6)", + "stb (r7)", + "stb (r8)", + "stb (r9)", + "stb (r10)", + "stb (r11)", + "loop", + "alt1", + "alt2", + "alt3", + + // 40 - 4f + "ldb (r0)", + "ldb (r1)", + "ldb (r2)", + "ldb (r3)", + "ldb (r4)", + "ldb (r5)", + "ldb (r6)", + "ldb (r7)", + "ldb (r8)", + "ldb (r9)", + "ldb (r10)", + "ldb (r11)", + "rpix", + "swap", + "cmode", + "not", + + // 50 - 5f + "adc r0", + "adc r1", + "adc r2", + "adc r3", + "adc r4", + "adc r5", + "adc r6", + "adc r7", + "adc r8", + "adc r9", + "adc r10", + "adc r11", + "adc r12", + "adc r13", + "adc r14", + "adc r15", + + // 60 - 6f + "sbc r0", + "sbc r1", + "sbc r2", + "sbc r3", + "sbc r4", + "sbc r5", + "sbc r6", + "sbc r7", + "sbc r8", + "sbc r9", + "sbc r10", + "sbc r11", + "sbc r12", + "sbc r13", + "sbc r14", + "sbc r15", + + // 70 - 7f + "merge", + "bic r1", + "bic r2", + "bic r3", + "bic r4", + "bic r5", + "bic r6", + "bic r7", + "bic r8", + "bic r9", + "bic r10", + "bic r11", + "bic r12", + "bic r13", + "bic r14", + "bic r15", + + // 80 - 8f + "umult r0", + "umult r1", + "umult r2", + "umult r3", + "umult r4", + "umult r5", + "umult r6", + "umult r7", + "umult r8", + "umult r9", + "umult r10", + "umult r11", + "umult r12", + "umult r13", + "umult r14", + "umult r15", + + // 90 - 9f + "sbk", + "link #1", + "link #2", + "link #3", + "link #4", + "sex", + "div2", + "ror", + "ljmp (r8)", + "ljmp (r9)", + "ljmp (r10)", + "ljmp (r11)", + "ljmp (r12)", + "ljmp (r13)", + "lob", + "lmult", + + // a0 - af + "lms r0, ($%04x)", + "lms r1, ($%04x)", + "lms r2, ($%04x)", + "lms r3, ($%04x)", + "lms r4, ($%04x)", + "lms r5, ($%04x)", + "lms r6, ($%04x)", + "lms r7, ($%04x)", + "lms r8, ($%04x)", + "lms r9, ($%04x)", + "lms r10, ($%04x)", + "lms r11, ($%04x)", + "lms r12, ($%04x)", + "lms r13, ($%04x)", + "lms r14, ($%04x)", + "lms r15, ($%04x)", + + // b0 - bf + "from r0", + "from r1", + "from r2", + "from r3", + "from r4", + "from r5", + "from r6", + "from r7", + "from r8", + "from r9", + "from r10", + "from r11", + "from r12", + "from r13", + "from r14", + "from r15", + + // c0 - cf + "hib", + "xor r1", + "xor r2", + "xor r3", + "xor r4", + "xor r5", + "xor r6", + "xor r7", + "xor r8", + "xor r9", + "xor r10", + "xor r11", + "xor r12", + "xor r13", + "xor r14", + "xor r15", + + // d0 - df + "inc r0", + "inc r1", + "inc r2", + "inc r3", + "inc r4", + "inc r5", + "inc r6", + "inc r7", + "inc r8", + "inc r9", + "inc r10", + "inc r11", + "inc r12", + "inc r13", + "inc r14", + "getc", + + // e0 - ef + "dec r0", + "dec r1", + "dec r2", + "dec r3", + "dec r4", + "dec r5", + "dec r6", + "dec r7", + "dec r8", + "dec r9", + "dec r10", + "dec r11", + "dec r12", + "dec r13", + "dec r14", + "getbh", + + // f0 - ff + "lm r0, ($%04x)", + "lm r1, ($%04x)", + "lm r2, ($%04x)", + "lm r3, ($%04x)", + "lm r4, ($%04x)", + "lm r5, ($%04x)", + "lm r6, ($%04x)", + "lm r7, ($%04x)", + "lm r8, ($%04x)", + "lm r9, ($%04x)", + "lm r10, ($%04x)", + "lm r11, ($%04x)", + "lm r12, ($%04x)", + "lm r13, ($%04x)", + "lm r14, ($%04x)", + "lm r15, ($%04x)", + + // ALT2 Table + + // 00 - 0f + "stop", + "nop", + "cache", + "lsr", + "rol", + "bra $%04x", + "blt $%04x", + "bge $%04x", + "bne $%04x", + "beq $%04x", + "bpl $%04x", + "bmi $%04x", + "bcc $%04x", + "bcs $%04x", + "bvc $%04x", + "bvs $%04x", + + // 10 - 1f + "to r0", + "to r1", + "to r2", + "to r3", + "to r4", + "to r5", + "to r6", + "to r7", + "to r8", + "to r9", + "to r10", + "to r11", + "to r12", + "to r13", + "to r14", + "to r15", + + // 20 - 2f + "with r0", + "with r1", + "with r2", + "with r3", + "with r4", + "with r5", + "with r6", + "with r7", + "with r8", + "with r9", + "with r10", + "with r11", + "with r12", + "with r13", + "with r14", + "with r15", + + // 30 - 3f + "stw (r0)", + "stw (r1)", + "stw (r2)", + "stw (r3)", + "stw (r4)", + "stw (r5)", + "stw (r6)", + "stw (r7)", + "stw (r8)", + "stw (r9)", + "stw (r10)", + "stw (r11)", + "loop", + "alt1", + "alt2", + "alt3", + + // 40 - 4f + "ldw (r0)", + "ldw (r1)", + "ldw (r2)", + "ldw (r3)", + "ldw (r4)", + "ldw (r5)", + "ldw (r6)", + "ldw (r7)", + "ldw (r8)", + "ldw (r9)", + "ldw (r10)", + "ldw (r11)", + "plot", + "swap", + "color", + "not", + + // 50 - 5f + "add #0", + "add #1", + "add #2", + "add #3", + "add #4", + "add #5", + "add #6", + "add #7", + "add #8", + "add #9", + "add #10", + "add #11", + "add #12", + "add #13", + "add #14", + "add #15", + + // 60 - 6f + "sub #0", + "sub #1", + "sub #2", + "sub #3", + "sub #4", + "sub #5", + "sub #6", + "sub #7", + "sub #8", + "sub #9", + "sub #10", + "sub #11", + "sub #12", + "sub #13", + "sub #14", + "sub #15", + + // 70 - 7f + "merge", + "and #1", + "and #2", + "and #3", + "and #4", + "and #5", + "and #6", + "and #7", + "and #8", + "and #9", + "and #10", + "and #11", + "and #12", + "and #13", + "and #14", + "and #15", + + // 80 - 8f + "mult #0", + "mult #1", + "mult #2", + "mult #3", + "mult #4", + "mult #5", + "mult #6", + "mult #7", + "mult #8", + "mult #9", + "mult #10", + "mult #11", + "mult #12", + "mult #13", + "mult #14", + "mult #15", + + // 90 - 9f + "sbk", + "link #1", + "link #2", + "link #3", + "link #4", + "sex", + "asr", + "ror", + "jmp (r8)", + "jmp (r9)", + "jmp (r10)", + "jmp (r11)", + "jmp (r12)", + "jmp (r13)", + "lob", + "fmult", + + // a0 - af + "sms ($%04x), r0", + "sms ($%04x), r1", + "sms ($%04x), r2", + "sms ($%04x), r3", + "sms ($%04x), r4", + "sms ($%04x), r5", + "sms ($%04x), r6", + "sms ($%04x), r7", + "sms ($%04x), r8", + "sms ($%04x), r9", + "sms ($%04x), r10", + "sms ($%04x), r11", + "sms ($%04x), r12", + "sms ($%04x), r13", + "sms ($%04x), r14", + "sms ($%04x), r15", + + // b0 - bf + "from r0", + "from r1", + "from r2", + "from r3", + "from r4", + "from r5", + "from r6", + "from r7", + "from r8", + "from r9", + "from r10", + "from r11", + "from r12", + "from r13", + "from r14", + "from r15", + + // c0 - cf + "hib", + "or #1", + "or #2", + "or #3", + "or #4", + "or #5", + "or #6", + "or #7", + "or #8", + "or #9", + "or #10", + "or #11", + "or #12", + "or #13", + "or #14", + "or #15", + + // d0 - df + "inc r0", + "inc r1", + "inc r2", + "inc r3", + "inc r4", + "inc r5", + "inc r6", + "inc r7", + "inc r8", + "inc r9", + "inc r10", + "inc r11", + "inc r12", + "inc r13", + "inc r14", + "ramb", + + // e0 - ef + "dec r0", + "dec r1", + "dec r2", + "dec r3", + "dec r4", + "dec r5", + "dec r6", + "dec r7", + "dec r8", + "dec r9", + "dec r10", + "dec r11", + "dec r12", + "dec r13", + "dec r14", + "getbl", + + // f0 - ff + "sm ($%04x), r0", + "sm ($%04x), r1", + "sm ($%04x), r2", + "sm ($%04x), r3", + "sm ($%04x), r4", + "sm ($%04x), r5", + "sm ($%04x), r6", + "sm ($%04x), r7", + "sm ($%04x), r8", + "sm ($%04x), r9", + "sm ($%04x), r10", + "sm ($%04x), r11", + "sm ($%04x), r12", + "sm ($%04x), r13", + "sm ($%04x), r14", + "sm ($%04x), r15", + + // ALT3 Table + + // 00 - 0f + "stop", + "nop", + "cache", + "lsr", + "rol", + "bra $%04x", + "blt $%04x", + "bge $%04x", + "bne $%04x", + "beq $%04x", + "bpl $%04x", + "bmi $%04x", + "bcc $%04x", + "bcs $%04x", + "bvc $%04x", + "bvs $%04x", + + // 10 - 1f + "to r0", + "to r1", + "to r2", + "to r3", + "to r4", + "to r5", + "to r6", + "to r7", + "to r8", + "to r9", + "to r10", + "to r11", + "to r12", + "to r13", + "to r14", + "to r15", + + // 20 - 2f + "with r0", + "with r1", + "with r2", + "with r3", + "with r4", + "with r5", + "with r6", + "with r7", + "with r8", + "with r9", + "with r10", + "with r11", + "with r12", + "with r13", + "with r14", + "with r15", + + // 30 - 3f + "stb (r0)", + "stb (r1)", + "stb (r2)", + "stb (r3)", + "stb (r4)", + "stb (r5)", + "stb (r6)", + "stb (r7)", + "stb (r8)", + "stb (r9)", + "stb (r10)", + "stb (r11)", + "loop", + "alt1", + "alt2", + "alt3", + + // 40 - 4f + "ldb (r0)", + "ldb (r1)", + "ldb (r2)", + "ldb (r3)", + "ldb (r4)", + "ldb (r5)", + "ldb (r6)", + "ldb (r7)", + "ldb (r8)", + "ldb (r9)", + "ldb (r10)", + "ldb (r11)", + "rpix", + "swap", + "cmode", + "not", + + // 50 - 5f + "adc #0", + "adc #1", + "adc #2", + "adc #3", + "adc #4", + "adc #5", + "adc #6", + "adc #7", + "adc #8", + "adc #9", + "adc #10", + "adc #11", + "adc #12", + "adc #13", + "adc #14", + "adc #15", + + // 60 - 6f + "cmp r0", + "cmp r1", + "cmp r2", + "cmp r3", + "cmp r4", + "cmp r5", + "cmp r6", + "cmp r7", + "cmp r8", + "cmp r9", + "cmp r10", + "cmp r11", + "cmp r12", + "cmp r13", + "cmp r14", + "cmp r15", + + // 70 - 7f + "merge", + "bic #1", + "bic #2", + "bic #3", + "bic #4", + "bic #5", + "bic #6", + "bic #7", + "bic #8", + "bic #9", + "bic #10", + "bic #11", + "bic #12", + "bic #13", + "bic #14", + "bic #15", + + // 80 - 8f + "umult #0", + "umult #1", + "umult #2", + "umult #3", + "umult #4", + "umult #5", + "umult #6", + "umult #7", + "umult #8", + "umult #9", + "umult #10", + "umult #11", + "umult #12", + "umult #13", + "umult #14", + "umult #15", + + // 90 - 9f + "sbk", + "link #1", + "link #2", + "link #3", + "link #4", + "sex", + "div2", + "ror", + "ljmp (r8)", + "ljmp (r9)", + "ljmp (r10)", + "ljmp (r11)", + "ljmp (r12)", + "ljmp (r13)", + "lob", + "lmult", + + // a0 - af + "lms r0, ($%04x)", + "lms r1, ($%04x)", + "lms r2, ($%04x)", + "lms r3, ($%04x)", + "lms r4, ($%04x)", + "lms r5, ($%04x)", + "lms r6, ($%04x)", + "lms r7, ($%04x)", + "lms r8, ($%04x)", + "lms r9, ($%04x)", + "lms r10, ($%04x)", + "lms r11, ($%04x)", + "lms r12, ($%04x)", + "lms r13, ($%04x)", + "lms r14, ($%04x)", + "lms r15, ($%04x)", + + // b0 - bf + "from r0", + "from r1", + "from r2", + "from r3", + "from r4", + "from r5", + "from r6", + "from r7", + "from r8", + "from r9", + "from r10", + "from r11", + "from r12", + "from r13", + "from r14", + "from r15", + + // c0 - cf + "hib", + "xor #1", + "xor #2", + "xor #3", + "xor #4", + "xor #5", + "xor #6", + "xor #7", + "xor #8", + "xor #9", + "xor #10", + "xor #11", + "xor #12", + "xor #13", + "xor #14", + "xor #15", + + // d0 - df + "inc r0", + "inc r1", + "inc r2", + "inc r3", + "inc r4", + "inc r5", + "inc r6", + "inc r7", + "inc r8", + "inc r9", + "inc r10", + "inc r11", + "inc r12", + "inc r13", + "inc r14", + "romb", + + // e0 - ef + "dec r0", + "dec r1", + "dec r2", + "dec r3", + "dec r4", + "dec r5", + "dec r6", + "dec r7", + "dec r8", + "dec r9", + "dec r10", + "dec r11", + "dec r12", + "dec r13", + "dec r14", + "getbs", + + // f0 - ff + "lm r0, ($%04x)", + "lm r1, ($%04x)", + "lm r2, ($%04x)", + "lm r3, ($%04x)", + "lm r4, ($%04x)", + "lm r5, ($%04x)", + "lm r6, ($%04x)", + "lm r7, ($%04x)", + "lm r8, ($%04x)", + "lm r9, ($%04x)", + "lm r10, ($%04x)", + "lm r11, ($%04x)", + "lm r12, ($%04x)", + "lm r13, ($%04x)", + "lm r14, ($%04x)", + "lm r15, ($%04x)" +}; +*/ + +/* +static void FxPipeString (char *pvString) +{ + uint32 vOpcode = (GSU.vStatusReg & 0x300) | ((uint32) PIPE); + const char *m = fx_apvMnemonicTable[vOpcode]; + uint8 vPipe1, vPipe2, vByte1, vByte2; + uint8 vPipeBank = GSU.vPipeAdr >> 16; + char *p; + + // The next two bytes after the pipe's address + vPipe1 = GSU.apvRomBank[vPipeBank][USEX16(GSU.vPipeAdr + 1)]; + vPipe2 = GSU.apvRomBank[vPipeBank][USEX16(GSU.vPipeAdr + 2)]; + + // The actual next two bytes to be read + vByte1 = PRGBANK(USEX16(R15)); + vByte2 = PRGBANK(USEX16(R15 + 1)); + + // Print ROM address of the pipe + sprintf(pvString, "%02x:%04x %02x ", USEX8(vPipeBank), USEX16(GSU.vPipeAdr), USEX8(PIPE)); + p = &pvString[strlen(pvString)]; + + if (PIPE >= 0x05 && PIPE <= 0x0f) // Check if it's a branch instruction + { + sprintf(&pvString[11], "%02x ", USEX8(vPipe1)); + #ifdef BRANCH_DELAY_RELATIVE + sprintf(p, m, USEX16(R15 + SEX8(vByte1) + 1)); + #else + sprintf(p, m, USEX16(R15 + SEX8(vByte1) - 1)); + #endif + } + else + if (PIPE >= 0x10 && PIPE <= 0x1f && TF(B)) // Check for 'move' instruction + sprintf(p, "move r%d, r%d", USEX8(PIPE & 0x0f), (uint32) (GSU.pvSreg - GSU.avReg)); + else + if (PIPE >= 0xa0 && PIPE <= 0xaf) // Check for 'ibt', 'lms' or 'sms' + { + sprintf(&pvString[11], "%02x ", USEX8(vPipe1)); + if ((GSU.vStatusReg & 0x300) == 0x100 || (GSU.vStatusReg & 0x300) == 0x200) + sprintf(p, m, USEX16(vByte1) << 1); + else + sprintf(p, m, USEX16(vByte1)); + } + else + if (PIPE >= 0xb0 && PIPE <= 0xbf && TF(B)) // Check for 'moves' + sprintf(p, "moves r%d, r%d", (uint32) (GSU.pvDreg - GSU.avReg), USEX8(PIPE & 0x0f)); + else + if (PIPE >= 0xf0) // Check for 'iwt', 'lm' or 'sm' + { + sprintf(&pvString[11], "%02x %02x ", USEX8(vPipe1), USEX8(vPipe2)); + sprintf(p, m, USEX8(vByte1) | (USEX16(vByte2) << 8)); + } + else // Normal instruction + strcpy(p, m); +} +*/ + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/fxemu.cpp b/plugins/snes9x_gx/source/snes9x/fxemu.cpp new file mode 100644 index 00000000..b3237ae6 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/fxemu.cpp @@ -0,0 +1,987 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "fxinst.h" +#include "fxemu.h" + +static void FxReset (struct FxInfo_s *); +static void fx_readRegisterSpace (void); +static void fx_writeRegisterSpace (void); +static void fx_updateRamBank (uint8); +static void fx_dirtySCBR (void); +static bool8 fx_checkStartAddress (void); +static uint32 FxEmulate (uint32); +static void FxCacheWriteAccess (uint16); +static void FxFlushCache (void); + + +void S9xInitSuperFX (void) +{ + memset((uint8 *) &GSU, 0, sizeof(struct FxRegs_s)); +} + +void S9xResetSuperFX (void) +{ + // FIXME: Snes9x can't execute CPU and SuperFX at a time. Don't ask me what is 0.417 :P + SuperFX.speedPerLine = (uint32) (0.417 * 10.5e6 * ((1.0 / (float) Memory.ROMFramesPerSecond) / ((float) (Timings.V_Max)))); + SuperFX.oneLineDone = FALSE; + SuperFX.vFlags = 0; + FxReset(&SuperFX); +} + +void S9xSetSuperFX (uint8 byte, uint16 address) +{ + switch (address) + { + case 0x3030: + if ((Memory.FillRAM[0x3030] ^ byte) & FLG_G) + { + Memory.FillRAM[0x3030] = byte; + if (byte & FLG_G) + { + if (!SuperFX.oneLineDone) + { + S9xSuperFXExec(); + SuperFX.oneLineDone = TRUE; + } + } + else + FxFlushCache(); + } + else + Memory.FillRAM[0x3030] = byte; + + break; + + case 0x3031: + Memory.FillRAM[0x3031] = byte; + break; + + case 0x3033: + Memory.FillRAM[0x3033] = byte; + break; + + case 0x3034: + Memory.FillRAM[0x3034] = byte & 0x7f; + break; + + case 0x3036: + Memory.FillRAM[0x3036] = byte & 0x7f; + break; + + case 0x3037: + Memory.FillRAM[0x3037] = byte; + break; + + case 0x3038: + Memory.FillRAM[0x3038] = byte; + fx_dirtySCBR(); + break; + + case 0x3039: + Memory.FillRAM[0x3039] = byte; + break; + + case 0x303a: + Memory.FillRAM[0x303a] = byte; + break; + + case 0x303b: + break; + + case 0x303c: + Memory.FillRAM[0x303c] = byte; + fx_updateRamBank(byte); + break; + + case 0x303f: + Memory.FillRAM[0x303f] = byte; + break; + + case 0x301f: + Memory.FillRAM[0x301f] = byte; + Memory.FillRAM[0x3000 + GSU_SFR] |= FLG_G; + if (!SuperFX.oneLineDone) + { + S9xSuperFXExec(); + SuperFX.oneLineDone = TRUE; + } + + break; + + default: + Memory.FillRAM[address] = byte; + if (address >= 0x3100) + FxCacheWriteAccess(address); + + break; + } +} + +uint8 S9xGetSuperFX (uint16 address) +{ + uint8 byte; + + byte = Memory.FillRAM[address]; +#ifdef CPU_SHUTDOWN + if (address == 0x3030) + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; +#endif + if (address == 0x3031) + { + S9xClearIRQ(GSU_IRQ_SOURCE); + Memory.FillRAM[0x3031] = byte & 0x7f; + } + + return (byte); +} + +void S9xSuperFXExec (void) +{ + if ((Memory.FillRAM[0x3000 + GSU_SFR] & FLG_G) && (Memory.FillRAM[0x3000 + GSU_SCMR] & 0x18) == 0x18) + { + FxEmulate((Memory.FillRAM[0x3000 + GSU_CLSR] & 1) ? SuperFX.speedPerLine * 2 : SuperFX.speedPerLine); + + uint16 GSUStatus = Memory.FillRAM[0x3000 + GSU_SFR] | (Memory.FillRAM[0x3000 + GSU_SFR + 1] << 8); + if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ) + S9xSetIRQ(GSU_IRQ_SOURCE); + } +} + +static void FxReset (struct FxInfo_s *psFxInfo) +{ + // Clear all internal variables + memset((uint8 *) &GSU, 0, sizeof(struct FxRegs_s)); + + // Set default registers + GSU.pvSreg = GSU.pvDreg = &R0; + + // Set RAM and ROM pointers + GSU.pvRegisters = psFxInfo->pvRegisters; + GSU.nRamBanks = psFxInfo->nRamBanks; + GSU.pvRam = psFxInfo->pvRam; + GSU.nRomBanks = psFxInfo->nRomBanks; + GSU.pvRom = psFxInfo->pvRom; + GSU.vPrevScreenHeight = ~0; + GSU.vPrevMode = ~0; + + // The GSU can't access more than 2mb (16mbits) + if (GSU.nRomBanks > 0x20) + GSU.nRomBanks = 0x20; + + // Clear FxChip register space + memset(GSU.pvRegisters, 0, 0x300); + + // Set FxChip version Number + GSU.pvRegisters[0x3b] = 0; + + // Make ROM bank table + for (int i = 0; i < 256; i++) + { + uint32 b = i & 0x7f; + + if (b >= 0x40) + { + if (GSU.nRomBanks > 1) + b %= GSU.nRomBanks; + else + b &= 1; + + GSU.apvRomBank[i] = &GSU.pvRom[b << 16]; + } + else + { + b %= GSU.nRomBanks * 2; + GSU.apvRomBank[i] = &GSU.pvRom[(b << 16) + 0x200000]; + } + } + + // Make RAM bank table + for (int i = 0; i < 4; i++) + { + GSU.apvRamBank[i] = &GSU.pvRam[(i % GSU.nRamBanks) << 16]; + GSU.apvRomBank[0x70 + i] = GSU.apvRamBank[i]; + } + + // Start with a nop in the pipe + GSU.vPipe = 0x01; + + // Set pointer to GSU cache + GSU.pvCache = &GSU.pvRegisters[0x100]; + + fx_readRegisterSpace(); +} + +static void fx_readRegisterSpace (void) +{ + static uint32 avHeight[] = { 128, 160, 192, 256 }; + static uint32 avMult[] = { 16, 32, 32, 64 }; + + uint8 *p; + int n; + + GSU.vErrorCode = 0; + + // Update R0-R15 + p = GSU.pvRegisters; + for (int i = 0; i < 16; i++) + { + GSU.avReg[i] = *p++; + GSU.avReg[i] += ((uint32) (*p++)) << 8; + } + + // Update other registers + p = GSU.pvRegisters; + GSU.vStatusReg = (uint32) p[GSU_SFR]; + GSU.vStatusReg |= ((uint32) p[GSU_SFR + 1]) << 8; + GSU.vPrgBankReg = (uint32) p[GSU_PBR]; + GSU.vRomBankReg = (uint32) p[GSU_ROMBR]; + GSU.vRamBankReg = ((uint32) p[GSU_RAMBR]) & (FX_RAM_BANKS - 1); + GSU.vCacheBaseReg = (uint32) p[GSU_CBR]; + GSU.vCacheBaseReg |= ((uint32) p[GSU_CBR + 1]) << 8; + + // Update status register variables + GSU.vZero = !(GSU.vStatusReg & FLG_Z); + GSU.vSign = (GSU.vStatusReg & FLG_S) << 12; + GSU.vOverflow = (GSU.vStatusReg & FLG_OV) << 16; + GSU.vCarry = (GSU.vStatusReg & FLG_CY) >> 2; + + // Set bank pointers + GSU.pvRamBank = GSU.apvRamBank[GSU.vRamBankReg & 0x3]; + GSU.pvRomBank = GSU.apvRomBank[GSU.vRomBankReg]; + GSU.pvPrgBank = GSU.apvRomBank[GSU.vPrgBankReg]; + + // Set screen pointers + GSU.pvScreenBase = &GSU.pvRam[USEX8(p[GSU_SCBR]) << 10]; + n = (int) (!!(p[GSU_SCMR] & 0x04)); + n |= ((int) (!!(p[GSU_SCMR] & 0x20))) << 1; + GSU.vScreenHeight = GSU.vScreenRealHeight = avHeight[n]; + GSU.vMode = p[GSU_SCMR] & 0x03; + + if (n == 3) + GSU.vScreenSize = (256 / 8) * (256 / 8) * 32; + else + GSU.vScreenSize = (GSU.vScreenHeight / 8) * (256 / 8) * avMult[GSU.vMode]; + + if (GSU.vPlotOptionReg & 0x10) // OBJ Mode (for drawing into sprites) + GSU.vScreenHeight = 256; + + if (GSU.pvScreenBase + GSU.vScreenSize > GSU.pvRam + (GSU.nRamBanks * 65536)) + GSU.pvScreenBase = GSU.pvRam + (GSU.nRamBanks * 65536) - GSU.vScreenSize; + + GSU.pfPlot = fx_PlotTable[GSU.vMode]; + GSU.pfRpix = fx_PlotTable[GSU.vMode + 5]; + + fx_OpcodeTable[0x04c] = GSU.pfPlot; + fx_OpcodeTable[0x14c] = GSU.pfRpix; + fx_OpcodeTable[0x24c] = GSU.pfPlot; + fx_OpcodeTable[0x34c] = GSU.pfRpix; + + fx_computeScreenPointers(); + + //fx_backupCache(); +} + +static void fx_writeRegisterSpace (void) +{ + uint8 *p; + + p = GSU.pvRegisters; + for (int i = 0; i < 16; i++) + { + *p++ = (uint8) GSU.avReg[i]; + *p++ = (uint8) (GSU.avReg[i] >> 8); + } + + // Update status register + if (USEX16(GSU.vZero) == 0) + SF(Z); + else + CF(Z); + + if (GSU.vSign & 0x8000) + SF(S); + else + CF(S); + + if (GSU.vOverflow >= 0x8000 || GSU.vOverflow < -0x8000) + SF(OV); + else + CF(OV); + + if (GSU.vCarry) + SF(CY); + else + CF(CY); + + p = GSU.pvRegisters; + p[GSU_SFR] = (uint8) GSU.vStatusReg; + p[GSU_SFR + 1] = (uint8) (GSU.vStatusReg >> 8); + p[GSU_PBR] = (uint8) GSU.vPrgBankReg; + p[GSU_ROMBR] = (uint8) GSU.vRomBankReg; + p[GSU_RAMBR] = (uint8) GSU.vRamBankReg; + p[GSU_CBR] = (uint8) GSU.vCacheBaseReg; + p[GSU_CBR + 1] = (uint8) (GSU.vCacheBaseReg >> 8); + + //fx_restoreCache(); +} + +// Update RamBankReg and RAM Bank pointer +static void fx_updateRamBank (uint8 byte) +{ + // Update BankReg and Bank pointer + GSU.vRamBankReg = (uint32) byte & (FX_RAM_BANKS - 1); + GSU.pvRamBank = GSU.apvRamBank[byte & 0x3]; +} + +// SCBR write seen. We need to update our cached screen pointers +static void fx_dirtySCBR (void) +{ + GSU.vSCBRDirty = TRUE; +} + +static bool8 fx_checkStartAddress (void) +{ + // Check if we start inside the cache + if (GSU.bCacheActive && R15 >= GSU.vCacheBaseReg && R15 < (GSU.vCacheBaseReg + 512)) + return (TRUE); + + /* + // Check if we're in an unused area + if (GSU.vPrgBankReg < 0x40 && R15 < 0x8000) + return (FALSE); + */ + + if (GSU.vPrgBankReg >= 0x60 && GSU.vPrgBankReg <= 0x6f) + return (FALSE); + + if (GSU.vPrgBankReg >= 0x74) + return (FALSE); + + // Check if we're in RAM and the RAN flag is not set + if (GSU.vPrgBankReg >= 0x70 && GSU.vPrgBankReg <= 0x73 && !(SCMR & (1 << 3))) + return (FALSE); + + // If not, we're in ROM, so check if the RON flag is set + if (!(SCMR & (1 << 4))) + return (FALSE); + + return (TRUE); +} + +// Execute until the next stop instruction +static uint32 FxEmulate (uint32 nInstructions) +{ + uint32 vCount; + + // Read registers and initialize GSU session + fx_readRegisterSpace(); + + // Check if the start address is valid + if (!fx_checkStartAddress()) + { + CF(G); + fx_writeRegisterSpace(); + /* + GSU.vIllegalAddress = (GSU.vPrgBankReg << 24) | R15; + return (FX_ERROR_ILLEGAL_ADDRESS); + */ + + return (0); + } + + // Execute GSU session + CF(IRQ); + + /* + if (GSU.bBreakPoint) + vCount = fx_run_to_breakpoint(nInstructions); + else + */ + vCount = fx_run(nInstructions); + + // Store GSU registers + fx_writeRegisterSpace(); + + // Check for error code + if (GSU.vErrorCode) + return (GSU.vErrorCode); + else + return (vCount); +} + +void fx_computeScreenPointers (void) +{ + if (GSU.vMode != GSU.vPrevMode || GSU.vPrevScreenHeight != GSU.vScreenHeight || GSU.vSCBRDirty) + { + GSU.vSCBRDirty = FALSE; + + // Make a list of pointers to the start of each screen column + switch (GSU.vScreenHeight) + { + case 128: + switch (GSU.vMode) + { + case 0: + for (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); + GSU.x[i] = i << 8; + } + + break; + + case 1: + for (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); + GSU.x[i] = i << 9; + } + + break; + + case 2: + case 3: + for (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); + GSU.x[i] = i << 10; + } + + break; + } + + break; + + case 160: + switch (GSU.vMode) + { + case 0: + for (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); + GSU.x[i] = (i << 8) + (i << 6); + } + + break; + + case 1: + for (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); + GSU.x[i] = (i << 9) + (i << 7); + } + + break; + + case 2: + case 3: + for (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); + GSU.x[i] = (i << 10) + (i << 8); + } + + break; + } + + break; + + case 192: + switch (GSU.vMode) + { + case 0: + for (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); + GSU.x[i] = (i << 8) + (i << 7); + } + + break; + + case 1: + for (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); + GSU.x[i] = (i << 9) + (i << 8); + } + + break; + + case 2: + case 3: + for (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); + GSU.x[i] = (i << 10) + (i << 9); + } + + break; + } + + break; + + case 256: + switch (GSU.vMode) + { + case 0: + for (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + ((i & 0x10) << 9) + ((i & 0xf) << 8); + GSU.x[i] = ((i & 0x10) << 8) + ((i & 0xf) << 4); + } + + break; + + case 1: + for (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + ((i & 0x10) << 10) + ((i & 0xf) << 9); + GSU.x[i] = ((i & 0x10) << 9) + ((i & 0xf) << 5); + } + + break; + + case 2: + case 3: + for (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + ((i & 0x10) << 11) + ((i & 0xf) << 10); + GSU.x[i] = ((i & 0x10) << 10) + ((i & 0xf) << 6); + } + + break; + } + + break; + } + + GSU.vPrevMode = GSU.vMode; + GSU.vPrevScreenHeight = GSU.vScreenHeight; + } +} + +// Write access to the cache +static void FxCacheWriteAccess (uint16 vAddress) +{ + /* + if (!GSU.bCacheActive) + { + uint8 v = GSU.pvCache[GSU.pvCache[vAddress & 0x1ff]; + fx_setCache(); + GSU.pvCache[GSU.pvCache[vAddress & 0x1ff] = v; + } + */ + + if ((vAddress & 0x00f) == 0x00f) + GSU.vCacheFlags |= 1 << ((vAddress & 0x1f0) >> 4); +} + +static void FxFlushCache (void) +{ + GSU.vCacheFlags = 0; + GSU.vCacheBaseReg = 0; + GSU.bCacheActive = FALSE; + //GSU.vPipe = 0x1; +} + +void fx_flushCache (void) +{ + //fx_restoreCache(); + GSU.vCacheFlags = 0; + GSU.bCacheActive = FALSE; +} + +/* +static void fx_setCache (void) +{ + uint32 c; + + GSU.bCacheActive = TRUE; + GSU.pvRegisters[0x3e] &= 0xf0; + + c = (uint32) GSU.pvRegisters[0x3e]; + c |= ((uint32) GSU.pvRegisters[0x3f]) << 8; + if (c == GSU.vCacheBaseReg) + return; + + GSU.vCacheBaseReg = c; + GSU.vCacheFlags = 0; + + if (c < (0x10000 - 512)) + { + const uint8 *t = &ROM(c); + memcpy(GSU.pvCache, t, 512); + } + else + { + const uint8 *t1, *t2; + uint32 i = 0x10000 - c; + + t1 = &ROM(c); + t2 = &ROM(0); + memcpy(GSU.pvCache, t1, i); + memcpy(&GSU.pvCache[i], t2, 512 - i); + } +} +*/ + +/* +static void fx_backupCache (void) +{ + uint32 v = GSU.vCacheFlags; + uint32 c = USEX16(GSU.vCacheBaseReg); + + if (v) + { + for (int i = 0; i < 32; i++) + { + if (v & 1) + { + if (c < (0x10000 - 16)) + { + uint8 *t = &GSU.pvPrgBank[c]; + memcpy(&GSU.avCacheBackup[i << 4], t, 16); + memcpy(t, &GSU.pvCache[i << 4], 16); + } + else + { + uint8 *t1, *t2; + uint32 a = 0x10000 - c; + + t1 = &GSU.pvPrgBank[c]; + t2 = &GSU.pvPrgBank[0]; + memcpy(&GSU.avCacheBackup[i << 4], t1, a); + memcpy(t1, &GSU.pvCache[i << 4], a); + memcpy(&GSU.avCacheBackup[(i << 4) + a], t2, 16 - a); + memcpy(t2, &GSU.pvCache[(i << 4) + a], 16 - a); + } + } + + c = USEX16(c + 16); + v >>= 1; + } + } +} +*/ + +/* +static void fx_restoreCache() +{ + uint32 v = GSU.vCacheFlags; + uint32 c = USEX16(GSU.vCacheBaseReg); + + if (v) + { + for (int i = 0; i < 32; i++) + { + if (v & 1) + { + if (c < (0x10000 - 16)) + { + uint8 *t = &GSU.pvPrgBank[c]; + memcpy(t, &GSU.avCacheBackup[i << 4], 16); + memcpy(&GSU.pvCache[i << 4], t, 16); + } + else + { + uint8 *t1, *t2; + uint32 a = 0x10000 - c; + + t1 = &GSU.pvPrgBank[c]; + t2 = &GSU.pvPrgBank[0]; + memcpy(t1, &GSU.avCacheBackup[i << 4], a); + memcpy(&GSU.pvCache[i << 4], t1, a); + memcpy(t2, &GSU.avCacheBackup[(i << 4) + a], 16 - a); + memcpy(&GSU.pvCache[(i << 4) + a], t2, 16 - a); + } + } + + c = USEX16(c + 16); + v >>= 1; + } + } +} +*/ + +// Breakpoints +/* +static void FxBreakPointSet (uint32 vAddress) +{ + GSU.bBreakPoint = TRUE; + GSU.vBreakPoint = USEX16(vAddress); +} +*/ + +/* +static void FxBreakPointClear (void) +{ + GSU.bBreakPoint = FALSE; +} +*/ + +// Step by step execution +/* +static uint32 FxStepOver (uint32 nInstructions) +{ + uint32 vCount; + + fx_readRegisterSpace(); + + if (!fx_checkStartAddress()) + { + CF(G); + #if 0 + GSU.vIllegalAddress = (GSU.vPrgBankReg << 24) | R15; + return (FX_ERROR_ILLEGAL_ADDRESS); + #else + return (0); + #endif + } + + if (PIPE >= 0xf0) + GSU.vStepPoint = USEX16(R15 + 3); + else + if ((PIPE >= 0x05 && PIPE <= 0x0f) || (PIPE >= 0xa0 && PIPE <= 0xaf)) + GSU.vStepPoint = USEX16(R15 + 2); + else + GSU.vStepPoint = USEX16(R15 + 1); + + vCount = fx_step_over(nInstructions); + + fx_writeRegisterSpace(); + + if (GSU.vErrorCode) + return (GSU.vErrorCode); + else + return (vCount); +} +*/ + +// Errors +/* +static int FxGetErrorCode (void) +{ + return (GSU.vErrorCode); +} +*/ + +/* +static int FxGetIllegalAddress (void) +{ + return (GSU.vIllegalAddress); +} +*/ + +// Access to internal registers +/* +static uint32 FxGetColorRegister (void) +{ + return (GSU.vColorReg & 0xff); +} +*/ + +/* +static uint32 FxGetPlotOptionRegister (void) +{ + return (GSU.vPlotOptionReg & 0x1f); +} +*/ + +/* +static uint32 FxGetSourceRegisterIndex (void) +{ + return (GSU.pvSreg - GSU.avReg); +} +*/ + +/* +static uint32 FxGetDestinationRegisterIndex (void) +{ + return (GSU.pvDreg - GSU.avReg); +} +*/ + +// Get the byte currently in the pipe +/* +static uint8 FxPipe (void) +{ + return (GSU.vPipe); +} +*/ diff --git a/plugins/snes9x_gx/source/snes9x/fxemu.h b/plugins/snes9x_gx/source/snes9x/fxemu.h new file mode 100644 index 00000000..b2ce64e7 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/fxemu.h @@ -0,0 +1,208 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _FXEMU_H_ +#define _FXEMU_H_ + +#define FX_BREAKPOINT (-1) +#define FX_ERROR_ILLEGAL_ADDRESS (-2) + +// The FxInfo_s structure, the link between the FxEmulator and the Snes Emulator +struct FxInfo_s +{ + uint32 vFlags; + uint8 *pvRegisters; // 768 bytes located in the memory at address 0x3000 + uint32 nRamBanks; // Number of 64kb-banks in GSU-RAM/BackupRAM (banks 0x70-0x73) + uint8 *pvRam; // Pointer to GSU-RAM + uint32 nRomBanks; // Number of 32kb-banks in Cart-ROM + uint8 *pvRom; // Pointer to Cart-ROM + uint32 speedPerLine; + bool8 oneLineDone; +}; + +extern struct FxInfo_s SuperFX; + +void S9xInitSuperFX (void); +void S9xResetSuperFX (void); +void S9xSuperFXExec (void); +void S9xSetSuperFX (uint8, uint16); +uint8 S9xGetSuperFX (uint16); +void fx_flushCache (void); +void fx_computeScreenPointers (void); +uint32 fx_run (uint32); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/fxinst.cpp b/plugins/snes9x_gx/source/snes9x/fxinst.cpp new file mode 100644 index 00000000..5f7df2bf --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/fxinst.cpp @@ -0,0 +1,4424 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "fxinst.h" +#include "fxemu.h" + +// Set this define if you wish the plot instruction to check for y-pos limits (I don't think it's nessecary) +#define CHECK_LIMITS + + +/* + Codes used: + rn = a GSU register (r0 - r15) + #n = 4 bit immediate value + #pp = 8 bit immediate value + (yy) = 8 bit word address (0x0000 - 0x01fe) + #xx = 16 bit immediate value + (xx) = 16 bit address (0x0000 - 0xffff) +*/ + +// 00 - stop - stop GSU execution (and maybe generate an IRQ) +static void fx_stop (void) +{ + CF(G); + GSU.vCounter = 0; + GSU.vInstCount = GSU.vCounter; + + // Check if we need to generate an IRQ + if (!(GSU.pvRegisters[GSU_CFGR] & 0x80)) + SF(IRQ); + + GSU.vPlotOptionReg = 0; + GSU.vPipe = 1; + CLRFLAGS; + R15++; +} + +// 01 - nop - no operation +static void fx_nop (void) +{ + CLRFLAGS; + R15++; +} + +// 02 - cache - reintialize GSU cache +static void fx_cache (void) +{ + uint32 c = R15 & 0xfff0; + + if (GSU.vCacheBaseReg != c || !GSU.bCacheActive) + { + fx_flushCache(); + GSU.vCacheBaseReg = c; + GSU.bCacheActive = TRUE; + + #if 0 + if (c < (0x10000 - 512)) + { + const uint8 *t = &ROM(c); + memcpy(GSU.pvCache, t, 512); + } + else + { + const uint8 *t1, t2; + uint32 i = 0x10000 - c; + t1 = &ROM(c); + t2 = &ROM(0); + memcpy(GSU.pvCache, t1, i); + memcpy(&GSU.pvCache[i], t2, 512 - i); + } + #endif + } + + CLRFLAGS; + R15++; +} + +// 03 - lsr - logic shift right +static void fx_lsr (void) +{ + uint32 v; + GSU.vCarry = SREG & 1; + v = USEX16(SREG) >> 1; + R15++; + DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +// 04 - rol - rotate left +static void fx_rol (void) +{ + uint32 v = USEX16((SREG << 1) + GSU.vCarry); + GSU.vCarry = (SREG >> 15) & 1; + R15++; + DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +// 05 - bra - branch always +static void fx_bra (void) +{ + uint8 v = PIPE; + R15++; + FETCHPIPE; + R15 += SEX8(v); +} + +// Branch on condition +#define BRA_COND(cond) \ + uint8 v = PIPE; \ + R15++; \ + FETCHPIPE; \ + if (cond) \ + R15 += SEX8(v); \ + else \ + R15++ + +#define TEST_S (GSU.vSign & 0x8000) +#define TEST_Z (USEX16(GSU.vZero) == 0) +#define TEST_OV (GSU.vOverflow >= 0x8000 || GSU.vOverflow < -0x8000) +#define TEST_CY (GSU.vCarry & 1) + +// 06 - blt - branch on less than +static void fx_blt (void) +{ + BRA_COND((TEST_S != 0) != (TEST_OV != 0)); +} + +// 07 - bge - branch on greater or equals +static void fx_bge (void) +{ + BRA_COND((TEST_S != 0) == (TEST_OV != 0)); +} + +// 08 - bne - branch on not equal +static void fx_bne (void) +{ + BRA_COND(!TEST_Z); +} + +// 09 - beq - branch on equal +static void fx_beq (void) +{ + BRA_COND(TEST_Z); +} + +// 0a - bpl - branch on plus +static void fx_bpl (void) +{ + BRA_COND(!TEST_S); +} + +// 0b - bmi - branch on minus +static void fx_bmi (void) +{ + BRA_COND(TEST_S); +} + +// 0c - bcc - branch on carry clear +static void fx_bcc (void) +{ + BRA_COND(!TEST_CY); +} + +// 0d - bcs - branch on carry set +static void fx_bcs (void) +{ + BRA_COND(TEST_CY); +} + +// 0e - bvc - branch on overflow clear +static void fx_bvc (void) +{ + BRA_COND(!TEST_OV); +} + +// 0f - bvs - branch on overflow set +static void fx_bvs (void) +{ + BRA_COND(TEST_OV); +} + +// 10-1f - to rn - set register n as destination register +// 10-1f (B) - move rn - move one register to another (if B flag is set) +#define FX_TO(reg) \ + if (TF(B)) \ + { \ + GSU.avReg[(reg)] = SREG; \ + CLRFLAGS; \ + } \ + else \ + GSU.pvDreg = &GSU.avReg[reg]; \ + R15++ + +#define FX_TO_R14(reg) \ + if (TF(B)) \ + { \ + GSU.avReg[(reg)] = SREG; \ + CLRFLAGS; \ + READR14; \ + } \ + else \ + GSU.pvDreg = &GSU.avReg[reg]; \ + R15++ + +#define FX_TO_R15(reg) \ + if (TF(B)) \ + { \ + GSU.avReg[(reg)] = SREG; \ + CLRFLAGS; \ + } \ + else \ + { \ + GSU.pvDreg = &GSU.avReg[reg]; \ + R15++; \ + } + +static void fx_to_r0 (void) +{ + FX_TO(0); +} + +static void fx_to_r1 (void) +{ + FX_TO(1); +} + +static void fx_to_r2 (void) +{ + FX_TO(2); +} + +static void fx_to_r3 (void) +{ + FX_TO(3); +} + +static void fx_to_r4 (void) +{ + FX_TO(4); +} + +static void fx_to_r5 (void) +{ + FX_TO(5); +} + +static void fx_to_r6 (void) +{ + FX_TO(6); +} + +static void fx_to_r7 (void) +{ + FX_TO(7); +} + +static void fx_to_r8 (void) +{ + FX_TO(8); +} + +static void fx_to_r9 (void) +{ + FX_TO(9); +} + +static void fx_to_r10 (void) +{ + FX_TO(10); +} + +static void fx_to_r11 (void) +{ + FX_TO(11); +} + +static void fx_to_r12 (void) +{ + FX_TO(12); +} + +static void fx_to_r13 (void) +{ + FX_TO(13); +} + +static void fx_to_r14 (void) +{ + FX_TO_R14(14); +} + +static void fx_to_r15 (void) +{ + FX_TO_R15(15); +} + +// 20-2f - to rn - set register n as source and destination register +#define FX_WITH(reg) \ + SF(B); \ + GSU.pvSreg = GSU.pvDreg = &GSU.avReg[reg]; \ + R15++ + +static void fx_with_r0 (void) +{ + FX_WITH(0); +} + +static void fx_with_r1 (void) +{ + FX_WITH(1); +} + +static void fx_with_r2 (void) +{ + FX_WITH(2); +} + +static void fx_with_r3 (void) +{ + FX_WITH(3); +} + +static void fx_with_r4 (void) +{ + FX_WITH(4); +} + +static void fx_with_r5 (void) +{ + FX_WITH(5); +} + +static void fx_with_r6 (void) +{ + FX_WITH(6); +} + +static void fx_with_r7 (void) +{ + FX_WITH(7); +} + +static void fx_with_r8 (void) +{ + FX_WITH(8); +} + +static void fx_with_r9 (void) +{ + FX_WITH(9); +} + +static void fx_with_r10 (void) +{ + FX_WITH(10); +} + +static void fx_with_r11 (void) +{ + FX_WITH(11); +} + +static void fx_with_r12 (void) +{ + FX_WITH(12); +} + +static void fx_with_r13 (void) +{ + FX_WITH(13); +} + +static void fx_with_r14 (void) +{ + FX_WITH(14); +} + +static void fx_with_r15 (void) +{ + FX_WITH(15); +} + +// 30-3b - stw (rn) - store word +#define FX_STW(reg) \ + GSU.vLastRamAdr = GSU.avReg[reg]; \ + RAM(GSU.avReg[reg]) = (uint8) SREG; \ + RAM(GSU.avReg[reg] ^ 1) = (uint8) (SREG >> 8); \ + CLRFLAGS; \ + R15++ + +static void fx_stw_r0 (void) +{ + FX_STW(0); +} + +static void fx_stw_r1 (void) +{ + FX_STW(1); +} + +static void fx_stw_r2 (void) +{ + FX_STW(2); +} + +static void fx_stw_r3 (void) +{ + FX_STW(3); +} + +static void fx_stw_r4 (void) +{ + FX_STW(4); +} + +static void fx_stw_r5 (void) +{ + FX_STW(5); +} + +static void fx_stw_r6 (void) +{ + FX_STW(6); +} + +static void fx_stw_r7 (void) +{ + FX_STW(7); +} + +static void fx_stw_r8 (void) +{ + FX_STW(8); +} + +static void fx_stw_r9 (void) +{ + FX_STW(9); +} + +static void fx_stw_r10 (void) +{ + FX_STW(10); +} + +static void fx_stw_r11 (void) +{ + FX_STW(11); +} + +// 30-3b (ALT1) - stb (rn) - store byte +#define FX_STB(reg) \ + GSU.vLastRamAdr = GSU.avReg[reg]; \ + RAM(GSU.avReg[reg]) = (uint8) SREG; \ + CLRFLAGS; \ + R15++ + +static void fx_stb_r0 (void) +{ + FX_STB(0); +} + +static void fx_stb_r1 (void) +{ + FX_STB(1); +} + +static void fx_stb_r2 (void) +{ + FX_STB(2); +} + +static void fx_stb_r3 (void) +{ + FX_STB(3); +} + +static void fx_stb_r4 (void) +{ + FX_STB(4); +} + +static void fx_stb_r5 (void) +{ + FX_STB(5); +} + +static void fx_stb_r6 (void) +{ + FX_STB(6); +} + +static void fx_stb_r7 (void) +{ + FX_STB(7); +} + +static void fx_stb_r8 (void) +{ + FX_STB(8); +} + +static void fx_stb_r9 (void) +{ + FX_STB(9); +} + +static void fx_stb_r10 (void) +{ + FX_STB(10); +} + +static void fx_stb_r11 (void) +{ + FX_STB(11); +} + +// 3c - loop - decrement loop counter, and branch on not zero +static void fx_loop (void) +{ + GSU.vSign = GSU.vZero = --R12; + if ((uint16) R12 != 0) + R15 = R13; + else + R15++; + CLRFLAGS; +} + +// 3d - alt1 - set alt1 mode +static void fx_alt1 (void) +{ + SF(ALT1); + CF(B); + R15++; +} + +// 3e - alt2 - set alt2 mode +static void fx_alt2 (void) +{ + SF(ALT2); + CF(B); + R15++; +} + +// 3f - alt3 - set alt3 mode +static void fx_alt3 (void) +{ + SF(ALT1); + SF(ALT2); + CF(B); + R15++; +} + +// 40-4b - ldw (rn) - load word from RAM +#define FX_LDW(reg) \ + uint32 v; \ + GSU.vLastRamAdr = GSU.avReg[reg]; \ + v = (uint32) RAM(GSU.avReg[reg]); \ + v |= ((uint32) RAM(GSU.avReg[reg] ^ 1)) << 8; \ + R15++; \ + DREG = v; \ + TESTR14; \ + CLRFLAGS + +static void fx_ldw_r0 (void) +{ + FX_LDW(0); +} + +static void fx_ldw_r1 (void) +{ + FX_LDW(1); +} + +static void fx_ldw_r2 (void) +{ + FX_LDW(2); +} + +static void fx_ldw_r3 (void) +{ + FX_LDW(3); +} + +static void fx_ldw_r4 (void) +{ + FX_LDW(4); +} + +static void fx_ldw_r5 (void) +{ + FX_LDW(5); +} + +static void fx_ldw_r6 (void) +{ + FX_LDW(6); +} + +static void fx_ldw_r7 (void) +{ + FX_LDW(7); +} + +static void fx_ldw_r8 (void) +{ + FX_LDW(8); +} + +static void fx_ldw_r9 (void) +{ + FX_LDW(9); +} + +static void fx_ldw_r10 (void) +{ + FX_LDW(10); +} + +static void fx_ldw_r11 (void) +{ + FX_LDW(11); +} + +// 40-4b (ALT1) - ldb (rn) - load byte +#define FX_LDB(reg) \ + uint32 v; \ + GSU.vLastRamAdr = GSU.avReg[reg]; \ + v = (uint32) RAM(GSU.avReg[reg]); \ + R15++; \ + DREG = v; \ + TESTR14; \ + CLRFLAGS + +static void fx_ldb_r0 (void) +{ + FX_LDB(0); +} + +static void fx_ldb_r1 (void) +{ + FX_LDB(1); +} + +static void fx_ldb_r2 (void) +{ + FX_LDB(2); +} + +static void fx_ldb_r3 (void) +{ + FX_LDB(3); +} + +static void fx_ldb_r4 (void) +{ + FX_LDB(4); +} + +static void fx_ldb_r5 (void) +{ + FX_LDB(5); +} + +static void fx_ldb_r6 (void) +{ + FX_LDB(6); +} + +static void fx_ldb_r7 (void) +{ + FX_LDB(7); +} + +static void fx_ldb_r8 (void) +{ + FX_LDB(8); +} + +static void fx_ldb_r9 (void) +{ + FX_LDB(9); +} + +static void fx_ldb_r10 (void) +{ + FX_LDB(10); +} + +static void fx_ldb_r11 (void) +{ + FX_LDB(11); +} + +// 4c - plot - plot pixel with R1, R2 as x, y and the color register as the color +static void fx_plot_2bit (void) +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v, c; + + R15++; + CLRFLAGS; + R1++; + +#ifdef CHECK_LIMITS + if (y >= GSU.vScreenHeight) + return; +#endif + + if (GSU.vPlotOptionReg & 0x02) + c = (x ^ y) & 1 ? (uint8) (GSU.vColorReg >> 4) : (uint8) GSU.vColorReg; + else + c = (uint8) GSU.vColorReg; + + if (!(GSU.vPlotOptionReg & 0x01) && !(c & 0xf)) + return; + + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x & 7); + + if (c & 0x01) + a[0] |= v; + else + a[0] &= ~v; + + if (c & 0x02) + a[1] |= v; + else + a[1] &= ~v; +} + +// 4c (ALT1) - rpix - read color of the pixel with R1, R2 as x, y +static void fx_rpix_2bit (void) +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v; + + R15++; + CLRFLAGS; + +#ifdef CHECK_LIMITS + if (y >= GSU.vScreenHeight) + return; +#endif + + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x & 7); + + DREG = 0; + DREG |= ((uint32) ((a[0] & v) != 0)) << 0; + DREG |= ((uint32) ((a[1] & v) != 0)) << 1; + TESTR14; +} + +// 4c - plot - plot pixel with R1, R2 as x, y and the color register as the color +static void fx_plot_4bit (void) +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v, c; + + R15++; + CLRFLAGS; + R1++; + +#ifdef CHECK_LIMITS + if (y >= GSU.vScreenHeight) + return; +#endif + + if (GSU.vPlotOptionReg & 0x02) + c = (x ^ y) & 1 ? (uint8) (GSU.vColorReg >> 4) : (uint8) GSU.vColorReg; + else + c = (uint8) GSU.vColorReg; + + if (!(GSU.vPlotOptionReg & 0x01) && !(c & 0xf)) + return; + + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x & 7); + + if (c & 0x01) + a[0x00] |= v; + else + a[0x00] &= ~v; + + if (c & 0x02) + a[0x01] |= v; + else + a[0x01] &= ~v; + + if (c & 0x04) + a[0x10] |= v; + else + a[0x10] &= ~v; + + if (c & 0x08) + a[0x11] |= v; + else + a[0x11] &= ~v; +} + +// 4c (ALT1) - rpix - read color of the pixel with R1, R2 as x, y +static void fx_rpix_4bit (void) +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v; + + R15++; + CLRFLAGS; + +#ifdef CHECK_LIMITS + if (y >= GSU.vScreenHeight) + return; +#endif + + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x & 7); + + DREG = 0; + DREG |= ((uint32) ((a[0x00] & v) != 0)) << 0; + DREG |= ((uint32) ((a[0x01] & v) != 0)) << 1; + DREG |= ((uint32) ((a[0x10] & v) != 0)) << 2; + DREG |= ((uint32) ((a[0x11] & v) != 0)) << 3; + TESTR14; +} + +// 4c - plot - plot pixel with R1, R2 as x, y and the color register as the color +static void fx_plot_8bit (void) +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v, c; + + R15++; + CLRFLAGS; + R1++; + +#ifdef CHECK_LIMITS + if (y >= GSU.vScreenHeight) + return; +#endif + + c = (uint8) GSU.vColorReg; + if (!(GSU.vPlotOptionReg & 0x10)) + { + if (!(GSU.vPlotOptionReg & 0x01) && !(c & 0xf)) + return; + } + else + if (!(GSU.vPlotOptionReg & 0x01) && !c) + return; + + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x & 7); + + if (c & 0x01) + a[0x00] |= v; + else + a[0x00] &= ~v; + + if (c & 0x02) + a[0x01] |= v; + else + a[0x01] &= ~v; + + if (c & 0x04) + a[0x10] |= v; + else + a[0x10] &= ~v; + + if (c & 0x08) + a[0x11] |= v; + else + a[0x11] &= ~v; + + if (c & 0x10) + a[0x20] |= v; + else + a[0x20] &= ~v; + + if (c & 0x20) + a[0x21] |= v; + else + a[0x21] &= ~v; + + if (c & 0x40) + a[0x30] |= v; + else + a[0x30] &= ~v; + + if (c & 0x80) + a[0x31] |= v; + else + a[0x31] &= ~v; +} + +// 4c (ALT1) - rpix - read color of the pixel with R1, R2 as x, y +static void fx_rpix_8bit (void) +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v; + + R15++; + CLRFLAGS; + +#ifdef CHECK_LIMITS + if (y >= GSU.vScreenHeight) + return; +#endif + + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x & 7); + + DREG = 0; + DREG |= ((uint32) ((a[0x00] & v) != 0)) << 0; + DREG |= ((uint32) ((a[0x01] & v) != 0)) << 1; + DREG |= ((uint32) ((a[0x10] & v) != 0)) << 2; + DREG |= ((uint32) ((a[0x11] & v) != 0)) << 3; + DREG |= ((uint32) ((a[0x20] & v) != 0)) << 4; + DREG |= ((uint32) ((a[0x21] & v) != 0)) << 5; + DREG |= ((uint32) ((a[0x30] & v) != 0)) << 6; + DREG |= ((uint32) ((a[0x31] & v) != 0)) << 7; + GSU.vZero = DREG; + TESTR14; +} + +// 4c - plot - plot pixel with R1, R2 as x, y and the color register as the color +static void fx_plot_obj (void) +{ +#ifdef DEBUGGER + fprintf(stderr, "ERROR fx_plot_obj called\n"); +#endif +} + +// 4c (ALT1) - rpix - read color of the pixel with R1, R2 as x, y +static void fx_rpix_obj (void) +{ +#ifdef DEBUGGER + fprintf(stderr, "ERROR fx_rpix_obj called\n"); +#endif +} + +// 4d - swap - swap upper and lower byte of a register +static void fx_swap (void) +{ + uint8 c = (uint8) SREG; + uint8 d = (uint8) (SREG >> 8); + uint32 v = (((uint32) c) << 8) | ((uint32) d); + R15++; + DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +// 4e - color - copy source register to color register +static void fx_color (void) +{ + uint8 c = (uint8) SREG; + + if (GSU.vPlotOptionReg & 0x04) + c = (c & 0xf0) | (c >> 4); + if (GSU.vPlotOptionReg & 0x08) + { + GSU.vColorReg &= 0xf0; + GSU.vColorReg |= c & 0x0f; + } + else + GSU.vColorReg = USEX8(c); + + CLRFLAGS; + R15++; +} + +// 4e (ALT1) - cmode - set plot option register +static void fx_cmode (void) +{ + GSU.vPlotOptionReg = SREG; + + if (GSU.vPlotOptionReg & 0x10) + GSU.vScreenHeight = 256; // OBJ Mode (for drawing into sprites) + else + GSU.vScreenHeight = GSU.vScreenRealHeight; + + fx_computeScreenPointers(); + CLRFLAGS; + R15++; +} + +// 4f - not - perform exclusive exor with 1 on all bits +static void fx_not (void) +{ + uint32 v = ~SREG; + R15++; + DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +// 50-5f - add rn - add, register + register +#define FX_ADD(reg) \ + int32 s = SUSEX16(SREG) + SUSEX16(GSU.avReg[reg]); \ + GSU.vCarry = s >= 0x10000; \ + GSU.vOverflow = ~(SREG ^ GSU.avReg[reg]) & (GSU.avReg[reg] ^ s) & 0x8000; \ + GSU.vSign = s; \ + GSU.vZero = s; \ + R15++; \ + DREG = s; \ + TESTR14; \ + CLRFLAGS + +static void fx_add_r0 (void) +{ + FX_ADD(0); +} + +static void fx_add_r1 (void) +{ + FX_ADD(1); +} + +static void fx_add_r2 (void) +{ + FX_ADD(2); +} + +static void fx_add_r3 (void) +{ + FX_ADD(3); +} + +static void fx_add_r4 (void) +{ + FX_ADD(4); +} + +static void fx_add_r5 (void) +{ + FX_ADD(5); +} + +static void fx_add_r6 (void) +{ + FX_ADD(6); +} + +static void fx_add_r7 (void) +{ + FX_ADD(7); +} + +static void fx_add_r8 (void) +{ + FX_ADD(8); +} + +static void fx_add_r9 (void) +{ + FX_ADD(9); +} + +static void fx_add_r10 (void) +{ + FX_ADD(10); +} + +static void fx_add_r11 (void) +{ + FX_ADD(11); +} + +static void fx_add_r12 (void) +{ + FX_ADD(12); +} + +static void fx_add_r13 (void) +{ + FX_ADD(13); +} + +static void fx_add_r14 (void) +{ + FX_ADD(14); +} + +static void fx_add_r15 (void) +{ + FX_ADD(15); +} + +// 50-5f (ALT1) - adc rn - add with carry, register + register +#define FX_ADC(reg) \ + int32 s = SUSEX16(SREG) + SUSEX16(GSU.avReg[reg]) + SEX16(GSU.vCarry); \ + GSU.vCarry = s >= 0x10000; \ + GSU.vOverflow = ~(SREG ^ GSU.avReg[reg]) & (GSU.avReg[reg] ^ s) & 0x8000; \ + GSU.vSign = s; \ + GSU.vZero = s; \ + R15++; \ + DREG = s; \ + TESTR14; \ + CLRFLAGS + +static void fx_adc_r0 (void) +{ + FX_ADC(0); +} + +static void fx_adc_r1 (void) +{ + FX_ADC(1); +} + +static void fx_adc_r2 (void) +{ + FX_ADC(2); +} + +static void fx_adc_r3 (void) +{ + FX_ADC(3); +} + +static void fx_adc_r4 (void) +{ + FX_ADC(4); +} + +static void fx_adc_r5 (void) +{ + FX_ADC(5); +} + +static void fx_adc_r6 (void) +{ + FX_ADC(6); +} + +static void fx_adc_r7 (void) +{ + FX_ADC(7); +} + +static void fx_adc_r8 (void) +{ + FX_ADC(8); +} + +static void fx_adc_r9 (void) +{ + FX_ADC(9); +} + +static void fx_adc_r10 (void) +{ + FX_ADC(10); +} + +static void fx_adc_r11 (void) +{ + FX_ADC(11); +} + +static void fx_adc_r12 (void) +{ + FX_ADC(12); +} + +static void fx_adc_r13 (void) +{ + FX_ADC(13); +} + +static void fx_adc_r14 (void) +{ + FX_ADC(14); +} + +static void fx_adc_r15 (void) +{ + FX_ADC(15); +} + +// 50-5f (ALT2) - add #n - add, register + immediate +#define FX_ADD_I(imm) \ + int32 s = SUSEX16(SREG) + imm; \ + GSU.vCarry = s >= 0x10000; \ + GSU.vOverflow = ~(SREG ^ imm) & (imm ^ s) & 0x8000; \ + GSU.vSign = s; \ + GSU.vZero = s; \ + R15++; \ + DREG = s; \ + TESTR14; \ + CLRFLAGS + +static void fx_add_i0 (void) +{ + FX_ADD_I(0); +} + +static void fx_add_i1 (void) +{ + FX_ADD_I(1); +} + +static void fx_add_i2 (void) +{ + FX_ADD_I(2); +} + +static void fx_add_i3 (void) +{ + FX_ADD_I(3); +} + +static void fx_add_i4 (void) +{ + FX_ADD_I(4); +} + +static void fx_add_i5 (void) +{ + FX_ADD_I(5); +} + +static void fx_add_i6 (void) +{ + FX_ADD_I(6); +} + +static void fx_add_i7 (void) +{ + FX_ADD_I(7); +} + +static void fx_add_i8 (void) +{ + FX_ADD_I(8); +} + +static void fx_add_i9 (void) +{ + FX_ADD_I(9); +} + +static void fx_add_i10 (void) +{ + FX_ADD_I(10); +} + +static void fx_add_i11 (void) +{ + FX_ADD_I(11); +} + +static void fx_add_i12 (void) +{ + FX_ADD_I(12); +} + +static void fx_add_i13 (void) +{ + FX_ADD_I(13); +} + +static void fx_add_i14 (void) +{ + FX_ADD_I(14); +} + +static void fx_add_i15 (void) +{ + FX_ADD_I(15); +} + +// 50-5f (ALT3) - adc #n - add with carry, register + immediate +#define FX_ADC_I(imm) \ + int32 s = SUSEX16(SREG) + imm + SUSEX16(GSU.vCarry); \ + GSU.vCarry = s >= 0x10000; \ + GSU.vOverflow = ~(SREG ^ imm) & (imm ^ s) & 0x8000; \ + GSU.vSign = s; \ + GSU.vZero = s; \ + R15++; \ + DREG = s; \ + TESTR14; \ + CLRFLAGS + +static void fx_adc_i0 (void) +{ + FX_ADC_I(0); +} + +static void fx_adc_i1 (void) +{ + FX_ADC_I(1); +} + +static void fx_adc_i2 (void) +{ + FX_ADC_I(2); +} + +static void fx_adc_i3 (void) +{ + FX_ADC_I(3); +} + +static void fx_adc_i4 (void) +{ + FX_ADC_I(4); +} + +static void fx_adc_i5 (void) +{ + FX_ADC_I(5); +} + +static void fx_adc_i6 (void) +{ + FX_ADC_I(6); +} + +static void fx_adc_i7 (void) +{ + FX_ADC_I(7); +} + +static void fx_adc_i8 (void) +{ + FX_ADC_I(8); +} + +static void fx_adc_i9 (void) +{ + FX_ADC_I(9); +} + +static void fx_adc_i10 (void) +{ + FX_ADC_I(10); +} + +static void fx_adc_i11 (void) +{ + FX_ADC_I(11); +} + +static void fx_adc_i12 (void) +{ + FX_ADC_I(12); +} + +static void fx_adc_i13 (void) +{ + FX_ADC_I(13); +} + +static void fx_adc_i14 (void) +{ + FX_ADC_I(14); +} + +static void fx_adc_i15 (void) +{ + FX_ADC_I(15); +} + +// 60-6f - sub rn - subtract, register - register +#define FX_SUB(reg) \ + int32 s = SUSEX16(SREG) - SUSEX16(GSU.avReg[reg]); \ + GSU.vCarry = s >= 0; \ + GSU.vOverflow = (SREG ^ GSU.avReg[reg]) & (SREG ^ s) & 0x8000; \ + GSU.vSign = s; \ + GSU.vZero = s; \ + R15++; \ + DREG = s; \ + TESTR14; \ + CLRFLAGS + +static void fx_sub_r0 (void) +{ + FX_SUB(0); +} + +static void fx_sub_r1 (void) +{ + FX_SUB(1); +} + +static void fx_sub_r2 (void) +{ + FX_SUB(2); +} + +static void fx_sub_r3 (void) +{ + FX_SUB(3); +} + +static void fx_sub_r4 (void) +{ + FX_SUB(4); +} + +static void fx_sub_r5 (void) +{ + FX_SUB(5); +} + +static void fx_sub_r6 (void) +{ + FX_SUB(6); +} + +static void fx_sub_r7 (void) +{ + FX_SUB(7); +} + +static void fx_sub_r8 (void) +{ + FX_SUB(8); +} + +static void fx_sub_r9 (void) +{ + FX_SUB(9); +} + +static void fx_sub_r10 (void) +{ + FX_SUB(10); +} + +static void fx_sub_r11 (void) +{ + FX_SUB(11); +} + +static void fx_sub_r12 (void) +{ + FX_SUB(12); +} + +static void fx_sub_r13 (void) +{ + FX_SUB(13); +} + +static void fx_sub_r14 (void) +{ + FX_SUB(14); +} + +static void fx_sub_r15 (void) +{ + FX_SUB(15); +} + +// 60-6f (ALT1) - sbc rn - subtract with carry, register - register +#define FX_SBC(reg) \ + int32 s = SUSEX16(SREG) - SUSEX16(GSU.avReg[reg]) - (SUSEX16(GSU.vCarry ^ 1)); \ + GSU.vCarry = s >= 0; \ + GSU.vOverflow = (SREG ^ GSU.avReg[reg]) & (SREG ^ s) & 0x8000; \ + GSU.vSign = s; \ + GSU.vZero = s; \ + R15++; \ + DREG = s; \ + TESTR14; \ + CLRFLAGS + +static void fx_sbc_r0 (void) +{ + FX_SBC(0); +} + +static void fx_sbc_r1 (void) +{ + FX_SBC(1); +} + +static void fx_sbc_r2 (void) +{ + FX_SBC(2); +} + +static void fx_sbc_r3 (void) +{ + FX_SBC(3); +} + +static void fx_sbc_r4 (void) +{ + FX_SBC(4); +} + +static void fx_sbc_r5 (void) +{ + FX_SBC(5); +} + +static void fx_sbc_r6 (void) +{ + FX_SBC(6); +} + +static void fx_sbc_r7 (void) +{ + FX_SBC(7); +} + +static void fx_sbc_r8 (void) +{ + FX_SBC(8); +} + +static void fx_sbc_r9 (void) +{ + FX_SBC(9); +} + +static void fx_sbc_r10 (void) +{ + FX_SBC(10); +} + +static void fx_sbc_r11 (void) +{ + FX_SBC(11); +} + +static void fx_sbc_r12 (void) +{ + FX_SBC(12); +} + +static void fx_sbc_r13 (void) +{ + FX_SBC(13); +} + +static void fx_sbc_r14 (void) +{ + FX_SBC(14); +} + +static void fx_sbc_r15 (void) +{ + FX_SBC(15); +} + +// 60-6f (ALT2) - sub #n - subtract, register - immediate +#define FX_SUB_I(imm) \ + int32 s = SUSEX16(SREG) - imm; \ + GSU.vCarry = s >= 0; \ + GSU.vOverflow = (SREG ^ imm) & (SREG ^ s) & 0x8000; \ + GSU.vSign = s; \ + GSU.vZero = s; \ + R15++; \ + DREG = s; \ + TESTR14; \ + CLRFLAGS + +static void fx_sub_i0 (void) +{ + FX_SUB_I(0); +} + +static void fx_sub_i1 (void) +{ + FX_SUB_I(1); +} + +static void fx_sub_i2 (void) +{ + FX_SUB_I(2); +} + +static void fx_sub_i3 (void) +{ + FX_SUB_I(3); +} + +static void fx_sub_i4 (void) +{ + FX_SUB_I(4); +} + +static void fx_sub_i5 (void) +{ + FX_SUB_I(5); +} + +static void fx_sub_i6 (void) +{ + FX_SUB_I(6); +} + +static void fx_sub_i7 (void) +{ + FX_SUB_I(7); +} + +static void fx_sub_i8 (void) +{ + FX_SUB_I(8); +} + +static void fx_sub_i9 (void) +{ + FX_SUB_I(9); +} + +static void fx_sub_i10 (void) +{ + FX_SUB_I(10); +} + +static void fx_sub_i11 (void) +{ + FX_SUB_I(11); +} + +static void fx_sub_i12 (void) +{ + FX_SUB_I(12); +} + +static void fx_sub_i13 (void) +{ + FX_SUB_I(13); +} + +static void fx_sub_i14 (void) +{ + FX_SUB_I(14); +} + +static void fx_sub_i15 (void) +{ + FX_SUB_I(15); +} + +// 60-6f (ALT3) - cmp rn - compare, register, register +#define FX_CMP(reg) \ + int32 s = SUSEX16(SREG) - SUSEX16(GSU.avReg[reg]); \ + GSU.vCarry = s >= 0; \ + GSU.vOverflow = (SREG ^ GSU.avReg[reg]) & (SREG ^ s) & 0x8000; \ + GSU.vSign = s; \ + GSU.vZero = s; \ + R15++; \ + CLRFLAGS + +static void fx_cmp_r0 (void) +{ + FX_CMP(0); +} + +static void fx_cmp_r1 (void) +{ + FX_CMP(1); +} + +static void fx_cmp_r2 (void) +{ + FX_CMP(2); +} + +static void fx_cmp_r3 (void) +{ + FX_CMP(3); +} + +static void fx_cmp_r4 (void) +{ + FX_CMP(4); +} + +static void fx_cmp_r5 (void) +{ + FX_CMP(5); +} + +static void fx_cmp_r6 (void) +{ + FX_CMP(6); +} + +static void fx_cmp_r7 (void) +{ + FX_CMP(7); +} + +static void fx_cmp_r8 (void) +{ + FX_CMP(8); +} + +static void fx_cmp_r9 (void) +{ + FX_CMP(9); +} + +static void fx_cmp_r10 (void) +{ + FX_CMP(10); +} + +static void fx_cmp_r11 (void) +{ + FX_CMP(11); +} + +static void fx_cmp_r12 (void) +{ + FX_CMP(12); +} + +static void fx_cmp_r13 (void) +{ + FX_CMP(13); +} + +static void fx_cmp_r14 (void) +{ + FX_CMP(14); +} + +static void fx_cmp_r15 (void) +{ + FX_CMP(15); +} + +// 70 - merge - R7 as upper byte, R8 as lower byte (used for texture-mapping) +static void fx_merge (void) +{ + uint32 v = (R7 & 0xff00) | ((R8 & 0xff00) >> 8); + R15++; + DREG = v; + GSU.vOverflow = (v & 0xc0c0) << 16; + GSU.vZero = !(v & 0xf0f0); + GSU.vSign = ((v | (v << 8)) & 0x8000); + GSU.vCarry = (v & 0xe0e0) != 0; + TESTR14; + CLRFLAGS; +} + +// 71-7f - and rn - reister & register +#define FX_AND(reg) \ + uint32 v = SREG & GSU.avReg[reg]; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS + +static void fx_and_r1 (void) +{ + FX_AND(1); +} + +static void fx_and_r2 (void) +{ + FX_AND(2); +} + +static void fx_and_r3 (void) +{ + FX_AND(3); +} + +static void fx_and_r4 (void) +{ + FX_AND(4); +} + +static void fx_and_r5 (void) +{ + FX_AND(5); +} + +static void fx_and_r6 (void) +{ + FX_AND(6); +} + +static void fx_and_r7 (void) +{ + FX_AND(7); +} + +static void fx_and_r8 (void) +{ + FX_AND(8); +} + +static void fx_and_r9 (void) +{ + FX_AND(9); +} + +static void fx_and_r10 (void) +{ + FX_AND(10); +} + +static void fx_and_r11 (void) +{ + FX_AND(11); +} + +static void fx_and_r12 (void) +{ + FX_AND(12); +} + +static void fx_and_r13 (void) +{ + FX_AND(13); +} + +static void fx_and_r14 (void) +{ + FX_AND(14); +} + +static void fx_and_r15 (void) +{ + FX_AND(15); +} + +// 71-7f (ALT1) - bic rn - reister & ~register +#define FX_BIC(reg) \ + uint32 v = SREG & ~GSU.avReg[reg]; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS + +static void fx_bic_r1 (void) +{ + FX_BIC(1); +} + +static void fx_bic_r2 (void) +{ + FX_BIC(2); +} + +static void fx_bic_r3 (void) +{ + FX_BIC(3); +} + +static void fx_bic_r4 (void) +{ + FX_BIC(4); +} + +static void fx_bic_r5 (void) +{ + FX_BIC(5); +} + +static void fx_bic_r6 (void) +{ + FX_BIC(6); +} + +static void fx_bic_r7 (void) +{ + FX_BIC(7); +} + +static void fx_bic_r8 (void) +{ + FX_BIC(8); +} + +static void fx_bic_r9 (void) +{ + FX_BIC(9); +} + +static void fx_bic_r10 (void) +{ + FX_BIC(10); +} + +static void fx_bic_r11 (void) +{ + FX_BIC(11); +} + +static void fx_bic_r12 (void) +{ + FX_BIC(12); +} + +static void fx_bic_r13 (void) +{ + FX_BIC(13); +} + +static void fx_bic_r14 (void) +{ + FX_BIC(14); +} + +static void fx_bic_r15 (void) +{ + FX_BIC(15); +} + +// 71-7f (ALT2) - and #n - reister & immediate +#define FX_AND_I(imm) \ + uint32 v = SREG & imm; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS + +static void fx_and_i1 (void) +{ + FX_AND_I(1); +} + +static void fx_and_i2 (void) +{ + FX_AND_I(2); +} + +static void fx_and_i3 (void) +{ + FX_AND_I(3); +} + +static void fx_and_i4 (void) +{ + FX_AND_I(4); +} + +static void fx_and_i5 (void) +{ + FX_AND_I(5); +} + +static void fx_and_i6 (void) +{ + FX_AND_I(6); +} + +static void fx_and_i7 (void) +{ + FX_AND_I(7); +} + +static void fx_and_i8 (void) +{ + FX_AND_I(8); +} + +static void fx_and_i9 (void) +{ + FX_AND_I(9); +} + +static void fx_and_i10 (void) +{ + FX_AND_I(10); +} + +static void fx_and_i11 (void) +{ + FX_AND_I(11); +} + +static void fx_and_i12 (void) +{ + FX_AND_I(12); +} + +static void fx_and_i13 (void) +{ + FX_AND_I(13); +} + +static void fx_and_i14 (void) +{ + FX_AND_I(14); +} + +static void fx_and_i15 (void) +{ + FX_AND_I(15); +} + +// 71-7f (ALT3) - bic #n - reister & ~immediate +#define FX_BIC_I(imm) \ + uint32 v = SREG & ~imm; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS + +static void fx_bic_i1 (void) +{ + FX_BIC_I(1); +} + +static void fx_bic_i2 (void) +{ + FX_BIC_I(2); +} + +static void fx_bic_i3 (void) +{ + FX_BIC_I(3); +} + +static void fx_bic_i4 (void) +{ + FX_BIC_I(4); +} + +static void fx_bic_i5 (void) +{ + FX_BIC_I(5); +} + +static void fx_bic_i6 (void) +{ + FX_BIC_I(6); +} + +static void fx_bic_i7 (void) +{ + FX_BIC_I(7); +} + +static void fx_bic_i8 (void) +{ + FX_BIC_I(8); +} + +static void fx_bic_i9 (void) +{ + FX_BIC_I(9); +} + +static void fx_bic_i10 (void) +{ + FX_BIC_I(10); +} + +static void fx_bic_i11 (void) +{ + FX_BIC_I(11); +} + +static void fx_bic_i12 (void) +{ + FX_BIC_I(12); +} + +static void fx_bic_i13 (void) +{ + FX_BIC_I(13); +} + +static void fx_bic_i14 (void) +{ + FX_BIC_I(14); +} + +static void fx_bic_i15 (void) +{ + FX_BIC_I(15); +} + +// 80-8f - mult rn - 8 bit to 16 bit signed multiply, register * register +#define FX_MULT(reg) \ + uint32 v = (uint32) (SEX8(SREG) * SEX8(GSU.avReg[reg])); \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS + +static void fx_mult_r0 (void) +{ + FX_MULT(0); +} + +static void fx_mult_r1 (void) +{ + FX_MULT(1); +} + +static void fx_mult_r2 (void) +{ + FX_MULT(2); +} + +static void fx_mult_r3 (void) +{ + FX_MULT(3); +} + +static void fx_mult_r4 (void) +{ + FX_MULT(4); +} + +static void fx_mult_r5 (void) +{ + FX_MULT(5); +} + +static void fx_mult_r6 (void) +{ + FX_MULT(6); +} + +static void fx_mult_r7 (void) +{ + FX_MULT(7); +} + +static void fx_mult_r8 (void) +{ + FX_MULT(8); +} + +static void fx_mult_r9 (void) +{ + FX_MULT(9); +} + +static void fx_mult_r10 (void) +{ + FX_MULT(10); +} + +static void fx_mult_r11 (void) +{ + FX_MULT(11); +} + +static void fx_mult_r12 (void) +{ + FX_MULT(12); +} + +static void fx_mult_r13 (void) +{ + FX_MULT(13); +} + +static void fx_mult_r14 (void) +{ + FX_MULT(14); +} + +static void fx_mult_r15 (void) +{ + FX_MULT(15); +} + +// 80-8f (ALT1) - umult rn - 8 bit to 16 bit unsigned multiply, register * register +#define FX_UMULT(reg) \ + uint32 v = USEX8(SREG) * USEX8(GSU.avReg[reg]); \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS + +static void fx_umult_r0 (void) +{ + FX_UMULT(0); +} + +static void fx_umult_r1 (void) +{ + FX_UMULT(1); +} + +static void fx_umult_r2 (void) +{ + FX_UMULT(2); +} + +static void fx_umult_r3 (void) +{ + FX_UMULT(3); +} + +static void fx_umult_r4 (void) +{ + FX_UMULT(4); +} + +static void fx_umult_r5 (void) +{ + FX_UMULT(5); +} + +static void fx_umult_r6 (void) +{ + FX_UMULT(6); +} + +static void fx_umult_r7 (void) +{ + FX_UMULT(7); +} + +static void fx_umult_r8 (void) +{ + FX_UMULT(8); +} + +static void fx_umult_r9 (void) +{ + FX_UMULT(9); +} + +static void fx_umult_r10 (void) +{ + FX_UMULT(10); +} + +static void fx_umult_r11 (void) +{ + FX_UMULT(11); +} + +static void fx_umult_r12 (void) +{ + FX_UMULT(12); +} + +static void fx_umult_r13 (void) +{ + FX_UMULT(13); +} + +static void fx_umult_r14 (void) +{ + FX_UMULT(14); +} + +static void fx_umult_r15 (void) +{ + FX_UMULT(15); +} + +// 80-8f (ALT2) - mult #n - 8 bit to 16 bit signed multiply, register * immediate +#define FX_MULT_I(imm) \ + uint32 v = (uint32) (SEX8(SREG) * ((int32) imm)); \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS + +static void fx_mult_i0 (void) +{ + FX_MULT_I(0); +} + +static void fx_mult_i1 (void) +{ + FX_MULT_I(1); +} + +static void fx_mult_i2 (void) +{ + FX_MULT_I(2); +} + +static void fx_mult_i3 (void) +{ + FX_MULT_I(3); +} + +static void fx_mult_i4 (void) +{ + FX_MULT_I(4); +} + +static void fx_mult_i5 (void) +{ + FX_MULT_I(5); +} + +static void fx_mult_i6 (void) +{ + FX_MULT_I(6); +} + +static void fx_mult_i7 (void) +{ + FX_MULT_I(7); +} + +static void fx_mult_i8 (void) +{ + FX_MULT_I(8); +} + +static void fx_mult_i9 (void) +{ + FX_MULT_I(9); +} + +static void fx_mult_i10 (void) +{ + FX_MULT_I(10); +} + +static void fx_mult_i11 (void) +{ + FX_MULT_I(11); +} + +static void fx_mult_i12 (void) +{ + FX_MULT_I(12); +} + +static void fx_mult_i13 (void) +{ + FX_MULT_I(13); +} + +static void fx_mult_i14 (void) +{ + FX_MULT_I(14); +} + +static void fx_mult_i15 (void) +{ + FX_MULT_I(15); +} + +// 80-8f (ALT3) - umult #n - 8 bit to 16 bit unsigned multiply, register * immediate +#define FX_UMULT_I(imm) \ + uint32 v = USEX8(SREG) * ((uint32) imm); \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS + +static void fx_umult_i0 (void) +{ + FX_UMULT_I(0); +} + +static void fx_umult_i1 (void) +{ + FX_UMULT_I(1); +} + +static void fx_umult_i2 (void) +{ + FX_UMULT_I(2); +} + +static void fx_umult_i3 (void) +{ + FX_UMULT_I(3); +} + +static void fx_umult_i4 (void) +{ + FX_UMULT_I(4); +} + +static void fx_umult_i5 (void) +{ + FX_UMULT_I(5); +} + +static void fx_umult_i6 (void) +{ + FX_UMULT_I(6); +} + +static void fx_umult_i7 (void) +{ + FX_UMULT_I(7); +} + +static void fx_umult_i8 (void) +{ + FX_UMULT_I(8); +} + +static void fx_umult_i9 (void) +{ + FX_UMULT_I(9); +} + +static void fx_umult_i10 (void) +{ + FX_UMULT_I(10); +} + +static void fx_umult_i11 (void) +{ + FX_UMULT_I(11); +} + +static void fx_umult_i12 (void) +{ + FX_UMULT_I(12); +} + +static void fx_umult_i13 (void) +{ + FX_UMULT_I(13); +} + +static void fx_umult_i14 (void) +{ + FX_UMULT_I(14); +} + +static void fx_umult_i15 (void) +{ + FX_UMULT_I(15); +} + +// 90 - sbk - store word to last accessed RAM address +static void fx_sbk (void) +{ + RAM(GSU.vLastRamAdr) = (uint8) SREG; + RAM(GSU.vLastRamAdr ^ 1) = (uint8) (SREG >> 8); + CLRFLAGS; + R15++; +} + +// 91-94 - link #n - R11 = R15 + immediate +#define FX_LINK_I(lkn) \ + R11 = R15 + lkn; \ + CLRFLAGS; \ + R15++ + +static void fx_link_i1 (void) +{ + FX_LINK_I(1); +} + +static void fx_link_i2 (void) +{ + FX_LINK_I(2); +} + +static void fx_link_i3 (void) +{ + FX_LINK_I(3); +} + +static void fx_link_i4 (void) +{ + FX_LINK_I(4); +} + +// 95 - sex - sign extend 8 bit to 16 bit +static void fx_sex (void) +{ + uint32 v = (uint32) SEX8(SREG); + R15++; + DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +// 96 - asr - aritmetric shift right by one +static void fx_asr (void) +{ + uint32 v; + GSU.vCarry = SREG & 1; + v = (uint32) (SEX16(SREG) >> 1); + R15++; + DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +// 96 (ALT1) - div2 - aritmetric shift right by one +static void fx_div2 (void) +{ + uint32 v; + int32 s = SEX16(SREG); + GSU.vCarry = s & 1; + if (s == -1) + v = 0; + else + v = (uint32) (s >> 1); + R15++; + DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +// 97 - ror - rotate right by one +static void fx_ror (void) +{ + uint32 v = (USEX16(SREG) >> 1) | (GSU.vCarry << 15); + GSU.vCarry = SREG & 1; + R15++; + DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +// 98-9d - jmp rn - jump to address of register +#define FX_JMP(reg) \ + R15 = GSU.avReg[reg]; \ + CLRFLAGS + +static void fx_jmp_r8 (void) +{ + FX_JMP(8); +} + +static void fx_jmp_r9 (void) +{ + FX_JMP(9); +} + +static void fx_jmp_r10 (void) +{ + FX_JMP(10); +} + +static void fx_jmp_r11 (void) +{ + FX_JMP(11); +} + +static void fx_jmp_r12 (void) +{ + FX_JMP(12); +} + +static void fx_jmp_r13 (void) +{ + FX_JMP(13); +} + +// 98-9d (ALT1) - ljmp rn - set program bank to source register and jump to address of register +#define FX_LJMP(reg) \ + GSU.vPrgBankReg = GSU.avReg[reg] & 0x7f; \ + GSU.pvPrgBank = GSU.apvRomBank[GSU.vPrgBankReg]; \ + R15 = SREG; \ + GSU.bCacheActive = FALSE; \ + fx_cache(); \ + R15-- + +static void fx_ljmp_r8 (void) +{ + FX_LJMP(8); +} + +static void fx_ljmp_r9 (void) +{ + FX_LJMP(9); +} + +static void fx_ljmp_r10 (void) +{ + FX_LJMP(10); +} + +static void fx_ljmp_r11 (void) +{ + FX_LJMP(11); +} + +static void fx_ljmp_r12 (void) +{ + FX_LJMP(12); +} + +static void fx_ljmp_r13 (void) +{ + FX_LJMP(13); +} + +// 9e - lob - set upper byte to zero (keep low byte) +static void fx_lob (void) +{ + uint32 v = USEX8(SREG); + R15++; + DREG = v; + GSU.vSign = v << 8; + GSU.vZero = v << 8; + TESTR14; + CLRFLAGS; +} + +// 9f - fmult - 16 bit to 32 bit signed multiplication, upper 16 bits only +static void fx_fmult (void) +{ + uint32 v; + uint32 c = (uint32) (SEX16(SREG) * SEX16(R6)); + v = c >> 16; + R15++; + DREG = v; + GSU.vSign = v; + GSU.vZero = v; + GSU.vCarry = (c >> 15) & 1; + TESTR14; + CLRFLAGS; +} + +// 9f (ALT1) - lmult - 16 bit to 32 bit signed multiplication +static void fx_lmult (void) +{ + uint32 v; + uint32 c = (uint32) (SEX16(SREG) * SEX16(R6)); + R4 = c; + v = c >> 16; + R15++; + DREG = v; + GSU.vSign = v; + GSU.vZero = v; + // XXX: R6 or R4? + GSU.vCarry = (R4 >> 15) & 1; // should it be bit 15 of R4 instead ? + TESTR14; + CLRFLAGS; +} + +// a0-af - ibt rn, #pp - immediate byte transfer +#define FX_IBT(reg) \ + uint8 v = PIPE; \ + R15++; \ + FETCHPIPE; \ + R15++; \ + GSU.avReg[reg] = SEX8(v); \ + CLRFLAGS + +static void fx_ibt_r0 (void) +{ + FX_IBT(0); +} + +static void fx_ibt_r1 (void) +{ + FX_IBT(1); +} + +static void fx_ibt_r2 (void) +{ + FX_IBT(2); +} + +static void fx_ibt_r3 (void) +{ + FX_IBT(3); +} + +static void fx_ibt_r4 (void) +{ + FX_IBT(4); +} + +static void fx_ibt_r5 (void) +{ + FX_IBT(5); +} + +static void fx_ibt_r6 (void) +{ + FX_IBT(6); +} + +static void fx_ibt_r7 (void) +{ + FX_IBT(7); +} + +static void fx_ibt_r8 (void) +{ + FX_IBT(8); +} + +static void fx_ibt_r9 (void) +{ + FX_IBT(9); +} + +static void fx_ibt_r10 (void) +{ + FX_IBT(10); +} + +static void fx_ibt_r11 (void) +{ + FX_IBT(11); +} + +static void fx_ibt_r12 (void) +{ + FX_IBT(12); +} + +static void fx_ibt_r13 (void) +{ + FX_IBT(13); +} + +static void fx_ibt_r14 (void) +{ + FX_IBT(14); + READR14; +} + +static void fx_ibt_r15 (void) +{ + FX_IBT(15); +} + +// a0-af (ALT1) - lms rn, (yy) - load word from RAM (short address) +#define FX_LMS(reg) \ + GSU.vLastRamAdr = ((uint32) PIPE) << 1; \ + R15++; \ + FETCHPIPE; \ + R15++; \ + GSU.avReg[reg] = (uint32) RAM(GSU.vLastRamAdr); \ + GSU.avReg[reg] |= ((uint32) RAM(GSU.vLastRamAdr + 1)) << 8; \ + CLRFLAGS + +static void fx_lms_r0 (void) +{ + FX_LMS(0); +} + +static void fx_lms_r1 (void) +{ + FX_LMS(1); +} + +static void fx_lms_r2 (void) +{ + FX_LMS(2); +} + +static void fx_lms_r3 (void) +{ + FX_LMS(3); +} + +static void fx_lms_r4 (void) +{ + FX_LMS(4); +} + +static void fx_lms_r5 (void) +{ + FX_LMS(5); +} + +static void fx_lms_r6 (void) +{ + FX_LMS(6); +} + +static void fx_lms_r7 (void) +{ + FX_LMS(7); +} + +static void fx_lms_r8 (void) +{ + FX_LMS(8); +} + +static void fx_lms_r9 (void) +{ + FX_LMS(9); +} + +static void fx_lms_r10 (void) +{ + FX_LMS(10); +} + +static void fx_lms_r11 (void) +{ + FX_LMS(11); +} + +static void fx_lms_r12 (void) +{ + FX_LMS(12); +} + +static void fx_lms_r13 (void) +{ + FX_LMS(13); +} + +static void fx_lms_r14 (void) +{ + FX_LMS(14); + READR14; +} + +static void fx_lms_r15 (void) +{ + FX_LMS(15); +} + +// a0-af (ALT2) - sms (yy), rn - store word in RAM (short address) +// XXX: If rn == r15, is the value of r15 before or after the extra byte is read ? +#define FX_SMS(reg) \ + uint32 v = GSU.avReg[reg]; \ + GSU.vLastRamAdr = ((uint32) PIPE) << 1; \ + R15++; \ + FETCHPIPE; \ + RAM(GSU.vLastRamAdr) = (uint8) v; \ + RAM(GSU.vLastRamAdr + 1) = (uint8) (v >> 8); \ + CLRFLAGS; \ + R15++ + +static void fx_sms_r0 (void) +{ + FX_SMS(0); +} + +static void fx_sms_r1 (void) +{ + FX_SMS(1); +} + +static void fx_sms_r2 (void) +{ + FX_SMS(2); +} + +static void fx_sms_r3 (void) +{ + FX_SMS(3); +} + +static void fx_sms_r4 (void) +{ + FX_SMS(4); +} + +static void fx_sms_r5 (void) +{ + FX_SMS(5); +} + +static void fx_sms_r6 (void) +{ + FX_SMS(6); +} + +static void fx_sms_r7 (void) +{ + FX_SMS(7); +} + +static void fx_sms_r8 (void) +{ + FX_SMS(8); +} + +static void fx_sms_r9 (void) +{ + FX_SMS(9); +} + +static void fx_sms_r10 (void) +{ + FX_SMS(10); +} + +static void fx_sms_r11 (void) +{ + FX_SMS(11); +} + +static void fx_sms_r12 (void) +{ + FX_SMS(12); +} + +static void fx_sms_r13 (void) +{ + FX_SMS(13); +} + +static void fx_sms_r14 (void) +{ + FX_SMS(14); +} + +static void fx_sms_r15 (void) +{ + FX_SMS(15); +} + +// b0-bf - from rn - set source register +// b0-bf (B) - moves rn - move register to register, and set flags, (if B flag is set) +#define FX_FROM(reg) \ + if (TF(B)) \ + { \ + uint32 v = GSU.avReg[reg]; \ + R15++; \ + DREG = v; \ + GSU.vOverflow = (v & 0x80) << 16; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS; \ + } \ + else \ + { \ + GSU.pvSreg = &GSU.avReg[reg]; \ + R15++; \ + } + +static void fx_from_r0 (void) +{ + FX_FROM(0); +} + +static void fx_from_r1 (void) +{ + FX_FROM(1); +} + +static void fx_from_r2 (void) +{ + FX_FROM(2); +} + +static void fx_from_r3 (void) +{ + FX_FROM(3); +} + +static void fx_from_r4 (void) +{ + FX_FROM(4); +} + +static void fx_from_r5 (void) +{ + FX_FROM(5); +} + +static void fx_from_r6 (void) +{ + FX_FROM(6); +} + +static void fx_from_r7 (void) +{ + FX_FROM(7); +} + +static void fx_from_r8 (void) +{ + FX_FROM(8); +} + +static void fx_from_r9 (void) +{ + FX_FROM(9); +} + +static void fx_from_r10 (void) +{ + FX_FROM(10); +} + +static void fx_from_r11 (void) +{ + FX_FROM(11); +} + +static void fx_from_r12 (void) +{ + FX_FROM(12); +} + +static void fx_from_r13 (void) +{ + FX_FROM(13); +} + +static void fx_from_r14 (void) +{ + FX_FROM(14); +} + +static void fx_from_r15 (void) +{ + FX_FROM(15); +} + +// c0 - hib - move high-byte to low-byte +static void fx_hib (void) +{ + uint32 v = USEX8(SREG >> 8); + R15++; + DREG = v; + GSU.vSign = v << 8; + GSU.vZero = v << 8; + TESTR14; + CLRFLAGS; +} + +// c1-cf - or rn +#define FX_OR(reg) \ + uint32 v = SREG | GSU.avReg[reg]; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS + +static void fx_or_r1 (void) +{ + FX_OR(1); +} + +static void fx_or_r2 (void) +{ + FX_OR(2); +} + +static void fx_or_r3 (void) +{ + FX_OR(3); +} + +static void fx_or_r4 (void) +{ + FX_OR(4); +} + +static void fx_or_r5 (void) +{ + FX_OR(5); +} + +static void fx_or_r6 (void) +{ + FX_OR(6); +} + +static void fx_or_r7 (void) +{ + FX_OR(7); +} + +static void fx_or_r8 (void) +{ + FX_OR(8); +} + +static void fx_or_r9 (void) +{ + FX_OR(9); +} + +static void fx_or_r10 (void) +{ + FX_OR(10); +} + +static void fx_or_r11 (void) +{ + FX_OR(11); +} + +static void fx_or_r12 (void) +{ + FX_OR(12); +} + +static void fx_or_r13 (void) +{ + FX_OR(13); +} + +static void fx_or_r14 (void) +{ + FX_OR(14); +} + +static void fx_or_r15 (void) +{ + FX_OR(15); +} + +// c1-cf (ALT1) - xor rn +#define FX_XOR(reg) \ + uint32 v = SREG ^ GSU.avReg[reg]; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS + +static void fx_xor_r1 (void) +{ + FX_XOR(1); +} + +static void fx_xor_r2 (void) +{ + FX_XOR(2); +} + +static void fx_xor_r3 (void) +{ + FX_XOR(3); +} + +static void fx_xor_r4 (void) +{ + FX_XOR(4); +} + +static void fx_xor_r5 (void) +{ + FX_XOR(5); +} + +static void fx_xor_r6 (void) +{ + FX_XOR(6); +} + +static void fx_xor_r7 (void) +{ + FX_XOR(7); +} + +static void fx_xor_r8 (void) +{ + FX_XOR(8); +} + +static void fx_xor_r9 (void) +{ + FX_XOR(9); +} + +static void fx_xor_r10 (void) +{ + FX_XOR(10); +} + +static void fx_xor_r11 (void) +{ + FX_XOR(11); +} + +static void fx_xor_r12 (void) +{ + FX_XOR(12); +} + +static void fx_xor_r13 (void) +{ + FX_XOR(13); +} + +static void fx_xor_r14 (void) +{ + FX_XOR(14); +} + +static void fx_xor_r15 (void) +{ + FX_XOR(15); +} + +// c1-cf (ALT2) - or #n +#define FX_OR_I(imm) \ + uint32 v = SREG | imm; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS + +static void fx_or_i1 (void) +{ + FX_OR_I(1); +} + +static void fx_or_i2 (void) +{ + FX_OR_I(2); +} + +static void fx_or_i3 (void) +{ + FX_OR_I(3); +} + +static void fx_or_i4 (void) +{ + FX_OR_I(4); +} + +static void fx_or_i5 (void) +{ + FX_OR_I(5); +} + +static void fx_or_i6 (void) +{ + FX_OR_I(6); +} + +static void fx_or_i7 (void) +{ + FX_OR_I(7); +} + +static void fx_or_i8 (void) +{ + FX_OR_I(8); +} + +static void fx_or_i9 (void) +{ + FX_OR_I(9); +} + +static void fx_or_i10 (void) +{ + FX_OR_I(10); +} + +static void fx_or_i11 (void) +{ + FX_OR_I(11); +} + +static void fx_or_i12 (void) +{ + FX_OR_I(12); +} + +static void fx_or_i13 (void) +{ + FX_OR_I(13); +} + +static void fx_or_i14 (void) +{ + FX_OR_I(14); +} + +static void fx_or_i15 (void) +{ + FX_OR_I(15); +} + +// c1-cf (ALT3) - xor #n +#define FX_XOR_I(imm) \ + uint32 v = SREG ^ imm; \ + R15++; \ + DREG = v; \ + GSU.vSign = v; \ + GSU.vZero = v; \ + TESTR14; \ + CLRFLAGS + +static void fx_xor_i1 (void) +{ + FX_XOR_I(1); +} + +static void fx_xor_i2 (void) +{ + FX_XOR_I(2); +} + +static void fx_xor_i3 (void) +{ + FX_XOR_I(3); +} + +static void fx_xor_i4 (void) +{ + FX_XOR_I(4); +} + +static void fx_xor_i5 (void) +{ + FX_XOR_I(5); +} + +static void fx_xor_i6 (void) +{ + FX_XOR_I(6); +} + +static void fx_xor_i7 (void) +{ + FX_XOR_I(7); +} + +static void fx_xor_i8 (void) +{ + FX_XOR_I(8); +} + +static void fx_xor_i9 (void) +{ + FX_XOR_I(9); +} + +static void fx_xor_i10 (void) +{ + FX_XOR_I(10); +} + +static void fx_xor_i11 (void) +{ + FX_XOR_I(11); +} + +static void fx_xor_i12 (void) +{ + FX_XOR_I(12); +} + +static void fx_xor_i13 (void) +{ + FX_XOR_I(13); +} + +static void fx_xor_i14 (void) +{ + FX_XOR_I(14); +} + +static void fx_xor_i15 (void) +{ + FX_XOR_I(15); +} + +// d0-de - inc rn - increase by one +#define FX_INC(reg) \ + GSU.avReg[reg] += 1; \ + GSU.vSign = GSU.avReg[reg]; \ + GSU.vZero = GSU.avReg[reg]; \ + CLRFLAGS; \ + R15++ + +static void fx_inc_r0 (void) +{ + FX_INC(0); +} + +static void fx_inc_r1 (void) +{ + FX_INC(1); +} + +static void fx_inc_r2 (void) +{ + FX_INC(2); +} + +static void fx_inc_r3 (void) +{ + FX_INC(3); +} + +static void fx_inc_r4 (void) +{ + FX_INC(4); +} + +static void fx_inc_r5 (void) +{ + FX_INC(5); +} + +static void fx_inc_r6 (void) +{ + FX_INC(6); +} + +static void fx_inc_r7 (void) +{ + FX_INC(7); +} + +static void fx_inc_r8 (void) +{ + FX_INC(8); +} + +static void fx_inc_r9 (void) +{ + FX_INC(9); +} + +static void fx_inc_r10 (void) +{ + FX_INC(10); +} + +static void fx_inc_r11 (void) +{ + FX_INC(11); +} + +static void fx_inc_r12 (void) +{ + FX_INC(12); +} + +static void fx_inc_r13 (void) +{ + FX_INC(13); +} + +static void fx_inc_r14 (void) +{ + FX_INC(14); + READR14; +} + +// df - getc - transfer ROM buffer to color register +static void fx_getc (void) +{ +#ifndef FX_DO_ROMBUFFER + uint8 c = ROM(R14); +#else + uint8 c = GSU.vRomBuffer; +#endif + + if (GSU.vPlotOptionReg & 0x04) + c = (c & 0xf0) | (c >> 4); + + if (GSU.vPlotOptionReg & 0x08) + { + GSU.vColorReg &= 0xf0; + GSU.vColorReg |= c & 0x0f; + } + else + GSU.vColorReg = USEX8(c); + + CLRFLAGS; + R15++; +} + +// df (ALT2) - ramb - set current RAM bank +static void fx_ramb (void) +{ + GSU.vRamBankReg = SREG & (FX_RAM_BANKS - 1); + GSU.pvRamBank = GSU.apvRamBank[GSU.vRamBankReg & 0x3]; + CLRFLAGS; + R15++; +} + +// df (ALT3) - romb - set current ROM bank +static void fx_romb (void) +{ + GSU.vRomBankReg = USEX8(SREG) & 0x7f; + GSU.pvRomBank = GSU.apvRomBank[GSU.vRomBankReg]; + CLRFLAGS; + R15++; +} + +// e0-ee - dec rn - decrement by one +#define FX_DEC(reg) \ + GSU.avReg[reg] -= 1; \ + GSU.vSign = GSU.avReg[reg]; \ + GSU.vZero = GSU.avReg[reg]; \ + CLRFLAGS; \ + R15++ + +static void fx_dec_r0 (void) +{ + FX_DEC(0); +} + +static void fx_dec_r1 (void) +{ + FX_DEC(1); +} + +static void fx_dec_r2 (void) +{ + FX_DEC(2); +} + +static void fx_dec_r3 (void) +{ + FX_DEC(3); +} + +static void fx_dec_r4 (void) +{ + FX_DEC(4); +} + +static void fx_dec_r5 (void) +{ + FX_DEC(5); +} + +static void fx_dec_r6 (void) +{ + FX_DEC(6); +} + +static void fx_dec_r7 (void) +{ + FX_DEC(7); +} + +static void fx_dec_r8 (void) +{ + FX_DEC(8); +} + +static void fx_dec_r9 (void) +{ + FX_DEC(9); +} + +static void fx_dec_r10 (void) +{ + FX_DEC(10); +} + +static void fx_dec_r11 (void) +{ + FX_DEC(11); +} + +static void fx_dec_r12 (void) +{ + FX_DEC(12); +} + +static void fx_dec_r13 (void) +{ + FX_DEC(13); +} + +static void fx_dec_r14 (void) +{ + FX_DEC(14); + READR14; +} + +// ef - getb - get byte from ROM at address R14 +static void fx_getb (void) +{ + uint32 v; +#ifndef FX_DO_ROMBUFFER + v = (uint32) ROM(R14); +#else + v = (uint32) GSU.vRomBuffer; +#endif + R15++; + DREG = v; + TESTR14; + CLRFLAGS; +} + +// ef (ALT1) - getbh - get high-byte from ROM at address R14 +static void fx_getbh (void) +{ + uint32 v; +#ifndef FX_DO_ROMBUFFER + uint32 c = (uint32) ROM(R14); +#else + uint32 c = USEX8(GSU.vRomBuffer); +#endif + v = USEX8(SREG) | (c << 8); + R15++; + DREG = v; + TESTR14; + CLRFLAGS; +} + +// ef (ALT2) - getbl - get low-byte from ROM at address R14 +static void fx_getbl (void) +{ + uint32 v; +#ifndef FX_DO_ROMBUFFER + uint32 c = (uint32) ROM(R14); +#else + uint32 c = USEX8(GSU.vRomBuffer); +#endif + v = (SREG & 0xff00) | c; + R15++; + DREG = v; + TESTR14; + CLRFLAGS; +} + +// ef (ALT3) - getbs - get sign extended byte from ROM at address R14 +static void fx_getbs (void) +{ + uint32 v; +#ifndef FX_DO_ROMBUFFER + int8 c; + c = ROM(R14); + v = SEX8(c); +#else + v = SEX8(GSU.vRomBuffer); +#endif + R15++; + DREG = v; + TESTR14; + CLRFLAGS; +} + +// f0-ff - iwt rn, #xx - immediate word transfer to register +#define FX_IWT(reg) \ + uint32 v = PIPE; \ + R15++; \ + FETCHPIPE; \ + R15++; \ + v |= USEX8(PIPE) << 8; \ + FETCHPIPE; \ + R15++; \ + GSU.avReg[reg] = v; \ + CLRFLAGS + +static void fx_iwt_r0 (void) +{ + FX_IWT(0); +} + +static void fx_iwt_r1 (void) +{ + FX_IWT(1); +} + +static void fx_iwt_r2 (void) +{ + FX_IWT(2); +} + +static void fx_iwt_r3 (void) +{ + FX_IWT(3); +} + +static void fx_iwt_r4 (void) +{ + FX_IWT(4); +} + +static void fx_iwt_r5 (void) +{ + FX_IWT(5); +} + +static void fx_iwt_r6 (void) +{ + FX_IWT(6); +} + +static void fx_iwt_r7 (void) +{ + FX_IWT(7); +} + +static void fx_iwt_r8 (void) +{ + FX_IWT(8); +} + +static void fx_iwt_r9 (void) +{ + FX_IWT(9); +} + +static void fx_iwt_r10 (void) +{ + FX_IWT(10); +} + +static void fx_iwt_r11 (void) +{ + FX_IWT(11); +} + +static void fx_iwt_r12 (void) +{ + FX_IWT(12); +} + +static void fx_iwt_r13 (void) +{ + FX_IWT(13); +} + +static void fx_iwt_r14 (void) +{ + FX_IWT(14); + READR14; +} + +static void fx_iwt_r15 (void) +{ + FX_IWT(15); +} + +// f0-ff (ALT1) - lm rn, (xx) - load word from RAM +#define FX_LM(reg) \ + GSU.vLastRamAdr = PIPE; \ + R15++; \ + FETCHPIPE; \ + R15++; \ + GSU.vLastRamAdr |= USEX8(PIPE) << 8; \ + FETCHPIPE; \ + R15++; \ + GSU.avReg[reg] = RAM(GSU.vLastRamAdr); \ + GSU.avReg[reg] |= USEX8(RAM(GSU.vLastRamAdr ^ 1)) << 8; \ + CLRFLAGS + +static void fx_lm_r0 (void) +{ + FX_LM(0); +} + +static void fx_lm_r1 (void) +{ + FX_LM(1); +} + +static void fx_lm_r2 (void) +{ + FX_LM(2); +} + +static void fx_lm_r3 (void) +{ + FX_LM(3); +} + +static void fx_lm_r4 (void) +{ + FX_LM(4); +} + +static void fx_lm_r5 (void) +{ + FX_LM(5); +} + +static void fx_lm_r6 (void) +{ + FX_LM(6); +} + +static void fx_lm_r7 (void) +{ + FX_LM(7); +} + +static void fx_lm_r8 (void) +{ + FX_LM(8); +} + +static void fx_lm_r9 (void) +{ + FX_LM(9); +} + +static void fx_lm_r10 (void) +{ + FX_LM(10); +} + +static void fx_lm_r11 (void) +{ + FX_LM(11); +} + +static void fx_lm_r12 (void) +{ + FX_LM(12); +} + +static void fx_lm_r13 (void) +{ + FX_LM(13); +} + +static void fx_lm_r14 (void) +{ + FX_LM(14); + READR14; +} + +static void fx_lm_r15 (void) +{ + FX_LM(15); +} + +// f0-ff (ALT2) - sm (xx), rn - store word in RAM +// XXX: If rn == r15, is the value of r15 before or after the extra bytes are read ? +#define FX_SM(reg) \ + uint32 v = GSU.avReg[reg]; \ + GSU.vLastRamAdr = PIPE; \ + R15++; \ + FETCHPIPE; \ + R15++; \ + GSU.vLastRamAdr |= USEX8(PIPE) << 8; \ + FETCHPIPE; \ + RAM(GSU.vLastRamAdr) = (uint8) v; \ + RAM(GSU.vLastRamAdr ^ 1) = (uint8) (v >> 8); \ + CLRFLAGS; \ + R15++ + +static void fx_sm_r0 (void) +{ + FX_SM(0); +} + +static void fx_sm_r1 (void) +{ + FX_SM(1); +} + +static void fx_sm_r2 (void) +{ + FX_SM(2); +} + +static void fx_sm_r3 (void) +{ + FX_SM(3); +} + +static void fx_sm_r4 (void) +{ + FX_SM(4); +} + +static void fx_sm_r5 (void) +{ + FX_SM(5); +} + +static void fx_sm_r6 (void) +{ + FX_SM(6); +} + +static void fx_sm_r7 (void) +{ + FX_SM(7); +} + +static void fx_sm_r8 (void) +{ + FX_SM(8); +} + +static void fx_sm_r9 (void) +{ + FX_SM(9); +} + +static void fx_sm_r10 (void) +{ + FX_SM(10); +} + +static void fx_sm_r11 (void) +{ + FX_SM(11); +} + +static void fx_sm_r12 (void) +{ + FX_SM(12); +} + +static void fx_sm_r13 (void) +{ + FX_SM(13); +} + +static void fx_sm_r14 (void) +{ + FX_SM(14); +} + +static void fx_sm_r15 (void) +{ + FX_SM(15); +} + +// GSU executions functions + +uint32 fx_run (uint32 nInstructions) +{ + GSU.vCounter = nInstructions; + READR14; + while (TF(G) && (GSU.vCounter-- > 0)) + FX_STEP; +#if 0 +#ifndef FX_ADDRESS_CHECK + GSU.vPipeAdr = USEX16(R15 - 1) | (USEX8(GSU.vPrgBankReg) << 16); +#endif +#endif + + return (nInstructions - GSU.vInstCount); +} + +/* +uint32 fx_run_to_breakpoint (uint32 nInstructions) +{ + uint32 vCounter = 0; + + while (TF(G) && vCounter < nInstructions) + { + vCounter++; + FX_STEP; + + if (USEX16(R15) == GSU.vBreakPoint) + { + GSU.vErrorCode = FX_BREAKPOINT; + break; + } + } + +#if 0 +#ifndef FX_ADDRESS_CHECK + GSU.vPipeAdr = USEX16(R15 - 1) | (USEX8(GSU.vPrgBankReg) << 16); +#endif +#endif + + return (vCounter); +} +*/ + +/* +uint32 fx_step_over (uint32 nInstructions) +{ + uint32 vCounter = 0; + + while (TF(G) && vCounter < nInstructions) + { + vCounter++; + FX_STEP; + + if (USEX16(R15) == GSU.vBreakPoint) + { + GSU.vErrorCode = FX_BREAKPOINT; + break; + } + + if (USEX16(R15) == GSU.vStepPoint) + break; + } + +#if 0 +#ifndef FX_ADDRESS_CHECK + GSU.vPipeAdr = USEX16(R15 - 1) | (USEX8(GSU.vPrgBankReg) << 16); +#endif +#endif + + return (vCounter); +} +*/ + +// Special table for the different plot configurations + +void (*fx_PlotTable[]) (void) = +{ + &fx_plot_2bit, &fx_plot_4bit, &fx_plot_4bit, &fx_plot_8bit, &fx_plot_obj, + &fx_rpix_2bit, &fx_rpix_4bit, &fx_rpix_4bit, &fx_rpix_8bit, &fx_rpix_obj +}; + +// Opcode table + +void (*fx_OpcodeTable[]) (void) = +{ + // ALT0 Table + + // 00 - 0f + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + // 10 - 1f + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + // 20 - 2f + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + // 30 - 3f + &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, + &fx_stw_r8, &fx_stw_r9, &fx_stw_r10, &fx_stw_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + // 40 - 4f + &fx_ldw_r0, &fx_ldw_r1, &fx_ldw_r2, &fx_ldw_r3, &fx_ldw_r4, &fx_ldw_r5, &fx_ldw_r6, &fx_ldw_r7, + &fx_ldw_r8, &fx_ldw_r9, &fx_ldw_r10, &fx_ldw_r11, &fx_plot_2bit, &fx_swap, &fx_color, &fx_not, + // 50 - 5f + &fx_add_r0, &fx_add_r1, &fx_add_r2, &fx_add_r3, &fx_add_r4, &fx_add_r5, &fx_add_r6, &fx_add_r7, + &fx_add_r8, &fx_add_r9, &fx_add_r10, &fx_add_r11, &fx_add_r12, &fx_add_r13, &fx_add_r14, &fx_add_r15, + // 60 - 6f + &fx_sub_r0, &fx_sub_r1, &fx_sub_r2, &fx_sub_r3, &fx_sub_r4, &fx_sub_r5, &fx_sub_r6, &fx_sub_r7, + &fx_sub_r8, &fx_sub_r9, &fx_sub_r10, &fx_sub_r11, &fx_sub_r12, &fx_sub_r13, &fx_sub_r14, &fx_sub_r15, + // 70 - 7f + &fx_merge, &fx_and_r1, &fx_and_r2, &fx_and_r3, &fx_and_r4, &fx_and_r5, &fx_and_r6, &fx_and_r7, + &fx_and_r8, &fx_and_r9, &fx_and_r10, &fx_and_r11, &fx_and_r12, &fx_and_r13, &fx_and_r14, &fx_and_r15, + // 80 - 8f + &fx_mult_r0, &fx_mult_r1, &fx_mult_r2, &fx_mult_r3, &fx_mult_r4, &fx_mult_r5, &fx_mult_r6, &fx_mult_r7, + &fx_mult_r8, &fx_mult_r9, &fx_mult_r10, &fx_mult_r11, &fx_mult_r12, &fx_mult_r13, &fx_mult_r14, &fx_mult_r15, + // 90 - 9f + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_asr, &fx_ror, + &fx_jmp_r8, &fx_jmp_r9, &fx_jmp_r10, &fx_jmp_r11, &fx_jmp_r12, &fx_jmp_r13, &fx_lob, &fx_fmult, + // a0 - af + &fx_ibt_r0, &fx_ibt_r1, &fx_ibt_r2, &fx_ibt_r3, &fx_ibt_r4, &fx_ibt_r5, &fx_ibt_r6, &fx_ibt_r7, + &fx_ibt_r8, &fx_ibt_r9, &fx_ibt_r10, &fx_ibt_r11, &fx_ibt_r12, &fx_ibt_r13, &fx_ibt_r14, &fx_ibt_r15, + // b0 - bf + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + // c0 - cf + &fx_hib, &fx_or_r1, &fx_or_r2, &fx_or_r3, &fx_or_r4, &fx_or_r5, &fx_or_r6, &fx_or_r7, + &fx_or_r8, &fx_or_r9, &fx_or_r10, &fx_or_r11, &fx_or_r12, &fx_or_r13, &fx_or_r14, &fx_or_r15, + // d0 - df + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_getc, + // e0 - ef + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getb, + // f0 - ff + &fx_iwt_r0, &fx_iwt_r1, &fx_iwt_r2, &fx_iwt_r3, &fx_iwt_r4, &fx_iwt_r5, &fx_iwt_r6, &fx_iwt_r7, + &fx_iwt_r8, &fx_iwt_r9, &fx_iwt_r10, &fx_iwt_r11, &fx_iwt_r12, &fx_iwt_r13, &fx_iwt_r14, &fx_iwt_r15, + + // ALT1 Table + + // 00 - 0f + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + // 10 - 1f + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + // 20 - 2f + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + // 30 - 3f + &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, + &fx_stb_r8, &fx_stb_r9, &fx_stb_r10, &fx_stb_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + // 40 - 4f + &fx_ldb_r0, &fx_ldb_r1, &fx_ldb_r2, &fx_ldb_r3, &fx_ldb_r4, &fx_ldb_r5, &fx_ldb_r6, &fx_ldb_r7, + &fx_ldb_r8, &fx_ldb_r9, &fx_ldb_r10, &fx_ldb_r11, &fx_rpix_2bit, &fx_swap, &fx_cmode, &fx_not, + // 50 - 5f + &fx_adc_r0, &fx_adc_r1, &fx_adc_r2, &fx_adc_r3, &fx_adc_r4, &fx_adc_r5, &fx_adc_r6, &fx_adc_r7, + &fx_adc_r8, &fx_adc_r9, &fx_adc_r10, &fx_adc_r11, &fx_adc_r12, &fx_adc_r13, &fx_adc_r14, &fx_adc_r15, + // 60 - 6f + &fx_sbc_r0, &fx_sbc_r1, &fx_sbc_r2, &fx_sbc_r3, &fx_sbc_r4, &fx_sbc_r5, &fx_sbc_r6, &fx_sbc_r7, + &fx_sbc_r8, &fx_sbc_r9, &fx_sbc_r10, &fx_sbc_r11, &fx_sbc_r12, &fx_sbc_r13, &fx_sbc_r14, &fx_sbc_r15, + // 70 - 7f + &fx_merge, &fx_bic_r1, &fx_bic_r2, &fx_bic_r3, &fx_bic_r4, &fx_bic_r5, &fx_bic_r6, &fx_bic_r7, + &fx_bic_r8, &fx_bic_r9, &fx_bic_r10, &fx_bic_r11, &fx_bic_r12, &fx_bic_r13, &fx_bic_r14, &fx_bic_r15, + // 80 - 8f + &fx_umult_r0, &fx_umult_r1, &fx_umult_r2, &fx_umult_r3, &fx_umult_r4, &fx_umult_r5, &fx_umult_r6, &fx_umult_r7, + &fx_umult_r8, &fx_umult_r9, &fx_umult_r10, &fx_umult_r11, &fx_umult_r12, &fx_umult_r13, &fx_umult_r14, &fx_umult_r15, + // 90 - 9f + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_div2, &fx_ror, + &fx_ljmp_r8, &fx_ljmp_r9, &fx_ljmp_r10, &fx_ljmp_r11, &fx_ljmp_r12, &fx_ljmp_r13, &fx_lob, &fx_lmult, + // a0 - af + &fx_lms_r0, &fx_lms_r1, &fx_lms_r2, &fx_lms_r3, &fx_lms_r4, &fx_lms_r5, &fx_lms_r6, &fx_lms_r7, + &fx_lms_r8, &fx_lms_r9, &fx_lms_r10, &fx_lms_r11, &fx_lms_r12, &fx_lms_r13, &fx_lms_r14, &fx_lms_r15, + // b0 - bf + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + // c0 - cf + &fx_hib, &fx_xor_r1, &fx_xor_r2, &fx_xor_r3, &fx_xor_r4, &fx_xor_r5, &fx_xor_r6, &fx_xor_r7, + &fx_xor_r8, &fx_xor_r9, &fx_xor_r10, &fx_xor_r11, &fx_xor_r12, &fx_xor_r13, &fx_xor_r14, &fx_xor_r15, + // d0 - df + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_getc, + // e0 - ef + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbh, + // f0 - ff + &fx_lm_r0, &fx_lm_r1, &fx_lm_r2, &fx_lm_r3, &fx_lm_r4, &fx_lm_r5, &fx_lm_r6, &fx_lm_r7, + &fx_lm_r8, &fx_lm_r9, &fx_lm_r10, &fx_lm_r11, &fx_lm_r12, &fx_lm_r13, &fx_lm_r14, &fx_lm_r15, + + // ALT2 Table + + // 00 - 0f + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + // 10 - 1f + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + // 20 - 2f + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + // 30 - 3f + &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, + &fx_stw_r8, &fx_stw_r9, &fx_stw_r10, &fx_stw_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + // 40 - 4f + &fx_ldw_r0, &fx_ldw_r1, &fx_ldw_r2, &fx_ldw_r3, &fx_ldw_r4, &fx_ldw_r5, &fx_ldw_r6, &fx_ldw_r7, + &fx_ldw_r8, &fx_ldw_r9, &fx_ldw_r10, &fx_ldw_r11, &fx_plot_2bit, &fx_swap, &fx_color, &fx_not, + // 50 - 5f + &fx_add_i0, &fx_add_i1, &fx_add_i2, &fx_add_i3, &fx_add_i4, &fx_add_i5, &fx_add_i6, &fx_add_i7, + &fx_add_i8, &fx_add_i9, &fx_add_i10, &fx_add_i11, &fx_add_i12, &fx_add_i13, &fx_add_i14, &fx_add_i15, + // 60 - 6f + &fx_sub_i0, &fx_sub_i1, &fx_sub_i2, &fx_sub_i3, &fx_sub_i4, &fx_sub_i5, &fx_sub_i6, &fx_sub_i7, + &fx_sub_i8, &fx_sub_i9, &fx_sub_i10, &fx_sub_i11, &fx_sub_i12, &fx_sub_i13, &fx_sub_i14, &fx_sub_i15, + // 70 - 7f + &fx_merge, &fx_and_i1, &fx_and_i2, &fx_and_i3, &fx_and_i4, &fx_and_i5, &fx_and_i6, &fx_and_i7, + &fx_and_i8, &fx_and_i9, &fx_and_i10, &fx_and_i11, &fx_and_i12, &fx_and_i13, &fx_and_i14, &fx_and_i15, + // 80 - 8f + &fx_mult_i0, &fx_mult_i1, &fx_mult_i2, &fx_mult_i3, &fx_mult_i4, &fx_mult_i5, &fx_mult_i6, &fx_mult_i7, + &fx_mult_i8, &fx_mult_i9, &fx_mult_i10, &fx_mult_i11, &fx_mult_i12, &fx_mult_i13, &fx_mult_i14, &fx_mult_i15, + // 90 - 9f + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_asr, &fx_ror, + &fx_jmp_r8, &fx_jmp_r9, &fx_jmp_r10, &fx_jmp_r11, &fx_jmp_r12, &fx_jmp_r13, &fx_lob, &fx_fmult, + // a0 - af + &fx_sms_r0, &fx_sms_r1, &fx_sms_r2, &fx_sms_r3, &fx_sms_r4, &fx_sms_r5, &fx_sms_r6, &fx_sms_r7, + &fx_sms_r8, &fx_sms_r9, &fx_sms_r10, &fx_sms_r11, &fx_sms_r12, &fx_sms_r13, &fx_sms_r14, &fx_sms_r15, + // b0 - bf + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + // c0 - cf + &fx_hib, &fx_or_i1, &fx_or_i2, &fx_or_i3, &fx_or_i4, &fx_or_i5, &fx_or_i6, &fx_or_i7, + &fx_or_i8, &fx_or_i9, &fx_or_i10, &fx_or_i11, &fx_or_i12, &fx_or_i13, &fx_or_i14, &fx_or_i15, + // d0 - df + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_ramb, + // e0 - ef + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbl, + // f0 - ff + &fx_sm_r0, &fx_sm_r1, &fx_sm_r2, &fx_sm_r3, &fx_sm_r4, &fx_sm_r5, &fx_sm_r6, &fx_sm_r7, + &fx_sm_r8, &fx_sm_r9, &fx_sm_r10, &fx_sm_r11, &fx_sm_r12, &fx_sm_r13, &fx_sm_r14, &fx_sm_r15, + + // ALT3 Table + + // 00 - 0f + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + // 10 - 1f + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + // 20 - 2f + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + // 30 - 3f + &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, + &fx_stb_r8, &fx_stb_r9, &fx_stb_r10, &fx_stb_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + // 40 - 4f + &fx_ldb_r0, &fx_ldb_r1, &fx_ldb_r2, &fx_ldb_r3, &fx_ldb_r4, &fx_ldb_r5, &fx_ldb_r6, &fx_ldb_r7, + &fx_ldb_r8, &fx_ldb_r9, &fx_ldb_r10, &fx_ldb_r11, &fx_rpix_2bit, &fx_swap, &fx_cmode, &fx_not, + // 50 - 5f + &fx_adc_i0, &fx_adc_i1, &fx_adc_i2, &fx_adc_i3, &fx_adc_i4, &fx_adc_i5, &fx_adc_i6, &fx_adc_i7, + &fx_adc_i8, &fx_adc_i9, &fx_adc_i10, &fx_adc_i11, &fx_adc_i12, &fx_adc_i13, &fx_adc_i14, &fx_adc_i15, + // 60 - 6f + &fx_cmp_r0, &fx_cmp_r1, &fx_cmp_r2, &fx_cmp_r3, &fx_cmp_r4, &fx_cmp_r5, &fx_cmp_r6, &fx_cmp_r7, + &fx_cmp_r8, &fx_cmp_r9, &fx_cmp_r10, &fx_cmp_r11, &fx_cmp_r12, &fx_cmp_r13, &fx_cmp_r14, &fx_cmp_r15, + // 70 - 7f + &fx_merge, &fx_bic_i1, &fx_bic_i2, &fx_bic_i3, &fx_bic_i4, &fx_bic_i5, &fx_bic_i6, &fx_bic_i7, + &fx_bic_i8, &fx_bic_i9, &fx_bic_i10, &fx_bic_i11, &fx_bic_i12, &fx_bic_i13, &fx_bic_i14, &fx_bic_i15, + // 80 - 8f + &fx_umult_i0, &fx_umult_i1, &fx_umult_i2, &fx_umult_i3, &fx_umult_i4, &fx_umult_i5, &fx_umult_i6, &fx_umult_i7, + &fx_umult_i8, &fx_umult_i9, &fx_umult_i10, &fx_umult_i11, &fx_umult_i12, &fx_umult_i13, &fx_umult_i14, &fx_umult_i15, + // 90 - 9f + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_div2, &fx_ror, + &fx_ljmp_r8, &fx_ljmp_r9, &fx_ljmp_r10, &fx_ljmp_r11, &fx_ljmp_r12, &fx_ljmp_r13, &fx_lob, &fx_lmult, + // a0 - af + &fx_lms_r0, &fx_lms_r1, &fx_lms_r2, &fx_lms_r3, &fx_lms_r4, &fx_lms_r5, &fx_lms_r6, &fx_lms_r7, + &fx_lms_r8, &fx_lms_r9, &fx_lms_r10, &fx_lms_r11, &fx_lms_r12, &fx_lms_r13, &fx_lms_r14, &fx_lms_r15, + // b0 - bf + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + // c0 - cf + &fx_hib, &fx_xor_i1, &fx_xor_i2, &fx_xor_i3, &fx_xor_i4, &fx_xor_i5, &fx_xor_i6, &fx_xor_i7, + &fx_xor_i8, &fx_xor_i9, &fx_xor_i10, &fx_xor_i11, &fx_xor_i12, &fx_xor_i13, &fx_xor_i14, &fx_xor_i15, + // d0 - df + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_romb, + // e0 - ef + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbs, + // f0 - ff + &fx_lm_r0, &fx_lm_r1, &fx_lm_r2, &fx_lm_r3, &fx_lm_r4, &fx_lm_r5, &fx_lm_r6, &fx_lm_r7, + &fx_lm_r8, &fx_lm_r9, &fx_lm_r10, &fx_lm_r11, &fx_lm_r12, &fx_lm_r13, &fx_lm_r14, &fx_lm_r15 +}; diff --git a/plugins/snes9x_gx/source/snes9x/fxinst.h b/plugins/snes9x_gx/source/snes9x/fxinst.h new file mode 100644 index 00000000..dd3736ec --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/fxinst.h @@ -0,0 +1,542 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _FXINST_H_ +#define _FXINST_H_ + +/* + * FxChip(GSU) register space specification + * (Register address space 3000-32ff) + * + * The 16 generic 16 bit registers: + * (Some have a special function in special circumstances) + * 3000 - R0 default source/destination register + * 3002 - R1 pixel plot X position register + * 3004 - R2 pixel plot Y position register + * 3006 - R3 + * 3008 - R4 lower 16 bit result of lmult + * 300a - R5 + * 300c - R6 multiplier for fmult and lmult + * 300e - R7 fixed point texel X position for merge + * 3010 - R8 fixed point texel Y position for merge + * 3012 - R9 + * 3014 - R10 + * 3016 - R11 return address set by link + * 3018 - R12 loop counter + * 301a - R13 loop point address + * 301c - R14 rom address for getb, getbh, getbl, getbs + * 301e - R15 program counter + * + * 3020-302f - unused + * + * Other internal registers + * 3030 - SFR status flag register (16bit) + * 3032 - unused + * 3033 - BRAMR Backup RAM register (8bit) + * 3034 - PBR program bank register (8bit) + * 3035 - unused + * 3036 - ROMBR rom bank register (8bit) + * 3037 - CFGR control flags register (8bit) + * 3038 - SCBR screen base register (8bit) + * 3039 - CLSR clock speed register (8bit) + * 303a - SCMR screen mode register (8bit) + * 303b - VCR version code register (8bit) (read only) + * 303c - RAMBR ram bank register (8bit) + * 303d - unused + * 303e - CBR cache base register (16bit) + * + * 3040-30ff - unused + * + * 3100-32ff - CACHERAM 512 bytes of GSU cache memory + * + * SFR status flag register bits: + * 0 - + * 1 Z Zero flag + * 2 CY Carry flag + * 3 S Sign flag + * 4 OV Overflow flag + * 5 G Go flag (set to 1 when the GSU is running) + * 6 R Set to 1 when reading ROM using R14 address + * 7 - + * 8 ALT1 Mode set-up flag for the next instruction + * 9 ALT2 Mode set-up flag for the next instruction + * 10 IL Immediate lower 8-bit flag + * 11 IH Immediate higher 8-bit flag + * 12 B Set to 1 when the WITH instruction is executed + * 13 - + * 14 - + * 15 IRQ Set to 1 when GSU caused an interrupt + * Set to 0 when read by 658c16 + * + * BRAMR = 0, BackupRAM is disabled + * BRAMR = 1, BackupRAM is enabled + * + * CFGR control flags register bits: + * 0 - + * 1 - + * 2 - + * 3 - + * 4 - + * 5 MS0 Multiplier speed, 0=standard, 1=high speed + * 6 - + * 7 IRQ Set to 1 when GSU interrupt request is masked + * + * CLSR clock speed register bits: + * 0 CLSR clock speed, 0 = 10.7Mhz, 1 = 21.4Mhz + * + * SCMR screen mode register bits: + * 0 MD0 color depth mode bit 0 + * 1 MD1 color depth mode bit 1 + * 2 HT0 screen height bit 1 + * 3 RAN RAM access control + * 4 RON ROM access control + * 5 HT1 screen height bit 2 + * 6 - + * 7 - + * + * RON = 0 SNES CPU has ROM access + * RON = 1 GSU has ROM access + * + * RAN = 0 SNES has game pak RAM access + * RAN = 1 GSU has game pak RAM access + * + * HT1 HT0 Screen height mode + * 0 0 128 pixels high + * 0 1 160 pixels high + * 1 0 192 pixels high + * 1 1 OBJ mode + * + * MD1 MD0 Color depth mode + * 0 0 4 color mode + * 0 1 16 color mode + * 1 0 not used + * 1 1 256 color mode + * + * CBR cache base register bits: + * 15-4 Specify base address for data to cache from ROM or RAM + * 3-0 Are 0 when address is read + * + * Write access to the program counter (301e) from + * the SNES-CPU will start the GSU, and it will not + * stop until it reaches a stop instruction. + * + */ + +// Number of banks in GSU RAM +#define FX_RAM_BANKS 4 + +// Emulate proper R14 ROM access (slower, but safer) +#define FX_DO_ROMBUFFER + +// Address checking (definately slow) +//#define FX_ADDRESS_CHECK + +struct FxRegs_s +{ + // FxChip registers + uint32 avReg[16]; // 16 Generic registers + uint32 vColorReg; // Internal color register + uint32 vPlotOptionReg; // Plot option register + uint32 vStatusReg; // Status register + uint32 vPrgBankReg; // Program bank index register + uint32 vRomBankReg; // Rom bank index register + uint32 vRamBankReg; // Ram bank index register + uint32 vCacheBaseReg; // Cache base address register + uint32 vCacheFlags; // Saying what parts of the cache was written to + uint32 vLastRamAdr; // Last RAM address accessed + uint32 *pvDreg; // Pointer to current destination register + uint32 *pvSreg; // Pointer to current source register + uint8 vRomBuffer; // Current byte read by R14 + uint8 vPipe; // Instructionset pipe + uint32 vPipeAdr; // The address of where the pipe was read from + + // Status register optimization stuff + uint32 vSign; // v & 0x8000 + uint32 vZero; // v == 0 + uint32 vCarry; // a value of 1 or 0 + int32 vOverflow; // (v >= 0x8000 || v < -0x8000) + + // Other emulator variables + int32 vErrorCode; + uint32 vIllegalAddress; + + uint8 bBreakPoint; + uint32 vBreakPoint; + uint32 vStepPoint; + + uint8 *pvRegisters; // 768 bytes located in the memory at address 0x3000 + uint32 nRamBanks; // Number of 64kb-banks in FxRam (Don't confuse it with SNES-Ram!!!) + uint8 *pvRam; // Pointer to FxRam + uint32 nRomBanks; // Number of 32kb-banks in Cart-ROM + uint8 *pvRom; // Pointer to Cart-ROM + + uint32 vMode; // Color depth/mode + uint32 vPrevMode; // Previous depth + uint8 *pvScreenBase; + uint8 *apvScreen[32]; // Pointer to each of the 32 screen colums + int32 x[32]; + uint32 vScreenHeight; // 128, 160, 192 or 256 (could be overriden by cmode) + uint32 vScreenRealHeight; // 128, 160, 192 or 256 + uint32 vPrevScreenHeight; + uint32 vScreenSize; + void (*pfPlot) (void); + void (*pfRpix) (void); + + uint8 *pvRamBank; // Pointer to current RAM-bank + uint8 *pvRomBank; // Pointer to current ROM-bank + uint8 *pvPrgBank; // Pointer to current program ROM-bank + + uint8 *apvRamBank[FX_RAM_BANKS]; // Ram bank table (max 256kb) + uint8 *apvRomBank[256]; // Rom bank table + + uint8 bCacheActive; + uint8 *pvCache; // Pointer to the GSU cache + uint8 avCacheBackup[512]; // Backup of ROM when the cache has replaced it + uint32 vCounter; + uint32 vInstCount; + uint32 vSCBRDirty; // If SCBR is written, our cached screen pointers need updating + + uint8 *avRegAddr; // To reference avReg in snapshot.cpp +}; + +extern struct FxRegs_s GSU; + +// GSU registers +#define GSU_R0 0x000 +#define GSU_R1 0x002 +#define GSU_R2 0x004 +#define GSU_R3 0x006 +#define GSU_R4 0x008 +#define GSU_R5 0x00a +#define GSU_R6 0x00c +#define GSU_R7 0x00e +#define GSU_R8 0x010 +#define GSU_R9 0x012 +#define GSU_R10 0x014 +#define GSU_R11 0x016 +#define GSU_R12 0x018 +#define GSU_R13 0x01a +#define GSU_R14 0x01c +#define GSU_R15 0x01e +#define GSU_SFR 0x030 +#define GSU_BRAMR 0x033 +#define GSU_PBR 0x034 +#define GSU_ROMBR 0x036 +#define GSU_CFGR 0x037 +#define GSU_SCBR 0x038 +#define GSU_CLSR 0x039 +#define GSU_SCMR 0x03a +#define GSU_VCR 0x03b +#define GSU_RAMBR 0x03c +#define GSU_CBR 0x03e +#define GSU_CACHERAM 0x100 + +// SFR flags +#define FLG_Z (1 << 1) +#define FLG_CY (1 << 2) +#define FLG_S (1 << 3) +#define FLG_OV (1 << 4) +#define FLG_G (1 << 5) +#define FLG_R (1 << 6) +#define FLG_ALT1 (1 << 8) +#define FLG_ALT2 (1 << 9) +#define FLG_IL (1 << 10) +#define FLG_IH (1 << 11) +#define FLG_B (1 << 12) +#define FLG_IRQ (1 << 15) + +// Test flag +#define TF(a) (GSU.vStatusReg & FLG_##a) +#define CF(a) (GSU.vStatusReg &= ~FLG_##a) +#define SF(a) (GSU.vStatusReg |= FLG_##a) + +// Test and set flag if condition, clear if not +#define TS(a, b) GSU.vStatusReg = ((GSU.vStatusReg & (~FLG_##a)) | ((!!(##b)) * FLG_##a)) + +// Testing ALT1 & ALT2 bits +#define ALT0 (!TF(ALT1) && !TF(ALT2)) +#define ALT1 ( TF(ALT1) && !TF(ALT2)) +#define ALT2 (!TF(ALT1) && TF(ALT2)) +#define ALT3 ( TF(ALT1) && TF(ALT2)) + +// Sign extend from 8/16 bit to 32 bit +#define SEX8(a) ((int32) ((int8) (a))) +#define SEX16(a) ((int32) ((int16) (a))) + +// Unsign extend from 8/16 bit to 32 bit +#define USEX8(a) ((uint32) ((uint8) (a))) +#define USEX16(a) ((uint32) ((uint16) (a))) +#define SUSEX16(a) ((int32) ((uint16) (a))) + +// Set/Clr Sign and Zero flag +#define TSZ(num) TS(S, ((num) & 0x8000)); TS(Z, (!USEX16(num))) + +// Clear flags +#define CLRFLAGS GSU.vStatusReg &= ~(FLG_ALT1 | FLG_ALT2 | FLG_B); GSU.pvDreg = GSU.pvSreg = &R0 + +// Read current RAM-Bank +#define RAM(adr) GSU.pvRamBank[USEX16(adr)] + +// Read current ROM-Bank +#define ROM(idx) GSU.pvRomBank[USEX16(idx)] + +// Access the current value in the pipe +#define PIPE GSU.vPipe + +// Access data in the current program bank +#define PRGBANK(idx) GSU.pvPrgBank[USEX16(idx)] + +// Update pipe from ROM +#if 0 +#define FETCHPIPE { PIPE = PRGBANK(R15); GSU.vPipeAdr = (GSU.vPrgBankReg << 16) + R15; } +#else +#define FETCHPIPE { PIPE = PRGBANK(R15); } +#endif + +// ABS +#define ABS(x) ((x) < 0 ? -(x) : (x)) + +// Access source register +#define SREG (*GSU.pvSreg) + +// Access destination register +#define DREG (*GSU.pvDreg) + +#ifndef FX_DO_ROMBUFFER + +// Don't read R14 +#define READR14 + +// Don't test and/or read R14 +#define TESTR14 + +#else + +// Read R14 +#define READR14 GSU.vRomBuffer = ROM(R14) + +// Test and/or read R14 +#define TESTR14 if (GSU.pvDreg == &R14) READR14 + +#endif + +// Access to registers +#define R0 GSU.avReg[0] +#define R1 GSU.avReg[1] +#define R2 GSU.avReg[2] +#define R3 GSU.avReg[3] +#define R4 GSU.avReg[4] +#define R5 GSU.avReg[5] +#define R6 GSU.avReg[6] +#define R7 GSU.avReg[7] +#define R8 GSU.avReg[8] +#define R9 GSU.avReg[9] +#define R10 GSU.avReg[10] +#define R11 GSU.avReg[11] +#define R12 GSU.avReg[12] +#define R13 GSU.avReg[13] +#define R14 GSU.avReg[14] +#define R15 GSU.avReg[15] +#define SFR GSU.vStatusReg +#define PBR GSU.vPrgBankReg +#define ROMBR GSU.vRomBankReg +#define RAMBR GSU.vRamBankReg +#define CBR GSU.vCacheBaseReg +#define SCBR USEX8(GSU.pvRegisters[GSU_SCBR]) +#define SCMR USEX8(GSU.pvRegisters[GSU_SCMR]) +#define COLR GSU.vColorReg +#define POR GSU.vPlotOptionReg +#define BRAMR USEX8(GSU.pvRegisters[GSU_BRAMR]) +#define VCR USEX8(GSU.pvRegisters[GSU_VCR]) +#define CFGR USEX8(GSU.pvRegisters[GSU_CFGR]) +#define CLSR USEX8(GSU.pvRegisters[GSU_CLSR]) + +// Execute instruction from the pipe, and fetch next byte to the pipe +#define FX_STEP \ +{ \ + uint32 vOpcode = (uint32) PIPE; \ + FETCHPIPE; \ + (*fx_OpcodeTable[(GSU.vStatusReg & 0x300) | vOpcode])(); \ +} + +extern void (*fx_PlotTable[]) (void); +extern void (*fx_OpcodeTable[]) (void); + +// Set this define if branches are relative to the instruction in the delay slot (I think they are) +#define BRANCH_DELAY_RELATIVE + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/getset.h b/plugins/snes9x_gx/source/snes9x/getset.h new file mode 100644 index 00000000..bf5557b4 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/getset.h @@ -0,0 +1,1089 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _GETSET_H_ +#define _GETSET_H_ + +#include "cpuexec.h" +#include "dsp.h" +#include "sa1.h" +#include "spc7110.h" +#include "c4.h" +#include "obc1.h" +#include "seta.h" +#include "bsx.h" + +#if (S9X_ACCURACY_LEVEL >= 2) + +#define addCyclesInMemoryAccess \ + if (!CPU.InDMAorHDMA) \ + { \ + CPU.Cycles += speed; \ + while (CPU.Cycles >= CPU.NextEvent) \ + S9xDoHEventProcessing(); \ + } + +#define addCyclesInMemoryAccess_x2 \ + if (!CPU.InDMAorHDMA) \ + { \ + CPU.Cycles += speed << 1; \ + while (CPU.Cycles >= CPU.NextEvent) \ + S9xDoHEventProcessing(); \ + } + +#else + +#define addCyclesInMemoryAccess \ + if (!CPU.InDMAorHDMA) \ + CPU.Cycles += speed; + +#define addCyclesInMemoryAccess_x2 \ + if (!CPU.InDMAorHDMA) \ + CPU.Cycles += speed << 1; + +#endif + +extern uint8 OpenBus; + +static inline int32 memory_speed (uint32 address) +{ + if (address & 0x408000) + { + if (address & 0x800000) + return (CPU.FastROMSpeed); + + return (SLOW_ONE_CYCLE); + } + + if ((address + 0x6000) & 0x4000) + return (SLOW_ONE_CYCLE); + + if ((address - 0x4000) & 0x7e00) + return (ONE_CYCLE); + + return (TWO_CYCLES); +} + +inline uint8 S9xGetByte (uint32 Address) +{ + int block = (Address & 0xffffff) >> MEMMAP_SHIFT; + uint8 *GetAddress = Memory.Map[block]; + int32 speed = memory_speed(Address); + uint8 byte; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { + #ifdef CPU_SHUTDOWN + if (Memory.BlockIsRAM[block]) + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; + #endif + byte = *(GetAddress + (Address & 0xffff)); + addCyclesInMemoryAccess; + return (byte); + } + + switch ((pint) GetAddress) + { + case CMemory::MAP_CPU: + byte = S9xGetCPU(Address & 0xffff); + addCyclesInMemoryAccess; + return (byte); + + case CMemory::MAP_PPU: + if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100) + return (OpenBus); + + byte = S9xGetPPU(Address & 0xffff); + addCyclesInMemoryAccess; + return (byte); + + case CMemory::MAP_LOROM_SRAM: + case CMemory::MAP_SA1RAM: + // Address & 0x7fff : offset into bank + // Address & 0xff0000 : bank + // bank >> 1 | offset : SRAM address, unbound + // unbound & SRAMMask : SRAM offset + byte = *(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)); + addCyclesInMemoryAccess; + return (byte); + + case CMemory::MAP_LOROM_SRAM_B: + byte = *(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)); + addCyclesInMemoryAccess; + return (byte); + + case CMemory::MAP_HIROM_SRAM: + case CMemory::MAP_RONLY_SRAM: + byte = *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)); + addCyclesInMemoryAccess; + return (byte); + + case CMemory::MAP_BWRAM: + byte = *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)); + addCyclesInMemoryAccess; + return (byte); + + case CMemory::MAP_DSP: + byte = S9xGetDSP(Address & 0xffff); + addCyclesInMemoryAccess; + return (byte); + + case CMemory::MAP_SPC7110_ROM: + byte = S9xGetSPC7110Byte(Address); + addCyclesInMemoryAccess; + return (byte); + + case CMemory::MAP_SPC7110_DRAM: + byte = S9xGetSPC7110(0x4800); + addCyclesInMemoryAccess; + return (byte); + + case CMemory::MAP_C4: + byte = S9xGetC4(Address & 0xffff); + addCyclesInMemoryAccess; + return (byte); + + case CMemory::MAP_OBC_RAM: + byte = S9xGetOBC1(Address & 0xffff); + addCyclesInMemoryAccess; + return (byte); + + case CMemory::MAP_SETA_DSP: + byte = S9xGetSetaDSP(Address); + addCyclesInMemoryAccess; + return (byte); + + case CMemory::MAP_SETA_RISC: + byte = S9xGetST018(Address); + addCyclesInMemoryAccess; + return (byte); + + case CMemory::MAP_BSX: + byte = S9xGetBSX(Address); + addCyclesInMemoryAccess; + return (byte); + + case CMemory::MAP_NONE: + default: + byte = OpenBus; + addCyclesInMemoryAccess; + return (byte); + } +} + +inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE) +{ + uint32 mask = MEMMAP_MASK & (w == WRAP_PAGE ? 0xff : (w == WRAP_BANK ? 0xffff : 0xffffff)); + if ((Address & mask) == mask) + { + PC_t a; + + OpenBus = S9xGetByte(Address); + + switch (w) + { + case WRAP_PAGE: + a.xPBPC = Address; + a.B.xPCl++; + return (OpenBus | (S9xGetByte(a.xPBPC) << 8)); + + case WRAP_BANK: + a.xPBPC = Address; + a.W.xPC++; + return (OpenBus | (S9xGetByte(a.xPBPC) << 8)); + + case WRAP_NONE: + default: + return (OpenBus | (S9xGetByte(Address + 1) << 8)); + } + } + + int block = (Address & 0xffffff) >> MEMMAP_SHIFT; + uint8 *GetAddress = Memory.Map[block]; + int32 speed = memory_speed(Address); + uint16 word; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { + #ifdef CPU_SHUTDOWN + if (Memory.BlockIsRAM[block]) + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; + #endif + word = READ_WORD(GetAddress + (Address & 0xffff)); + addCyclesInMemoryAccess_x2; + return (word); + } + + switch ((pint) GetAddress) + { + case CMemory::MAP_CPU: + word = S9xGetCPU(Address & 0xffff); + addCyclesInMemoryAccess; + word |= S9xGetCPU((Address + 1) & 0xffff) << 8; + addCyclesInMemoryAccess; + return (word); + + case CMemory::MAP_PPU: + if (CPU.InDMAorHDMA) + { + OpenBus = S9xGetByte(Address); + return (OpenBus | (S9xGetByte(Address + 1) << 8)); + } + + word = S9xGetPPU(Address & 0xffff); + addCyclesInMemoryAccess; + word |= S9xGetPPU((Address + 1) & 0xffff) << 8; + addCyclesInMemoryAccess; + return (word); + + case CMemory::MAP_LOROM_SRAM: + case CMemory::MAP_SA1RAM: + if (Memory.SRAMMask >= MEMMAP_MASK) + word = READ_WORD(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)); + else + word = (*(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask))) | + ((*(Memory.SRAM + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Memory.SRAMMask))) << 8); + addCyclesInMemoryAccess_x2; + return (word); + + case CMemory::MAP_LOROM_SRAM_B: + if (Multi.sramMaskB >= MEMMAP_MASK) + word = READ_WORD(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)); + else + word = (*(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB))) | + ((*(Multi.sramB + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Multi.sramMaskB))) << 8); + addCyclesInMemoryAccess_x2; + return (word); + + case CMemory::MAP_HIROM_SRAM: + case CMemory::MAP_RONLY_SRAM: + if (Memory.SRAMMask >= MEMMAP_MASK) + word = READ_WORD(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)); + else + word = (*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) | + (*(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) << 8)); + addCyclesInMemoryAccess_x2; + return (word); + + case CMemory::MAP_BWRAM: + word = READ_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)); + addCyclesInMemoryAccess_x2; + return (word); + + case CMemory::MAP_DSP: + word = S9xGetDSP(Address & 0xffff); + addCyclesInMemoryAccess; + word |= S9xGetDSP((Address + 1) & 0xffff) << 8; + addCyclesInMemoryAccess; + return (word); + + case CMemory::MAP_SPC7110_ROM: + word = S9xGetSPC7110Byte(Address); + addCyclesInMemoryAccess; + word |= S9xGetSPC7110Byte(Address + 1) << 8; + addCyclesInMemoryAccess; + return (word); + + case CMemory::MAP_SPC7110_DRAM: + word = S9xGetSPC7110(0x4800); + addCyclesInMemoryAccess; + word |= S9xGetSPC7110(0x4800) << 8; + addCyclesInMemoryAccess; + return (word); + + case CMemory::MAP_C4: + word = S9xGetC4(Address & 0xffff); + addCyclesInMemoryAccess; + word |= S9xGetC4((Address + 1) & 0xffff) << 8; + addCyclesInMemoryAccess; + return (word); + + case CMemory::MAP_OBC_RAM: + word = S9xGetOBC1(Address & 0xffff); + addCyclesInMemoryAccess; + word |= S9xGetOBC1((Address + 1) & 0xffff) << 8; + addCyclesInMemoryAccess; + return (word); + + case CMemory::MAP_SETA_DSP: + word = S9xGetSetaDSP(Address); + addCyclesInMemoryAccess; + word |= S9xGetSetaDSP(Address + 1) << 8; + addCyclesInMemoryAccess; + return (word); + + case CMemory::MAP_SETA_RISC: + word = S9xGetST018(Address); + addCyclesInMemoryAccess; + word |= S9xGetST018(Address + 1) << 8; + addCyclesInMemoryAccess; + return (word); + + case CMemory::MAP_BSX: + word = S9xGetBSX(Address); + addCyclesInMemoryAccess; + word |= S9xGetBSX(Address + 1) << 8; + addCyclesInMemoryAccess; + return (word); + + case CMemory::MAP_NONE: + default: + word = OpenBus | (OpenBus << 8); + addCyclesInMemoryAccess_x2; + return (word); + } +} + +inline void S9xSetByte (uint8 Byte, uint32 Address) +{ +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + int block = (Address & 0xffffff) >> MEMMAP_SHIFT; + uint8 *SetAddress = Memory.WriteMap[block]; + int32 speed = memory_speed(Address); + + if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + { + #ifdef CPU_SHUTDOWN + SetAddress += (Address & 0xffff); + *SetAddress = Byte; + addCyclesInMemoryAccess; + + if (Settings.SA1) + { + if (SetAddress == SA1.WaitByteAddress1 || SetAddress == SA1.WaitByteAddress2) + { + SA1.Executing = SA1.S9xOpcodes != NULL; + SA1.WaitCounter = 0; + } + } + #else + *(SetAddress + (Address & 0xffff)) = Byte; + addCyclesInMemoryAccess; + #endif + return; + } + + switch ((pint) SetAddress) + { + case CMemory::MAP_CPU: + S9xSetCPU(Byte, Address & 0xffff); + addCyclesInMemoryAccess; + return; + + case CMemory::MAP_PPU: + if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100) + return; + + S9xSetPPU(Byte, Address & 0xffff); + addCyclesInMemoryAccess; + return; + + case CMemory::MAP_LOROM_SRAM: + if (Memory.SRAMMask) + { + *(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)) = Byte; + CPU.SRAMModified = TRUE; + } + + addCyclesInMemoryAccess; + return; + + case CMemory::MAP_LOROM_SRAM_B: + if (Multi.sramMaskB) + { + *(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)) = Byte; + CPU.SRAMModified = TRUE; + } + + addCyclesInMemoryAccess; + return; + + case CMemory::MAP_HIROM_SRAM: + if (Memory.SRAMMask) + { + *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) = Byte; + CPU.SRAMModified = TRUE; + } + + addCyclesInMemoryAccess; + return; + + case CMemory::MAP_BWRAM: + *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) = Byte; + CPU.SRAMModified = TRUE; + addCyclesInMemoryAccess; + return; + + case CMemory::MAP_SA1RAM: + *(Memory.SRAM + (Address & 0xffff)) = Byte; + SA1.Executing = !SA1.Waiting; + addCyclesInMemoryAccess; + return; + + case CMemory::MAP_DSP: + S9xSetDSP(Byte, Address & 0xffff); + addCyclesInMemoryAccess; + return; + + case CMemory::MAP_C4: + S9xSetC4(Byte, Address & 0xffff); + addCyclesInMemoryAccess; + return; + + case CMemory::MAP_OBC_RAM: + S9xSetOBC1(Byte, Address & 0xffff); + addCyclesInMemoryAccess; + return; + + case CMemory::MAP_SETA_DSP: + S9xSetSetaDSP(Byte, Address); + addCyclesInMemoryAccess; + return; + + case CMemory::MAP_SETA_RISC: + S9xSetST018(Byte, Address); + addCyclesInMemoryAccess; + return; + + case CMemory::MAP_BSX: + S9xSetBSX(Byte, Address); + addCyclesInMemoryAccess; + return; + + case CMemory::MAP_NONE: + default: + addCyclesInMemoryAccess; + return; + } +} + +inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NONE, enum s9xwriteorder_t o = WRITE_01) +{ + uint32 mask = MEMMAP_MASK & (w == WRAP_PAGE ? 0xff : (w == WRAP_BANK ? 0xffff : 0xffffff)); + if ((Address & mask) == mask) + { + PC_t a; + + if (!o) + S9xSetByte((uint8) Word, Address); + + switch (w) + { + case WRAP_PAGE: + a.xPBPC = Address; + a.B.xPCl++; + S9xSetByte(Word >> 8, a.xPBPC); + break; + + case WRAP_BANK: + a.xPBPC = Address; + a.W.xPC++; + S9xSetByte(Word >> 8, a.xPBPC); + break; + + case WRAP_NONE: + default: + S9xSetByte(Word >> 8, Address + 1); + break; + } + + if (o) + S9xSetByte((uint8) Word, Address); + + return; + } + +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + int block = (Address & 0xffffff) >> MEMMAP_SHIFT; + uint8 *SetAddress = Memory.WriteMap[block]; + int32 speed = memory_speed(Address); + + if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + { + #ifdef CPU_SHUTDOWN + SetAddress += (Address & 0xffff); + WRITE_WORD(SetAddress, Word); + addCyclesInMemoryAccess_x2; + + if (Settings.SA1) + { + if (SetAddress == SA1.WaitByteAddress1 || SetAddress == SA1.WaitByteAddress2) + { + SA1.Executing = SA1.S9xOpcodes != NULL; + SA1.WaitCounter = 0; + } + } + #else + WRITE_WORD(SetAddress + (Address & 0xffff), Word); + addCyclesInMemoryAccess_x2; + #endif + return; + } + + switch ((pint) SetAddress) + { + case CMemory::MAP_CPU: + if (o) + { + S9xSetCPU(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; + S9xSetCPU((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; + return; + } + else + { + S9xSetCPU((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; + S9xSetCPU(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; + return; + } + + case CMemory::MAP_PPU: + if (CPU.InDMAorHDMA) + { + if ((Address & 0xff00) != 0x2100) + S9xSetPPU((uint8) Word, Address & 0xffff); + if (((Address + 1) & 0xff00) != 0x2100) + S9xSetPPU(Word >> 8, (Address + 1) & 0xffff); + return; + } + + if (o) + { + S9xSetPPU(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; + S9xSetPPU((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; + return; + } + else + { + S9xSetPPU((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; + S9xSetPPU(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; + return; + } + + case CMemory::MAP_LOROM_SRAM: + if (Memory.SRAMMask) + { + if (Memory.SRAMMask >= MEMMAP_MASK) + WRITE_WORD(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask), Word); + else + { + *(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)) = (uint8) Word; + *(Memory.SRAM + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Memory.SRAMMask)) = Word >> 8; + } + + CPU.SRAMModified = TRUE; + } + + addCyclesInMemoryAccess_x2; + return; + + case CMemory::MAP_LOROM_SRAM_B: + if (Multi.sramMaskB) + { + if (Multi.sramMaskB >= MEMMAP_MASK) + WRITE_WORD(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB), Word); + else + { + *(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)) = (uint8) Word; + *(Multi.sramB + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Multi.sramMaskB)) = Word >> 8; + } + + CPU.SRAMModified = TRUE; + } + + addCyclesInMemoryAccess_x2; + return; + + case CMemory::MAP_HIROM_SRAM: + if (Memory.SRAMMask) + { + if (Memory.SRAMMask >= MEMMAP_MASK) + WRITE_WORD(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask), Word); + else + { + *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) = (uint8) Word; + *(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) = Word >> 8; + } + + CPU.SRAMModified = TRUE; + } + + addCyclesInMemoryAccess_x2; + return; + + case CMemory::MAP_BWRAM: + WRITE_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000), Word); + CPU.SRAMModified = TRUE; + addCyclesInMemoryAccess_x2; + return; + + case CMemory::MAP_SA1RAM: + WRITE_WORD(Memory.SRAM + (Address & 0xffff), Word); + SA1.Executing = !SA1.Waiting; + addCyclesInMemoryAccess_x2; + return; + + case CMemory::MAP_DSP: + if (o) + { + S9xSetDSP(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; + S9xSetDSP((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; + return; + } + else + { + S9xSetDSP((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; + S9xSetDSP(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; + return; + } + + case CMemory::MAP_C4: + if (o) + { + S9xSetC4(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; + S9xSetC4((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; + return; + } + else + { + S9xSetC4((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; + S9xSetC4(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; + return; + } + + case CMemory::MAP_OBC_RAM: + if (o) + { + S9xSetOBC1(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; + S9xSetOBC1((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; + return; + } + else + { + S9xSetOBC1((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; + S9xSetOBC1(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; + return; + } + + case CMemory::MAP_SETA_DSP: + if (o) + { + S9xSetSetaDSP(Word >> 8, Address + 1); + addCyclesInMemoryAccess; + S9xSetSetaDSP((uint8) Word, Address); + addCyclesInMemoryAccess; + return; + } + else + { + S9xSetSetaDSP((uint8) Word, Address); + addCyclesInMemoryAccess; + S9xSetSetaDSP(Word >> 8, Address + 1); + addCyclesInMemoryAccess; + return; + } + + case CMemory::MAP_SETA_RISC: + if (o) + { + S9xSetST018(Word >> 8, Address + 1); + addCyclesInMemoryAccess; + S9xSetST018((uint8) Word, Address); + addCyclesInMemoryAccess; + return; + } + else + { + S9xSetST018((uint8) Word, Address); + addCyclesInMemoryAccess; + S9xSetST018(Word >> 8, Address + 1); + addCyclesInMemoryAccess; + return; + } + + case CMemory::MAP_BSX: + if (o) + { + S9xSetBSX(Word >> 8, Address + 1); + addCyclesInMemoryAccess; + S9xSetBSX((uint8) Word, Address); + addCyclesInMemoryAccess; + return; + } + else + { + S9xSetBSX((uint8) Word, Address); + addCyclesInMemoryAccess; + S9xSetBSX(Word >> 8, Address + 1); + addCyclesInMemoryAccess; + return; + } + + case CMemory::MAP_NONE: + default: + addCyclesInMemoryAccess_x2; + return; + } +} + +inline void S9xSetPCBase (uint32 Address) +{ + Registers.PBPC = Address & 0xffffff; + ICPU.ShiftedPB = Address & 0xff0000; + + int block; + uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; + + CPU.MemSpeed = memory_speed(Address); + CPU.MemSpeedx2 = CPU.MemSpeed << 1; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { + CPU.PCBase = GetAddress; + return; + } + + switch ((pint) GetAddress) + { + case CMemory::MAP_LOROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + CPU.PCBase = NULL; + else + CPU.PCBase = Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask) - (Address & 0xffff); + return; + + case CMemory::MAP_LOROM_SRAM_B: + if ((Multi.sramMaskB & MEMMAP_MASK) != MEMMAP_MASK) + CPU.PCBase = NULL; + else + CPU.PCBase = Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB) - (Address & 0xffff); + return; + + case CMemory::MAP_HIROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + CPU.PCBase = NULL; + else + CPU.PCBase = Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address & 0xffff); + return; + + case CMemory::MAP_BWRAM: + CPU.PCBase = Memory.BWRAM - 0x6000 - (Address & 0x8000); + return; + + case CMemory::MAP_SA1RAM: + CPU.PCBase = Memory.SRAM; + return; + + case CMemory::MAP_SPC7110_ROM: + CPU.PCBase = S9xGetBasePointerSPC7110(Address); + return; + + case CMemory::MAP_C4: + CPU.PCBase = S9xGetBasePointerC4(Address & 0xffff); + return; + + case CMemory::MAP_OBC_RAM: + CPU.PCBase = S9xGetBasePointerOBC1(Address & 0xffff); + return; + + case CMemory::MAP_BSX: + CPU.PCBase = S9xGetBasePointerBSX(Address); + return; + + case CMemory::MAP_NONE: + default: + CPU.PCBase = NULL; + return; + } +} + +inline uint8 * S9xGetBasePointer (uint32 Address) +{ + uint8 *GetAddress = Memory.Map[(Address & 0xffffff) >> MEMMAP_SHIFT]; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + return (GetAddress); + + switch ((pint) GetAddress) + { + case CMemory::MAP_LOROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + return (NULL); + return (Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask) - (Address & 0xffff)); + + case CMemory::MAP_LOROM_SRAM_B: + if ((Multi.sramMaskB & MEMMAP_MASK) != MEMMAP_MASK) + return (NULL); + return (Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB) - (Address & 0xffff)); + + case CMemory::MAP_HIROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + return (NULL); + return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address & 0xffff)); + + case CMemory::MAP_BWRAM: + return (Memory.BWRAM - 0x6000 - (Address & 0x8000)); + + case CMemory::MAP_SA1RAM: + return (Memory.SRAM); + + case CMemory::MAP_SPC7110_ROM: + return (S9xGetBasePointerSPC7110(Address)); + + case CMemory::MAP_C4: + return (S9xGetBasePointerC4(Address & 0xffff)); + + case CMemory::MAP_OBC_RAM: + return (S9xGetBasePointerOBC1(Address & 0xffff)); + + case CMemory::MAP_NONE: + default: + return (NULL); + } +} + +inline uint8 * S9xGetMemPointer (uint32 Address) +{ + uint8 *GetAddress = Memory.Map[(Address & 0xffffff) >> MEMMAP_SHIFT]; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + return (GetAddress + (Address & 0xffff)); + + switch ((pint) GetAddress) + { + case CMemory::MAP_LOROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + return (NULL); + return (Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)); + + case CMemory::MAP_LOROM_SRAM_B: + if ((Multi.sramMaskB & MEMMAP_MASK) != MEMMAP_MASK) + return (NULL); + return (Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)); + + case CMemory::MAP_HIROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + return (NULL); + return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)); + + case CMemory::MAP_BWRAM: + return (Memory.BWRAM - 0x6000 + (Address & 0x7fff)); + + case CMemory::MAP_SA1RAM: + return (Memory.SRAM + (Address & 0xffff)); + + case CMemory::MAP_SPC7110_ROM: + return (S9xGetBasePointerSPC7110(Address) + (Address & 0xffff)); + + case CMemory::MAP_C4: + return (S9xGetMemPointerC4(Address & 0xffff)); + + case CMemory::MAP_OBC_RAM: + return (S9xGetMemPointerOBC1(Address & 0xffff)); + + case CMemory::MAP_NONE: + default: + return (NULL); + } +} + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/gfx.cpp b/plugins/snes9x_gx/source/snes9x/gfx.cpp new file mode 100644 index 00000000..579aa526 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/gfx.cpp @@ -0,0 +1,2413 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "ppu.h" +#include "tile.h" +#include "controls.h" +#include "crosshairs.h" +#include "cheats.h" +#include "movie.h" +#include "screenshot.h" +#include "font.h" +#include "display.h" + +extern struct SCheatData Cheat; +extern struct SLineData LineData[240]; +extern struct SLineMatrixData LineMatrixData[240]; + +void S9xComputeClipWindows (void); + +static int font_width = 8, font_height = 9; + +static void SetupOBJ (void); +static void DrawOBJS (int); +static void DisplayFrameRate (void); +static void DisplayPressedKeys (void); +static void DisplayWatchedAddresses (void); +static void DisplayStringFromBottom (const char *, int, int, bool); +static void DrawBackground (int, uint8, uint8); +static void DrawBackgroundMosaic (int, uint8, uint8); +static void DrawBackgroundOffset (int, uint8, uint8, int); +static void DrawBackgroundOffsetMosaic (int, uint8, uint8, int); +static inline void DrawBackgroundMode7 (int, void (*DrawMath) (uint32, uint32, int), void (*DrawNomath) (uint32, uint32, int), int); +static inline void DrawBackdrop (void); +static inline void RenderScreen (bool8); +static uint16 get_crosshair_color (uint8); + +#define TILE_PLUS(t, x) (((t) & 0xfc00) | ((t + x) & 0x3ff)) + + +bool8 S9xGraphicsInit (void) +{ + S9xInitTileRenderer(); + ZeroMemory(BlackColourMap, 256 * sizeof(uint16)); + +#ifdef GFX_MULTI_FORMAT + if (GFX.BuildPixel == NULL) + S9xSetRenderPixelFormat(RGB565); +#endif + + GFX.DoInterlace = 0; + GFX.InterlaceFrame = 0; + GFX.RealPPL = GFX.Pitch >> 1; + IPPU.OBJChanged = TRUE; + IPPU.DirectColourMapsNeedRebuild = TRUE; + Settings.BG_Forced = 0; + S9xFixColourBrightness(); + + GFX.X2 = (uint16 *) malloc(sizeof(uint16) * 0x10000); + GFX.ZERO = (uint16 *) malloc(sizeof(uint16) * 0x10000); + + GFX.ScreenSize = GFX.Pitch / 2 * SNES_HEIGHT_EXTENDED * (Settings.SupportHiRes ? 2 : 1); + GFX.SubScreen = (uint16 *) malloc(GFX.ScreenSize * sizeof(uint16)); + GFX.ZBuffer = (uint8 *) malloc(GFX.ScreenSize); + GFX.SubZBuffer = (uint8 *) malloc(GFX.ScreenSize); + + if (!GFX.X2 || !GFX.ZERO || !GFX.SubScreen || !GFX.ZBuffer || !GFX.SubZBuffer) + { + S9xGraphicsDeinit(); + return (FALSE); + } + + // Lookup table for color addition + ZeroMemory(GFX.X2, 0x10000 * sizeof(uint16)); + for (uint32 r = 0; r <= MAX_RED; r++) + { + uint32 r2 = r << 1; + if (r2 > MAX_RED) + r2 = MAX_RED; + + for (uint32 g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g << 1; + if (g2 > MAX_GREEN) + g2 = MAX_GREEN; + + for (uint32 b = 0; b <= MAX_BLUE; b++) + { + uint32 b2 = b << 1; + if (b2 > MAX_BLUE) + b2 = MAX_BLUE; + + GFX.X2[BUILD_PIXEL2(r, g, b)] = BUILD_PIXEL2(r2, g2, b2); + GFX.X2[BUILD_PIXEL2(r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2(r2, g2, b2); + } + } + } + + // Lookup table for 1/2 color subtraction + ZeroMemory(GFX.ZERO, 0x10000 * sizeof(uint16)); + for (uint32 r = 0; r <= MAX_RED; r++) + { + uint32 r2 = r; + if (r2 & 0x10) + r2 &= ~0x10; + else + r2 = 0; + + for (uint32 g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g; + if (g2 & GREEN_HI_BIT) + g2 &= ~GREEN_HI_BIT; + else + g2 = 0; + + for (uint32 b = 0; b <= MAX_BLUE; b++) + { + uint32 b2 = b; + if (b2 & 0x10) + b2 &= ~0x10; + else + b2 = 0; + + GFX.ZERO[BUILD_PIXEL2(r, g, b)] = BUILD_PIXEL2(r2, g2, b2); + GFX.ZERO[BUILD_PIXEL2(r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2(r2, g2, b2); + } + } + } + + return (TRUE); +} + +void S9xGraphicsDeinit (void) +{ + if (GFX.X2) { free(GFX.X2); GFX.X2 = NULL; } + if (GFX.ZERO) { free(GFX.ZERO); GFX.ZERO = NULL; } + if (GFX.SubScreen) { free(GFX.SubScreen); GFX.SubScreen = NULL; } + if (GFX.ZBuffer) { free(GFX.ZBuffer); GFX.ZBuffer = NULL; } + if (GFX.SubZBuffer) { free(GFX.SubZBuffer); GFX.SubZBuffer = NULL; } +} + +void S9xBuildDirectColourMaps (void) +{ + IPPU.XB = mul_brightness[PPU.Brightness]; + + for (uint32 p = 0; p < 8; p++) + for (uint32 c = 0; c < 256; c++) + DirectColourMaps[p][c] = BUILD_PIXEL(IPPU.XB[((c & 7) << 2) | ((p & 1) << 1)], IPPU.XB[((c & 0x38) >> 1) | (p & 2)], IPPU.XB[((c & 0xc0) >> 3) | (p & 4)]); + + IPPU.DirectColourMapsNeedRebuild = FALSE; +} + +void S9xStartScreenRefresh (void) +{ + if (IPPU.RenderThisFrame) + { + GFX.InterlaceFrame = !GFX.InterlaceFrame; + if (!GFX.DoInterlace || !GFX.InterlaceFrame) + { + if (!S9xInitUpdate()) + { + IPPU.RenderThisFrame = FALSE; + return; + } + + if (GFX.DoInterlace) + GFX.DoInterlace--; + + IPPU.MaxBrightness = PPU.Brightness; + + IPPU.Interlace = Memory.FillRAM[0x2133] & 1; + IPPU.InterlaceOBJ = Memory.FillRAM[0x2133] & 2; + IPPU.PseudoHires = Memory.FillRAM[0x2133] & 8; + + if (Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires)) + { + GFX.RealPPL = GFX.Pitch >> 1; + IPPU.DoubleWidthPixels = TRUE; + IPPU.RenderedScreenWidth = SNES_WIDTH << 1; + } + else + { + #ifdef USE_OPENGL + if (Settings.OpenGLEnable) + GFX.RealPPL = SNES_WIDTH; + else + #endif + GFX.RealPPL = GFX.Pitch >> 1; + IPPU.DoubleWidthPixels = FALSE; + IPPU.RenderedScreenWidth = SNES_WIDTH; + } + + if (Settings.SupportHiRes && IPPU.Interlace) + { + GFX.PPL = GFX.RealPPL << 1; + IPPU.DoubleHeightPixels = TRUE; + IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; + GFX.DoInterlace++; + } + else + { + GFX.PPL = GFX.RealPPL; + IPPU.DoubleHeightPixels = FALSE; + IPPU.RenderedScreenHeight = PPU.ScreenHeight; + } + + IPPU.RenderedFramesCount++; + } + + PPU.MosaicStart = 0; + PPU.RecomputeClipWindows = TRUE; + IPPU.PreviousLine = IPPU.CurrentLine = 0; + + ZeroMemory(GFX.ZBuffer, GFX.ScreenSize); + ZeroMemory(GFX.SubZBuffer, GFX.ScreenSize); + } + + if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0) + { + IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount; + IPPU.RenderedFramesCount = 0; + IPPU.FrameCount = 0; + } + + if (GFX.InfoStringTimeout > 0 && --GFX.InfoStringTimeout == 0) + GFX.InfoString = NULL; + + IPPU.TotalEmulatedFrames++; +} + +void S9xEndScreenRefresh (void) +{ + if (IPPU.RenderThisFrame) + { + FLUSH_REDRAW(); + + if (GFX.DoInterlace && GFX.InterlaceFrame == 0) + { + S9xControlEOF(); + S9xContinueUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); + } + else + { + if (IPPU.ColorsChanged) + { + uint32 saved = PPU.CGDATA[0]; + IPPU.ColorsChanged = FALSE; + S9xSetPalette(); + PPU.CGDATA[0] = saved; + } + + S9xControlEOF(); + + if (Settings.TakeScreenshot) + S9xDoScreenshot(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); + + if (Settings.AutoDisplayMessages) + S9xDisplayMessages(GFX.Screen, GFX.RealPPL, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, 1); + + S9xDeinitUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); + } + } + else + S9xControlEOF(); + + S9xApplyCheats(); + +#ifdef DEBUGGER + if (CPU.Flags & FRAME_ADVANCE_FLAG) + { + if (ICPU.FrameAdvanceCount) + { + ICPU.FrameAdvanceCount--; + IPPU.RenderThisFrame = TRUE; + IPPU.FrameSkip = 0; + } + else + { + CPU.Flags &= ~FRAME_ADVANCE_FLAG; + CPU.Flags |= DEBUG_MODE_FLAG; + } + } +#endif + + if (CPU.SRAMModified) + { + if (!CPU.AutoSaveTimer) + { + if (!(CPU.AutoSaveTimer = Settings.AutoSaveDelay * Memory.ROMFramesPerSecond)) + CPU.SRAMModified = FALSE; + } + else + { + if (!--CPU.AutoSaveTimer) + { + S9xAutoSaveSRAM(); + CPU.SRAMModified = FALSE; + } + } + } +} + +void RenderLine (uint8 C) +{ + if (IPPU.RenderThisFrame) + { + LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1; + LineData[C].BG[0].HOffset = PPU.BG[0].HOffset; + LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1; + LineData[C].BG[1].HOffset = PPU.BG[1].HOffset; + + if (PPU.BGMode == 7) + { + struct SLineMatrixData *p = &LineMatrixData[C]; + p->MatrixA = PPU.MatrixA; + p->MatrixB = PPU.MatrixB; + p->MatrixC = PPU.MatrixC; + p->MatrixD = PPU.MatrixD; + p->CentreX = PPU.CentreX; + p->CentreY = PPU.CentreY; + p->M7HOFS = PPU.M7HOFS; + p->M7VOFS = PPU.M7VOFS; + } + else + { + LineData[C].BG[2].VOffset = PPU.BG[2].VOffset + 1; + LineData[C].BG[2].HOffset = PPU.BG[2].HOffset; + LineData[C].BG[3].VOffset = PPU.BG[3].VOffset + 1; + LineData[C].BG[3].HOffset = PPU.BG[3].HOffset; + } + + IPPU.CurrentLine = C + 1; + } + else + { + // if we're not rendering this frame, we still need to update this + // XXX: Check ForceBlank? Or anything else? + if (IPPU.OBJChanged) + SetupOBJ(); + PPU.RangeTimeOver |= GFX.OBJLines[C].RTOFlags; + } +} + +static inline void RenderScreen (bool8 sub) +{ + uint8 BGActive; + int D; + + if (!sub) + { + GFX.S = GFX.Screen; + if (GFX.DoInterlace && GFX.InterlaceFrame) + GFX.S += GFX.RealPPL; + GFX.DB = GFX.ZBuffer; + GFX.Clip = IPPU.Clip[0]; + BGActive = Memory.FillRAM[0x212c] & ~Settings.BG_Forced; + D = 32; + } + else + { + GFX.S = GFX.SubScreen; + GFX.DB = GFX.SubZBuffer; + GFX.Clip = IPPU.Clip[1]; + BGActive = Memory.FillRAM[0x212d] & ~Settings.BG_Forced; + D = (Memory.FillRAM[0x2130] & 2) << 4; // 'do math' depth flag + } + + if (BGActive & 0x10) + { + BG.TileAddress = PPU.OBJNameBase; + BG.NameSelect = PPU.OBJNameSelect; + BG.EnableMath = !sub && (Memory.FillRAM[0x2131] & 0x10); + BG.StartPalette = 128; + S9xSelectTileConverter(4, FALSE, sub, FALSE); + S9xSelectTileRenderers(PPU.BGMode, sub, TRUE); + DrawOBJS(D + 4); + } + + BG.NameSelect = 0; + S9xSelectTileRenderers(PPU.BGMode, sub, FALSE); + + #define DO_BG(n, pal, depth, hires, offset, Zh, Zl, voffoff) \ + if (BGActive & (1 << n)) \ + { \ + BG.StartPalette = pal; \ + BG.EnableMath = !sub && (Memory.FillRAM[0x2131] & (1 << n)); \ + BG.TileSizeH = (!hires && PPU.BG[n].BGSize) ? 16 : 8; \ + BG.TileSizeV = (PPU.BG[n].BGSize) ? 16 : 8; \ + S9xSelectTileConverter(depth, hires, sub, PPU.BGMosaic[n]); \ + \ + if (offset) \ + { \ + BG.OffsetSizeH = (!hires && PPU.BG[2].BGSize) ? 16 : 8; \ + BG.OffsetSizeV = (PPU.BG[2].BGSize) ? 16 : 8; \ + \ + if (PPU.BGMosaic[n] && (hires || PPU.Mosaic > 1)) \ + DrawBackgroundOffsetMosaic(n, D + Zh, D + Zl, voffoff); \ + else \ + DrawBackgroundOffset(n, D + Zh, D + Zl, voffoff); \ + } \ + else \ + { \ + if (PPU.BGMosaic[n] && (hires || PPU.Mosaic > 1)) \ + DrawBackgroundMosaic(n, D + Zh, D + Zl); \ + else \ + DrawBackground(n, D + Zh, D + Zl); \ + } \ + } + + switch (PPU.BGMode) + { + case 0: + DO_BG(0, 0, 2, FALSE, FALSE, 15, 11, 0); + DO_BG(1, 32, 2, FALSE, FALSE, 14, 10, 0); + DO_BG(2, 64, 2, FALSE, FALSE, 7, 3, 0); + DO_BG(3, 96, 2, FALSE, FALSE, 6, 2, 0); + break; + + case 1: + DO_BG(0, 0, 4, FALSE, FALSE, 15, 11, 0); + DO_BG(1, 0, 4, FALSE, FALSE, 14, 10, 0); + DO_BG(2, 0, 2, FALSE, FALSE, (PPU.BG3Priority ? 17 : 7), 3, 0); + break; + + case 2: + DO_BG(0, 0, 4, FALSE, TRUE, 15, 7, 8); + DO_BG(1, 0, 4, FALSE, TRUE, 11, 3, 8); + break; + + case 3: + DO_BG(0, 0, 8, FALSE, FALSE, 15, 7, 0); + DO_BG(1, 0, 4, FALSE, FALSE, 11, 3, 0); + break; + + case 4: + DO_BG(0, 0, 8, FALSE, TRUE, 15, 7, 0); + DO_BG(1, 0, 2, FALSE, TRUE, 11, 3, 0); + break; + + case 5: + DO_BG(0, 0, 4, TRUE, FALSE, 15, 7, 0); + DO_BG(1, 0, 2, TRUE, FALSE, 11, 3, 0); + break; + + case 6: + DO_BG(0, 0, 4, TRUE, TRUE, 15, 7, 8); + break; + + case 7: + if (BGActive & 0x01) + { + BG.EnableMath = !sub && (Memory.FillRAM[0x2131] & 1); + DrawBackgroundMode7(0, GFX.DrawMode7BG1Math, GFX.DrawMode7BG1Nomath, D); + } + + if ((Memory.FillRAM[0x2133] & 0x40) && (BGActive & 0x02)) + { + BG.EnableMath = !sub && (Memory.FillRAM[0x2131] & 2); + DrawBackgroundMode7(1, GFX.DrawMode7BG2Math, GFX.DrawMode7BG2Nomath, D); + } + + break; + } + + #undef DO_BG + + BG.EnableMath = !sub && (Memory.FillRAM[0x2131] & 0x20); + + DrawBackdrop(); +} + +void S9xUpdateScreen (void) +{ + if (IPPU.OBJChanged || IPPU.InterlaceOBJ) + SetupOBJ(); + + // XXX: Check ForceBlank? Or anything else? + PPU.RangeTimeOver |= GFX.OBJLines[GFX.EndY].RTOFlags; + + GFX.StartY = IPPU.PreviousLine; + if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight) + GFX.EndY = PPU.ScreenHeight - 1; + + if (!PPU.ForcedBlanking) + { + // If force blank, may as well completely skip all this. We only did + // the OBJ because (AFAWK) the RTO flags are updated even during force-blank. + + if (PPU.RecomputeClipWindows) + { + S9xComputeClipWindows(); + PPU.RecomputeClipWindows = FALSE; + } + + if (Settings.SupportHiRes) + { + if (!IPPU.DoubleWidthPixels && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires)) + { + #ifdef USE_OPENGL + if (Settings.OpenGLEnable && GFX.RealPPL == 256) + { + // Have to back out of the speed up hack where the low res. + // SNES image was rendered into a 256x239 sized buffer, + // ignoring the true, larger size of the buffer. + GFX.RealPPL = GFX.Pitch >> 1; + + for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--) + { + register uint16 *p = GFX.Screen + y * GFX.PPL + 255; + register uint16 *q = GFX.Screen + y * GFX.RealPPL + 510; + + for (register int x = 255; x >= 0; x--, p--, q -= 2) + *q = *(q + 1) = *p; + } + + GFX.PPL = GFX.RealPPL; // = GFX.Pitch >> 1 above + } + else + #endif + { + // Have to back out of the regular speed hack + for (register uint32 y = 0; y < GFX.StartY; y++) + { + register uint16 *p = GFX.Screen + y * GFX.PPL + 255; + register uint16 *q = GFX.Screen + y * GFX.PPL + 510; + + for (register int x = 255; x >= 0; x--, p--, q -= 2) + *q = *(q + 1) = *p; + } + } + + IPPU.DoubleWidthPixels = TRUE; + IPPU.RenderedScreenWidth = 512; + } + + if (!IPPU.DoubleHeightPixels && IPPU.Interlace) + { + IPPU.DoubleHeightPixels = TRUE; + IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; + GFX.PPL = GFX.RealPPL << 1; + GFX.DoInterlace = 2; + + for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--) + memmove(GFX.Screen + y * GFX.PPL, GFX.Screen + y * GFX.RealPPL, IPPU.RenderedScreenWidth * sizeof(uint16)); + } + else if (IPPU.DoubleHeightPixels && !IPPU.Interlace) + { + for (register int32 y = 0; y < (int32) GFX.StartY; y++) + memmove(GFX.Screen + y * GFX.RealPPL, GFX.Screen + y * GFX.PPL, IPPU.RenderedScreenWidth * sizeof(uint16)); + + IPPU.DoubleHeightPixels = FALSE; + IPPU.RenderedScreenHeight = PPU.ScreenHeight; + GFX.PPL = GFX.RealPPL; + GFX.DoInterlace = 0; + } + } + + if ((Memory.FillRAM[0x2130] & 0x30) != 0x30 && (Memory.FillRAM[0x2131] & 0x3f)) + GFX.FixedColour = BUILD_PIXEL(IPPU.XB[PPU.FixedColourRed], IPPU.XB[PPU.FixedColourGreen], IPPU.XB[PPU.FixedColourBlue]); + + if (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires || + ((Memory.FillRAM[0x2130] & 0x30) != 0x30 && (Memory.FillRAM[0x2130] & 2) && (Memory.FillRAM[0x2131] & 0x3f) && (Memory.FillRAM[0x212d] & 0x1f))) + // If hires (Mode 5/6 or pseudo-hires) or math is to be done + // involving the subscreen, then we need to render the subscreen... + RenderScreen(TRUE); + + RenderScreen(FALSE); + } + else + { + const uint16 black = BUILD_PIXEL(0, 0, 0); + + GFX.S = GFX.Screen + GFX.StartY * GFX.PPL; + if (GFX.DoInterlace && GFX.InterlaceFrame) + GFX.S += GFX.RealPPL; + + for (uint32 l = GFX.StartY; l <= GFX.EndY; l++, GFX.S += GFX.PPL) + for (int x = 0; x < IPPU.RenderedScreenWidth; x++) + GFX.S[x] = black; + } + + IPPU.PreviousLine = IPPU.CurrentLine; +} + +static void SetupOBJ (void) +{ + int SmallWidth, SmallHeight, LargeWidth, LargeHeight; + + switch (PPU.OBJSizeSelect) + { + case 0: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 16; + break; + + case 1: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 32; + break; + + case 2: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 64; + break; + + case 3: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 32; + break; + + case 4: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 64; + break; + + case 5: + default: + SmallWidth = SmallHeight = 32; + LargeWidth = LargeHeight = 64; + break; + + case 6: + SmallWidth = 16; SmallHeight = 32; + LargeWidth = 32; LargeHeight = 64; + break; + + case 7: + SmallWidth = 16; SmallHeight = 32; + LargeWidth = LargeHeight = 32; + break; + } + + int inc = IPPU.InterlaceOBJ ? 2 : 1; + + int startline = (IPPU.InterlaceOBJ && GFX.InterlaceFrame) ? 1 : 0; + + // OK, we have three cases here. Either there's no priority, priority is + // normal FirstSprite, or priority is FirstSprite+Y. The first two are + // easy, the last is somewhat more ... interesting. So we split them up. + + int Height; + uint8 S; + + if (!PPU.OAMPriorityRotation || !(PPU.OAMFlip & PPU.OAMAddr & 1)) // normal case + { + uint8 LineOBJ[SNES_HEIGHT_EXTENDED]; + ZeroMemory(LineOBJ, sizeof(LineOBJ)); + + for (int i = 0; i < SNES_HEIGHT_EXTENDED; i++) + { + GFX.OBJLines[i].RTOFlags = 0; + GFX.OBJLines[i].Tiles = 34; + for (int j = 0; j < 32; j++) + GFX.OBJLines[i].OBJ[j].Sprite = -1; + } + + uint8 FirstSprite = PPU.FirstSprite; + S = FirstSprite; + + do + { + if (PPU.OBJ[S].Size) + { + GFX.OBJWidths[S] = LargeWidth; + Height = LargeHeight; + } + else + { + GFX.OBJWidths[S] = SmallWidth; + Height = SmallHeight; + } + + int HPos = PPU.OBJ[S].HPos; + if (HPos == -256) + HPos = 0; + + if (HPos > -GFX.OBJWidths[S] && HPos <= 256) + { + if (HPos < 0) + GFX.OBJVisibleTiles[S] = (GFX.OBJWidths[S] + HPos + 7) >> 3; + else + if (HPos + GFX.OBJWidths[S] > 255) + GFX.OBJVisibleTiles[S] = (256 - HPos + 7) >> 3; + else + GFX.OBJVisibleTiles[S] = GFX.OBJWidths[S] >> 3; + + for (uint8 line = startline, Y = (uint8) (PPU.OBJ[S].VPos & 0xff); line < Height; Y++, line += inc) + { + if (Y >= SNES_HEIGHT_EXTENDED) + continue; + + if (LineOBJ[Y] >= 32) + { + GFX.OBJLines[Y].RTOFlags |= 0x40; + continue; + } + + GFX.OBJLines[Y].Tiles -= GFX.OBJVisibleTiles[S]; + if (GFX.OBJLines[Y].Tiles < 0) + GFX.OBJLines[Y].RTOFlags |= 0x80; + + GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Sprite = S; + if (PPU.OBJ[S].VFlip) + // Yes, Width not Height. It so happens that the + // sprites with H=2*W flip as two WxW sprites. + GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Line = line ^ (GFX.OBJWidths[S] - 1); + else + GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Line = line; + + LineOBJ[Y]++; + } + } + + S = (S + 1) & 0x7f; + } while (S != FirstSprite); + + for (int Y = 1; Y < SNES_HEIGHT_EXTENDED; Y++) + GFX.OBJLines[Y].RTOFlags |= GFX.OBJLines[Y - 1].RTOFlags; + } + else // evil FirstSprite+Y case + { + // First, find out which sprites are on which lines + uint8 OBJOnLine[SNES_HEIGHT_EXTENDED][128]; + ZeroMemory(OBJOnLine, sizeof(OBJOnLine)); + + for (S = 0; S < 128; S++) + { + if (PPU.OBJ[S].Size) + { + GFX.OBJWidths[S] = LargeWidth; + Height = LargeHeight; + } + else + { + GFX.OBJWidths[S] = SmallWidth; + Height = SmallHeight; + } + + int HPos = PPU.OBJ[S].HPos; + if (HPos == -256) + HPos = 256; + + if (HPos > -GFX.OBJWidths[S] && HPos <= 256) + { + if (HPos < 0) + GFX.OBJVisibleTiles[S] = (GFX.OBJWidths[S] + HPos + 7) >> 3; + else + if (HPos + GFX.OBJWidths[S] >= 257) + GFX.OBJVisibleTiles[S] = (257 - HPos + 7) >> 3; + else + GFX.OBJVisibleTiles[S] = GFX.OBJWidths[S] >> 3; + + for (uint8 line = startline, Y = (uint8) (PPU.OBJ[S].VPos & 0xff); line < Height; Y++, line += inc) + { + if (Y >= SNES_HEIGHT_EXTENDED) + continue; + + if (PPU.OBJ[S].VFlip) + // Yes, Width not Height. It so happens that the + // sprites with H=2*W flip as two WxW sprites. + OBJOnLine[Y][S] = (line ^ (GFX.OBJWidths[S] - 1)) | 0x80; + else + OBJOnLine[Y][S] = line | 0x80; + } + } + } + + // Now go through and pull out those OBJ that are actually visible. + int j; + for (int Y = 0; Y < SNES_HEIGHT_EXTENDED; Y++) + { + GFX.OBJLines[Y].RTOFlags = Y ? GFX.OBJLines[Y - 1].RTOFlags : 0; + GFX.OBJLines[Y].Tiles = 34; + + uint8 FirstSprite = (PPU.FirstSprite + Y) & 0x7f; + S = FirstSprite; + j = 0; + + do + { + if (OBJOnLine[Y][S]) + { + if (j >= 32) + { + GFX.OBJLines[Y].RTOFlags |= 0x40; + break; + } + + GFX.OBJLines[Y].Tiles -= GFX.OBJVisibleTiles[S]; + if (GFX.OBJLines[Y].Tiles < 0) + GFX.OBJLines[Y].RTOFlags |= 0x80; + GFX.OBJLines[Y].OBJ[j].Sprite = S; + GFX.OBJLines[Y].OBJ[j++].Line = OBJOnLine[Y][S] & ~0x80; + } + + S = (S + 1) & 0x7f; + } while (S != FirstSprite); + + if (j < 32) + GFX.OBJLines[Y].OBJ[j].Sprite = -1; + } + } + + IPPU.OBJChanged = FALSE; +} + +static void DrawOBJS (int D) +{ + void (*DrawTile) (uint32, uint32, uint32, uint32) = NULL; + void (*DrawClippedTile) (uint32, uint32, uint32, uint32, uint32, uint32) = NULL; + + int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1; + BG.InterlaceLine = GFX.InterlaceFrame ? 8 : 0; + GFX.Z1 = 2; + + for (uint32 Y = GFX.StartY, Offset = Y * GFX.PPL; Y <= GFX.EndY; Y++, Offset += GFX.PPL) + { + int I = 0; + int tiles = GFX.OBJLines[Y].Tiles; + + for (int S = GFX.OBJLines[Y].OBJ[I].Sprite; S >= 0 && I < 32; S = GFX.OBJLines[Y].OBJ[++I].Sprite) + { + tiles += GFX.OBJVisibleTiles[S]; + if (tiles <= 0) + continue; + + int BaseTile = (((GFX.OBJLines[Y].OBJ[I].Line << 1) + (PPU.OBJ[S].Name & 0xf0)) & 0xf0) | (PPU.OBJ[S].Name & 0x100) | (PPU.OBJ[S].Palette << 10); + int TileX = PPU.OBJ[S].Name & 0x0f; + int TileLine = (GFX.OBJLines[Y].OBJ[I].Line & 7) * 8; + int TileInc = 1; + + if (PPU.OBJ[S].HFlip) + { + TileX = (TileX + (GFX.OBJWidths[S] >> 3) - 1) & 0x0f; + BaseTile |= H_FLIP; + TileInc = -1; + } + + GFX.Z2 = D + PPU.OBJ[S].Priority * 4; + + int DrawMode = 3; + int clip = 0, next_clip = -1000; + int X = PPU.OBJ[S].HPos; + if (X == -256) + X = 256; + + for (int t = tiles, O = Offset + X * PixWidth; X <= 256 && X < PPU.OBJ[S].HPos + GFX.OBJWidths[S]; TileX = (TileX + TileInc) & 0x0f, X += 8, O += 8 * PixWidth) + { + if (X < -7 || --t < 0 || X == 256) + continue; + + for (int x = X; x < X + 8;) + { + if (x >= next_clip) + { + for (; clip < GFX.Clip[4].Count && GFX.Clip[4].Left[clip] <= x; clip++) ; + if (clip == 0 || x >= GFX.Clip[4].Right[clip - 1]) + { + DrawMode = 0; + next_clip = ((clip < GFX.Clip[4].Count) ? GFX.Clip[4].Left[clip] : 1000); + } + else + { + DrawMode = GFX.Clip[4].DrawMode[clip - 1]; + next_clip = GFX.Clip[4].Right[clip - 1]; + GFX.ClipColors = !(DrawMode & 1); + + if (BG.EnableMath && (PPU.OBJ[S].Palette & 4) && (DrawMode & 2)) + { + DrawTile = GFX.DrawTileMath; + DrawClippedTile = GFX.DrawClippedTileMath; + } + else + { + DrawTile = GFX.DrawTileNomath; + DrawClippedTile = GFX.DrawClippedTileNomath; + } + } + } + + if (x == X && x + 8 < next_clip) + { + if (DrawMode) + DrawTile(BaseTile | TileX, O, TileLine, 1); + x += 8; + } + else + { + int w = (next_clip <= X + 8) ? next_clip - x : X + 8 - x; + if (DrawMode) + DrawClippedTile(BaseTile | TileX, O, x - X, w, TileLine, 1); + x += w; + } + } + } + } + } +} + +static void DrawBackground (int bg, uint8 Zh, uint8 Zl) +{ + BG.TileAddress = PPU.BG[bg].NameBase << 1; + + uint32 Tile; + uint16 *SC0, *SC1, *SC2, *SC3; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + SC1 = (PPU.BG[bg].SCSize & 1) ? SC0 + 1024 : SC0; + if (SC1 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC1 -= 0x8000; + SC2 = (PPU.BG[bg].SCSize & 2) ? SC1 + 1024 : SC0; + if (SC2 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC2 -= 0x8000; + SC3 = (PPU.BG[bg].SCSize & 1) ? SC2 + 1024 : SC2; + if (SC3 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC3 -= 0x8000; + + uint32 Lines; + int OffsetMask = (BG.TileSizeH == 16) ? 0x3ff : 0x1ff; + int OffsetShift = (BG.TileSizeV == 16) ? 4 : 3; + int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1; + bool8 HiresInterlace = IPPU.Interlace && IPPU.DoubleWidthPixels; + + void (*DrawTile) (uint32, uint32, uint32, uint32); + void (*DrawClippedTile) (uint32, uint32, uint32, uint32, uint32, uint32); + + for (int clip = 0; clip < GFX.Clip[bg].Count; clip++) + { + GFX.ClipColors = !(GFX.Clip[bg].DrawMode[clip] & 1); + + if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) + { + DrawTile = GFX.DrawTileMath; + DrawClippedTile = GFX.DrawClippedTileMath; + } + else + { + DrawTile = GFX.DrawTileNomath; + DrawClippedTile = GFX.DrawClippedTileNomath; + } + + for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines) + { + uint32 Y2 = HiresInterlace ? Y * 2 + GFX.InterlaceFrame : Y; + uint32 VOffset = LineData[Y].BG[bg].VOffset + (HiresInterlace ? 1 : 0); + uint32 HOffset = LineData[Y].BG[bg].HOffset; + int VirtAlign = ((Y2 + VOffset) & 7) >> (HiresInterlace ? 1 : 0); + + for (Lines = 1; Lines < GFX.LinesPerTile - VirtAlign; Lines++) + { + if ((VOffset != LineData[Y + Lines].BG[bg].VOffset) || (HOffset != LineData[Y + Lines].BG[bg].HOffset)) + break; + } + + if (Y + Lines > GFX.EndY) + Lines = GFX.EndY - Y + 1; + + VirtAlign <<= 3; + + uint32 t1, t2; + uint32 TilemapRow = (VOffset + Y2) >> OffsetShift; + BG.InterlaceLine = ((VOffset + Y2) & 1) << 3; + + if ((VOffset + Y2) & 8) + { + t1 = 16; + t2 = 0; + } + else + { + t1 = 0; + t2 = 16; + } + + uint16 *b1, *b2; + + if (TilemapRow & 0x20) + { + b1 = SC2; + b2 = SC3; + } + else + { + b1 = SC0; + b2 = SC1; + } + + b1 += (TilemapRow & 0x1f) << 5; + b2 += (TilemapRow & 0x1f) << 5; + + uint32 Left = GFX.Clip[bg].Left[clip]; + uint32 Right = GFX.Clip[bg].Right[clip]; + uint32 Offset = Left * PixWidth + Y * GFX.PPL; + uint32 HPos = (HOffset + Left) & OffsetMask; + uint32 HTile = HPos >> 3; + uint16 *t; + + if (BG.TileSizeH == 8) + { + if (HTile > 31) + t = b2 + (HTile & 0x1f); + else + t = b1 + HTile; + } + else + { + if (HTile > 63) + t = b2 + ((HTile >> 1) & 0x1f); + else + t = b1 + (HTile >> 1); + } + + uint32 Width = Right - Left; + + if (HPos & 7) + { + uint32 l = HPos & 7; + uint32 w = 8 - l; + if (w > Width) + w = Width; + + Offset -= l * PixWidth; + Tile = READ_WORD(t); + GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; + + if (BG.TileSizeV == 16) + Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); + + if (BG.TileSizeH == 8) + { + DrawClippedTile(Tile, Offset, l, w, VirtAlign, Lines); + t++; + if (HTile == 31) + t = b2; + else + if (HTile == 63) + t = b1; + } + else + { + if (!(Tile & H_FLIP)) + DrawClippedTile(TILE_PLUS(Tile, (HTile & 1)), Offset, l, w, VirtAlign, Lines); + else + DrawClippedTile(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, l, w, VirtAlign, Lines); + t += HTile & 1; + if (HTile == 63) + t = b2; + else + if (HTile == 127) + t = b1; + } + + HTile++; + Offset += 8 * PixWidth; + Width -= w; + } + + while (Width >= 8) + { + Tile = READ_WORD(t); + GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; + + if (BG.TileSizeV == 16) + Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); + + if (BG.TileSizeH == 8) + { + DrawTile(Tile, Offset, VirtAlign, Lines); + t++; + if (HTile == 31) + t = b2; + else + if (HTile == 63) + t = b1; + } + else + { + if (!(Tile & H_FLIP)) + DrawTile(TILE_PLUS(Tile, (HTile & 1)), Offset, VirtAlign, Lines); + else + DrawTile(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, VirtAlign, Lines); + t += HTile & 1; + if (HTile == 63) + t = b2; + else + if (HTile == 127) + t = b1; + } + + HTile++; + Offset += 8 * PixWidth; + Width -= 8; + } + + if (Width) + { + Tile = READ_WORD(t); + GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; + + if (BG.TileSizeV == 16) + Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); + + if (BG.TileSizeH == 8) + DrawClippedTile(Tile, Offset, 0, Width, VirtAlign, Lines); + else + { + if (!(Tile & H_FLIP)) + DrawClippedTile(TILE_PLUS(Tile, (HTile & 1)), Offset, 0, Width, VirtAlign, Lines); + else + DrawClippedTile(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, 0, Width, VirtAlign, Lines); + } + } + } + } +} + +static void DrawBackgroundMosaic (int bg, uint8 Zh, uint8 Zl) +{ + BG.TileAddress = PPU.BG[bg].NameBase << 1; + + uint32 Tile; + uint16 *SC0, *SC1, *SC2, *SC3; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + SC1 = (PPU.BG[bg].SCSize & 1) ? SC0 + 1024 : SC0; + if (SC1 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC1 -= 0x8000; + SC2 = (PPU.BG[bg].SCSize & 2) ? SC1 + 1024 : SC0; + if (SC2 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC2 -= 0x8000; + SC3 = (PPU.BG[bg].SCSize & 1) ? SC2 + 1024 : SC2; + if (SC3 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC3 -= 0x8000; + + int Lines; + int OffsetMask = (BG.TileSizeH == 16) ? 0x3ff : 0x1ff; + int OffsetShift = (BG.TileSizeV == 16) ? 4 : 3; + int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1; + bool8 HiresInterlace = IPPU.Interlace && IPPU.DoubleWidthPixels; + + void (*DrawPix) (uint32, uint32, uint32, uint32, uint32, uint32); + + int MosaicStart = ((uint32) GFX.StartY - PPU.MosaicStart) % PPU.Mosaic; + + for (int clip = 0; clip < GFX.Clip[bg].Count; clip++) + { + GFX.ClipColors = !(GFX.Clip[bg].DrawMode[clip] & 1); + + if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) + DrawPix = GFX.DrawMosaicPixelMath; + else + DrawPix = GFX.DrawMosaicPixelNomath; + + for (uint32 Y = GFX.StartY - MosaicStart; Y <= GFX.EndY; Y += PPU.Mosaic) + { + uint32 Y2 = HiresInterlace ? Y * 2 : Y; + uint32 VOffset = LineData[Y].BG[bg].VOffset + (HiresInterlace ? 1 : 0); + uint32 HOffset = LineData[Y].BG[bg].HOffset; + + Lines = PPU.Mosaic - MosaicStart; + if (Y + MosaicStart + Lines > GFX.EndY) + Lines = GFX.EndY - Y - MosaicStart + 1; + + int VirtAlign = (((Y2 + VOffset) & 7) >> (HiresInterlace ? 1 : 0)) << 3; + + uint32 t1, t2; + uint32 TilemapRow = (VOffset + Y2) >> OffsetShift; + BG.InterlaceLine = ((VOffset + Y2) & 1) << 3; + + if ((VOffset + Y2) & 8) + { + t1 = 16; + t2 = 0; + } + else + { + t1 = 0; + t2 = 16; + } + + uint16 *b1, *b2; + + if (TilemapRow & 0x20) + { + b1 = SC2; + b2 = SC3; + } + else + { + b1 = SC0; + b2 = SC1; + } + + b1 += (TilemapRow & 0x1f) << 5; + b2 += (TilemapRow & 0x1f) << 5; + + uint32 Left = GFX.Clip[bg].Left[clip]; + uint32 Right = GFX.Clip[bg].Right[clip]; + uint32 Offset = Left * PixWidth + (Y + MosaicStart) * GFX.PPL; + uint32 HPos = (HOffset + Left - (Left % PPU.Mosaic)) & OffsetMask; + uint32 HTile = HPos >> 3; + uint16 *t; + + if (BG.TileSizeH == 8) + { + if (HTile > 31) + t = b2 + (HTile & 0x1f); + else + t = b1 + HTile; + } + else + { + if (HTile > 63) + t = b2 + ((HTile >> 1) & 0x1f); + else + t = b1 + (HTile >> 1); + } + + uint32 Width = Right - Left; + + HPos &= 7; + + while (Left < Right) + { + uint32 w = PPU.Mosaic - (Left % PPU.Mosaic); + if (w > Width) + w = Width; + + Tile = READ_WORD(t); + GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; + + if (BG.TileSizeV == 16) + Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); + + if (BG.TileSizeH == 8) + DrawPix(Tile, Offset, VirtAlign, HPos & 7, w, Lines); + else + { + if (!(Tile & H_FLIP)) + DrawPix(TILE_PLUS(Tile, (HTile & 1)), Offset, VirtAlign, HPos & 7, w, Lines); + else + DrawPix(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, VirtAlign, HPos & 7, w, Lines); + } + + HPos += PPU.Mosaic; + + while (HPos >= 8) + { + HPos -= 8; + + if (BG.TileSizeH == 8) + { + t++; + if (HTile == 31) + t = b2; + else + if (HTile == 63) + t = b1; + } + else + { + t += HTile & 1; + if (HTile == 63) + t = b2; + else + if (HTile == 127) + t = b1; + } + + HTile++; + } + + Offset += w * PixWidth; + Width -= w; + Left += w; + } + + MosaicStart = 0; + } + } +} + +static void DrawBackgroundOffset (int bg, uint8 Zh, uint8 Zl, int VOffOff) +{ + BG.TileAddress = PPU.BG[bg].NameBase << 1; + + uint32 Tile; + uint16 *SC0, *SC1, *SC2, *SC3; + uint16 *BPS0, *BPS1, *BPS2, *BPS3; + + BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1]; + BPS1 = (PPU.BG[2].SCSize & 1) ? BPS0 + 1024 : BPS0; + if (BPS1 >= (uint16 *) (Memory.VRAM + 0x10000)) + BPS1 -= 0x8000; + BPS2 = (PPU.BG[2].SCSize & 2) ? BPS1 + 1024 : BPS0; + if (BPS2 >= (uint16 *) (Memory.VRAM + 0x10000)) + BPS2 -= 0x8000; + BPS3 = (PPU.BG[2].SCSize & 1) ? BPS2 + 1024 : BPS2; + if (BPS3 >= (uint16 *) (Memory.VRAM + 0x10000)) + BPS3 -= 0x8000; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + SC1 = (PPU.BG[bg].SCSize & 1) ? SC0 + 1024 : SC0; + if (SC1 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC1 -= 0x8000; + SC2 = (PPU.BG[bg].SCSize & 2) ? SC1 + 1024 : SC0; + if (SC2 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC2 -= 0x8000; + SC3 = (PPU.BG[bg].SCSize & 1) ? SC2 + 1024 : SC2; + if (SC3 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC3 -= 0x8000; + + int OffsetMask = (BG.TileSizeH == 16) ? 0x3ff : 0x1ff; + int OffsetShift = (BG.TileSizeV == 16) ? 4 : 3; + int Offset2Mask = (BG.OffsetSizeH == 16) ? 0x3ff : 0x1ff; + int Offset2Shift = (BG.OffsetSizeV == 16) ? 4 : 3; + int OffsetEnableMask = 0x2000 << bg; + int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1; + bool8 HiresInterlace = IPPU.Interlace && IPPU.DoubleWidthPixels; + + void (*DrawTile) (uint32, uint32, uint32, uint32); + void (*DrawClippedTile) (uint32, uint32, uint32, uint32, uint32, uint32); + + for (int clip = 0; clip < GFX.Clip[bg].Count; clip++) + { + GFX.ClipColors = !(GFX.Clip[bg].DrawMode[clip] & 1); + + if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) + { + DrawTile = GFX.DrawTileMath; + DrawClippedTile = GFX.DrawClippedTileMath; + } + else + { + DrawTile = GFX.DrawTileNomath; + DrawClippedTile = GFX.DrawClippedTileNomath; + } + + for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++) + { + uint32 Y2 = HiresInterlace ? Y * 2 + GFX.InterlaceFrame : Y; + uint32 VOff = LineData[Y].BG[2].VOffset - 1; + uint32 HOff = LineData[Y].BG[2].HOffset; + uint32 HOffsetRow = VOff >> Offset2Shift; + uint32 VOffsetRow = (VOff + VOffOff) >> Offset2Shift; + uint16 *s, *s1, *s2; + + if (HOffsetRow & 0x20) + { + s1 = BPS2; + s2 = BPS3; + } + else + { + s1 = BPS0; + s2 = BPS1; + } + + s1 += (HOffsetRow & 0x1f) << 5; + s2 += (HOffsetRow & 0x1f) << 5; + s = ((VOffsetRow & 0x20) ? BPS2 : BPS0) + ((VOffsetRow & 0x1f) << 5); + int32 VOffsetOffset = s - s1; + + uint32 Left = GFX.Clip[bg].Left[clip]; + uint32 Right = GFX.Clip[bg].Right[clip]; + uint32 Offset = Left * PixWidth + Y * GFX.PPL; + uint32 LineHOffset = LineData[Y].BG[bg].HOffset; + bool8 left_edge = (Left < (8 - (LineHOffset & 7))); + uint32 Width = Right - Left; + + while (Left < Right) + { + uint32 VOffset, HOffset; + + if (left_edge) + { + // SNES cannot do OPT for leftmost tile column + VOffset = LineData[Y].BG[bg].VOffset; + HOffset = LineHOffset; + left_edge = FALSE; + } + else + { + int HOffTile = ((HOff + Left - 1) & Offset2Mask) >> 3; + + if (BG.OffsetSizeH == 8) + { + if (HOffTile > 31) + s = s2 + (HOffTile & 0x1f); + else + s = s1 + HOffTile; + } + else + { + if (HOffTile > 63) + s = s2 + ((HOffTile >> 1) & 0x1f); + else + s = s1 + (HOffTile >> 1); + } + + uint16 HCellOffset = READ_WORD(s); + uint16 VCellOffset; + + if (VOffOff) + VCellOffset = READ_WORD(s + VOffsetOffset); + else + { + if (HCellOffset & 0x8000) + { + VCellOffset = HCellOffset; + HCellOffset = 0; + } + else + VCellOffset = 0; + } + + if (VCellOffset & OffsetEnableMask) + VOffset = VCellOffset + 1; + else + VOffset = LineData[Y].BG[bg].VOffset; + + if (HCellOffset & OffsetEnableMask) + HOffset = (HCellOffset & ~7) | (LineHOffset & 7); + else + HOffset = LineHOffset; + } + + if (HiresInterlace) + VOffset++; + + uint32 t1, t2; + int VirtAlign = (((Y2 + VOffset) & 7) >> (HiresInterlace ? 1 : 0)) << 3; + int TilemapRow = (VOffset + Y2) >> OffsetShift; + BG.InterlaceLine = ((VOffset + Y2) & 1) << 3; + + if ((VOffset + Y2) & 8) + { + t1 = 16; + t2 = 0; + } + else + { + t1 = 0; + t2 = 16; + } + + uint16 *b1, *b2; + + if (TilemapRow & 0x20) + { + b1 = SC2; + b2 = SC3; + } + else + { + b1 = SC0; + b2 = SC1; + } + + b1 += (TilemapRow & 0x1f) << 5; + b2 += (TilemapRow & 0x1f) << 5; + + uint32 HPos = (HOffset + Left) & OffsetMask; + uint32 HTile = HPos >> 3; + uint16 *t; + + if (BG.TileSizeH == 8) + { + if (HTile > 31) + t = b2 + (HTile & 0x1f); + else + t = b1 + HTile; + } + else + { + if (HTile > 63) + t = b2 + ((HTile >> 1) & 0x1f); + else + t = b1 + (HTile >> 1); + } + + uint32 l = HPos & 7; + uint32 w = 8 - l; + if (w > Width) + w = Width; + + Offset -= l * PixWidth; + Tile = READ_WORD(t); + GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; + + if (BG.TileSizeV == 16) + Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); + + if (BG.TileSizeH == 8) + { + DrawClippedTile(Tile, Offset, l, w, VirtAlign, 1); + } + else + { + if (!(Tile & H_FLIP)) + DrawClippedTile(TILE_PLUS(Tile, (HTile & 1)), Offset, l, w, VirtAlign, 1); + else + DrawClippedTile(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, l, w, VirtAlign, 1); + } + + Left += w; + Offset += 8 * PixWidth; + Width -= w; + } + } + } +} + +static void DrawBackgroundOffsetMosaic (int bg, uint8 Zh, uint8 Zl, int VOffOff) +{ + BG.TileAddress = PPU.BG[bg].NameBase << 1; + + uint32 Tile; + uint16 *SC0, *SC1, *SC2, *SC3; + uint16 *BPS0, *BPS1, *BPS2, *BPS3; + + BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1]; + BPS1 = (PPU.BG[2].SCSize & 1) ? BPS0 + 1024 : BPS0; + if (BPS1 >= (uint16 *) (Memory.VRAM + 0x10000)) + BPS1 -= 0x8000; + BPS2 = (PPU.BG[2].SCSize & 2) ? BPS1 + 1024 : BPS0; + if (BPS2 >= (uint16 *) (Memory.VRAM + 0x10000)) + BPS2 -= 0x8000; + BPS3 = (PPU.BG[2].SCSize & 1) ? BPS2 + 1024 : BPS2; + if (BPS3 >= (uint16 *) (Memory.VRAM + 0x10000)) + BPS3 -= 0x8000; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + SC1 = (PPU.BG[bg].SCSize & 1) ? SC0 + 1024 : SC0; + if (SC1 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC1 -= 0x8000; + SC2 = (PPU.BG[bg].SCSize & 2) ? SC1 + 1024 : SC0; + if (SC2 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC2 -= 0x8000; + SC3 = (PPU.BG[bg].SCSize & 1) ? SC2 + 1024 : SC2; + if (SC3 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC3 -= 0x8000; + + int Lines; + int OffsetMask = (BG.TileSizeH == 16) ? 0x3ff : 0x1ff; + int OffsetShift = (BG.TileSizeV == 16) ? 4 : 3; + int Offset2Mask = (BG.OffsetSizeH == 16) ? 0x3ff : 0x1ff; + int Offset2Shift = (BG.OffsetSizeV == 16) ? 4 : 3; + int OffsetEnableMask = 0x2000 << bg; + int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1; + bool8 HiresInterlace = IPPU.Interlace && IPPU.DoubleWidthPixels; + + void (*DrawPix) (uint32, uint32, uint32, uint32, uint32, uint32); + + int MosaicStart = ((uint32) GFX.StartY - PPU.MosaicStart) % PPU.Mosaic; + + for (int clip = 0; clip < GFX.Clip[bg].Count; clip++) + { + GFX.ClipColors = !(GFX.Clip[bg].DrawMode[clip] & 1); + + if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) + DrawPix = GFX.DrawMosaicPixelMath; + else + DrawPix = GFX.DrawMosaicPixelNomath; + + for (uint32 Y = GFX.StartY - MosaicStart; Y <= GFX.EndY; Y += PPU.Mosaic) + { + uint32 Y2 = HiresInterlace ? Y * 2 : Y; + uint32 VOff = LineData[Y].BG[2].VOffset - 1; + uint32 HOff = LineData[Y].BG[2].HOffset; + + Lines = PPU.Mosaic - MosaicStart; + if (Y + MosaicStart + Lines > GFX.EndY) + Lines = GFX.EndY - Y - MosaicStart + 1; + + uint32 HOffsetRow = VOff >> Offset2Shift; + uint32 VOffsetRow = (VOff + VOffOff) >> Offset2Shift; + uint16 *s, *s1, *s2; + + if (HOffsetRow & 0x20) + { + s1 = BPS2; + s2 = BPS3; + } + else + { + s1 = BPS0; + s2 = BPS1; + } + + s1 += (HOffsetRow & 0x1f) << 5; + s2 += (HOffsetRow & 0x1f) << 5; + s = ((VOffsetRow & 0x20) ? BPS2 : BPS0) + ((VOffsetRow & 0x1f) << 5); + int32 VOffsetOffset = s - s1; + + uint32 Left = GFX.Clip[bg].Left[clip]; + uint32 Right = GFX.Clip[bg].Right[clip]; + uint32 Offset = Left * PixWidth + (Y + MosaicStart) * GFX.PPL; + uint32 LineHOffset = LineData[Y].BG[bg].HOffset; + bool8 left_edge = (Left < (8 - (LineHOffset & 7))); + uint32 Width = Right - Left; + + while (Left < Right) + { + uint32 VOffset, HOffset; + + if (left_edge) + { + // SNES cannot do OPT for leftmost tile column + VOffset = LineData[Y].BG[bg].VOffset; + HOffset = LineHOffset; + left_edge = FALSE; + } + else + { + int HOffTile = ((HOff + Left - 1) & Offset2Mask) >> 3; + + if (BG.OffsetSizeH == 8) + { + if (HOffTile > 31) + s = s2 + (HOffTile & 0x1f); + else + s = s1 + HOffTile; + } + else + { + if (HOffTile > 63) + s = s2 + ((HOffTile >> 1) & 0x1f); + else + s = s1 + (HOffTile >> 1); + } + + uint16 HCellOffset = READ_WORD(s); + uint16 VCellOffset; + + if (VOffOff) + VCellOffset = READ_WORD(s + VOffsetOffset); + else + { + if (HCellOffset & 0x8000) + { + VCellOffset = HCellOffset; + HCellOffset = 0; + } + else + VCellOffset = 0; + } + + if (VCellOffset & OffsetEnableMask) + VOffset = VCellOffset + 1; + else + VOffset = LineData[Y].BG[bg].VOffset; + + if (HCellOffset & OffsetEnableMask) + HOffset = (HCellOffset & ~7) | (LineHOffset & 7); + else + HOffset = LineHOffset; + } + + if (HiresInterlace) + VOffset++; + + uint32 t1, t2; + int VirtAlign = (((Y2 + VOffset) & 7) >> (HiresInterlace ? 1 : 0)) << 3; + int TilemapRow = (VOffset + Y2) >> OffsetShift; + BG.InterlaceLine = ((VOffset + Y2) & 1) << 3; + + if ((VOffset + Y2) & 8) + { + t1 = 16; + t2 = 0; + } + else + { + t1 = 0; + t2 = 16; + } + + uint16 *b1, *b2; + + if (TilemapRow & 0x20) + { + b1 = SC2; + b2 = SC3; + } + else + { + b1 = SC0; + b2 = SC1; + } + + b1 += (TilemapRow & 0x1f) << 5; + b2 += (TilemapRow & 0x1f) << 5; + + uint32 HPos = (HOffset + Left - (Left % PPU.Mosaic)) & OffsetMask; + uint32 HTile = HPos >> 3; + uint16 *t; + + if (BG.TileSizeH == 8) + { + if (HTile > 31) + t = b2 + (HTile & 0x1f); + else + t = b1 + HTile; + } + else + { + if (HTile > 63) + t = b2 + ((HTile >> 1) & 0x1f); + else + t = b1 + (HTile >> 1); + } + + uint32 w = PPU.Mosaic - (Left % PPU.Mosaic); + if (w > Width) + w = Width; + + Tile = READ_WORD(t); + GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; + + if (BG.TileSizeV == 16) + Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); + + if (BG.TileSizeH == 8) + DrawPix(Tile, Offset, VirtAlign, HPos & 7, w, Lines); + else + { + if (!(Tile & H_FLIP)) + DrawPix(TILE_PLUS(Tile, (HTile & 1)), Offset, VirtAlign, HPos & 7, w, Lines); + else + if (!(Tile & V_FLIP)) + DrawPix(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, VirtAlign, HPos & 7, w, Lines); + } + + Left += w; + Offset += w * PixWidth; + Width -= w; + } + + MosaicStart = 0; + } + } +} + +static inline void DrawBackgroundMode7 (int bg, void (*DrawMath) (uint32, uint32, int), void (*DrawNomath) (uint32, uint32, int), int D) +{ + for (int clip = 0; clip < GFX.Clip[bg].Count; clip++) + { + GFX.ClipColors = !(GFX.Clip[bg].DrawMode[clip] & 1); + + if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) + DrawMath(GFX.Clip[bg].Left[clip], GFX.Clip[bg].Right[clip], D); + else + DrawNomath(GFX.Clip[bg].Left[clip], GFX.Clip[bg].Right[clip], D); + } +} + +static inline void DrawBackdrop (void) +{ + uint32 Offset = GFX.StartY * GFX.PPL; + + for (int clip = 0; clip < GFX.Clip[5].Count; clip++) + { + GFX.ClipColors = !(GFX.Clip[5].DrawMode[clip] & 1); + + if (BG.EnableMath && (GFX.Clip[5].DrawMode[clip] & 2)) + GFX.DrawBackdropMath(Offset, GFX.Clip[5].Left[clip], GFX.Clip[5].Right[clip]); + else + GFX.DrawBackdropNomath(Offset, GFX.Clip[5].Left[clip], GFX.Clip[5].Right[clip]); + } +} + +void S9xReRefresh (void) +{ + // Be careful when calling this function from the thread other than the emulation one... + // Here it's assumed no drawing occurs from the emulation thread when Settings.Paused is TRUE. + if (Settings.Paused) + S9xDeinitUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); +} + +void S9xSetInfoString (const char *string) +{ + if (Settings.InitialInfoStringTimeout > 0) + { + GFX.InfoString = string; + GFX.InfoStringTimeout = Settings.InitialInfoStringTimeout; + S9xReRefresh(); + } +} + +void S9xDisplayChar (uint16 *s, uint8 c) +{ + const uint16 black = BUILD_PIXEL(0, 0, 0); + + int line = ((c - 32) >> 4) * font_height; + int offset = ((c - 32) & 15) * font_width; + + for (int h = 0; h < font_height; h++, line++, s += GFX.RealPPL - font_width) + { + for (int w = 0; w < font_width; w++, s++) + { + char p = font[line][offset + w]; + + if (p == '#') + *s = Settings.DisplayColor; + else + if (p == '.') + *s = black; + } + } +} + +static void DisplayStringFromBottom (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap) +{ + if (linesFromBottom <= 0) + linesFromBottom = 1; + + uint16 *dst = GFX.Screen + (IPPU.RenderedScreenHeight - font_height * linesFromBottom) * GFX.RealPPL + pixelsFromLeft; + + int len = strlen(string); + int max_chars = IPPU.RenderedScreenWidth / (font_width - 1); + int char_count = 0; + + for (int i = 0 ; i < len ; i++, char_count++) + { + if (char_count >= max_chars || (uint8) string[i] < 32) + { + if (!allowWrap) + break; + + dst += font_height * GFX.RealPPL - (font_width - 1) * max_chars; + if (dst >= GFX.Screen + IPPU.RenderedScreenHeight * GFX.RealPPL) + break; + + char_count -= max_chars; + } + + if ((uint8) string[i] < 32) + continue; + + S9xDisplayChar(dst, string[i]); + dst += font_width - 1; + } +} + +static void DisplayFrameRate (void) +{ + char string[10]; + static uint32 lastFrameCount = 0, calcFps = 0; + static time_t lastTime = time(NULL); + + time_t currTime = time(NULL); + if (lastTime != currTime) { + if (lastFrameCount < IPPU.TotalEmulatedFrames) { + calcFps = (IPPU.TotalEmulatedFrames - lastFrameCount) / (uint32)(currTime - lastTime); + } + lastTime = currTime; + lastFrameCount = IPPU.TotalEmulatedFrames; + } + sprintf(string, "%u fps", calcFps); + S9xDisplayString(string, 2, IPPU.RenderedScreenWidth - (font_width - 1) * strlen(string) - 1, false); + +#ifdef DEBUGGER + const int len = 8; + sprintf(string, "%02d/%02d %02d", (int) IPPU.DisplayedRenderedFrameCount, (int) Memory.ROMFramesPerSecond, (int) IPPU.FrameCount); +#else + const int len = 5; + sprintf(string, "%02d/%02d", (int) IPPU.DisplayedRenderedFrameCount, (int) Memory.ROMFramesPerSecond); +#endif + + S9xDisplayString(string, 1, IPPU.RenderedScreenWidth - (font_width - 1) * len - 1, false); +} + +static void DisplayPressedKeys (void) +{ + static char KeyMap[] = { '0', '1', '2', 'R', 'L', 'X', 'A', '>', '<', 'v', '^', 'S', 's', 'Y', 'B' }; + static int KeyOrder[] = { 8, 10, 7, 9, 0, 6, 14, 13, 5, 1, 4, 3, 2, 11, 12 }; // < ^ > v A B Y X L R S s + + enum controllers controller; + int line = 1; + int8 ids[4]; + char string[255]; + + for (int port = 0; port < 2; port++) + { + S9xGetController(port, &controller, &ids[0], &ids[1], &ids[2], &ids[3]); + + switch (controller) + { + case CTL_MOUSE: + { + uint8 buf[5], *p = buf; + MovieGetMouse(port, buf); + int16 x = READ_WORD(p); + int16 y = READ_WORD(p + 2); + uint8 buttons = buf[4]; + sprintf(string, "#%d %d: (%03d,%03d) %c%c", port, ids[0], x, y, + (buttons & 0x40) ? 'L' : ' ', (buttons & 0x80) ? 'R' : ' '); + S9xDisplayString(string, line++, 1, false); + break; + } + + case CTL_SUPERSCOPE: + { + uint8 buf[6], *p = buf; + MovieGetScope(port, buf); + int16 x = READ_WORD(p); + int16 y = READ_WORD(p + 2); + uint8 buttons = buf[4]; + sprintf(string, "#%d %d: (%03d,%03d) %c%c%c%c", port, ids[0], x, y, + (buttons & 0x80) ? 'F' : ' ', (buttons & 0x40) ? 'C' : ' ', + (buttons & 0x20) ? 'T' : ' ', (buttons & 0x10) ? 'P' : ' '); + S9xDisplayString(string, line++, 1, false); + break; + } + + case CTL_JUSTIFIER: + { + uint8 buf[11], *p = buf; + MovieGetJustifier(port, buf); + int16 x1 = READ_WORD(p); + int16 x2 = READ_WORD(p + 2); + int16 y1 = READ_WORD(p + 4); + int16 y2 = READ_WORD(p + 6); + uint8 buttons = buf[8]; + bool8 offscreen1 = buf[9]; + bool8 offscreen2 = buf[10]; + sprintf(string, "#%d %d: (%03d,%03d) %c%c%c / (%03d,%03d) %c%c%c", port, ids[0], + x1, y1, (buttons & 0x80) ? 'T' : ' ', (buttons & 0x20) ? 'S' : ' ', offscreen1 ? 'O' : ' ', + x2, y2, (buttons & 0x40) ? 'T' : ' ', (buttons & 0x10) ? 'S' : ' ', offscreen2 ? 'O' : ' '); + S9xDisplayString(string, line++, 1, false); + break; + } + + case CTL_JOYPAD: + { + sprintf(string, "#%d %d: ", port, ids[0]); + uint16 pad = MovieGetJoypad(ids[0]); + for (int i = 0; i < 15; i++) + { + int j = KeyOrder[i]; + int mask = (1 << (j + 1)); + string[6 + i]= (pad & mask) ? KeyMap[j] : ' '; + } + + S9xDisplayString(string, line++, 1, false); + break; + } + + case CTL_MP5: + { + for (int n = 0; n < 4; n++) + { + if (ids[n] != -1) + { + sprintf(string, "#%d %d: ", port, ids[n]); + uint16 pad = MovieGetJoypad(ids[n]); + for (int i = 0; i < 15; i++) + { + int j = KeyOrder[i]; + int mask = (1 << (j + 1)); + string[6 + i]= (pad & mask) ? KeyMap[j] : ' '; + } + + S9xDisplayString(string, line++, 1, false); + } + } + + break; + } + + case CTL_NONE: + { + sprintf(string, "#%d -", port); + S9xDisplayString(string, line++, 1, false); + break; + } + } + } +} + +static void DisplayWatchedAddresses (void) +{ + for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++) + { + if (!watches[i].on) + break; + + int32 displayNumber = 0; + char buf[32]; + + for (int r = 0; r < watches[i].size; r++) + displayNumber += (Cheat.CWatchRAM[(watches[i].address - 0x7E0000) + r]) << (8 * r); + + if (watches[i].format == 1) + sprintf(buf, "%s,%du = %u", watches[i].desc, watches[i].size, (unsigned int) displayNumber); + else + if (watches[i].format == 3) + sprintf(buf, "%s,%dx = %X", watches[i].desc, watches[i].size, (unsigned int) displayNumber); + else // signed + { + if (watches[i].size == 1) + displayNumber = (int32) ((int8) displayNumber); + else + if (watches[i].size == 2) + displayNumber = (int32) ((int16) displayNumber); + else + if (watches[i].size == 3) + if (displayNumber >= 8388608) + displayNumber -= 16777216; + + sprintf(buf, "%s,%ds = %d", watches[i].desc, watches[i].size, (int) displayNumber); + } + + S9xDisplayString(buf, 6 + i, 1, false); + } +} + +void S9xDisplayMessages (uint16 *screen, int ppl, int width, int height, int scale) +{ + if (Settings.DisplayFrameRate) + DisplayFrameRate(); + + if (Settings.DisplayWatchedAddresses) + DisplayWatchedAddresses(); + + if (Settings.DisplayPressedKeys) + DisplayPressedKeys(); + + if (Settings.DisplayMovieFrame && S9xMovieActive()) + S9xDisplayString(GFX.FrameDisplayString, 1, 1, false); + + if (GFX.InfoString && *GFX.InfoString) + S9xDisplayString(GFX.InfoString, 5, 1, true); +} + +static uint16 get_crosshair_color (uint8 color) +{ + switch (color & 15) + { + case 0: return (BUILD_PIXEL( 0, 0, 0)); // transparent, shouldn't be used + case 1: return (BUILD_PIXEL( 0, 0, 0)); // Black + case 2: return (BUILD_PIXEL( 8, 8, 8)); // 25Grey + case 3: return (BUILD_PIXEL(16, 16, 16)); // 50Grey + case 4: return (BUILD_PIXEL(23, 23, 23)); // 75Grey + case 5: return (BUILD_PIXEL(31, 31, 31)); // White + case 6: return (BUILD_PIXEL(31, 0, 0)); // Red + case 7: return (BUILD_PIXEL(31, 16, 0)); // Orange + case 8: return (BUILD_PIXEL(31, 31, 0)); // Yellow + case 9: return (BUILD_PIXEL( 0, 31, 0)); // Green + case 10: return (BUILD_PIXEL( 0, 31, 31)); // Cyan + case 11: return (BUILD_PIXEL( 0, 23, 31)); // Sky + case 12: return (BUILD_PIXEL( 0, 0, 31)); // Blue + case 13: return (BUILD_PIXEL(23, 0, 31)); // Violet + case 14: return (BUILD_PIXEL(31, 0, 31)); // Magenta + case 15: return (BUILD_PIXEL(31, 0, 16)); // Purple + } + + return (0); +} + +void S9xDrawCrosshair (const char *crosshair, uint8 fgcolor, uint8 bgcolor, int16 x, int16 y) +{ + if (!crosshair) + return; + + int16 r, rx = 1, c, cx = 1, W = SNES_WIDTH, H = PPU.ScreenHeight; + uint16 fg, bg; + + x -= 7; + y -= 7; + + if (IPPU.DoubleWidthPixels) { cx = 2; x *= 2; W *= 2; } + if (IPPU.DoubleHeightPixels) { rx = 2; y *= 2; H *= 2; } + + fg = get_crosshair_color(fgcolor); + bg = get_crosshair_color(bgcolor); + + // XXX: FIXME: why does it crash without this on Linux port? There are no out-of-bound writes without it... +#if (defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP)) + if (x >= 0 && y >= 0) +#endif + { + uint16 *s = GFX.Screen + y * GFX.RealPPL + x; + + for (r = 0; r < 15 * rx; r++, s += GFX.RealPPL - 15 * cx) + { + if (y + r < 0) + { + s += 15 * cx; + continue; + } + + if (y + r >= H) + break; + + for (c = 0; c < 15 * cx; c++, s++) + { + if (x + c < 0 || s < GFX.Screen) + continue; + + if (x + c >= W) + { + s += 15 * cx - c; + break; + } + + uint8 p = crosshair[(r / rx) * 15 + (c / cx)]; + + if (p == '#' && fgcolor) + *s = (fgcolor & 0x10) ? COLOR_ADD1_2(fg, *s) : fg; + else + if (p == '.' && bgcolor) + *s = (bgcolor & 0x10) ? COLOR_ADD1_2(*s, bg) : bg; + } + } + } +} + +#ifdef GFX_MULTI_FORMAT + +static uint32 BuildPixelRGB565 (uint32, uint32, uint32); +static uint32 BuildPixelRGB555 (uint32, uint32, uint32); +static uint32 BuildPixelBGR565 (uint32, uint32, uint32); +static uint32 BuildPixelBGR555 (uint32, uint32, uint32); +static uint32 BuildPixelGBR565 (uint32, uint32, uint32); +static uint32 BuildPixelGBR555 (uint32, uint32, uint32); +static uint32 BuildPixelRGB5551 (uint32, uint32, uint32); + +static uint32 BuildPixel2RGB565 (uint32, uint32, uint32); +static uint32 BuildPixel2RGB555 (uint32, uint32, uint32); +static uint32 BuildPixel2BGR565 (uint32, uint32, uint32); +static uint32 BuildPixel2BGR555 (uint32, uint32, uint32); +static uint32 BuildPixel2GBR565 (uint32, uint32, uint32); +static uint32 BuildPixel2GBR555 (uint32, uint32, uint32); +static uint32 BuildPixel2RGB5551 (uint32, uint32, uint32); + +static void DecomposePixelRGB565 (uint32, uint32 &, uint32 &, uint32 &); +static void DecomposePixelRGB555 (uint32, uint32 &, uint32 &, uint32 &); +static void DecomposePixelBGR565 (uint32, uint32 &, uint32 &, uint32 &); +static void DecomposePixelBGR555 (uint32, uint32 &, uint32 &, uint32 &); +static void DecomposePixelGBR565 (uint32, uint32 &, uint32 &, uint32 &); +static void DecomposePixelGBR555 (uint32, uint32 &, uint32 &, uint32 &); +static void DecomposePixelRGB5551 (uint32, uint32 &, uint32 &, uint32 &); + +#define _BUILD_PIXEL(F) \ +static uint32 BuildPixel##F (uint32 R, uint32 G, uint32 B) \ +{ \ + return (BUILD_PIXEL_##F(R, G, B)); \ +} \ +\ +static uint32 BuildPixel2##F (uint32 R, uint32 G, uint32 B) \ +{ \ + return (BUILD_PIXEL2_##F(R, G, B)); \ +} \ +\ +static void DecomposePixel##F (uint32 pixel, uint32 &R, uint32 &G, uint32 &B) \ +{ \ + DECOMPOSE_PIXEL_##F(pixel, R, G, B); \ +} + +_BUILD_PIXEL(RGB565) +_BUILD_PIXEL(RGB555) +_BUILD_PIXEL(BGR565) +_BUILD_PIXEL(BGR555) +_BUILD_PIXEL(GBR565) +_BUILD_PIXEL(GBR555) +_BUILD_PIXEL(RGB5551) + +#define _BUILD_SETUP(F) \ +GFX.BuildPixel = BuildPixel##F; \ +GFX.BuildPixel2 = BuildPixel2##F; \ +GFX.DecomposePixel = DecomposePixel##F; \ +RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_##F; \ +GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_##F; \ +BLUE_LOW_BIT_MASK = BLUE_LOW_BIT_MASK_##F; \ +RED_HI_BIT_MASK = RED_HI_BIT_MASK_##F; \ +GREEN_HI_BIT_MASK = GREEN_HI_BIT_MASK_##F; \ +BLUE_HI_BIT_MASK = BLUE_HI_BIT_MASK_##F; \ +MAX_RED = MAX_RED_##F; \ +MAX_GREEN = MAX_GREEN_##F; \ +MAX_BLUE = MAX_BLUE_##F; \ +SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_##F; \ +GREEN_HI_BIT = ((MAX_GREEN_##F + 1) >> 1); \ +RGB_LOW_BITS_MASK = (RED_LOW_BIT_MASK_##F | GREEN_LOW_BIT_MASK_##F | BLUE_LOW_BIT_MASK_##F); \ +RGB_HI_BITS_MASK = (RED_HI_BIT_MASK_##F | GREEN_HI_BIT_MASK_##F | BLUE_HI_BIT_MASK_##F); \ +RGB_HI_BITS_MASKx2 = (RED_HI_BIT_MASK_##F | GREEN_HI_BIT_MASK_##F | BLUE_HI_BIT_MASK_##F) << 1; \ +RGB_REMOVE_LOW_BITS_MASK = ~RGB_LOW_BITS_MASK; \ +FIRST_COLOR_MASK = FIRST_COLOR_MASK_##F; \ +SECOND_COLOR_MASK = SECOND_COLOR_MASK_##F; \ +THIRD_COLOR_MASK = THIRD_COLOR_MASK_##F; \ +ALPHA_BITS_MASK = ALPHA_BITS_MASK_##F; \ +FIRST_THIRD_COLOR_MASK = FIRST_COLOR_MASK | THIRD_COLOR_MASK; \ +TWO_LOW_BITS_MASK = RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 1); \ +HIGH_BITS_SHIFTED_TWO_MASK = ((FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) & ~TWO_LOW_BITS_MASK) >> 2; + +bool8 S9xSetRenderPixelFormat (int format) +{ + GFX.PixelFormat = format; + + switch (format) + { + case RGB565: + _BUILD_SETUP(RGB565) + return (TRUE); + + case RGB555: + _BUILD_SETUP(RGB555) + return (TRUE); + + case BGR565: + _BUILD_SETUP(BGR565) + return (TRUE); + + case BGR555: + _BUILD_SETUP(BGR555) + return (TRUE); + + case GBR565: + _BUILD_SETUP(GBR565) + return (TRUE); + + case GBR555: + _BUILD_SETUP(GBR555) + return (TRUE); + + case RGB5551: + _BUILD_SETUP(RGB5551) + return (TRUE); + + default: + break; + } + + return (FALSE); +} + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/gfx.h b/plugins/snes9x_gx/source/snes9x/gfx.h new file mode 100644 index 00000000..75981cc2 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/gfx.h @@ -0,0 +1,366 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _GFX_H_ +#define _GFX_H_ + +struct SGFX +{ + uint16 *Screen; + uint16 *SubScreen; + uint8 *ZBuffer; + uint8 *SubZBuffer; + uint32 Pitch; + uint32 ScreenSize; + uint16 *S; + uint8 *DB; + uint16 *X2; + uint16 *ZERO; + uint32 RealPPL; // true PPL of Screen buffer + uint32 PPL; // number of pixels on each of Screen buffer + uint32 LinesPerTile; // number of lines in 1 tile (4 or 8 due to interlace) + uint16 *ScreenColors; // screen colors for rendering main + uint16 *RealScreenColors; // screen colors, ignoring color window clipping + uint8 Z1; // depth for comparison + uint8 Z2; // depth to save + uint32 FixedColour; + uint8 DoInterlace; + uint8 InterlaceFrame; + uint32 StartY; + uint32 EndY; + bool8 ClipColors; + uint8 OBJWidths[128]; + uint8 OBJVisibleTiles[128]; + + struct ClipData *Clip; + + struct + { + uint8 RTOFlags; + int16 Tiles; + + struct + { + int8 Sprite; + uint8 Line; + } OBJ[32]; + } OBJLines[SNES_HEIGHT_EXTENDED]; + +#ifdef GFX_MULTI_FORMAT + uint32 PixelFormat; + uint32 (*BuildPixel) (uint32, uint32, uint32); + uint32 (*BuildPixel2) (uint32, uint32, uint32); + void (*DecomposePixel) (uint32, uint32 &, uint32 &, uint32 &); +#endif + + void (*DrawBackdropMath) (uint32, uint32, uint32); + void (*DrawBackdropNomath) (uint32, uint32, uint32); + void (*DrawTileMath) (uint32, uint32, uint32, uint32); + void (*DrawTileNomath) (uint32, uint32, uint32, uint32); + void (*DrawClippedTileMath) (uint32, uint32, uint32, uint32, uint32, uint32); + void (*DrawClippedTileNomath) (uint32, uint32, uint32, uint32, uint32, uint32); + void (*DrawMosaicPixelMath) (uint32, uint32, uint32, uint32, uint32, uint32); + void (*DrawMosaicPixelNomath) (uint32, uint32, uint32, uint32, uint32, uint32); + void (*DrawMode7BG1Math) (uint32, uint32, int); + void (*DrawMode7BG1Nomath) (uint32, uint32, int); + void (*DrawMode7BG2Math) (uint32, uint32, int); + void (*DrawMode7BG2Nomath) (uint32, uint32, int); + + const char *InfoString; + uint32 InfoStringTimeout; + char FrameDisplayString[256]; +}; + +struct SBG +{ + uint8 (*ConvertTile) (uint8 *, uint32, uint32); + uint8 (*ConvertTileFlip) (uint8 *, uint32, uint32); + + uint32 TileSizeH; + uint32 TileSizeV; + uint32 OffsetSizeH; + uint32 OffsetSizeV; + uint32 TileShift; + uint32 TileAddress; + uint32 NameSelect; + uint32 SCBase; + + uint32 StartPalette; + uint32 PaletteShift; + uint32 PaletteMask; + uint8 EnableMath; + uint8 InterlaceLine; + + uint8 *Buffer; + uint8 *BufferFlip; + uint8 *Buffered; + uint8 *BufferedFlip; + bool8 DirectColourMode; +}; + +struct SLineData +{ + struct + { + uint16 VOffset; + uint16 HOffset; + } BG[4]; +}; + +struct SLineMatrixData +{ + short MatrixA; + short MatrixB; + short MatrixC; + short MatrixD; + short CentreX; + short CentreY; + short M7HOFS; + short M7VOFS; +}; + +extern uint16 BlackColourMap[256]; +extern uint16 DirectColourMaps[8][256]; +extern uint8 mul_brightness[16][32]; +extern struct SBG BG; +extern struct SGFX GFX; + +#define H_FLIP 0x4000 +#define V_FLIP 0x8000 +#define BLANK_TILE 2 + +#define COLOR_ADD1_2(C1, C2) \ + ((((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \ + ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + \ + ((C1) & (C2) & RGB_LOW_BITS_MASK)) | ALPHA_BITS_MASK) + +#define COLOR_ADD(C1, C2) \ + (GFX.X2[((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \ + ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + \ + ((C1) & (C2) & RGB_LOW_BITS_MASK)] | \ + (((C1) ^ (C2)) & RGB_LOW_BITS_MASK)) + +#define COLOR_SUB1_2(C1, C2) \ + GFX.ZERO[(((C1) | RGB_HI_BITS_MASKx2) - \ + ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1] + +inline uint16 COLOR_SUB (uint16 C1, uint16 C2) +{ + uint16 mC1, mC2, v = ALPHA_BITS_MASK; + + mC1 = C1 & FIRST_COLOR_MASK; + mC2 = C2 & FIRST_COLOR_MASK; + if (mC1 > mC2) v += (mC1 - mC2); + + mC1 = C1 & SECOND_COLOR_MASK; + mC2 = C2 & SECOND_COLOR_MASK; + if (mC1 > mC2) v += (mC1 - mC2); + + mC1 = C1 & THIRD_COLOR_MASK; + mC2 = C2 & THIRD_COLOR_MASK; + if (mC1 > mC2) v += (mC1 - mC2); + + return (v); +} + +void S9xStartScreenRefresh (void); +void S9xEndScreenRefresh (void); +void S9xUpdateScreen (void); +void S9xBuildDirectColourMaps (void); +void RenderLine (uint8); +void S9xComputeClipWindows (void); +void S9xDisplayChar (uint16 *, uint8); +// called automatically unless Settings.AutoDisplayMessages is false +void S9xDisplayMessages (uint16 *, int, int, int, int); +#ifdef GFX_MULTI_FORMAT +bool8 S9xSetRenderPixelFormat (int); +#endif + +// external port interface which must be implemented or initialised for each port +bool8 S9xGraphicsInit (void); +void S9xGraphicsDeinit (void); +bool8 S9xInitUpdate (void); +bool8 S9xDeinitUpdate (int, int); +bool8 S9xContinueUpdate (int, int); +void S9xReRefresh (void); +void S9xSetPalette (void); +void S9xSyncSpeed (void); + +// called instead of S9xDisplayString if set to non-NULL +extern void (*S9xCustomDisplayString) (const char *, int, int, bool); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/globals.cpp b/plugins/snes9x_gx/source/snes9x/globals.cpp new file mode 100644 index 00000000..60d7959f --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/globals.cpp @@ -0,0 +1,399 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "dma.h" +#include "apu/apu.h" +#include "fxinst.h" +#include "fxemu.h" +#include "srtc.h" +#include "cheats.h" +#ifdef NETPLAY_SUPPORT +#include "netplay.h" +#endif +#ifdef DEBUGGER +#include "debug.h" +#include "missing.h" +#endif + +struct SCPUState CPU; +struct SICPU ICPU; +struct SRegisters Registers; +struct SPPU PPU; +struct InternalPPU IPPU; +struct SDMA DMA[8]; +struct STimings Timings; +struct SGFX GFX; +struct SBG BG; +struct SLineData LineData[240]; +struct SLineMatrixData LineMatrixData[240]; +struct SDSP0 DSP0; +struct SDSP1 DSP1; +struct SDSP2 DSP2; +struct SDSP3 DSP3; +struct SDSP4 DSP4; +struct SSA1 SA1; +struct SSA1Registers SA1Registers; +struct FxRegs_s GSU; +struct FxInfo_s SuperFX; +struct SST010 ST010; +struct SST011 ST011; +struct SST018 ST018; +struct SOBC1 OBC1; +struct SSPC7110Snapshot s7snap; +struct SSRTCSnapshot srtcsnap; +struct SRTCData RTCData; +struct SBSX BSX; +struct SMulti Multi; +struct SSettings Settings; +struct SSNESGameFixes SNESGameFixes; +#ifdef NETPLAY_SUPPORT +struct SNetPlay NetPlay; +#endif +#ifdef DEBUGGER +struct Missing missing; +#endif +struct SCheatData Cheat; +struct Watch watches[16]; +CMemory Memory; + +char String[513]; +uint8 OpenBus = 0; +uint8 *HDMAMemPointers[8]; +uint16 BlackColourMap[256]; +uint16 DirectColourMaps[8][256]; + +SnesModel M1SNES = { 1, 3, 2 }; +SnesModel M2SNES = { 2, 4, 3 }; +SnesModel *Model = &M1SNES; + +#ifdef GFX_MULTI_FORMAT +uint32 RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_RGB565; +uint32 GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_RGB565; +uint32 BLUE_LOW_BIT_MASK = BLUE_LOW_BIT_MASK_RGB565; +uint32 RED_HI_BIT_MASK = RED_HI_BIT_MASK_RGB565; +uint32 GREEN_HI_BIT_MASK = GREEN_HI_BIT_MASK_RGB565; +uint32 BLUE_HI_BIT_MASK = BLUE_HI_BIT_MASK_RGB565; +uint32 MAX_RED = MAX_RED_RGB565; +uint32 MAX_GREEN = MAX_GREEN_RGB565; +uint32 MAX_BLUE = MAX_BLUE_RGB565; +uint32 SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_RGB565; +uint32 GREEN_HI_BIT = (MAX_GREEN_RGB565 + 1) >> 1; +uint32 RGB_LOW_BITS_MASK = (RED_LOW_BIT_MASK_RGB565 | GREEN_LOW_BIT_MASK_RGB565 | BLUE_LOW_BIT_MASK_RGB565); +uint32 RGB_HI_BITS_MASK = (RED_HI_BIT_MASK_RGB565 | GREEN_HI_BIT_MASK_RGB565 | BLUE_HI_BIT_MASK_RGB565); +uint32 RGB_HI_BITS_MASKx2 = (RED_HI_BIT_MASK_RGB565 | GREEN_HI_BIT_MASK_RGB565 | BLUE_HI_BIT_MASK_RGB565) << 1; +uint32 RGB_REMOVE_LOW_BITS_MASK = ~RGB_LOW_BITS_MASK; +uint32 FIRST_COLOR_MASK = FIRST_COLOR_MASK_RGB565; +uint32 SECOND_COLOR_MASK = SECOND_COLOR_MASK_RGB565; +uint32 THIRD_COLOR_MASK = THIRD_COLOR_MASK_RGB565; +uint32 ALPHA_BITS_MASK = ALPHA_BITS_MASK_RGB565; +uint32 FIRST_THIRD_COLOR_MASK = 0; +uint32 TWO_LOW_BITS_MASK = 0; +uint32 HIGH_BITS_SHIFTED_TWO_MASK = 0; +#endif + +uint16 SignExtend[2] = +{ + 0x0000, + 0xff00 +}; + +int HDMA_ModeByteCounts[8] = +{ + 1, 2, 2, 4, 4, 4, 2, 4 +}; + +uint8 mul_brightness[16][32] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }, + { 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04 }, + { 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06 }, + { 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, + 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08 }, + { 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, + 0x05, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a }, + { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, + 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c }, + { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, + 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e }, + { 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x08, + 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x11 }, + { 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, + 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x11, 0x12, 0x13 }, + { 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x05, 0x06, 0x07, 0x07, 0x08, 0x09, 0x09, 0x0a, + 0x0b, 0x0b, 0x0c, 0x0d, 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x11, 0x12, 0x13, 0x13, 0x14, 0x15 }, + { 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x05, 0x06, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0a, 0x0b, + 0x0c, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14, 0x15, 0x15, 0x16, 0x17 }, + { 0x00, 0x01, 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0a, 0x0b, 0x0c, + 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14, 0x15, 0x16, 0x16, 0x17, 0x18, 0x19 }, + { 0x00, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x17, 0x18, 0x19, 0x1a, 0x1b }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f } +}; + +uint8 S9xOpLengthsM0X0[256] = +{ +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 0 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 + 3, 2, 4, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 2 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 + 1, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 4 + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 + 1, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 6 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 + 2, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 8 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 + 3, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // A + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B + 3, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // C + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D + 3, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // E + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F +}; + +uint8 S9xOpLengthsM0X1[256] = +{ +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 0 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 + 3, 2, 4, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 2 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 + 1, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 4 + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 + 1, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 6 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 + 2, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 8 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // A + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // C + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // E + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F +}; + +uint8 S9xOpLengthsM1X0[256] = +{ +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 0 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 + 3, 2, 4, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 2 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 + 1, 2, 2, 2, 3, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 4 + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 + 1, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 6 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 + 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 8 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 + 3, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // A + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B + 3, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // C + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D + 3, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // E + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F +}; + +uint8 S9xOpLengthsM1X1[256] = +{ +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 0 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 + 3, 2, 4, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 2 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 + 1, 2, 2, 2, 3, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 4 + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 + 1, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 6 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 + 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 8 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // A + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // C + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // E + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F +}; diff --git a/plugins/snes9x_gx/source/snes9x/language.h b/plugins/snes9x_gx/source/snes9x/language.h new file mode 100644 index 00000000..49a30ae1 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/language.h @@ -0,0 +1,202 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _LANGUAGE_H_ +#define _LANGUAGE_H_ + +// Movie Messages +#define MOVIE_ERR_SNAPSHOT_WRONG_MOVIE "Snapshot not from this movie" +#define MOVIE_ERR_SNAPSHOT_NOT_MOVIE "Not a movie snapshot" +#define MOVIE_INFO_REPLAY "Movie replay" +#define MOVIE_INFO_RECORD "Movie record" +#define MOVIE_INFO_RERECORD "Movie re-record" +#define MOVIE_INFO_REWIND "Movie rewind" +#define MOVIE_INFO_STOP "Movie stop" +#define MOVIE_INFO_END "Movie end" +#define MOVIE_INFO_SNAPSHOT "Movie snapshot" +#define MOVIE_ERR_SNAPSHOT_INCONSISTENT "Snapshot inconsistent with movie" + +// Snapshot Messages +#define SAVE_INFO_SNAPSHOT "Saved" +#define SAVE_INFO_LOAD "Loaded" +#define SAVE_INFO_OOPS "Auto-saving 'oops' snapshot" +#define SAVE_ERR_WRONG_FORMAT "File not in Snes9x snapshot format" +#define SAVE_ERR_WRONG_VERSION "Incompatable snapshot version" +#define SAVE_ERR_ROM_NOT_FOUND "ROM image \"%s\" for snapshot not found" +#define SAVE_ERR_SAVE_NOT_FOUND "Snapshot %s does not exist" + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/logger.cpp b/plugins/snes9x_gx/source/snes9x/logger.cpp new file mode 100644 index 00000000..235c5335 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/logger.cpp @@ -0,0 +1,267 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "movie.h" +#include "logger.h" + +static int resetno = 0; +static int framecounter = 0; +static FILE *video = NULL; +static FILE *audio = NULL; + + +void S9xResetLogger (void) +{ + if (!Settings.DumpStreams) + return; + + char buffer[128]; + + S9xCloseLogger(); + framecounter = 0; + + sprintf(buffer, "videostream%d.dat", resetno); + video = fopen(buffer, "wb"); + if (!video) + { + printf("Opening %s failed. Logging cancelled.\n", buffer); + return; + } + + sprintf(buffer, "audiostream%d.dat", resetno); + audio = fopen(buffer, "wb"); + if (!audio) + { + printf("Opening %s failed. Logging cancelled.\n", buffer); + fclose(video); + return; + } + + resetno++; +} + +void S9xCloseLogger (void) +{ + if (video) + { + fclose(video); + video = NULL; + } + + if (audio) + { + fclose(audio); + audio = NULL; + } +} + +void S9xVideoLogger (void *pixels, int width, int height, int depth, int bytes_per_line) +{ + int fc = S9xMovieGetFrameCounter(); + if (fc > 0) + framecounter = fc; + else + framecounter++; + + if (video) + { + char *data = (char *) pixels; + size_t ignore; + + for (int i = 0; i < height; i++) + ignore = fwrite(data + i * bytes_per_line, depth, width, video); + fflush(video); + fflush(audio); + + if (Settings.DumpStreamsMaxFrames > 0 && framecounter >= Settings.DumpStreamsMaxFrames) + { + printf("Logging ended.\n"); + S9xCloseLogger(); + } + + } +} + +void S9xAudioLogger (void *samples, int length) +{ + if (audio) + { + size_t ignore; + ignore = fwrite(samples, 1, length, audio); + } +} diff --git a/plugins/snes9x_gx/source/snes9x/logger.h b/plugins/snes9x_gx/source/snes9x/logger.h new file mode 100644 index 00000000..63aa30b7 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/logger.h @@ -0,0 +1,186 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _LOGGER_H_ +#define _LOGGER_H_ + +void S9xResetLogger(void); +void S9xCloseLogger(void); +void S9xVideoLogger(void *, int, int, int, int); +void S9xAudioLogger(void *, int); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/memmap.cpp b/plugins/snes9x_gx/source/snes9x/memmap.cpp new file mode 100644 index 00000000..d7297693 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/memmap.cpp @@ -0,0 +1,4613 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + +#ifdef GEKKO +#include <gccore.h> +#include <malloc.h> +#endif + +#include <string> +#include <numeric> +#include <assert.h> + +#ifdef UNZIP_SUPPORT +#include "unzip/unzip.h" +#endif + +#ifdef JMA_SUPPORT +#include "jma/s9x-jma.h" +#endif + +#include "snes9x.h" +#include "memmap.h" +#include "apu/apu.h" +#include "fxemu.h" +#include "sdd1.h" +#include "srtc.h" +#include "controls.h" +#include "cheats.h" +#include "movie.h" +#include "reader.h" +#include "display.h" + +#ifdef GEKKO +#include "../filebrowser.h" +extern int WiiFileLoader(); +extern void WiiSetupCheats(); +#endif + +#ifndef SET_UI_COLOR +#define SET_UI_COLOR(r, g, b) ; +#endif + +#ifndef max +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +static bool8 stopMovie = TRUE; +static char LastRomFilename[PATH_MAX + 1] = ""; + +// from NSRT +static const char *nintendo_licensees[] = +{ + "Unlicensed", + "Nintendo", + "Rocket Games/Ajinomoto", + "Imagineer-Zoom", + "Gray Matter", + "Zamuse", + "Falcom", + NULL, + "Capcom", + "Hot B Co.", + "Jaleco", + "Coconuts Japan", + "Coconuts Japan/G.X.Media", + "Micronet", + "Technos", + "Mebio Software", + "Shouei System", + "Starfish", + NULL, + "Mitsui Fudosan/Dentsu", + NULL, + "Warashi Inc.", + NULL, + "Nowpro", + NULL, + "Game Village", + "IE Institute", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Banarex", + "Starfish", + "Infocom", + "Electronic Arts Japan", + NULL, + "Cobra Team", + "Human/Field", + "KOEI", + "Hudson Soft", + "S.C.P./Game Village", + "Yanoman", + NULL, + "Tecmo Products", + "Japan Glary Business", + "Forum/OpenSystem", + "Virgin Games (Japan)", + "SMDE", + "Yojigen", + NULL, + "Daikokudenki", + NULL, + NULL, + NULL, + NULL, + NULL, + "Creatures Inc.", + "TDK Deep Impresion", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Destination Software/KSS", + "Sunsoft/Tokai Engineering", + "POW (Planning Office Wada)/VR 1 Japan", + "Micro World", + NULL, + "San-X", + "Enix", + "Loriciel/Electro Brain", + "Kemco Japan", + "Seta Co.,Ltd.", + "Culture Brain", + "Irem Corp.", + "Palsoft", + "Visit Co., Ltd.", + "Intec", + "System Sacom", + "Poppo", + "Ubisoft Japan", + NULL, + "Media Works", + "NEC InterChannel", + "Tam", + "Gajin/Jordan", + "Smilesoft", + NULL, + NULL, + "Mediakite", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Viacom", + "Carrozzeria", + "Dynamic", + NULL, + "Magifact", + "Hect", + "Codemasters", + "Taito/GAGA Communications", + "Laguna", + "Telstar Fun & Games/Event/Taito", + NULL, + "Arcade Zone Ltd.", + "Entertainment International/Empire Software", + "Loriciel", + "Gremlin Graphics", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Seika Corp.", + "UBI SOFT Entertainment Software", + "Sunsoft US", + NULL, + "Life Fitness", + NULL, + "System 3", + "Spectrum Holobyte", + NULL, + "Irem", + NULL, + "Raya Systems", + "Renovation Products", + "Malibu Games", + NULL, + "Eidos/U.S. Gold", + "Playmates Interactive", + NULL, + NULL, + "Fox Interactive", + "Time Warner Interactive", + NULL, + NULL, + NULL, + NULL, + NULL, + "Disney Interactive", + NULL, + "Black Pearl", + NULL, + "Advanced Productions", + NULL, + NULL, + "GT Interactive", + "RARE", + "Crave Entertainment", + "Absolute Entertainment", + "Acclaim", + "Activision", + "American Sammy", + "Take 2/GameTek", + "Hi Tech", + "LJN Ltd.", + NULL, + "Mattel", + NULL, + "Mindscape/Red Orb Entertainment", + "Romstar", + "Taxan", + "Midway/Tradewest", + NULL, + "American Softworks Corp.", + "Majesco Sales Inc.", + "3DO", + NULL, + NULL, + "Hasbro", + "NewKidCo", + "Telegames", + "Metro3D", + NULL, + "Vatical Entertainment", + "LEGO Media", + NULL, + "Xicat Interactive", + "Cryo Interactive", + NULL, + NULL, + "Red Storm Entertainment", + "Microids", + NULL, + "Conspiracy/Swing", + "Titus", + "Virgin Interactive", + "Maxis", + NULL, + "LucasArts Entertainment", + NULL, + NULL, + "Ocean", + NULL, + "Electronic Arts", + NULL, + "Laser Beam", + NULL, + NULL, + "Elite Systems", + "Electro Brain", + "The Learning Company", + "BBC", + NULL, + "Software 2000", + NULL, + "BAM! Entertainment", + "Studio 3", + NULL, + NULL, + NULL, + "Classified Games", + NULL, + "TDK Mediactive", + NULL, + "DreamCatcher", + "JoWood Produtions", + "SEGA", + "Wannado Edition", + "LSP (Light & Shadow Prod.)", + "ITE Media", + "Infogrames", + "Interplay", + "JVC (US)", + "Parker Brothers", + NULL, + "SCI (Sales Curve Interactive)/Storm", + NULL, + NULL, + "THQ Software", + "Accolade Inc.", + "Triffix Entertainment", + NULL, + "Microprose Software", + "Universal Interactive/Sierra/Simon & Schuster", + NULL, + "Kemco", + "Rage Software", + "Encore", + NULL, + "Zoo", + "Kiddinx", + "Simon & Schuster Interactive", + "Asmik Ace Entertainment Inc./AIA", + "Empire Interactive", + NULL, + NULL, + "Jester Interactive", + NULL, + "Rockstar Games", + "Scholastic", + "Ignition Entertainment", + "Summitsoft", + "Stadlbauer", + NULL, + NULL, + NULL, + "Misawa", + "Teichiku", + "Namco Ltd.", + "LOZC", + "KOEI", + NULL, + "Tokuma Shoten Intermedia", + "Tsukuda Original", + "DATAM-Polystar", + NULL, + NULL, + "Bullet-Proof Software", + "Vic Tokai Inc.", + NULL, + "Character Soft", + "I'Max", + "Saurus", + NULL, + NULL, + "General Entertainment", + NULL, + NULL, + "I'Max", + "Success", + NULL, + "SEGA Japan", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Takara", + "Chun Soft", + "Video System Co., Ltd./McO'River", + "BEC", + NULL, + "Varie", + "Yonezawa/S'pal", + "Kaneko", + NULL, + "Victor Interactive Software/Pack-in-Video", + "Nichibutsu/Nihon Bussan", + "Tecmo", + "Imagineer", + NULL, + NULL, + "Nova", + "Den'Z", + "Bottom Up", + NULL, + "TGL (Technical Group Laboratory)", + NULL, + "Hasbro Japan", + NULL, + "Marvelous Entertainment", + NULL, + "Keynet Inc.", + "Hands-On Entertainment", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Telenet", + "Hori", + NULL, + NULL, + "Konami", + "K.Amusement Leasing Co.", + "Kawada", + "Takara", + NULL, + "Technos Japan Corp.", + "JVC (Europe/Japan)/Victor Musical Industries", + NULL, + "Toei Animation", + "Toho", + NULL, + "Namco", + "Media Rings Corp.", + "J-Wing", + NULL, + "Pioneer LDC", + "KID", + "Mediafactory", + NULL, + NULL, + NULL, + "Infogrames Hudson", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Acclaim Japan", + "ASCII Co./Nexoft", + "Bandai", + NULL, + "Enix", + NULL, + "HAL Laboratory/Halken", + "SNK", + NULL, + "Pony Canyon Hanbai", + "Culture Brain", + "Sunsoft", + "Toshiba EMI", + "Sony Imagesoft", + NULL, + "Sammy", + "Magical", + "Visco", + NULL, + "Compile", + NULL, + "MTO Inc.", + NULL, + "Sunrise Interactive", + NULL, + "Global A Entertainment", + "Fuuki", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Taito", + NULL, + "Kemco", + "Square", + "Tokuma Shoten", + "Data East", + "Tonkin House", + NULL, + "KOEI", + NULL, + "Konami/Ultra/Palcom", + "NTVIC/VAP", + "Use Co., Ltd.", + "Meldac", + "Pony Canyon (Japan)/FCI (US)", + "Angel/Sotsu Agency/Sunrise", + "Yumedia/Aroma Co., Ltd.", + NULL, + NULL, + "Boss", + "Axela/Crea-Tech", + "Sekaibunka-Sha/Sumire kobo/Marigul Management Inc.", + "Konami Computer Entertainment Osaka", + NULL, + NULL, + "Enterbrain", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Taito/Disco", + "Sofel", + "Quest Corp.", + "Sigma", + "Ask Kodansha", + NULL, + "Naxat", + "Copya System", + "Capcom Co., Ltd.", + "Banpresto", + "TOMY", + "Acclaim/LJN Japan", + NULL, + "NCS", + "Human Entertainment", + "Altron", + "Jaleco", + "Gaps Inc.", + NULL, + NULL, + NULL, + NULL, + NULL, + "Elf", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Jaleco", + NULL, + "Yutaka", + "Varie", + "T&ESoft", + "Epoch Co., Ltd.", + NULL, + "Athena", + "Asmik", + "Natsume", + "King Records", + "Atlus", + "Epic/Sony Records (Japan)", + NULL, + "IGS (Information Global Service)", + NULL, + "Chatnoir", + "Right Stuff", + NULL, + "NTT COMWARE", + NULL, + "Spike", + "Konami Computer Entertainment Tokyo", + "Alphadream Corp.", + NULL, + "Sting", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "A Wave", + "Motown Software", + "Left Field Entertainment", + "Extreme Entertainment Group", + "TecMagik", + NULL, + NULL, + NULL, + NULL, + "Cybersoft", + NULL, + "Psygnosis", + NULL, + NULL, + "Davidson/Western Tech.", + "Unlicensed", + NULL, + NULL, + NULL, + NULL, + "The Game Factory Europe", + "Hip Games", + "Aspyr", + NULL, + NULL, + "Mastiff", + "iQue", + "Digital Tainment Pool", + "XS Games", + "Daiwon", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "PCCW Japan", + NULL, + NULL, + "KiKi Co. Ltd.", + "Open Sesame Inc.", + "Sims", + "Broccoli", + "Avex", + "D3 Publisher", + NULL, + "Konami Computer Entertainment Japan", + NULL, + "Square-Enix", + "KSG", + "Micott & Basara Inc.", + NULL, + "Orbital Media", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "The Game Factory USA", + NULL, + NULL, + "Treasure", + "Aruze", + "Ertain", + "SNK Playmore", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Yojigen" +}; + +static const uint32 crc32Table[256] = +{ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +static void S9xDeinterleaveType1 (int, uint8 *); +static void S9xDeinterleaveType2 (int, uint8 *); +static void S9xDeinterleaveGD24 (int, uint8 *); +static bool8 allASCII (uint8 *, int); +static bool8 is_SufamiTurbo_BIOS (uint8 *, uint32); +static bool8 is_SufamiTurbo_Cart (uint8 *, uint32); +static bool8 is_SameGame_BIOS (uint8 *, uint32); +static bool8 is_SameGame_Add_On (uint8 *, uint32); +static uint32 caCRC32 (uint8 *, uint32, uint32 crc32 = 0xffffffff); +static uint32 ReadUPSPointer (const uint8 *, unsigned &, unsigned); +static bool8 ReadUPSPatch (Reader *, long, int32 &); +static long ReadInt (Reader *, unsigned); +static bool8 ReadIPSPatch (Reader *, long, int32 &); +#ifdef UNZIP_SUPPORT +static int unzFindExtension (unzFile &, const char *, bool restart = TRUE, bool print = TRUE); +#endif + +// deinterleave + +static void S9xDeinterleaveType1 (int size, uint8 *base) +{ + Settings.DisplayColor = BUILD_PIXEL(0, 31, 0); + SET_UI_COLOR(0, 255, 0); + + uint8 blocks[256]; + int nblocks = size >> 16; + + for (int i = 0; i < nblocks; i++) + { + blocks[i * 2] = i + nblocks; + blocks[i * 2 + 1] = i; + } + + uint8 *tmp = (uint8 *) memalign(32,0x8000); + if (tmp) + { + for (int i = 0; i < nblocks * 2; i++) + { + for (int j = i; j < nblocks * 2; j++) + { + if (blocks[j] == i) + { + memmove(tmp, &base[blocks[j] * 0x8000], 0x8000); + memmove(&base[blocks[j] * 0x8000], &base[blocks[i] * 0x8000], 0x8000); + memmove(&base[blocks[i] * 0x8000], tmp, 0x8000); + uint8 b = blocks[j]; + blocks[j] = blocks[i]; + blocks[i] = b; + break; + } + } + } + + free(tmp); + } +} + +static void S9xDeinterleaveType2 (int size, uint8 *base) +{ + // for odd Super FX images + Settings.DisplayColor = BUILD_PIXEL(31, 14, 6); + SET_UI_COLOR(255, 119, 25); + + uint8 blocks[256]; + int nblocks = size >> 16; + int step = 64; + + while (nblocks <= step) + step >>= 1; + nblocks = step; + + for (int i = 0; i < nblocks * 2; i++) + blocks[i] = (i & ~0xf) | ((i & 3) << 2) | ((i & 12) >> 2); + + uint8 *tmp = (uint8 *) memalign(32,0x10000); + if (tmp) + { + for (int i = 0; i < nblocks * 2; i++) + { + for (int j = i; j < nblocks * 2; j++) + { + if (blocks[j] == i) + { + memmove(tmp, &base[blocks[j] * 0x10000], 0x10000); + memmove(&base[blocks[j] * 0x10000], &base[blocks[i] * 0x10000], 0x10000); + memmove(&base[blocks[i] * 0x10000], tmp, 0x10000); + uint8 b = blocks[j]; + blocks[j] = blocks[i]; + blocks[i] = b; + break; + } + } + } + + free(tmp); + } +} + +static void S9xDeinterleaveGD24 (int size, uint8 *base) +{ + // for 24Mb images dumped with Game Doctor + if (size != 0x300000) + return; + + Settings.DisplayColor = BUILD_PIXEL(0, 31, 31); + SET_UI_COLOR(0, 255, 255); + + uint8 *tmp = (uint8 *) memalign(32,0x80000); + if (tmp) + { + memmove(tmp, &base[0x180000], 0x80000); + memmove(&base[0x180000], &base[0x200000], 0x80000); + memmove(&base[0x200000], &base[0x280000], 0x80000); + memmove(&base[0x280000], tmp, 0x80000); + + free(tmp); + + S9xDeinterleaveType1(size, base); + } +} + +// allocation and deallocation + +bool8 CMemory::Init (void) +{ + RAM = (uint8 *) memalign(32,0x20000); + SRAM = (uint8 *) memalign(32,0x20000); + VRAM = (uint8 *) memalign(32,0x10000); + ROM = (uint8 *) memalign(32,MAX_ROM_SIZE + 0x200 + 0x8000); + + IPPU.TileCache[TILE_2BIT] = (uint8 *) memalign(32,MAX_2BIT_TILES * 64); + IPPU.TileCache[TILE_4BIT] = (uint8 *) memalign(32,MAX_4BIT_TILES * 64); + IPPU.TileCache[TILE_8BIT] = (uint8 *) memalign(32,MAX_8BIT_TILES * 64); + IPPU.TileCache[TILE_2BIT_EVEN] = (uint8 *) memalign(32,MAX_2BIT_TILES * 64); + IPPU.TileCache[TILE_2BIT_ODD] = (uint8 *) memalign(32,MAX_2BIT_TILES * 64); + IPPU.TileCache[TILE_4BIT_EVEN] = (uint8 *) memalign(32,MAX_4BIT_TILES * 64); + IPPU.TileCache[TILE_4BIT_ODD] = (uint8 *) memalign(32,MAX_4BIT_TILES * 64); + + IPPU.TileCached[TILE_2BIT] = (uint8 *) memalign(32,MAX_2BIT_TILES); + IPPU.TileCached[TILE_4BIT] = (uint8 *) memalign(32,MAX_4BIT_TILES); + IPPU.TileCached[TILE_8BIT] = (uint8 *) memalign(32,MAX_8BIT_TILES); + IPPU.TileCached[TILE_2BIT_EVEN] = (uint8 *) memalign(32,MAX_2BIT_TILES); + IPPU.TileCached[TILE_2BIT_ODD] = (uint8 *) memalign(32,MAX_2BIT_TILES); + IPPU.TileCached[TILE_4BIT_EVEN] = (uint8 *) memalign(32,MAX_4BIT_TILES); + IPPU.TileCached[TILE_4BIT_ODD] = (uint8 *) memalign(32,MAX_4BIT_TILES); + + if (!RAM || !SRAM || !VRAM || !ROM || + !IPPU.TileCache[TILE_2BIT] || + !IPPU.TileCache[TILE_4BIT] || + !IPPU.TileCache[TILE_8BIT] || + !IPPU.TileCache[TILE_2BIT_EVEN] || + !IPPU.TileCache[TILE_2BIT_ODD] || + !IPPU.TileCache[TILE_4BIT_EVEN] || + !IPPU.TileCache[TILE_4BIT_ODD] || + !IPPU.TileCached[TILE_2BIT] || + !IPPU.TileCached[TILE_4BIT] || + !IPPU.TileCached[TILE_8BIT] || + !IPPU.TileCached[TILE_2BIT_EVEN] || + !IPPU.TileCached[TILE_2BIT_ODD] || + !IPPU.TileCached[TILE_4BIT_EVEN] || + !IPPU.TileCached[TILE_4BIT_ODD]) + { + Deinit(); + return (FALSE); + } + + ZeroMemory(RAM, 0x20000); + ZeroMemory(SRAM, 0x20000); + ZeroMemory(VRAM, 0x10000); + ZeroMemory(ROM, MAX_ROM_SIZE + 0x200 + 0x8000); + + ZeroMemory(IPPU.TileCache[TILE_2BIT], MAX_2BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_4BIT], MAX_4BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_8BIT], MAX_8BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_2BIT_EVEN], MAX_2BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_2BIT_ODD], MAX_2BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_4BIT_EVEN], MAX_4BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_4BIT_ODD], MAX_4BIT_TILES * 64); + + ZeroMemory(IPPU.TileCached[TILE_2BIT], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT], MAX_4BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_8BIT], MAX_8BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_2BIT_EVEN], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_2BIT_ODD], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT_EVEN], MAX_4BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT_ODD], MAX_4BIT_TILES); + + // FillRAM uses first 32K of ROM image area, otherwise space just + // wasted. Might be read by the SuperFX code. + + FillRAM = ROM; + + // Add 0x8000 to ROM image pointer to stop SuperFX code accessing + // unallocated memory (can cause crash on some ports). + + ROM += 0x8000; + + C4RAM = ROM + 0x400000 + 8192 * 8; // C4 + OBC1RAM = ROM + 0x400000; // OBC1 + BIOSROM = ROM + 0x300000; // BS + BSRAM = ROM + 0x400000; // BS + + SuperFX.pvRegisters = FillRAM + 0x3000; + SuperFX.nRamBanks = 2; // Most only use 1. 1=64KB=512Mb, 2=128KB=1024Mb + SuperFX.pvRam = SRAM; + SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024); + SuperFX.pvRom = (uint8 *) ROM; + + PostRomInitFunc = NULL; + + return (TRUE); +} + +void CMemory::Deinit (void) +{ + if (RAM) + { + free(RAM); + RAM = NULL; + } + + if (SRAM) + { + free(SRAM); + SRAM = NULL; + } + + if (VRAM) + { + free(VRAM); + VRAM = NULL; + } + + if (ROM) + { + ROM -= 0x8000; + free(ROM); + ROM = NULL; + } + + for (int t = 0; t < 7; t++) + { + if (IPPU.TileCache[t]) + { + free(IPPU.TileCache[t]); + IPPU.TileCache[t] = NULL; + } + + if (IPPU.TileCached[t]) + { + free(IPPU.TileCached[t]); + IPPU.TileCached[t] = NULL; + } + } + + Safe(NULL); + SafeANK(NULL); +} + +// file management and ROM detection + +static bool8 allASCII (uint8 *b, int size) +{ + for (int i = 0; i < size; i++) + { + if (b[i] < 32 || b[i] > 126) + return (FALSE); + } + + return (TRUE); +} + +static bool8 is_SufamiTurbo_BIOS (uint8 *data, uint32 size) +{ + if (size == 0x40000 && + strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0 && strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) == 0) + return (TRUE); + else + return (FALSE); +} + +static bool8 is_SufamiTurbo_Cart (uint8 *data, uint32 size) +{ + if (size >= 0x80000 && size <= 0x100000 && + strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0 && strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) != 0) + return (TRUE); + else + return (FALSE); +} + +static bool8 is_SameGame_BIOS (uint8 *data, uint32 size) +{ + if (size == 0x100000 && strncmp((char *) (data + 0xffc0), "Same Game Tsume Game", 20) == 0) + return (TRUE); + else + return (FALSE); +} + +static bool8 is_SameGame_Add_On (uint8 *data, uint32 size) +{ + if (size == 0x80000) + return (TRUE); + else + return (FALSE); +} + +int CMemory::ScoreHiROM (bool8 skip_header, int32 romoff) +{ + uint8 *buf = ROM + 0xff00 + romoff + (skip_header ? 0x200 : 0); + int score = 0; + + if (buf[0xd5] & 0x1) + score += 2; + + // Mode23 is SA-1 + if (buf[0xd5] == 0x23) + score -= 2; + + if (buf[0xd4] == 0x20) + score += 2; + + if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff) + { + score += 2; + if (0 != (buf[0xde] + (buf[0xdf] << 8))) + score++; + } + + if (buf[0xda] == 0x33) + score += 2; + + if ((buf[0xd5] & 0xf) < 4) + score += 2; + + if (!(buf[0xfd] & 0x80)) + score -= 6; + + if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0) + score -= 2; // reduced after looking at a scan by Cowering + + if (CalculatedSize > 1024 * 1024 * 3) + score += 4; + + if ((1 << (buf[0xd7] - 7)) > 48) + score -= 1; + + if (!allASCII(&buf[0xb0], 6)) + score -= 1; + + if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1)) + score -= 1; + + return (score); +} + +int CMemory::ScoreLoROM (bool8 skip_header, int32 romoff) +{ + uint8 *buf = ROM + 0x7f00 + romoff + (skip_header ? 0x200 : 0); + int score = 0; + + if (!(buf[0xd5] & 0x1)) + score += 3; + + // Mode23 is SA-1 + if (buf[0xd5] == 0x23) + score += 2; + + if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff) + { + score += 2; + if (0 != (buf[0xde] + (buf[0xdf] << 8))) + score++; + } + + if (buf[0xda] == 0x33) + score += 2; + + if ((buf[0xd5] & 0xf) < 4) + score += 2; + + if (!(buf[0xfd] & 0x80)) + score -= 6; + + if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0) + score -= 2; // reduced per Cowering suggestion + + if (CalculatedSize <= 1024 * 1024 * 16) + score += 2; + + if ((1 << (buf[0xd7] - 7)) > 48) + score -= 1; + + if (!allASCII(&buf[0xb0], 6)) + score -= 1; + + if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1)) + score -= 1; + + return (score); +} + +uint32 CMemory::HeaderRemove (uint32 size, int32 &headerCount, uint8 *buf) +{ + uint32 calc_size = (size / 0x2000) * 0x2000; + + if ((size - calc_size == 512 && !Settings.ForceNoHeader) || Settings.ForceHeader) + { + uint8 *NSRTHead = buf + 0x1D0; // NSRT Header Location + + // detect NSRT header + if (!strncmp("NSRT", (char *) &NSRTHead[24], 4)) + { + if (NSRTHead[28] == 22) + { + if (((std::accumulate(NSRTHead, NSRTHead + sizeof(NSRTHeader), 0) & 0xFF) == NSRTHead[30]) && + (NSRTHead[30] + NSRTHead[31] == 255) && ((NSRTHead[0] & 0x0F) <= 13) && + (((NSRTHead[0] & 0xF0) >> 4) <= 3) && ((NSRTHead[0] & 0xF0) >> 4)) + memcpy(NSRTHeader, NSRTHead, sizeof(NSRTHeader)); + } + } + + memmove(buf, buf + 512, calc_size); + headerCount++; + size -= 512; + } + + return (size); +} + +uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize) +{ + // <- ROM size without header + // ** Memory.HeaderCount + // ** Memory.ROMFilename + + int32 totalSize = 0; + char fname[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], name[_MAX_FNAME + 1], exts[_MAX_EXT + 1]; + char *ext; + +#if defined(__WIN32__) || defined(__MACOSX__) + ext = &exts[1]; +#else + ext = &exts[0]; +#endif + + memset(NSRTHeader, 0, sizeof(NSRTHeader)); + HeaderCount = 0; + + _splitpath(filename, drive, dir, name, exts); + _makepath(fname, drive, dir, name, exts); + + int nFormat = FILE_DEFAULT; + if (strcasecmp(ext, "zip") == 0) + nFormat = FILE_ZIP; + else + if (strcasecmp(ext, "jma") == 0) + nFormat = FILE_JMA; + + switch (nFormat) + { + case FILE_ZIP: + { + #ifdef UNZIP_SUPPORT + if (!LoadZip(fname, &totalSize, &HeaderCount, buffer)) + { + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid Zip archive."); + return (0); + } + + strcpy(ROMFilename, fname); + #else + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with Zip support."); + return (0); + #endif + break; + } + + case FILE_JMA: + { + #ifdef JMA_SUPPORT + size_t size = load_jma_file(fname, buffer); + if (!size) + { + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid JMA archive."); + return (0); + } + + totalSize = HeaderRemove(size, HeaderCount, buffer); + + strcpy(ROMFilename, fname); + #else + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with JMA support."); + return (0); + #endif + break; + } + + case FILE_DEFAULT: + default: + { + STREAM fp = OPEN_STREAM(fname, "rb"); + if (!fp) + return (0); + + strcpy(ROMFilename, fname); + + int len = 0; + uint32 size = 0; + bool8 more = FALSE; + uint8 *ptr = buffer; + + do + { + size = READ_STREAM(ptr, maxsize + 0x200 - (ptr - buffer), fp); + CLOSE_STREAM(fp); + + size = HeaderRemove(size, HeaderCount, ptr); + totalSize += size; + ptr += size; + + // check for multi file roms + if (ptr - buffer < maxsize + 0x200 && + (isdigit(ext[0]) && ext[1] == 0 && ext[0] < '9')) + { + more = TRUE; + ext[0]++; + _makepath(fname, drive, dir, name, exts); + } + else + if (ptr - buffer < maxsize + 0x200 && + (((len = strlen(name)) == 7 || len == 8) && + strncasecmp(name, "sf", 2) == 0 && + isdigit(name[2]) && isdigit(name[3]) && isdigit(name[4]) && isdigit(name[5]) && + isalpha(name[len - 1]))) + { + more = TRUE; + name[len - 1]++; + _makepath(fname, drive, dir, name, exts); + } + else + more = FALSE; + + } while (more && (fp = OPEN_STREAM(fname, "rb")) != NULL); + + break; + } + } + + if (HeaderCount == 0) + S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "No ROM file header found."); + else + if (HeaderCount == 1) + S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found ROM file header (and ignored it)."); + else + S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found multiple ROM file headers (and ignored them)."); + + return ((uint32) totalSize); +} + +bool8 CMemory::LoadROM (const char *filename) +{ + int retry_count = 0; + + if (!filename || !*filename) + return (FALSE); + + ZeroMemory(ROM, MAX_ROM_SIZE); + ZeroMemory(&Multi, sizeof(Multi)); + +again: + Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); + SET_UI_COLOR(255, 255, 255); + + CalculatedSize = 0; + ExtendedFormat = NOPE; + + int32 totalFileSize; + +#ifdef GEKKO + totalFileSize = WiiFileLoader(); +#else + totalFileSize = FileLoader(ROM, filename, MAX_ROM_SIZE); +#endif + + if (!totalFileSize) + return (FALSE); + + if (!Settings.NoPatch) + CheckForAnyPatch(filename, HeaderCount != 0, totalFileSize); + + int hi_score, lo_score; + + hi_score = ScoreHiROM(FALSE); + lo_score = ScoreLoROM(FALSE); + + if (HeaderCount == 0 && !Settings.ForceNoHeader && + ((hi_score > lo_score && ScoreHiROM(TRUE) > hi_score) || + (hi_score <= lo_score && ScoreLoROM(TRUE) > lo_score))) + { + memmove(ROM, ROM + 512, totalFileSize - 512); + totalFileSize -= 512; + S9xMessage(S9X_INFO, S9X_HEADER_WARNING, "Try 'force no-header' option if the game doesn't work"); + // modifying ROM, so we need to rescore + hi_score = ScoreHiROM(FALSE); + lo_score = ScoreLoROM(FALSE); + } + + CalculatedSize = (totalFileSize / 0x2000) * 0x2000; + + if (CalculatedSize > 0x400000 && + (ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x4332 && // exclude S-DD1 + (ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x4532 && + (ROM[0xffd5] + (ROM[0xffd6] << 8)) != 0xF93a && // exclude SPC7110 + (ROM[0xffd5] + (ROM[0xffd6] << 8)) != 0xF53a) + ExtendedFormat = YEAH; + + // if both vectors are invalid, it's type 1 interleaved LoROM + if (ExtendedFormat == NOPE && + ((ROM[0x7ffc] + (ROM[0x7ffd] << 8)) < 0x8000) && + ((ROM[0xfffc] + (ROM[0xfffd] << 8)) < 0x8000)) + { + if (!Settings.ForceInterleaved && !Settings.ForceNotInterleaved) + S9xDeinterleaveType1(totalFileSize, ROM); + } + + // CalculatedSize is now set, so rescore + hi_score = ScoreHiROM(FALSE); + lo_score = ScoreLoROM(FALSE); + + uint8 *RomHeader = ROM; + + if (ExtendedFormat != NOPE) + { + int swappedhirom, swappedlorom; + + swappedhirom = ScoreHiROM(FALSE, 0x400000); + swappedlorom = ScoreLoROM(FALSE, 0x400000); + + // set swapped here + if (max(swappedlorom, swappedhirom) >= max(lo_score, hi_score)) + { + ExtendedFormat = BIGFIRST; + hi_score = swappedhirom; + lo_score = swappedlorom; + RomHeader += 0x400000; + } + else + ExtendedFormat = SMALLFIRST; + } + + bool8 interleaved, tales = FALSE; + + interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2 || Settings.ForceInterleaveGD24; + + if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score)) + { + LoROM = TRUE; + HiROM = FALSE; + + // ignore map type byte if not 0x2x or 0x3x + if ((RomHeader[0x7fd5] & 0xf0) == 0x20 || (RomHeader[0x7fd5] & 0xf0) == 0x30) + { + switch (RomHeader[0x7fd5] & 0xf) + { + case 1: + interleaved = TRUE; + break; + + case 5: + interleaved = TRUE; + tales = TRUE; + break; + } + } + } + else + { + LoROM = FALSE; + HiROM = TRUE; + + if ((RomHeader[0xffd5] & 0xf0) == 0x20 || (RomHeader[0xffd5] & 0xf0) == 0x30) + { + switch (RomHeader[0xffd5] & 0xf) + { + case 0: + case 3: + interleaved = TRUE; + break; + } + } + } + + // this two games fail to be detected + if (!Settings.ForceHiROM && !Settings.ForceLoROM) + { + if (strncmp((char *) &ROM[0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0 || + (strncmp((char *) &ROM[0xffc0], "BATMAN--REVENGE JOKER", 21) == 0)) + { + LoROM = TRUE; + HiROM = FALSE; + interleaved = FALSE; + tales = FALSE; + } + } + + if (!Settings.ForceNotInterleaved && interleaved) + { + S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "ROM image is in interleaved format - converting..."); + + if (tales) + { + if (ExtendedFormat == BIGFIRST) + { + S9xDeinterleaveType1(0x400000, ROM); + S9xDeinterleaveType1(CalculatedSize - 0x400000, ROM + 0x400000); + } + else + { + S9xDeinterleaveType1(CalculatedSize - 0x400000, ROM); + S9xDeinterleaveType1(0x400000, ROM + CalculatedSize - 0x400000); + } + + LoROM = FALSE; + HiROM = TRUE; + } + else + if (Settings.ForceInterleaveGD24 && CalculatedSize == 0x300000) + { + bool8 t = LoROM; + LoROM = HiROM; + HiROM = t; + S9xDeinterleaveGD24(CalculatedSize, ROM); + } + else + if (Settings.ForceInterleaved2) + S9xDeinterleaveType2(CalculatedSize, ROM); + else + { + bool8 t = LoROM; + LoROM = HiROM; + HiROM = t; + S9xDeinterleaveType1(CalculatedSize, ROM); + } + + hi_score = ScoreHiROM(FALSE); + lo_score = ScoreLoROM(FALSE); + + if ((HiROM && (lo_score >= hi_score || hi_score < 0)) || + (LoROM && (hi_score > lo_score || lo_score < 0))) + { + if (retry_count == 0) + { + S9xMessage(S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO, "ROM lied about its type! Trying again."); + Settings.ForceNotInterleaved = TRUE; + Settings.ForceInterleaved = FALSE; + retry_count++; + goto again; + } + } + } + + if (ExtendedFormat == SMALLFIRST) + tales = TRUE; + + if (tales) + { + uint8 *tmp = (uint8 *) memalign(32,CalculatedSize - 0x400000); + if (tmp) + { + S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "Fixing swapped ExHiROM..."); + memmove(tmp, ROM, CalculatedSize - 0x400000); + memmove(ROM, ROM + CalculatedSize - 0x400000, 0x400000); + memmove(ROM + 0x400000, tmp, CalculatedSize - 0x400000); + free(tmp); + } + } + + if (strncmp(LastRomFilename, filename, PATH_MAX + 1)) + { + strncpy(LastRomFilename, filename, PATH_MAX + 1); + LastRomFilename[PATH_MAX] = 0; + } + + ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes)); + SNESGameFixes.SRAMInitialValue = 0x60; +#ifdef GEKKO + WiiSetupCheats(); +#else + S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); +#endif + InitROM(); + + S9xInitCheatData(); + S9xApplyCheats(); + + S9xReset(); + + return (TRUE); +} + +bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) +{ + bool8 r = TRUE; + + ZeroMemory(ROM, MAX_ROM_SIZE); + ZeroMemory(&Multi, sizeof(Multi)); + + Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); + SET_UI_COLOR(255, 255, 255); + + CalculatedSize = 0; + ExtendedFormat = NOPE; + + if (cartA && cartA[0]) + Multi.cartSizeA = FileLoader(ROM, cartA, MAX_ROM_SIZE); + + if (Multi.cartSizeA == 0) + { + if (cartB && cartB[0]) + Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE); + } + + if (Multi.cartSizeA) + { + if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeA)) + Multi.cartType = 4; + else + if (is_SameGame_BIOS(ROM, Multi.cartSizeA)) + Multi.cartType = 3; + } + else + if (Multi.cartSizeB) + { + if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeB)) + Multi.cartType = 4; + } + else + Multi.cartType = 4; // assuming BIOS only + + switch (Multi.cartType) + { + case 4: + r = LoadSufamiTurbo(cartA, cartB); + break; + + case 3: + r = LoadSameGame(cartA, cartB); + break; + + default: + r = FALSE; + } + + if (!r) + { + ZeroMemory(&Multi, sizeof(Multi)); + return (FALSE); + } + + ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes)); + SNESGameFixes.SRAMInitialValue = 0x60; + + S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); + + InitROM(); + + S9xInitCheatData(); + S9xApplyCheats(); + + S9xReset(); + + return (TRUE); +} + +bool8 CMemory::LoadSufamiTurbo (const char *cartA, const char *cartB) +{ + Multi.cartOffsetA = 0x100000; + Multi.cartOffsetB = 0x200000; + Multi.sramA = SRAM; + Multi.sramB = SRAM + 0x10000; + + if (Multi.cartSizeA) + { + Multi.sramSizeA = 4; // ROM[0x37]? + Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0; + + if (!Settings.NoPatch) + CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA); + + strcpy(Multi.fileNameA, cartA); + memcpy(ROM + Multi.cartOffsetA, ROM, Multi.cartSizeA); + } + + if (Multi.cartSizeA && !Multi.cartSizeB) + { + if (cartB && cartB[0]) + Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE); + + if (Multi.cartSizeB) + { + if (!is_SufamiTurbo_Cart(ROM, Multi.cartSizeB)) + Multi.cartSizeB = 0; + } + } + + if (Multi.cartSizeB) + { + Multi.sramSizeB = 4; // ROM[0x37]? + Multi.sramMaskB = Multi.sramSizeB ? ((1 << (Multi.sramSizeB + 3)) * 128 - 1) : 0; + + if (!Settings.NoPatch) + CheckForAnyPatch(cartB, HeaderCount != 0, Multi.cartSizeB); + + strcpy(Multi.fileNameB, cartB); + memcpy(ROM + Multi.cartOffsetB, ROM, Multi.cartSizeB); + } + + FILE *fp; + size_t size; + char path[PATH_MAX + 1]; + + strcpy(path, S9xGetDirectory(BIOS_DIR)); + strcat(path, SLASH_STR); + strcat(path, "STBIOS.bin"); + + fp = fopen(path, "rb"); + if (fp) + { + size = fread((void *) ROM, 1, 0x40000, fp); + fclose(fp); + if (!is_SufamiTurbo_BIOS(ROM, size)) + return (FALSE); + } + else + return (FALSE); + + if (Multi.cartSizeA) + strcpy(ROMFilename, Multi.fileNameA); + else + if (Multi.cartSizeB) + strcpy(ROMFilename, Multi.fileNameB); + else + strcpy(ROMFilename, path); + + LoROM = TRUE; + HiROM = FALSE; + CalculatedSize = 0x40000; + + return (TRUE); +} + +bool8 CMemory::LoadSameGame (const char *cartA, const char *cartB) +{ + Multi.cartOffsetA = 0; + Multi.cartOffsetB = 0x200000; + Multi.sramA = SRAM; + Multi.sramB = NULL; + + Multi.sramSizeA = ROM[0xffd8]; + Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0; + Multi.sramSizeB = 0; + Multi.sramMaskB = 0; + + if (!Settings.NoPatch) + CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA); + + strcpy(Multi.fileNameA, cartA); + + if (cartB && cartB[0]) + Multi.cartSizeB = FileLoader(ROM + Multi.cartOffsetB, cartB, MAX_ROM_SIZE - Multi.cartOffsetB); + + if (Multi.cartSizeB) + { + if (!is_SameGame_Add_On(ROM + Multi.cartOffsetB, Multi.cartSizeB)) + Multi.cartSizeB = 0; + else + strcpy(Multi.fileNameB, cartB); + } + + strcpy(ROMFilename, Multi.fileNameA); + + LoROM = FALSE; + HiROM = TRUE; + CalculatedSize = Multi.cartSizeA; + + return (TRUE); +} + +bool8 CMemory::LoadSRTC (void) +{ + FILE *fp; + size_t ignore; + + fp = fopen(S9xGetFilename(".rtc", SRAM_DIR), "rb"); + if (!fp) + return (FALSE); + + ignore = fread(RTCData.reg, 1, 20, fp); + fclose(fp); + + return (TRUE); +} + +bool8 CMemory::SaveSRTC (void) +{ + FILE *fp; + size_t ignore; + + fp = fopen(S9xGetFilename(".rtc", SRAM_DIR), "wb"); + if (!fp) + return (FALSE); + + ignore = fwrite(RTCData.reg, 1, 20, fp); + fclose(fp); + + return (TRUE); +} + +void CMemory::ClearSRAM (bool8 onlyNonSavedSRAM) +{ + if (onlyNonSavedSRAM) + if (!(Settings.SuperFX && ROMType < 0x15) && !(Settings.SA1 && ROMType == 0x34)) // can have SRAM + return; + + memset(SRAM, SNESGameFixes.SRAMInitialValue, 0x20000); +} + +bool8 CMemory::LoadSRAM (const char *filename) +{ + FILE *file; + int size, len; + char sramName[PATH_MAX + 1]; + + strcpy(sramName, filename); + + ClearSRAM(); + + if (Multi.cartType && Multi.sramSizeB) + { + char temp[PATH_MAX + 1]; + + strcpy(temp, ROMFilename); + strcpy(ROMFilename, Multi.fileNameB); + + size = (1 << (Multi.sramSizeB + 3)) * 128; + + file = fopen(S9xGetFilename(".srm", SRAM_DIR), "rb"); + if (file) + { + len = fread((char *) Multi.sramB, 1, 0x10000, file); + fclose(file); + if (len - size == 512) + memmove(Multi.sramB, Multi.sramB + 512, size); + } + + strcpy(ROMFilename, temp); + } + + size = SRAMSize ? (1 << (SRAMSize + 3)) * 128 : 0; + if (size > 0x20000) + size = 0x20000; + + if (size) + { + file = fopen(sramName, "rb"); + if (file) + { + len = fread((char *) SRAM, 1, 0x20000, file); + fclose(file); + if (len - size == 512) + memmove(SRAM, SRAM + 512, size); + + if (Settings.SRTC || Settings.SPC7110RTC) + LoadSRTC(); + + return (TRUE); + } + else + if (Settings.BS && !Settings.BSXItself) + { + // The BS game's SRAM was not found + // Try to read BS-X.srm instead + char path[PATH_MAX + 1]; + + strcpy(path, S9xGetDirectory(SRAM_DIR)); + strcat(path, SLASH_STR); + strcat(path, "BS-X.srm"); + + file = fopen(path, "rb"); + if (file) + { + len = fread((char *) SRAM, 1, 0x20000, file); + fclose(file); + if (len - size == 512) + memmove(SRAM, SRAM + 512, size); + + S9xMessage(S9X_INFO, S9X_ROM_INFO, "The SRAM file wasn't found: BS-X.srm was read instead."); + return (TRUE); + } + else + { + S9xMessage(S9X_INFO, S9X_ROM_INFO, "The SRAM file wasn't found, BS-X.srm wasn't found either."); + return (FALSE); + } + } + + return (FALSE); + } + + return (TRUE); +} + +bool8 CMemory::SaveSRAM (const char *filename) +{ + if (Settings.SuperFX && ROMType < 0x15) // doesn't have SRAM + return (TRUE); + + if (Settings.SA1 && ROMType == 0x34) // doesn't have SRAM + return (TRUE); + + FILE *file; + int size; + char sramName[PATH_MAX + 1]; + + strcpy(sramName, filename); + + if (Multi.cartType && Multi.sramSizeB) + { + char name[PATH_MAX + 1], temp[PATH_MAX + 1]; + + strcpy(temp, ROMFilename); + strcpy(ROMFilename, Multi.fileNameB); + strcpy(name, S9xGetFilename(".srm", SRAM_DIR)); + + size = (1 << (Multi.sramSizeB + 3)) * 128; + + file = fopen(name, "wb"); + if (file) + { + size_t ignore; + ignore = fwrite((char *) Multi.sramB, size, 1, file); + fclose(file); + #ifdef __linux + ignore = chown(name, getuid(), getgid()); + #endif + } + + strcpy(ROMFilename, temp); + } + + size = SRAMSize ? (1 << (SRAMSize + 3)) * 128 : 0; + if (size > 0x20000) + size = 0x20000; + + if (size) + { + file = fopen(sramName, "wb"); + if (file) + { + size_t ignore; + ignore = fwrite((char *) SRAM, size, 1, file); + fclose(file); + #ifdef __linux + ignore = chown(sramName, getuid(), getgid()); + #endif + + if (Settings.SRTC || Settings.SPC7110RTC) + SaveSRTC(); + + return (TRUE); + } + } + + return (FALSE); +} + +// initialization + +static uint32 caCRC32 (uint8 *array, uint32 size, uint32 crc32) +{ + for (uint32 i = 0; i < size; i++) + crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ array[i]) & 0xFF]; + + return (~crc32); +} + +char * CMemory::Safe (const char *s) +{ + static char *safe = NULL; + static int safe_len = 0; + + if (s == NULL) + { + if (safe) + { + free(safe); + safe = NULL; + } + + return (NULL); + } + + int len = strlen(s); + if (!safe || len + 1 > safe_len) + { + if (safe) + free(safe); + + safe_len = len + 1; + safe = (char *) memalign(32,safe_len); + } + + for (int i = 0; i < len; i++) + { + if (s[i] >= 32 && s[i] < 127) + safe[i] = s[i]; + else + safe[i] = '_'; + } + + safe[len] = 0; + + return (safe); +} + +char * CMemory::SafeANK (const char *s) +{ + static char *safe = NULL; + static int safe_len = 0; + + if (s == NULL) + { + if (safe) + { + free(safe); + safe = NULL; + } + + return (NULL); + } + + int len = strlen(s); + if (!safe || len + 1 > safe_len) + { + if (safe) + free(safe); + + safe_len = len + 1; + safe = (char *) memalign(32,safe_len); + } + + for (int i = 0; i < len; i++) + { + if (s[i] >= 32 && s[i] < 127) // ASCII + safe [i] = s[i]; + else + if (ROMRegion == 0 && ((uint8) s[i] >= 0xa0 && (uint8) s[i] < 0xe0)) // JIS X 201 - Katakana + safe [i] = s[i]; + else + safe [i] = '_'; + } + + safe [len] = 0; + + return (safe); +} + +void CMemory::ParseSNESHeader (uint8 *RomHeader) +{ + bool8 bs = Settings.BS & !Settings.BSXItself; + + strncpy(ROMName, (char *) &RomHeader[0x10], ROM_NAME_LEN - 1); + if (bs) + memset(ROMName + 16, 0x20, ROM_NAME_LEN - 17); + + if (bs) + { + if (!(((RomHeader[0x29] & 0x20) && CalculatedSize < 0x100000) || + (!(RomHeader[0x29] & 0x20) && CalculatedSize == 0x100000))) + printf("BS: Size mismatch\n"); + + // FIXME + int p = 0; + while ((1 << p) < (int) CalculatedSize) + p++; + ROMSize = p - 10; + } + else + ROMSize = RomHeader[0x27]; + + SRAMSize = bs ? 5 /* BS-X */ : RomHeader[0x28]; + ROMSpeed = bs ? RomHeader[0x28] : RomHeader[0x25]; + ROMType = bs ? 0xE5 /* BS-X */ : RomHeader[0x26]; + ROMRegion = bs ? 0 : RomHeader[0x29]; + + ROMChecksum = RomHeader[0x2E] + (RomHeader[0x2F] << 8); + ROMComplementChecksum = RomHeader[0x2C] + (RomHeader[0x2D] << 8); + + memmove(ROMId, &RomHeader[0x02], 4); + + if (RomHeader[0x2A] != 0x33) + CompanyId = ((RomHeader[0x2A] >> 4) & 0x0F) * 36 + (RomHeader[0x2A] & 0x0F); + else + if (isalnum(RomHeader[0x00]) && isalnum(RomHeader[0x01])) + { + int l, r, l2, r2; + l = toupper(RomHeader[0x00]); + r = toupper(RomHeader[0x01]); + l2 = (l > '9') ? l - '7' : l - '0'; + r2 = (r > '9') ? r - '7' : r - '0'; + CompanyId = l2 * 36 + r2; + } +} + +void CMemory::InitROM (void) +{ + Settings.SuperFX = FALSE; + Settings.DSP = 0; + Settings.SA1 = FALSE; + Settings.C4 = FALSE; + Settings.SDD1 = FALSE; + Settings.SPC7110 = FALSE; + Settings.SPC7110RTC = FALSE; + Settings.OBC1 = FALSE; + Settings.SETA = 0; + Settings.SRTC = FALSE; + Settings.BS = FALSE; + + SuperFX.nRomBanks = CalculatedSize >> 15; + + SA1.Executing = FALSE; + + //// Parse ROM header and read ROM informatoin + + CompanyId = -1; + memset(ROMId, 0, 5); + + uint8 *RomHeader = ROM + 0x7FB0; + if (ExtendedFormat == BIGFIRST) + RomHeader += 0x400000; + if (HiROM) + RomHeader += 0x8000; + + S9xInitBSX(); // Set BS header before parsing + + ParseSNESHeader(RomHeader); + + //// Detect and initialize chips + //// detection codes are compatible with NSRT + + // DSP1/2/3/4 + if (ROMType == 0x03) + { + if (ROMSpeed == 0x30) + Settings.DSP = 4; // DSP4 + else + Settings.DSP = 1; // DSP1 + } + else + if (ROMType == 0x05) + { + if (ROMSpeed == 0x20) + Settings.DSP = 2; // DSP2 + else + if (ROMSpeed == 0x30 && RomHeader[0x2a] == 0xb2) + Settings.DSP = 3; // DSP3 + else + Settings.DSP = 1; // DSP1 + } + + switch (Settings.DSP) + { + case 1: // DSP1 + if (HiROM) + { + DSP0.boundary = 0x7000; + DSP0.maptype = M_DSP1_HIROM; + } + else + if (CalculatedSize > 0x100000) + { + DSP0.boundary = 0x4000; + DSP0.maptype = M_DSP1_LOROM_L; + } + else + { + DSP0.boundary = 0xc000; + DSP0.maptype = M_DSP1_LOROM_S; + } + + SetDSP = &DSP1SetByte; + GetDSP = &DSP1GetByte; + break; + + case 2: // DSP2 + DSP0.boundary = 0x10000; + DSP0.maptype = M_DSP2_LOROM; + SetDSP = &DSP2SetByte; + GetDSP = &DSP2GetByte; + break; + + case 3: // DSP3 + DSP0.boundary = 0xc000; + DSP0.maptype = M_DSP3_LOROM; + SetDSP = &DSP3SetByte; + GetDSP = &DSP3GetByte; + break; + + case 4: // DSP4 + DSP0.boundary = 0xc000; + DSP0.maptype = M_DSP4_LOROM; + SetDSP = &DSP4SetByte; + GetDSP = &DSP4GetByte; + break; + + default: + SetDSP = NULL; + GetDSP = NULL; + break; + } + + uint32 identifier = ((ROMType & 0xff) << 8) + (ROMSpeed & 0xff); + + switch (identifier) + { + // SRTC + case 0x5535: + Settings.SRTC = TRUE; + S9xInitSRTC(); + break; + + // SPC7110 + case 0xF93A: + Settings.SPC7110RTC = TRUE; + case 0xF53A: + Settings.SPC7110 = TRUE; + S9xInitSPC7110(); + break; + + // OBC1 + case 0x2530: + Settings.OBC1 = TRUE; + break; + + // SA1 + case 0x3423: + case 0x3523: + Settings.SA1 = TRUE; + break; + + // SuperFX + case 0x1320: + case 0x1420: + case 0x1520: + case 0x1A20: + Settings.SuperFX = TRUE; + S9xInitSuperFX(); + if (ROM[0x7FDA] == 0x33) + SRAMSize = ROM[0x7FBD]; + else + SRAMSize = 5; + break; + + // SDD1 + case 0x4332: + case 0x4532: + Settings.SDD1 = TRUE; + break; + + // ST018 + case 0xF530: + Settings.SETA = ST_018; + SetSETA = NULL; + GetSETA = NULL; + SRAMSize = 2; + SNESGameFixes.SRAMInitialValue = 0x00; + break; + + // ST010/011 + case 0xF630: + if (ROM[0x7FD7] == 0x09) + { + Settings.SETA = ST_011; + SetSETA = &S9xSetST011; + GetSETA = &S9xGetST011; + } + else + { + Settings.SETA = ST_010; + SetSETA = &S9xSetST010; + GetSETA = &S9xGetST010; + } + + SRAMSize = 2; + SNESGameFixes.SRAMInitialValue = 0x00; + break; + + // C4 + case 0xF320: + Settings.C4 = TRUE; + break; + } + + //// Map memory and calculate checksum + + Map_Initialize(); + CalculatedChecksum = 0; + + if (HiROM) + { + if (Settings.BS) + /* Do nothing */; + else + if (Settings.SPC7110) + Map_SPC7110HiROMMap(); + else + if (ExtendedFormat != NOPE) + Map_ExtendedHiROMMap(); + else + if (Multi.cartType == 3) + Map_SameGameHiROMMap(); + else + Map_HiROMMap(); + } + else + { + if (Settings.BS) + /* Do nothing */; + else + if (Settings.SETA && Settings.SETA != ST_018) + Map_SetaDSPLoROMMap(); + else + if (Settings.SuperFX) + Map_SuperFXLoROMMap(); + else + if (Settings.SA1) + Map_SA1LoROMMap(); + else + if (Settings.SDD1) + Map_SDD1LoROMMap(); + else + if (ExtendedFormat != NOPE) + Map_JumboLoROMMap(); + else + if (strncmp(ROMName, "WANDERERS FROM YS", 17) == 0) + Map_NoMAD1LoROMMap(); + else + if (strncmp(ROMName, "SOUND NOVEL-TCOOL", 17) == 0 || + strncmp(ROMName, "DERBY STALLION 96", 17) == 0) + Map_ROM24MBSLoROMMap(); + else + if (strncmp(ROMName, "THOROUGHBRED BREEDER3", 21) == 0 || + strncmp(ROMName, "RPG-TCOOL 2", 11) == 0) + Map_SRAM512KLoROMMap(); + else + if (strncmp(ROMName, "ADD-ON BASE CASSETE", 19) == 0) + { + if (Multi.cartType == 4) + { + SRAMSize = Multi.sramSizeA; + Map_SufamiTurboLoROMMap(); + } + else + { + SRAMSize = 5; + Map_SufamiTurboPseudoLoROMMap(); + } + } + else + Map_LoROMMap(); + } + + Checksum_Calculate(); + + bool8 isChecksumOK = (ROMChecksum + ROMComplementChecksum == 0xffff) & + (ROMChecksum == CalculatedChecksum); + + //// Build more ROM information + + // CRC32 + if (!Settings.BS || Settings.BSXItself) // Not BS Dump + ROMCRC32 = caCRC32(ROM, CalculatedSize); + else // Convert to correct format before scan + { + int offset = HiROM ? 0xffc0 : 0x7fc0; + // Backup + uint8 BSMagic0 = ROM[offset + 22], + BSMagic1 = ROM[offset + 23]; + // uCONSRT standard + ROM[offset + 22] = 0x42; + ROM[offset + 23] = 0x00; + // Calc + ROMCRC32 = caCRC32(ROM, CalculatedSize); + // Convert back + ROM[offset + 22] = BSMagic0; + ROM[offset + 23] = BSMagic1; + } + + // NTSC/PAL + if (Settings.ForceNTSC) + Settings.PAL = FALSE; + else + if (Settings.ForcePAL) + Settings.PAL = TRUE; + else + if (!Settings.BS && (ROMRegion >= 2) && (ROMRegion <= 12)) + Settings.PAL = TRUE; + else + Settings.PAL = FALSE; + + if (Settings.PAL) + { + Settings.FrameTime = Settings.FrameTimePAL; + ROMFramesPerSecond = 50; + } + else + { + Settings.FrameTime = Settings.FrameTimeNTSC; + ROMFramesPerSecond = 60; + } + + // truncate cart name + ROMName[ROM_NAME_LEN - 1] = 0; + if (strlen(ROMName)) + { + char *p = ROMName + strlen(ROMName); + if (p > ROMName + 21 && ROMName[20] == ' ') + p = ROMName + 21; + while (p > ROMName && *(p - 1) == ' ') + p--; + *p = 0; + } + + // SRAM size + SRAMMask = SRAMSize ? ((1 << (SRAMSize + 3)) * 128) - 1 : 0; + + // checksum + if (!isChecksumOK || ((uint32) CalculatedSize > (uint32) (((1 << (ROMSize - 7)) * 128) * 1024))) + { + Settings.DisplayColor = BUILD_PIXEL(31, 31, 0); + SET_UI_COLOR(255, 255, 0); + } + + if (Multi.cartType == 4) + { + Settings.DisplayColor = BUILD_PIXEL(0, 16, 31); + SET_UI_COLOR(0, 128, 255); + } + + //// Initialize emulation + + Timings.H_Max_Master = SNES_CYCLES_PER_SCANLINE; + Timings.H_Max = Timings.H_Max_Master; + Timings.HBlankStart = SNES_HBLANK_START_HC; + Timings.HBlankEnd = SNES_HBLANK_END_HC; + Timings.HDMAInit = SNES_HDMA_INIT_HC; + Timings.HDMAStart = SNES_HDMA_START_HC; + Timings.RenderPos = SNES_RENDER_START_HC; + Timings.V_Max_Master = Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER; + Timings.V_Max = Timings.V_Max_Master; + /* From byuu: The total delay time for both the initial (H)DMA sync (to the DMA clock), + and the end (H)DMA sync (back to the last CPU cycle's mcycle rate (6, 8, or 12)) always takes between 12-24 mcycles. + Possible delays: { 12, 14, 16, 18, 20, 22, 24 } + XXX: Snes9x can't emulate this timing :( so let's use the average value... */ + Timings.DMACPUSync = 18; + /* If the CPU is halted (i.e. for DMA) while /NMI goes low, the NMI will trigger + after the DMA completes (even if /NMI goes high again before the DMA + completes). In this case, there is a 24-30 cycle delay between the end of DMA + and the NMI handler, time enough for an instruction or two. */ + // Wild Guns, Mighty Morphin Power Rangers - The Fighting Edition + Timings.NMIDMADelay = 24; + Timings.IRQPendCount = 0; + + IPPU.TotalEmulatedFrames = 0; + + //// Hack games + + ApplyROMFixes(); + + //// Show ROM information + char displayName[ROM_NAME_LEN]; + + strcpy(RawROMName, ROMName); + sprintf(displayName, "%s", SafeANK(ROMName)); + sprintf(ROMName, "%s", Safe(ROMName)); + sprintf(ROMId, "%s", Safe(ROMId)); + + sprintf(String, "\"%s\" [%s] %s, %s, %s, %s, SRAM:%s, ID:%s, CRC32:%08X", + displayName, isChecksumOK ? "checksum ok" : ((Multi.cartType == 4) ? "no checksum" : "bad checksum"), + MapType(), Size(), KartContents(), Settings.PAL ? "PAL" : "NTSC", StaticRAMSize(), ROMId, ROMCRC32); + S9xMessage(S9X_INFO, S9X_ROM_INFO, String); + + Settings.ForceLoROM = FALSE; + Settings.ForceHiROM = FALSE; + Settings.ForceHeader = FALSE; + Settings.ForceNoHeader = FALSE; + Settings.ForceInterleaved = FALSE; + Settings.ForceInterleaved2 = FALSE; + Settings.ForceInterleaveGD24 = FALSE; + Settings.ForceNotInterleaved = FALSE; + Settings.ForcePAL = FALSE; + Settings.ForceNTSC = FALSE; + + Settings.TakeScreenshot = FALSE; + + if (stopMovie) + S9xMovieStop(TRUE); + + if (PostRomInitFunc) + PostRomInitFunc(); + + S9xVerifyControllers(); +} + +// memory map + +uint32 CMemory::map_mirror (uint32 size, uint32 pos) +{ + // from bsnes + if (size == 0) + return (0); + if (pos < size) + return (pos); + + uint32 mask = 1 << 31; + while (!(pos & mask)) + mask >>= 1; + + if (size <= (pos & mask)) + return (map_mirror(size, pos - mask)); + else + return (mask + map_mirror(size - mask, pos - mask)); +} + +void CMemory::map_lorom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size) +{ + uint32 c, i, p, addr; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + addr = (c & 0x7f) * 0x8000; + Map[p] = ROM + map_mirror(size, addr) - (i & 0x8000); + BlockIsROM[p] = TRUE; + BlockIsRAM[p] = FALSE; + } + } +} + +void CMemory::map_hirom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size) +{ + uint32 c, i, p, addr; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + addr = c << 16; + Map[p] = ROM + map_mirror(size, addr); + BlockIsROM[p] = TRUE; + BlockIsRAM[p] = FALSE; + } + } +} + +void CMemory::map_lorom_offset (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size, uint32 offset) +{ + uint32 c, i, p, addr; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + addr = ((c - bank_s) & 0x7f) * 0x8000; + Map[p] = ROM + offset + map_mirror(size, addr) - (i & 0x8000); + BlockIsROM[p] = TRUE; + BlockIsRAM[p] = FALSE; + } + } +} + +void CMemory::map_hirom_offset (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size, uint32 offset) +{ + uint32 c, i, p, addr; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + addr = (c - bank_s) << 16; + Map[p] = ROM + offset + map_mirror(size, addr); + BlockIsROM[p] = TRUE; + BlockIsRAM[p] = FALSE; + } + } +} + +void CMemory::map_space (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint8 *data) +{ + uint32 c, i, p; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + Map[p] = data; + BlockIsROM[p] = FALSE; + BlockIsRAM[p] = TRUE; + } + } +} + +void CMemory::map_index (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, int index, int type) +{ + uint32 c, i, p; + bool8 isROM, isRAM; + + isROM = ((type == MAP_TYPE_I_O) || (type == MAP_TYPE_RAM)) ? FALSE : TRUE; + isRAM = ((type == MAP_TYPE_I_O) || (type == MAP_TYPE_ROM)) ? FALSE : TRUE; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + Map[p] = (uint8 *) index; + BlockIsROM[p] = isROM; + BlockIsRAM[p] = isRAM; + } + } +} + +void CMemory::map_System (void) +{ + // will be overwritten + map_space(0x00, 0x3f, 0x0000, 0x1fff, RAM); + map_index(0x00, 0x3f, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O); + map_index(0x00, 0x3f, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O); + map_space(0x80, 0xbf, 0x0000, 0x1fff, RAM); + map_index(0x80, 0xbf, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O); + map_index(0x80, 0xbf, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O); +} + +void CMemory::map_WRAM (void) +{ + // will overwrite others + map_space(0x7e, 0x7e, 0x0000, 0xffff, RAM); + map_space(0x7f, 0x7f, 0x0000, 0xffff, RAM + 0x10000); +} + +void CMemory::map_LoROMSRAM (void) +{ + map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + map_index(0xf0, 0xff, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM); +} + +void CMemory::map_HiROMSRAM (void) +{ + map_index(0x20, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); + map_index(0xa0, 0xbf, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); +} + +void CMemory::map_DSP (void) +{ + switch (DSP0.maptype) + { + case M_DSP1_LOROM_S: + map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + break; + + case M_DSP1_LOROM_L: + map_index(0x60, 0x6f, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xe0, 0xef, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); + break; + + case M_DSP1_HIROM: + map_index(0x00, 0x1f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); + map_index(0x80, 0x9f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); + break; + + case M_DSP2_LOROM: + map_index(0x20, 0x3f, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O); + map_index(0x20, 0x3f, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xa0, 0xbf, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xa0, 0xbf, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O); + break; + + case M_DSP3_LOROM: + map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + break; + + case M_DSP4_LOROM: + map_index(0x30, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xb0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + break; + } +} + +void CMemory::map_C4 (void) +{ + map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_C4, MAP_TYPE_I_O); + map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_C4, MAP_TYPE_I_O); +} + +void CMemory::map_OBC1 (void) +{ + map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_OBC_RAM, MAP_TYPE_I_O); + map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_OBC_RAM, MAP_TYPE_I_O); +} + +void CMemory::map_SetaRISC (void) +{ + map_index(0x00, 0x3f, 0x3000, 0x3fff, MAP_SETA_RISC, MAP_TYPE_I_O); + map_index(0x80, 0xbf, 0x3000, 0x3fff, MAP_SETA_RISC, MAP_TYPE_I_O); +} + +void CMemory::map_SetaDSP (void) +{ + // where does the SETA chip access, anyway? + // please confirm this? + map_index(0x68, 0x6f, 0x0000, 0x7fff, MAP_SETA_DSP, MAP_TYPE_RAM); + // and this! + map_index(0x60, 0x67, 0x0000, 0x3fff, MAP_SETA_DSP, MAP_TYPE_I_O); + + // ST-0010: + // map_index(0x68, 0x6f, 0x0000, 0x0fff, MAP_SETA_DSP, ?); +} + +void CMemory::map_WriteProtectROM (void) +{ + memmove((void *) WriteMap, (void *) Map, sizeof(Map)); + + for (int c = 0; c < 0x1000; c++) + { + if (BlockIsROM[c]) + WriteMap[c] = (uint8 *) MAP_NONE; + } +} + +void CMemory::Map_Initialize (void) +{ + for (int c = 0; c < 0x1000; c++) + { + Map[c] = (uint8 *) MAP_NONE; + WriteMap[c] = (uint8 *) MAP_NONE; + BlockIsROM[c] = FALSE; + BlockIsRAM[c] = FALSE; + } +} + +void CMemory::Map_LoROMMap (void) +{ + printf("Map_LoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); + + if (Settings.DSP) + map_DSP(); + else + if (Settings.C4) + map_C4(); + else + if (Settings.OBC1) + map_OBC1(); + else + if (Settings.SETA == ST_018) + map_SetaRISC(); + + map_LoROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_NoMAD1LoROMMap (void) +{ + printf("Map_NoMAD1LoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); + + map_index(0x70, 0x7f, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + map_index(0xf0, 0xff, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_JumboLoROMMap (void) +{ + // XXX: Which game uses this? + printf("Map_JumboLoROMMap\n"); + map_System(); + + map_lorom_offset(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize - 0x400000, 0x400000); + map_lorom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize - 0x400000, 0x400000); + map_lorom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0); + map_lorom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0x200000); + + map_LoROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_ROM24MBSLoROMMap (void) +{ + // PCB: BSC-1A5M-01, BSC-1A7M-10 + printf("Map_ROM24MBSLoROMMap\n"); + map_System(); + + map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x100000, 0); + map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000); + map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x100000, 0x200000); + map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000); + + map_LoROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SRAM512KLoROMMap (void) +{ + printf("Map_SRAM512KLoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); + + map_space(0x70, 0x70, 0x0000, 0xffff, SRAM); + map_space(0x71, 0x71, 0x0000, 0xffff, SRAM + 0x8000); + map_space(0x72, 0x72, 0x0000, 0xffff, SRAM + 0x10000); + map_space(0x73, 0x73, 0x0000, 0xffff, SRAM + 0x18000); + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SufamiTurboLoROMMap (void) +{ + printf("Map_SufamiTurboLoROMMap\n"); + map_System(); + + map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0); + map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_lorom_offset(0x40, 0x5f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x40000, 0); + map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_lorom_offset(0xc0, 0xdf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + + if (Multi.sramSizeA) + { + map_index(0x60, 0x63, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + map_index(0xe0, 0xe3, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + } + + if (Multi.sramSizeB) + { + map_index(0x70, 0x73, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM); + map_index(0xf0, 0xf3, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM); + } + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SufamiTurboPseudoLoROMMap (void) +{ + // for combined images + printf("Map_SufamiTurboPseudoLoROMMap\n"); + map_System(); + + map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0); + map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000); + map_lorom_offset(0x40, 0x5f, 0x8000, 0xffff, 0x100000, 0x200000); + map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x40000, 0); + map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000); + map_lorom_offset(0xc0, 0xdf, 0x8000, 0xffff, 0x100000, 0x200000); + + // I don't care :P + map_space(0x60, 0x63, 0x8000, 0xffff, SRAM - 0x8000); + map_space(0xe0, 0xe3, 0x8000, 0xffff, SRAM - 0x8000); + map_space(0x70, 0x73, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000); + map_space(0xf0, 0xf3, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000); + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SuperFXLoROMMap (void) +{ + printf("Map_SuperFXLoROMMap\n"); + map_System(); + + // Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K + // block is repeated twice in each 64K block. + for (int c = 0; c < 64; c++) + { + memmove(&ROM[0x200000 + c * 0x10000], &ROM[c * 0x8000], 0x8000); + memmove(&ROM[0x208000 + c * 0x10000], &ROM[c * 0x8000], 0x8000); + } + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + + map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize, 0); + map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0); + + map_space(0x00, 0x3f, 0x6000, 0x7fff, SRAM - 0x6000); + map_space(0x80, 0xbf, 0x6000, 0x7fff, SRAM - 0x6000); + map_space(0x70, 0x70, 0x0000, 0xffff, SRAM); + map_space(0x71, 0x71, 0x0000, 0xffff, SRAM + 0x10000); + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SetaDSPLoROMMap (void) +{ + printf("Map_SetaDSPLoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x40, 0x7f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_lorom(0xc0, 0xff, 0x8000, 0xffff, CalculatedSize); + + map_SetaDSP(); + + map_LoROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SDD1LoROMMap (void) +{ + printf("Map_SDD1LoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + + map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize, 0); + map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0); // will be overwritten dynamically + + map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SA1LoROMMap (void) +{ + printf("Map_SA1LoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + + map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0); + + map_space(0x00, 0x3f, 0x3000, 0x3fff, FillRAM); + map_space(0x80, 0xbf, 0x3000, 0x3fff, FillRAM); + map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O); + map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O); + + for (int c = 0x40; c < 0x80; c++) + map_space(c, c, 0x0000, 0xffff, SRAM + (c & 1) * 0x10000); + + map_WRAM(); + + map_WriteProtectROM(); + + // Now copy the map and correct it for the SA1 CPU. + memmove((void *) SA1.Map, (void *) Map, sizeof(Map)); + memmove((void *) SA1.WriteMap, (void *) WriteMap, sizeof(WriteMap)); + + // SA-1 Banks 00->3f and 80->bf + for (int c = 0x000; c < 0x400; c += 0x10) + { + SA1.Map[c + 0] = SA1.Map[c + 0x800] = FillRAM + 0x3000; + SA1.Map[c + 1] = SA1.Map[c + 0x801] = (uint8 *) MAP_NONE; + SA1.WriteMap[c + 0] = SA1.WriteMap[c + 0x800] = FillRAM + 0x3000; + SA1.WriteMap[c + 1] = SA1.WriteMap[c + 0x801] = (uint8 *) MAP_NONE; + } + + // SA-1 Banks 60->6f + for (int c = 0x600; c < 0x700; c++) + SA1.Map[c] = SA1.WriteMap[c] = (uint8 *) MAP_BWRAM_BITMAP; + + BWRAM = SRAM; +} + +void CMemory::Map_HiROMMap (void) +{ + printf("Map_HiROMMap\n"); + map_System(); + + map_hirom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_hirom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize); + map_hirom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_hirom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); + + if (Settings.DSP) + map_DSP(); + + map_HiROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_ExtendedHiROMMap (void) +{ + printf("Map_ExtendedHiROMMap\n"); + map_System(); + + map_hirom_offset(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize - 0x400000, 0x400000); + map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize - 0x400000, 0x400000); + map_hirom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0); + map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0); + + map_HiROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SameGameHiROMMap (void) +{ + printf("Map_SameGameHiROMMap\n"); + map_System(); + + map_hirom_offset(0x00, 0x1f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_hirom_offset(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + map_hirom_offset(0x40, 0x5f, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_hirom_offset(0x60, 0x7f, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + map_hirom_offset(0x80, 0x9f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_hirom_offset(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + map_hirom_offset(0xc0, 0xdf, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_hirom_offset(0xe0, 0xff, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + + map_HiROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SPC7110HiROMMap (void) +{ + printf("Map_SPC7110HiROMMap\n"); + map_System(); + + map_index(0x00, 0x00, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); + map_hirom(0x00, 0x0f, 0x8000, 0xffff, CalculatedSize); + map_index(0x30, 0x30, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); + map_index(0x50, 0x50, 0x0000, 0xffff, MAP_SPC7110_DRAM, MAP_TYPE_ROM); + map_hirom(0x80, 0x8f, 0x8000, 0xffff, CalculatedSize); + map_hirom_offset(0xc0, 0xcf, 0x0000, 0xffff, CalculatedSize, 0); + map_index(0xd0, 0xff, 0x0000, 0xffff, MAP_SPC7110_ROM, MAP_TYPE_ROM); + + map_WRAM(); + + map_WriteProtectROM(); +} + +// checksum + +uint16 CMemory::checksum_calc_sum (uint8 *data, uint32 length) +{ + uint16 sum = 0; + + for (uint32 i = 0; i < length; i++) + sum += data[i]; + + return (sum); +} + +uint16 CMemory::checksum_mirror_sum (uint8 *start, uint32 &length, uint32 mask) +{ + // from NSRT + while (!(length & mask)) + mask >>= 1; + + uint16 part1 = checksum_calc_sum(start, mask); + uint16 part2 = 0; + + uint32 next_length = length - mask; + if (next_length) + { + part2 = checksum_mirror_sum(start + mask, next_length, mask >> 1); + + while (next_length < mask) + { + next_length += next_length; + part2 += part2; + } + + length = mask + mask; + } + + return (part1 + part2); +} + +void CMemory::Checksum_Calculate (void) +{ + // from NSRT + uint16 sum = 0; + + if (Settings.BS && !Settings.BSXItself) + sum = checksum_calc_sum(ROM, CalculatedSize) - checksum_calc_sum(ROM + (HiROM ? 0xffb0 : 0x7fb0), 48); + else + if (Settings.SPC7110) + { + sum = checksum_calc_sum(ROM, CalculatedSize); + if (CalculatedSize == 0x300000) + sum += sum; + } + else + { + if (CalculatedSize & 0x7fff) + sum = checksum_calc_sum(ROM, CalculatedSize); + else + { + uint32 length = CalculatedSize; + sum = checksum_mirror_sum(ROM, length); + } + } + + CalculatedChecksum = sum; +} + +// information + +const char * CMemory::MapType (void) +{ + return (HiROM ? ((ExtendedFormat != NOPE) ? "ExHiROM": "HiROM") : "LoROM"); +} + +const char * CMemory::StaticRAMSize (void) +{ + static char str[20]; + + if (SRAMSize > 16) + strcpy(str, "Corrupt"); + else + sprintf(str, "%dKbits", 8 * (SRAMMask + 1) / 1024); + + return (str); +} + +const char * CMemory::Size (void) +{ + static char str[20]; + + if (Multi.cartType == 4) + strcpy(str, "N/A"); + else + if (ROMSize < 7 || ROMSize - 7 > 23) + strcpy(str, "Corrupt"); + else + sprintf(str, "%dMbits", 1 << (ROMSize - 7)); + + return (str); +} + +const char * CMemory::Revision (void) +{ + static char str[20]; + + sprintf(str, "1.%d", HiROM ? ((ExtendedFormat != NOPE) ? ROM[0x40ffdb] : ROM[0xffdb]) : ROM[0x7fdb]); + + return (str); +} + +const char * CMemory::KartContents (void) +{ + static char str[64]; + static const char *contents[3] = { "ROM", "ROM+RAM", "ROM+RAM+BAT" }; + + char chip[16]; + + if (ROMType == 0 && !Settings.BS) + return ("ROM"); + + if (Settings.BS) + strcpy(chip, "+BS"); + else + if (Settings.SuperFX) + strcpy(chip, "+Super FX"); + else + if (Settings.SDD1) + strcpy(chip, "+S-DD1"); + else + if (Settings.OBC1) + strcpy(chip, "+OBC1"); + else + if (Settings.SA1) + strcpy(chip, "+SA-1"); + else + if (Settings.SPC7110RTC) + strcpy(chip, "+SPC7110+RTC"); + else + if (Settings.SPC7110) + strcpy(chip, "+SPC7110"); + else + if (Settings.SRTC) + strcpy(chip, "+S-RTC"); + else + if (Settings.C4) + strcpy(chip, "+C4"); + else + if (Settings.SETA == ST_010) + strcpy(chip, "+ST-010"); + else + if (Settings.SETA == ST_011) + strcpy(chip, "+ST-011"); + else + if (Settings.SETA == ST_018) + strcpy(chip, "+ST-018"); + else + if (Settings.DSP) + sprintf(chip, "+DSP-%d", Settings.DSP); + else + strcpy(chip, ""); + + sprintf(str, "%s%s", contents[(ROMType & 0xf) % 3], chip); + + return (str); +} + +const char * CMemory::Country (void) +{ + switch (ROMRegion) + { + case 0: return("Japan"); + case 1: return("USA and Canada"); + case 2: return("Oceania, Europe and Asia"); + case 3: return("Sweden"); + case 4: return("Finland"); + case 5: return("Denmark"); + case 6: return("France"); + case 7: return("Holland"); + case 8: return("Spain"); + case 9: return("Germany, Austria and Switzerland"); + case 10: return("Italy"); + case 11: return("Hong Kong and China"); + case 12: return("Indonesia"); + case 13: return("South Korea"); + default: return("Unknown"); + } +} + +const char * CMemory::PublishingCompany (void) +{ + if (CompanyId >= (int) (sizeof(nintendo_licensees) / sizeof(nintendo_licensees[0])) || CompanyId < 0) + return ("Unknown"); + + if (nintendo_licensees[CompanyId] == NULL) + return ("Unknown"); + + return (nintendo_licensees[CompanyId]); +} + +void CMemory::MakeRomInfoText (char *romtext) +{ + char temp[256]; + + romtext[0] = 0; + + sprintf(temp, " Cart Name: %s", ROMName); + strcat(romtext, temp); + sprintf(temp, "\n Game Code: %s", ROMId); + strcat(romtext, temp); + sprintf(temp, "\n Contents: %s", KartContents()); + strcat(romtext, temp); + sprintf(temp, "\n Map: %s", MapType()); + strcat(romtext, temp); + sprintf(temp, "\n Speed: 0x%02X (%s)", ROMSpeed, (ROMSpeed & 0x10) ? "FastROM" : "SlowROM"); + strcat(romtext, temp); + sprintf(temp, "\n Type: 0x%02X", ROMType); + strcat(romtext, temp); + sprintf(temp, "\n Size (calculated): %dMbits", CalculatedSize / 0x20000); + strcat(romtext, temp); + sprintf(temp, "\n Size (header): %s", Size()); + strcat(romtext, temp); + sprintf(temp, "\n SRAM size: %s", StaticRAMSize()); + strcat(romtext, temp); + sprintf(temp, "\nChecksum (calculated): 0x%04X", CalculatedChecksum); + strcat(romtext, temp); + sprintf(temp, "\n Checksum (header): 0x%04X", ROMChecksum); + strcat(romtext, temp); + sprintf(temp, "\n Complement (header): 0x%04X", ROMComplementChecksum); + strcat(romtext, temp); + sprintf(temp, "\n Video Output: %s", (ROMRegion > 12 || ROMRegion < 2) ? "NTSC 60Hz" : "PAL 50Hz"); + strcat(romtext, temp); + sprintf(temp, "\n Revision: %s", Revision()); + strcat(romtext, temp); + sprintf(temp, "\n Licensee: %s", PublishingCompany()); + strcat(romtext, temp); + sprintf(temp, "\n Region: %s", Country()); + strcat(romtext, temp); + sprintf(temp, "\n CRC32: 0x%08X", ROMCRC32); + strcat(romtext, temp); +} + +// hack + +bool8 CMemory::match_na (const char *str) +{ + return (strcmp(ROMName, str) == 0); +} + +bool8 CMemory::match_nn (const char *str) +{ + return (strncmp(ROMName, str, strlen(str)) == 0); +} + +bool8 CMemory::match_nc (const char *str) +{ + return (strncasecmp(ROMName, str, strlen(str)) == 0); +} + +bool8 CMemory::match_id (const char *str) +{ + return (strncmp(ROMId, str, strlen(str)) == 0); +} + +void CMemory::ApplyROMFixes (void) +{ + Settings.Shutdown = Settings.ShutdownMaster; + Settings.BlockInvalidVRAMAccess = Settings.BlockInvalidVRAMAccessMaster; + + //// Warnings + + // Reject strange hacked games + if ((ROMCRC32 == 0x6810aa95) || + (ROMCRC32 == 0x340f23e5) || + (ROMCRC32 == 0x77fd806a) || + (match_nn("HIGHWAY BATTLE 2")) || + (match_na("FX SKIING NINTENDO 96") && (ROM[0x7fda] == 0)) || + (match_nn("HONKAKUHA IGO GOSEI") && (ROM[0xffd5] != 0x31))) + { + Settings.DisplayColor = BUILD_PIXEL(31, 0, 0); + SET_UI_COLOR(255, 0, 0); + } + + //// APU timing hacks :( + + Timings.APUSpeedup = 0; + Timings.APUAllowTimeOverflow = FALSE; + + if (!Settings.DisableGameSpecificHacks) + { + if (match_id("AVCJ")) // Rendering Ranger R2 + Timings.APUSpeedup = 4; + + if (match_na("GAIA GENSOUKI 1 JPN") || // Gaia Gensouki + match_id("JG ") || // Illusion of Gaia + match_id("CQ ") || // Stunt Race FX + match_na("SOULBLADER - 1") || // Soul Blader + match_na("SOULBLAZER - 1 USA") || // Soul Blazer + match_na("SLAP STICK 1 JPN") || // Slap Stick + match_id("E9 ") || // Robotrek + match_nn("ACTRAISER") || // Actraiser + match_nn("ActRaiser-2") || // Actraiser 2 + match_id("AQT") || // Tenchi Souzou, Terranigma + match_id("ATV") || // Tales of Phantasia + match_id("ARF") || // Star Ocean + match_id("APR") || // Zen-Nippon Pro Wrestling 2 - 3-4 Budoukan + match_id("A4B") || // Super Bomberman 4 + match_id("Y7 ") || // U.F.O. Kamen Yakisoban - Present Ban + match_id("Y9 ") || // U.F.O. Kamen Yakisoban - Shihan Ban + match_id("APB") || // Super Bomberman - Panic Bomber W + match_na("DARK KINGDOM") || // Dark Kingdom + match_na("ZAN3 SFC") || // Zan III Spirits + match_na("HIOUDEN") || // Hiouden - Mamono-tachi Tono Chikai + match_na("\xC3\xDD\xBC\xC9\xB3\xC0") || // Tenshi no Uta + match_na("FORTUNE QUEST") || // Fortune Quest - Dice wo Korogase + match_na("FISHING TO BASSING") || // Shimono Masaki no Fishing To Bassing + match_na("OHMONO BLACKBASS") || // Oomono Black Bass Fishing - Jinzouko Hen + match_na("MASTERS") || // Harukanaru Augusta 2 - Masters + match_na("SFC \xB6\xD2\xDD\xD7\xB2\xC0\xDE\xB0") || // Kamen Rider + match_na("ZENKI TENCHIMEIDOU") || // Kishin Douji Zenki - Tenchi Meidou + match_nn("TokyoDome '95Battle 7") || // Shin Nippon Pro Wrestling Kounin '95 - Tokyo Dome Battle 7 + match_nn("SWORD WORLD SFC") || // Sword World SFC/2 + match_nn("LETs PACHINKO(") || // BS Lets Pachinko Nante Gindama 1/2/3/4 + match_nn("THE FISHING MASTER") || // Mark Davis The Fishing Master + match_nn("Parlor") || // Parlor mini/2/3/4/5/6/7, Parlor Parlor!/2/3/4/5 + match_na("HEIWA Parlor!Mini8") || // Parlor mini 8 + match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!")) // SANKYO Fever! Fever! + Timings.APUSpeedup = 1; + + if (match_na ("EARTHWORM JIM 2") || // Earthworm Jim 2 + match_na ("NBA Hangtime") || // NBA Hang Time + match_na ("MSPACMAN") || // Ms Pacman + match_na ("THE MASK") || // The Mask + match_na ("PRIMAL RAGE") || // Primal Rage + match_na ("PORKY PIGS HAUNTED") || // Porky Pig's Haunted Holiday + match_na ("Big Sky Trooper") || // Big Sky Trooper + match_id ("A35") || // Mechwarrior 3050 / Battle Tech 3050 + match_na ("DOOM TROOPERS")) // Doom Troopers + Timings.APUAllowTimeOverflow = TRUE; + } + + S9xAPUTimingSetSpeedup(Timings.APUSpeedup); + S9xAPUAllowTimeOverflow(Timings.APUAllowTimeOverflow); + + //// Other timing hacks :( + + Timings.HDMAStart = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100; + Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC; + + if (!Settings.DisableGameSpecificHacks) + { + // The delay to sync CPU and DMA which Snes9x cannot emulate. + // Some games need really severe delay timing... + if (match_na("BATTLE GRANDPRIX")) // Battle Grandprix + { + Timings.DMACPUSync = 20; + printf("DMA sync: %d\n", Timings.DMACPUSync); + } + } + + if (!Settings.DisableGameSpecificHacks) + { + // Opcode-based emulators cannot escape from "reading $4211/BPL" infinite loop... + // The true IRQ can be triggered inside an opcode. + if (match_na("TRAVERSE")) // Traverse - Starlight & Prairie + { + Timings.IRQPendCount = 1; + printf("IRQ count hack: %d\n", Timings.IRQPendCount); + } + + // An infinite loop reads $4212 and waits V-blank end, whereas VIRQ is set V=0. + // If Snes9x succeeds to escape from the loop before jumping into the IRQ handler, the game goes further. + // If Snes9x jumps into the IRQ handler before escaping from the loop, + // Snes9x cannot escape from the loop permanently because the RTI is in the next V-blank. + if (match_na("Aero the AcroBat 2")) + { + Timings.IRQPendCount = 2; + printf("IRQ count hack: %d\n", Timings.IRQPendCount); + } + + if (match_na("BATTLE BLAZE")) + { + Timings.IRQPendCount = 1; + printf("IRQ count hack: %d\n", Timings.IRQPendCount); + } + } + + if (!Settings.DisableGameSpecificHacks) + { + // XXX: What's happening? + if (match_na("X-MEN")) // Spider-Man and the X-Men + { + Settings.BlockInvalidVRAMAccess = FALSE; + printf("Invalid VRAM access hack\n"); + } + } + + //// CPU speed-ups (CPU_Shutdown()) + + // Force disabling a speed-up hack + // Games which spool sound samples between the SNES and sound CPU using + // H-DMA as the sample is playing. + if (match_na("EARTHWORM JIM 2") || // Earth Worm Jim 2 + match_na("PRIMAL RAGE") || // Primal Rage + match_na("CLAY FIGHTER") || // Clay Fighter + match_na("ClayFighter 2") || // Clay Fighter 2 + match_na("WeaponLord") || // Weapon Lord + match_nn("WAR 2410") || // War 2410 + match_id("ARF") || // Star Ocean + match_id("A4WJ") || // Mini Yonku Shining Scorpion - Let's & Go!! + match_nn("NHL") || + match_nc("MADDEN")) + { + if (Settings.Shutdown) + printf("Disabled CPU shutdown hack.\n"); + Settings.Shutdown = FALSE; + } + + // SA-1 + SA1.WaitAddress = 0xffffffff; + SA1.WaitByteAddress1 = NULL; + SA1.WaitByteAddress2 = NULL; + + if (Settings.SA1) + { + // Itoi Shigesato no Bass Tsuri No.1 (J) + if (match_id("ZBPJ")) + { + SA1.WaitAddress = 0x0093f1; + SA1.WaitByteAddress1 = FillRAM + 0x304a; + } + + // Daisenryaku Expert WWII (J) + if (match_id("AEVJ")) + { + SA1.WaitAddress = 0x0ed18d; + SA1.WaitByteAddress1 = FillRAM + 0x3000; + } + + // Derby Jockey 2 (J) + if (match_id("A2DJ")) + { + SA1.WaitAddress = 0x008b62; + } + + // Dragon Ball Z - Hyper Dimension (J) + if (match_id("AZIJ")) + { + SA1.WaitAddress = 0x008083; + SA1.WaitByteAddress1 = FillRAM + 0x3020; + } + + // SD Gundam G NEXT (J) + if (match_id("ZX3J")) + { + SA1.WaitAddress = 0x0087f2; + SA1.WaitByteAddress1 = FillRAM + 0x30c4; + } + + // Shougi no Hanamichi (J) + if (match_id("AARJ")) + { + SA1.WaitAddress = 0xc1f85a; + SA1.WaitByteAddress1 = SRAM + 0x0c64; + SA1.WaitByteAddress2 = SRAM + 0x0c66; + } + + // Asahi Shinbun Rensai Katou Hifumi Kudan Shougi Shingiryu (J) + if (match_id("A23J")) + { + SA1.WaitAddress = 0xc25037; + SA1.WaitByteAddress1 = SRAM + 0x0c06; + SA1.WaitByteAddress2 = SRAM + 0x0c08; + } + + // Taikyoku Igo - Idaten (J) + if (match_id("AIIJ")) + { + SA1.WaitAddress = 0xc100be; + SA1.WaitByteAddress1 = SRAM + 0x1002; + SA1.WaitByteAddress2 = SRAM + 0x1004; + } + + // Takemiya Masaki Kudan no Igo Taishou (J) + if (match_id("AITJ")) + { + SA1.WaitAddress = 0x0080b7; + } + + // J. League '96 Dream Stadium (J) + if (match_id("AJ6J")) + { + SA1.WaitAddress = 0xc0f74a; + } + + // Jumpin' Derby (J) + if (match_id("AJUJ")) + { + SA1.WaitAddress = 0x00d926; + } + + // Kakinoki Shougi (J) + if (match_id("AKAJ")) + { + SA1.WaitAddress = 0x00f070; + } + + // Hoshi no Kirby 3 (J), Kirby's Dream Land 3 (U) + if (match_id("AFJJ") || match_id("AFJE")) + { + SA1.WaitAddress = 0x0082d4; + SA1.WaitByteAddress1 = SRAM + 0x72a4; + } + + // Hoshi no Kirby - Super Deluxe (J) + if (match_id("AKFJ")) + { + SA1.WaitAddress = 0x008c93; + SA1.WaitByteAddress1 = FillRAM + 0x300a; + SA1.WaitByteAddress2 = FillRAM + 0x300e; + } + + // Kirby Super Star (U) + if (match_id("AKFE")) + { + SA1.WaitAddress = 0x008cb8; + SA1.WaitByteAddress1 = FillRAM + 0x300a; + SA1.WaitByteAddress2 = FillRAM + 0x300e; + } + + // Super Mario RPG (J), (U) + if (match_id("ARWJ") || match_id("ARWE")) + { + SA1.WaitAddress = 0xc0816f; + SA1.WaitByteAddress1 = FillRAM + 0x3000; + } + + // Marvelous (J) + if (match_id("AVRJ")) + { + SA1.WaitAddress = 0x0085f2; + SA1.WaitByteAddress1 = FillRAM + 0x3024; + } + + // Harukanaru Augusta 3 - Masters New (J) + if (match_id("AO3J")) + { + SA1.WaitAddress = 0x00dddb; + SA1.WaitByteAddress1 = FillRAM + 0x37b4; + } + + // Jikkyou Oshaberi Parodius (J) + if (match_id("AJOJ")) + { + SA1.WaitAddress = 0x8084e5; + } + + // Super Bomberman - Panic Bomber W (J) + if (match_id("APBJ")) + { + SA1.WaitAddress = 0x00857a; + } + + // Pebble Beach no Hatou New - Tournament Edition (J) + if (match_id("AONJ")) + { + SA1.WaitAddress = 0x00df33; + SA1.WaitByteAddress1 = FillRAM + 0x37b4; + } + + // PGA European Tour (U) + if (match_id("AEPE")) + { + SA1.WaitAddress = 0x003700; + SA1.WaitByteAddress1 = FillRAM + 0x3102; + } + + // PGA Tour 96 (U) + if (match_id("A3GE")) + { + SA1.WaitAddress = 0x003700; + SA1.WaitByteAddress1 = FillRAM + 0x3102; + } + + // Power Rangers Zeo - Battle Racers (U) + if (match_id("A4RE")) + { + SA1.WaitAddress = 0x009899; + SA1.WaitByteAddress1 = FillRAM + 0x3000; + } + + // SD F-1 Grand Prix (J) + if (match_id("AGFJ")) + { + SA1.WaitAddress = 0x0181bc; + } + + // Saikousoku Shikou Shougi Mahjong (J) + if (match_id("ASYJ")) + { + SA1.WaitAddress = 0x00f2cc; + SA1.WaitByteAddress1 = SRAM + 0x7ffe; + SA1.WaitByteAddress2 = SRAM + 0x7ffc; + } + + // Shougi Saikyou II (J) + if (match_id("AX2J")) + { + SA1.WaitAddress = 0x00d675; + } + + // Mini Yonku Shining Scorpion - Let's & Go!! (J) + if (match_id("A4WJ")) + { + SA1.WaitAddress = 0xc048be; + } + + // Shin Shougi Club (J) + if (match_id("AHJJ")) + { + SA1.WaitAddress = 0xc1002a; + SA1.WaitByteAddress1 = SRAM + 0x0806; + SA1.WaitByteAddress2 = SRAM + 0x0808; + } + + // rest games: + // Habu Meijin no Omoshiro Shougi (J) + // Hayashi Kaihou Kudan no Igo Taidou (J) + // Shougi Saikyou (J) + // Super Robot Wars Gaiden (J) + // Super Shougi 3 - Kitaihei (J) + } + + //// SRAM initial value + + if (!Settings.DisableGameSpecificHacks) + { + if (match_na("HITOMI3")) + { + SRAMSize = 1; + SRAMMask = ((1 << (SRAMSize + 3)) * 128) - 1; + } + + // SRAM value fixes + if (match_na("SUPER DRIFT OUT") || // Super Drift Out + match_na("SATAN IS OUR FATHER!") || + match_na("goemon 4")) // Ganbare Goemon Kirakira Douchuu + SNESGameFixes.SRAMInitialValue = 0x00; + + // Additional game fixes by sanmaiwashi ... + // XXX: unnecessary? + if (match_na("SFX \xC5\xB2\xC4\xB6\xDE\xDD\xC0\xDE\xD1\xD3\xC9\xB6\xDE\xC0\xD8 1")) // SD Gundam Gaiden - Knight Gundam Monogatari + SNESGameFixes.SRAMInitialValue = 0x6b; + + // others: BS and ST-01x games are 0x00. + } + + //// OAM hacks :( + + if (!Settings.DisableGameSpecificHacks) + { + // OAM hacks because we don't fully understand the behavior of the SNES. + // Totally wacky display in 2P mode... + // seems to need a disproven behavior, so we're definitely overlooking some other bug? + if (match_nn("UNIRACERS")) // Uniracers + { + SNESGameFixes.Uniracers = TRUE; + printf("Applied Uniracers hack.\n"); + } + } +} + +// UPS % IPS + +static uint32 ReadUPSPointer (const uint8 *data, unsigned &addr, unsigned size) +{ + uint32 offset = 0, shift = 1; + while(addr < size) { + uint8 x = data[addr++]; + offset += (x & 0x7f) * shift; + if(x & 0x80) break; + shift <<= 7; + offset += shift; + } + return offset; +} + +//NOTE: UPS patches are *never* created against a headered ROM! +//this is per the UPS file specification. however, do note that it is +//technically possible for a non-compliant patcher to ignore this requirement. +//therefore, it is *imperative* that no emulator support such patches. +//thusly, we ignore the "long offset" parameter below. failure to do so would +//completely invalidate the purpose of UPS; which is to avoid header vs +//no-header patching errors that result in IPS patches having a 50/50 chance of +//being applied correctly. + +static bool8 ReadUPSPatch (Reader *r, long, int32 &rom_size) +{ + //Reader lacks size() and rewind(), so we need to read in the file to get its size + uint8 *data = new uint8[8 * 1024 * 1024]; //allocate a lot of memory, better safe than sorry ... + uint32 size = 0; + while(true) { + int value = r->get_char(); + if(value == EOF) break; + data[size++] = value; + if(size >= 8 * 1024 * 1024) { + //prevent buffer overflow: SNES-made UPS patches should never be this big anyway ... + delete[] data; + return false; + } + } + + //4-byte header + 1-byte input size + 1-byte output size + 4-byte patch CRC32 + 4-byte unpatched CRC32 + 4-byte patched CRC32 + if(size < 18) { delete[] data; return false; } //patch is too small + + uint32 addr = 0; + if(data[addr++] != 'U') { delete[] data; return false; } //patch has an invalid header + if(data[addr++] != 'P') { delete[] data; return false; } //... + if(data[addr++] != 'S') { delete[] data; return false; } //... + if(data[addr++] != '1') { delete[] data; return false; } //... + + uint32 patch_crc32 = caCRC32(data, size - 4); //don't include patch CRC32 itself in CRC32 calculation + uint32 rom_crc32 = caCRC32(Memory.ROM, rom_size); + uint32 px_crc32 = (data[size - 12] << 0) + (data[size - 11] << 8) + (data[size - 10] << 16) + (data[size - 9] << 24); + uint32 py_crc32 = (data[size - 8] << 0) + (data[size - 7] << 8) + (data[size - 6] << 16) + (data[size - 5] << 24); + uint32 pp_crc32 = (data[size - 4] << 0) + (data[size - 3] << 8) + (data[size - 2] << 16) + (data[size - 1] << 24); + if(patch_crc32 != pp_crc32) { delete[] data; return false; } //patch is corrupted + if((rom_crc32 != px_crc32) && (rom_crc32 != py_crc32)) { delete[] data; return false; } //patch is for a different ROM + + uint32 px_size = ReadUPSPointer(data, addr, size); + uint32 py_size = ReadUPSPointer(data, addr, size); + uint32 out_size = ((uint32) rom_size == px_size) ? py_size : px_size; + if(out_size > CMemory::MAX_ROM_SIZE) { delete[] data; return false; } //applying this patch will overflow Memory.ROM buffer + + //fill expanded area with 0x00s; so that XORing works as expected below. + //note that this is needed (and works) whether output ROM is larger or smaller than pre-patched ROM + for(unsigned i = min((uint32) rom_size, out_size); i < max((uint32) rom_size, out_size); i++) { + Memory.ROM[i] = 0x00; + } + + uint32 relative = 0; + while(addr < size - 12) { + relative += ReadUPSPointer(data, addr, size); + while(addr < size - 12) { + uint8 x = data[addr++]; + Memory.ROM[relative++] ^= x; + if(!x) break; + } + } + + rom_size = out_size; + delete[] data; + + uint32 out_crc32 = caCRC32(Memory.ROM, rom_size); + if(((rom_crc32 == px_crc32) && (out_crc32 == py_crc32)) + || ((rom_crc32 == py_crc32) && (out_crc32 == px_crc32)) + ) { + return true; + } else { + //technically, reaching here means that patching has failed. + //we should return false, but unfortunately Memory.ROM has already + //been modified above and cannot be undone. to do this properly, we + //would need to make a copy of Memory.ROM, apply the patch, and then + //copy that back to Memory.ROM. + // + //however, the only way for this case to happen is if the UPS patch file + //itself is corrupted, which should be detected by the patch CRC32 check + //above anyway. errors due to the wrong ROM or patch file being used are + //already caught above. + fprintf(stderr, "WARNING: UPS patching appears to have failed.\nGame may not be playable.\n"); + return true; + } +} + +static long ReadInt (Reader *r, unsigned nbytes) +{ + long v = 0; + + while (nbytes--) + { + int c = r->get_char(); + if (c == EOF) + return (-1); + v = (v << 8) | (c & 0xFF); + } + + return (v); +} + +static bool8 ReadIPSPatch (Reader *r, long offset, int32 &rom_size) +{ + const int32 IPS_EOF = 0x00454F46l; + int32 ofs; + char fname[6]; + + fname[5] = 0; + for (int i = 0; i < 5; i++) + { + int c = r->get_char(); + if (c == EOF) + return (0); + fname[i] = (char) c; + } + + if (strncmp(fname, "PATCH", 5)) + return (0); + + for (;;) + { + long len, rlen; + int rchar; + + ofs = ReadInt(r, 3); + if (ofs == -1) + return (0); + + if (ofs == IPS_EOF) + break; + + ofs -= offset; + + len = ReadInt(r, 2); + if (len == -1) + return (0); + + if (len) + { + if (ofs + len > CMemory::MAX_ROM_SIZE) + return (0); + + while (len--) + { + rchar = r->get_char(); + if (rchar == EOF) + return (0); + Memory.ROM[ofs++] = (uint8) rchar; + } + + if (ofs > rom_size) + rom_size = ofs; + } + else + { + rlen = ReadInt(r, 2); + if (rlen == -1) + return (0); + + rchar = r->get_char(); + if (rchar == EOF) + return (0); + + if (ofs + rlen > CMemory::MAX_ROM_SIZE) + return (0); + + while (rlen--) + Memory.ROM[ofs++] = (uint8) rchar; + + if (ofs > rom_size) + rom_size = ofs; + } + } + + ofs = ReadInt(r, 3); + if (ofs != -1 && ofs - offset < rom_size) + rom_size = ofs - offset; + + return (1); +} + +#ifdef UNZIP_SUPPORT +static int unzFindExtension (unzFile &file, const char *ext, bool restart, bool print) +{ + unz_file_info info; + int port, l = strlen(ext); + + if (restart) + port = unzGoToFirstFile(file); + else + port = unzGoToNextFile(file); + + while (port == UNZ_OK) + { + int len; + char name[132]; + + unzGetCurrentFileInfo(file, &info, name, 128, NULL, 0, NULL, 0); + len = strlen(name); + + if (len >= l + 1 && name[len - l - 1] == '.' && strcasecmp(name + len - l, ext) == 0 && unzOpenCurrentFile(file) == UNZ_OK) + { + if (print) + printf("Using IPS or UPS patch %s", name); + + return (port); + } + + port = unzGoToNextFile(file); + } + + return (port); +} +#endif + +void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &rom_size) +{ + if (Settings.NoPatch) + return; + +#ifdef GEKKO + int patchtype; + char patchpath[2][512]; + STREAM patchfile = NULL; + long offset = header ? 512 : 0; + + sprintf(patchpath[0], "%s%s.ips", browser.dir, Memory.ROMFilename); + sprintf(patchpath[1], "%s%s.ups", browser.dir, Memory.ROMFilename); + + for(patchtype=0; patchtype<2; patchtype++) + { + if ((patchfile = OPEN_STREAM(patchpath[patchtype], "rb")) != NULL) + { + if(patchtype == 0) + ReadIPSPatch(new fReader(patchfile), offset, rom_size); + else + ReadUPSPatch(new fReader(patchfile), 0, rom_size); + CLOSE_STREAM(patchfile); + break; + } + } +#else + STREAM patch_file = NULL; + uint32 i; + long offset = header ? 512 : 0; + int ret; + bool flag; + char dir[_MAX_DIR + 1], drive[_MAX_DRIVE + 1], name[_MAX_FNAME + 1], ext[_MAX_EXT + 1], ips[_MAX_EXT + 3], fname[PATH_MAX + 1]; + const char *n; + + // UPS + + _splitpath(rom_filename, drive, dir, name, ext); + _makepath(fname, drive, dir, name, "ups"); + + if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL) + { + printf("Using UPS patch %s", fname); + + ret = ReadUPSPatch(new fReader(patch_file), 0, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + return; + } + else + printf(" failed!\n"); + } + +#ifdef UNZIP_SUPPORT + if (!strcasecmp(ext, "zip") || !strcasecmp(ext, ".zip")) + { + unzFile file = unzOpen(rom_filename); + if (file) + { + int port = unzFindExtension(file, "ups"); + if (port == UNZ_OK) + { + printf(" in %s", rom_filename); + + ret = ReadUPSPatch(new unzReader(file), offset, rom_size); + unzCloseCurrentFile(file); + + if (ret) + printf("!\n"); + else + printf(" failed!\n"); + } + } + } +#endif + + n = S9xGetFilename(".ups", IPS_DIR); + + if ((patch_file = OPEN_STREAM(n, "rb")) != NULL) + { + printf("Using UPS patch %s", n); + + ret = ReadUPSPatch(new fReader(patch_file), 0, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + return; + } + else + printf(" failed!\n"); + } + + // IPS + + _splitpath(rom_filename, drive, dir, name, ext); + _makepath(fname, drive, dir, name, "ips"); + + if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL) + { + printf("Using IPS patch %s", fname); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + return; + } + else + printf(" failed!\n"); + } + + if (_MAX_EXT > 6) + { + i = 0; + flag = false; + + do + { + snprintf(ips, 8, "%03d.ips", i); + _makepath(fname, drive, dir, name, ips); + + if (!(patch_file = OPEN_STREAM(fname, "rb"))) + break; + + printf("Using IPS patch %s", fname); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + } while (++i < 1000); + + if (flag) + return; + } + + if (_MAX_EXT > 3) + { + i = 0; + flag = false; + + do + { + snprintf(ips, _MAX_EXT + 2, "ips%d", i); + if (strlen(ips) > _MAX_EXT) + break; + _makepath(fname, drive, dir, name, ips); + + if (!(patch_file = OPEN_STREAM(fname, "rb"))) + break; + + printf("Using IPS patch %s", fname); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + } while (++i != 0); + + if (flag) + return; + } + + if (_MAX_EXT > 2) + { + i = 0; + flag = false; + + do + { + snprintf(ips, 4, "ip%d", i); + _makepath(fname, drive, dir, name, ips); + + if (!(patch_file = OPEN_STREAM(fname, "rb"))) + break; + + printf("Using IPS patch %s", fname); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + } while (++i < 10); + + if (flag) + return; + } + +#ifdef UNZIP_SUPPORT + if (!strcasecmp(ext, "zip") || !strcasecmp(ext, ".zip")) + { + unzFile file = unzOpen(rom_filename); + if (file) + { + int port = unzFindExtension(file, "ips"); + while (port == UNZ_OK) + { + printf(" in %s", rom_filename); + + ret = ReadIPSPatch(new unzReader(file), offset, rom_size); + unzCloseCurrentFile(file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + printf(" failed!\n"); + + port = unzFindExtension(file, "ips", false); + } + + if (!flag) + { + i = 0; + + do + { + snprintf(ips, 8, "%03d.ips", i); + + if (unzFindExtension(file, ips) != UNZ_OK) + break; + + printf(" in %s", rom_filename); + + ret = ReadIPSPatch(new unzReader(file), offset, rom_size); + unzCloseCurrentFile(file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + + if (unzFindExtension(file, ips, false, false) == UNZ_OK) + printf("WARNING: Ignoring extra .%s files!\n", ips); + } while (++i < 1000); + } + + if (!flag) + { + i = 0; + + do + { + snprintf(ips, _MAX_EXT + 2, "ips%d", i); + if (strlen(ips) > _MAX_EXT) + break; + + if (unzFindExtension(file, ips) != UNZ_OK) + break; + + printf(" in %s", rom_filename); + + ret = ReadIPSPatch(new unzReader(file), offset, rom_size); + unzCloseCurrentFile(file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + + if (unzFindExtension(file, ips, false, false) == UNZ_OK) + printf("WARNING: Ignoring extra .%s files!\n", ips); + } while (++i != 0); + } + + if (!flag) + { + i = 0; + + do + { + snprintf(ips, 4, "ip%d", i); + + if (unzFindExtension(file, ips) != UNZ_OK) + break; + + printf(" in %s", rom_filename); + + ret = ReadIPSPatch(new unzReader(file), offset, rom_size); + unzCloseCurrentFile(file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + + if (unzFindExtension(file, ips, false, false) == UNZ_OK) + printf("WARNING: Ignoring extra .%s files!\n", ips); + } while (++i < 10); + } + + assert(unzClose(file) == UNZ_OK); + + if (flag) + return; + } + } +#endif + + n = S9xGetFilename(".ips", IPS_DIR); + + if ((patch_file = OPEN_STREAM(n, "rb")) != NULL) + { + printf("Using IPS patch %s", n); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + return; + } + else + printf(" failed!\n"); + } + + if (_MAX_EXT > 6) + { + i = 0; + flag = false; + + do + { + snprintf(ips, 9, ".%03d.ips", i); + n = S9xGetFilename(ips, IPS_DIR); + + if (!(patch_file = OPEN_STREAM(n, "rb"))) + break; + + printf("Using IPS patch %s", n); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + } while (++i < 1000); + + if (flag) + return; + } + + if (_MAX_EXT > 3) + { + i = 0; + flag = false; + + do + { + snprintf(ips, _MAX_EXT + 3, ".ips%d", i); + if (strlen(ips) > _MAX_EXT + 1) + break; + n = S9xGetFilename(ips, IPS_DIR); + + if (!(patch_file = OPEN_STREAM(n, "rb"))) + break; + + printf("Using IPS patch %s", n); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + } while (++i != 0); + + if (flag) + return; + } + + if (_MAX_EXT > 2) + { + i = 0; + flag = false; + + do + { + snprintf(ips, 5, ".ip%d", i); + n = S9xGetFilename(ips, IPS_DIR); + + if (!(patch_file = OPEN_STREAM(n, "rb"))) + break; + + printf("Using IPS patch %s", n); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + } while (++i < 10); + + if (flag) + return; + } +#endif +} diff --git a/plugins/snes9x_gx/source/snes9x/memmap.h b/plugins/snes9x_gx/source/snes9x/memmap.h new file mode 100644 index 00000000..153ae17d --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/memmap.h @@ -0,0 +1,381 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _MEMMAP_H_ +#define _MEMMAP_H_ + +#define MEMMAP_BLOCK_SIZE (0x1000) +#define MEMMAP_NUM_BLOCKS (0x1000000 / MEMMAP_BLOCK_SIZE) +#define MEMMAP_SHIFT (12) +#define MEMMAP_MASK (MEMMAP_BLOCK_SIZE - 1) + +struct CMemory +{ + enum +#ifdef HW_DOL + { MAX_ROM_SIZE = 0x600000 }; +#else + { MAX_ROM_SIZE = 0x800000 }; +#endif + enum file_formats + { FILE_ZIP, FILE_JMA, FILE_DEFAULT }; + + enum + { NOPE, YEAH, BIGFIRST, SMALLFIRST }; + + enum + { MAP_TYPE_I_O, MAP_TYPE_ROM, MAP_TYPE_RAM }; + + enum + { + MAP_CPU, + MAP_PPU, + MAP_LOROM_SRAM, + MAP_LOROM_SRAM_B, + MAP_HIROM_SRAM, + MAP_DSP, + MAP_SA1RAM, + MAP_BWRAM, + MAP_BWRAM_BITMAP, + MAP_BWRAM_BITMAP2, + MAP_SPC7110_ROM, + MAP_SPC7110_DRAM, + MAP_RONLY_SRAM, + MAP_C4, + MAP_OBC_RAM, + MAP_SETA_DSP, + MAP_SETA_RISC, + MAP_BSX, + MAP_NONE, + MAP_LAST + }; + + uint8 NSRTHeader[32]; + int32 HeaderCount; + + uint8 *RAM; + uint8 *ROM; + uint8 *SRAM; + uint8 *VRAM; + uint8 *FillRAM; + uint8 *BWRAM; + uint8 *C4RAM; + uint8 *OBC1RAM; + uint8 *BSRAM; + uint8 *BIOSROM; + + uint8 *Map[MEMMAP_NUM_BLOCKS]; + uint8 *WriteMap[MEMMAP_NUM_BLOCKS]; + uint8 BlockIsRAM[MEMMAP_NUM_BLOCKS]; + uint8 BlockIsROM[MEMMAP_NUM_BLOCKS]; + uint8 ExtendedFormat; + + char ROMFilename[PATH_MAX + 1]; + char ROMName[ROM_NAME_LEN]; + char RawROMName[ROM_NAME_LEN]; + char ROMId[5]; + int32 CompanyId; + uint8 ROMRegion; + uint8 ROMSpeed; + uint8 ROMType; + uint8 ROMSize; + uint32 ROMChecksum; + uint32 ROMComplementChecksum; + uint32 ROMCRC32; + int32 ROMFramesPerSecond; + + bool8 HiROM; + bool8 LoROM; + uint8 SRAMSize; + uint32 SRAMMask; + uint32 CalculatedSize; + uint32 CalculatedChecksum; + + // ports can assign this to perform some custom action upon loading a ROM (such as adjusting controls) + void (*PostRomInitFunc) (void); + + bool8 Init (void); + void Deinit (void); + + int ScoreHiROM (bool8, int32 romoff = 0); + int ScoreLoROM (bool8, int32 romoff = 0); + uint32 HeaderRemove (uint32, int32 &, uint8 *); + uint32 FileLoader (uint8 *, const char *, int32); + bool8 LoadROM (const char *); + bool8 LoadMultiCart (const char *, const char *); + bool8 LoadSufamiTurbo (const char *, const char *); + bool8 LoadSameGame (const char *, const char *); + bool8 LoadSRAM (const char *); + bool8 SaveSRAM (const char *); + void ClearSRAM (bool8 onlyNonSavedSRAM = 0); + bool8 LoadSRTC (void); + bool8 SaveSRTC (void); + + char * Safe (const char *); + char * SafeANK (const char *); + void ParseSNESHeader (uint8 *); + void InitROM (void); + + uint32 map_mirror (uint32, uint32); + void map_lorom (uint32, uint32, uint32, uint32, uint32); + void map_hirom (uint32, uint32, uint32, uint32, uint32); + void map_lorom_offset (uint32, uint32, uint32, uint32, uint32, uint32); + void map_hirom_offset (uint32, uint32, uint32, uint32, uint32, uint32); + void map_space (uint32, uint32, uint32, uint32, uint8 *); + void map_index (uint32, uint32, uint32, uint32, int, int); + void map_System (void); + void map_WRAM (void); + void map_LoROMSRAM (void); + void map_HiROMSRAM (void); + void map_DSP (void); + void map_C4 (void); + void map_OBC1 (void); + void map_SetaRISC (void); + void map_SetaDSP (void); + void map_WriteProtectROM (void); + void Map_Initialize (void); + void Map_LoROMMap (void); + void Map_NoMAD1LoROMMap (void); + void Map_JumboLoROMMap (void); + void Map_ROM24MBSLoROMMap (void); + void Map_SRAM512KLoROMMap (void); + void Map_SufamiTurboLoROMMap (void); + void Map_SufamiTurboPseudoLoROMMap (void); + void Map_SuperFXLoROMMap (void); + void Map_SetaDSPLoROMMap (void); + void Map_SDD1LoROMMap (void); + void Map_SA1LoROMMap (void); + void Map_HiROMMap (void); + void Map_ExtendedHiROMMap (void); + void Map_SameGameHiROMMap (void); + void Map_SPC7110HiROMMap (void); + + uint16 checksum_calc_sum (uint8 *, uint32); + uint16 checksum_mirror_sum (uint8 *, uint32 &, uint32 mask = 0x800000); + void Checksum_Calculate (void); + + bool8 match_na (const char *); + bool8 match_nn (const char *); + bool8 match_nc (const char *); + bool8 match_id (const char *); + void ApplyROMFixes (void); + void CheckForAnyPatch (const char *, bool8, int32 &); + + void MakeRomInfoText (char *); + + const char * MapType (void); + const char * StaticRAMSize (void); + const char * Size (void); + const char * Revision (void); + const char * KartContents (void); + const char * Country (void); + const char * PublishingCompany (void); +}; + +struct SMulti +{ + int cartType; + int32 cartSizeA, cartSizeB; + int32 sramSizeA, sramSizeB; + uint32 sramMaskA, sramMaskB; + uint32 cartOffsetA, cartOffsetB; + uint8 *sramA, *sramB; + char fileNameA[PATH_MAX + 1], fileNameB[PATH_MAX + 1]; +}; + +extern CMemory Memory; +extern SMulti Multi; + +void S9xAutoSaveSRAM (void); +bool8 LoadZip(const char *, int32 *, int32 *, uint8 *); + +enum s9xwrap_t +{ + WRAP_NONE, + WRAP_BANK, + WRAP_PAGE +}; + +enum s9xwriteorder_t +{ + WRITE_01, + WRITE_10 +}; + +#include "getset.h" + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/messages.h b/plugins/snes9x_gx/source/snes9x/messages.h new file mode 100644 index 00000000..f346a7ce --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/messages.h @@ -0,0 +1,228 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _MESSAGES_H_ +#define _MESSAGES_H_ + +// Types of message sent to S9xMessage() +enum +{ + S9X_TRACE, + S9X_DEBUG, + S9X_WARNING, + S9X_INFO, + S9X_ERROR, + S9X_FATAL_ERROR +}; + +// Individual message numbers +enum +{ + S9X_ROM_INFO, + S9X_HEADERS_INFO, + S9X_CONFIG_INFO, + S9X_ROM_CONFUSING_FORMAT_INFO, + S9X_ROM_INTERLEAVED_INFO, + S9X_SOUND_DEVICE_OPEN_FAILED, + S9X_APU_STOPPED, + S9X_USAGE, + S9X_GAME_GENIE_CODE_ERROR, + S9X_ACTION_REPLY_CODE_ERROR, + S9X_GOLD_FINGER_CODE_ERROR, + S9X_DEBUG_OUTPUT, + S9X_DMA_TRACE, + S9X_HDMA_TRACE, + S9X_WRONG_FORMAT, + S9X_WRONG_VERSION, + S9X_ROM_NOT_FOUND, + S9X_FREEZE_FILE_NOT_FOUND, + S9X_PPU_TRACE, + S9X_TRACE_DSP1, + S9X_FREEZE_ROM_NAME, + S9X_HEADER_WARNING, + S9X_NETPLAY_NOT_SERVER, + S9X_FREEZE_FILE_INFO, + S9X_TURBO_MODE, + S9X_SOUND_NOT_BUILT, + S9X_MOVIE_INFO, + S9X_WRONG_MOVIE_SNAPSHOT, + S9X_NOT_A_MOVIE_SNAPSHOT, + S9X_SNAPSHOT_INCONSISTENT, + S9X_AVI_INFO +}; + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/missing.h b/plugins/snes9x_gx/source/snes9x/missing.h new file mode 100644 index 00000000..9a41fab1 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/missing.h @@ -0,0 +1,256 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifdef DEBUGGER + +#ifndef _MISSING_H_ +#define _MISSING_H_ + +struct MissingHDMA +{ + uint8 used; + uint8 bbus_address; + uint8 abus_bank; + uint16 abus_address; + uint8 indirect_address; + uint8 force_table_address_write; + uint8 force_table_address_read; + uint8 line_count_write; + uint8 line_count_read; +}; + +struct Missing +{ + struct MissingHDMA hdma[8]; + uint8 emulate6502; + uint8 decimal_mode; + uint8 mv_8bit_index; + uint8 mv_8bit_acc; + uint8 interlace; + uint8 lines_239; + uint8 pseudo_512; + uint8 modes[8]; + uint8 mode7_fx; + uint8 mode7_flip; + uint8 mode7_bgmode; + uint8 direct; + uint8 matrix_multiply; + uint8 oam_read; + uint8 vram_read; + uint8 cgram_read; + uint8 wram_read; + uint8 dma_read; + uint8 vram_inc; + uint8 vram_full_graphic_inc; + uint8 virq; + uint8 hirq; + uint16 virq_pos; + uint16 hirq_pos; + uint8 h_v_latch; + uint8 h_counter_read; + uint8 v_counter_read; + uint8 fast_rom; + uint8 window1[6]; + uint8 window2[6]; + uint8 sprite_priority_rotation; + uint8 subscreen; + uint8 subscreen_add; + uint8 subscreen_sub; + uint8 fixed_colour_add; + uint8 fixed_colour_sub; + uint8 mosaic; + uint8 sprite_double_height; + uint8 dma_channels; + uint8 dma_this_frame; + uint8 oam_address_read; + uint8 bg_offset_read; + uint8 matrix_read; + uint8 hdma_channels; + uint8 hdma_this_frame; + uint16 unknownppu_read; + uint16 unknownppu_write; + uint16 unknowncpu_read; + uint16 unknowncpu_write; + uint16 unknowndsp_read; + uint16 unknowndsp_write; +}; + +extern struct Missing missing; + +#endif + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/movie.cpp b/plugins/snes9x_gx/source/snes9x/movie.cpp new file mode 100644 index 00000000..f8044ddb --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/movie.cpp @@ -0,0 +1,1201 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + +// Input recording/playback code +// (c) Copyright 2004 blip + +#ifndef __WIN32__ +#include <unistd.h> +#endif +#include "snes9x.h" +#include "memmap.h" +#include "controls.h" +#include "snapshot.h" +#include "movie.h" +#include "language.h" +#ifdef NETPLAY_SUPPORT +#include "netplay.h" +#endif + +#ifdef __WIN32__ +#include <io.h> +#ifndef W_OK +#define W_OK 2 +#endif +#define ftruncate chsize +#endif + +#define SMV_MAGIC 0x1a564d53 // SMV0x1a +#define SMV_VERSION 5 +#define SMV_HEADER_SIZE 64 +#define SMV_EXTRAROMINFO_SIZE 30 +#define BUFFER_GROWTH_SIZE 4096 + +enum MovieState +{ + MOVIE_STATE_NONE = 0, + MOVIE_STATE_PLAY, + MOVIE_STATE_RECORD +}; + +struct SMovie +{ + enum MovieState State; + + FILE *File; + char Filename[PATH_MAX + 1]; + char ROMName[23]; + uint32 ROMCRC32; + uint32 MovieId; + uint32 Version; + + uint32 SaveStateOffset; + uint32 ControllerDataOffset; + + uint8 ControllersMask; + uint8 Opts; + uint8 SyncFlags; + uint32 MaxFrame; + uint32 MaxSample; + uint32 CurrentFrame; + uint32 CurrentSample; + uint32 BytesPerSample; + uint32 RerecordCount; + bool8 ReadOnly; + uint8 PortType[2]; + int8 PortIDs[2][4]; + + uint8 *InputBuffer; + uint8 *InputBufferPtr; + uint32 InputBufferSize; +}; + +static struct SMovie Movie; + +static uint8 prevPortType[2]; +static int8 prevPortIDs[2][4]; +static bool8 prevMouseMaster, prevSuperScopeMaster, prevJustifierMaster, prevMultiPlayer5Master; + +static uint8 Read8 (uint8 *&); +static uint16 Read16 (uint8 *&); +static uint32 Read32 (uint8 *&); +static void Write8 (uint8, uint8 *&); +static void Write16 (uint16, uint8 *&); +static void Write32 (uint32, uint8 *&); +static void store_previous_settings (void); +static void restore_previous_settings (void); +static void store_movie_settings (void); +static void restore_movie_settings (void); +static int bytes_per_sample (void); +static void reserve_buffer_space (uint32); +static void reset_controllers (void); +static void read_frame_controller_data (bool); +static void write_frame_controller_data (void); +static void flush_movie (void); +static void truncate_movie (void); +static int read_movie_header (FILE *, SMovie *); +static int read_movie_extrarominfo (FILE *, SMovie *); +static void write_movie_header (FILE *, SMovie *); +static void write_movie_extrarominfo (FILE *, SMovie *); +static void change_state (MovieState); + +// HACK: reduce movie size by not storing changes that can only affect polled input in the movie for these types, +// because currently no port sets these types to polling +#define SKIPPED_POLLING_PORT_TYPE(x) (((x) == CTL_NONE) || ((x) == CTL_JOYPAD) || ((x) == CTL_MP5)) + +#ifndef max +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#endif + + +static uint8 Read8 (uint8 *&ptr) +{ + uint8 v = *ptr++; + return (v); +} + +static uint16 Read16 (uint8 *&ptr) +{ + uint16 v = READ_WORD(ptr); + ptr += 2; + return (v); +} + +static uint32 Read32 (uint8 *&ptr) +{ + uint32 v = READ_DWORD(ptr); + ptr += 4; + return (v); +} + +static void Write8 (uint8 v, uint8 *&ptr) +{ + *ptr++ = v; +} + +static void Write16 (uint16 v, uint8 *&ptr) +{ + WRITE_WORD(ptr, v); + ptr += 2; +} + +static void Write32 (uint32 v, uint8 *&ptr) +{ + WRITE_DWORD(ptr, v); + ptr += 4; +} + +static void store_previous_settings (void) +{ + for (int i = 0; i < 2; i++) + { + enum controllers pt; + S9xGetController(i, &pt, &prevPortIDs[i][0], &prevPortIDs[i][1], &prevPortIDs[i][2], &prevPortIDs[i][3]); + prevPortType[i] = (uint8) pt; + } + + prevMouseMaster = Settings.MouseMaster; + prevSuperScopeMaster = Settings.SuperScopeMaster; + prevJustifierMaster = Settings.JustifierMaster; + prevMultiPlayer5Master = Settings.MultiPlayer5Master; +} + +static void restore_previous_settings (void) +{ + Settings.MouseMaster = prevMouseMaster; + Settings.SuperScopeMaster = prevSuperScopeMaster; + Settings.JustifierMaster = prevJustifierMaster; + Settings.MultiPlayer5Master = prevMultiPlayer5Master; + + S9xSetController(0, (enum controllers) prevPortType[0], prevPortIDs[0][0], prevPortIDs[0][1], prevPortIDs[0][2], prevPortIDs[0][3]); + S9xSetController(1, (enum controllers) prevPortType[1], prevPortIDs[1][0], prevPortIDs[1][1], prevPortIDs[1][2], prevPortIDs[1][3]); +} + +static void store_movie_settings (void) +{ + for (int i = 0; i < 2; i++) + { + enum controllers pt; + S9xGetController(i, &pt, &Movie.PortIDs[i][0], &Movie.PortIDs[i][1], &Movie.PortIDs[i][2], &Movie.PortIDs[i][3]); + Movie.PortType[i] = (uint8) pt; + } +} + +static void restore_movie_settings (void) +{ + Settings.MouseMaster = (Movie.PortType[0] == CTL_MOUSE || Movie.PortType[1] == CTL_MOUSE); + Settings.SuperScopeMaster = (Movie.PortType[0] == CTL_SUPERSCOPE || Movie.PortType[1] == CTL_SUPERSCOPE); + Settings.JustifierMaster = (Movie.PortType[0] == CTL_JUSTIFIER || Movie.PortType[1] == CTL_JUSTIFIER); + Settings.MultiPlayer5Master = (Movie.PortType[0] == CTL_MP5 || Movie.PortType[1] == CTL_MP5); + + S9xSetController(0, (enum controllers) Movie.PortType[0], Movie.PortIDs[0][0], Movie.PortIDs[0][1], Movie.PortIDs[0][2], Movie.PortIDs[0][3]); + S9xSetController(1, (enum controllers) Movie.PortType[1], Movie.PortIDs[1][0], Movie.PortIDs[1][1], Movie.PortIDs[1][2], Movie.PortIDs[1][3]); +} + +static int bytes_per_sample (void) +{ + int num_controllers = 0; + + for (int i = 0; i < 8; i++) + { + if (Movie.ControllersMask & (1 << i)) + num_controllers++; + } + + int bytes = CONTROLLER_DATA_SIZE * num_controllers; + + for (int p = 0; p < 2; p++) + { + if (Movie.PortType[p] == CTL_MOUSE) + bytes += MOUSE_DATA_SIZE; + else + if (Movie.PortType[p] == CTL_SUPERSCOPE) + bytes += SCOPE_DATA_SIZE; + else + if (Movie.PortType[p] == CTL_JUSTIFIER) + bytes += JUSTIFIER_DATA_SIZE; + } + + return (bytes); +} + +static void reserve_buffer_space (uint32 space_needed) +{ + if (space_needed > Movie.InputBufferSize) + { + uint32 ptr_offset = Movie.InputBufferPtr - Movie.InputBuffer; + uint32 alloc_chunks = space_needed / BUFFER_GROWTH_SIZE; + + Movie.InputBufferSize = BUFFER_GROWTH_SIZE * (alloc_chunks + 1); + Movie.InputBuffer = (uint8 *) realloc(Movie.InputBuffer, Movie.InputBufferSize); + Movie.InputBufferPtr = Movie.InputBuffer + ptr_offset; + } +} + +static void reset_controllers (void) +{ + for (int i = 0; i < 8; i++) + MovieSetJoypad(i, 0); + + uint8 clearedMouse[MOUSE_DATA_SIZE]; + ZeroMemory(clearedMouse, MOUSE_DATA_SIZE); + clearedMouse[4] = 1; + + uint8 clearedScope[SCOPE_DATA_SIZE]; + ZeroMemory(clearedScope, SCOPE_DATA_SIZE); + + uint8 clearedJustifier[JUSTIFIER_DATA_SIZE]; + ZeroMemory(clearedJustifier, JUSTIFIER_DATA_SIZE); + + for (int p = 0; p < 2; p++) + { + MovieSetMouse(p, clearedMouse, true); + MovieSetScope(p, clearedScope); + MovieSetJustifier(p, clearedJustifier); + } +} + +static void read_frame_controller_data (bool addFrame) +{ + // reset code check + if (Movie.InputBufferPtr[0] == 0xff) + { + bool reset = true; + for (int i = 1; i < (int) Movie.BytesPerSample; i++) + { + if (Movie.InputBufferPtr[i] != 0xff) + { + reset = false; + break; + } + } + + if (reset) + { + Movie.InputBufferPtr += Movie.BytesPerSample; + S9xSoftReset(); + return; + } + } + + for (int i = 0; i < 8; i++) + { + if (Movie.ControllersMask & (1 << i)) + MovieSetJoypad(i, Read16(Movie.InputBufferPtr)); + else + MovieSetJoypad(i, 0); // pretend the controller is disconnected + } + + for (int p = 0; p < 2; p++) + { + if (Movie.PortType[p] == CTL_MOUSE) + { + uint8 buf[MOUSE_DATA_SIZE]; + memcpy(buf, Movie.InputBufferPtr, MOUSE_DATA_SIZE); + Movie.InputBufferPtr += MOUSE_DATA_SIZE; + MovieSetMouse(p, buf, !addFrame); + } + else + if (Movie.PortType[p] == CTL_SUPERSCOPE) + { + uint8 buf[SCOPE_DATA_SIZE]; + memcpy(buf, Movie.InputBufferPtr, SCOPE_DATA_SIZE); + Movie.InputBufferPtr += SCOPE_DATA_SIZE; + MovieSetScope(p, buf); + } + else + if (Movie.PortType[p] == CTL_JUSTIFIER) + { + uint8 buf[JUSTIFIER_DATA_SIZE]; + memcpy(buf, Movie.InputBufferPtr, JUSTIFIER_DATA_SIZE); + Movie.InputBufferPtr += JUSTIFIER_DATA_SIZE; + MovieSetJustifier(p, buf); + } + } +} + +static void write_frame_controller_data (void) +{ + reserve_buffer_space((uint32) (Movie.InputBufferPtr + Movie.BytesPerSample - Movie.InputBuffer)); + + for (int i = 0; i < 8; i++) + { + if (Movie.ControllersMask & (1 << i)) + Write16(MovieGetJoypad(i), Movie.InputBufferPtr); + else + MovieSetJoypad(i, 0); // pretend the controller is disconnected + } + + for (int p = 0; p < 2; p++) + { + if (Movie.PortType[p] == CTL_MOUSE) + { + uint8 buf[MOUSE_DATA_SIZE]; + MovieGetMouse(p, buf); + memcpy(Movie.InputBufferPtr, buf, MOUSE_DATA_SIZE); + Movie.InputBufferPtr += MOUSE_DATA_SIZE; + } + else + if (Movie.PortType[p] == CTL_SUPERSCOPE) + { + uint8 buf[SCOPE_DATA_SIZE]; + MovieGetScope(p, buf); + memcpy(Movie.InputBufferPtr, buf, SCOPE_DATA_SIZE); + Movie.InputBufferPtr += SCOPE_DATA_SIZE; + } + else + if (Movie.PortType[p] == CTL_JUSTIFIER) + { + uint8 buf[JUSTIFIER_DATA_SIZE]; + MovieGetJustifier(p, buf); + memcpy(Movie.InputBufferPtr, buf, JUSTIFIER_DATA_SIZE); + Movie.InputBufferPtr += JUSTIFIER_DATA_SIZE; + } + } +} + +static void flush_movie (void) +{ + if (!Movie.File) + return; + + fseek(Movie.File, 0, SEEK_SET); + write_movie_header(Movie.File, &Movie); + fseek(Movie.File, Movie.ControllerDataOffset, SEEK_SET); + + size_t ignore; + ignore = fwrite(Movie.InputBuffer, 1, Movie.BytesPerSample * (Movie.MaxSample + 1), Movie.File); +} + +static void truncate_movie (void) +{ + if (!Movie.File || !Settings.MovieTruncate) + return; + + if (Movie.SaveStateOffset > Movie.ControllerDataOffset) + return; + + int ignore; + ignore = ftruncate(fileno(Movie.File), Movie.ControllerDataOffset + Movie.BytesPerSample * (Movie.MaxSample + 1)); +} + +static int read_movie_header (FILE *fd, SMovie *movie) +{ + uint32 value; + uint8 buf[SMV_HEADER_SIZE], *ptr = buf; + + if (fread(buf, 1, SMV_HEADER_SIZE, fd) != SMV_HEADER_SIZE) + return (WRONG_FORMAT); + + value = Read32(ptr); + if (value != SMV_MAGIC) + return (WRONG_FORMAT); + + value = Read32(ptr); + if(value > SMV_VERSION || value < 4) + return (WRONG_VERSION); + + movie->Version = value; + movie->MovieId = Read32(ptr); + movie->RerecordCount = Read32(ptr); + movie->MaxFrame = Read32(ptr); + movie->ControllersMask = Read8(ptr); + movie->Opts = Read8(ptr); + ptr++; + movie->SyncFlags = Read8(ptr); + movie->SaveStateOffset = Read32(ptr); + movie->ControllerDataOffset = Read32(ptr); + movie->MaxSample = Read32(ptr); + movie->PortType[0] = Read8(ptr); + movie->PortType[1] = Read8(ptr); + for (int p = 0; p < 2; p++) + { + for (int i = 0; i < 4; i++) + movie->PortIDs[p][i] = Read8(ptr); + } + + if (movie->MaxSample < movie->MaxFrame) + movie->MaxSample = movie->MaxFrame; + + return (SUCCESS); +} + +static int read_movie_extrarominfo (FILE *fd, SMovie *movie) +{ + uint8 buf[SMV_EXTRAROMINFO_SIZE], *ptr = buf; + + fseek(fd, movie->SaveStateOffset - SMV_EXTRAROMINFO_SIZE, SEEK_SET); + + if (fread(buf, 1, SMV_EXTRAROMINFO_SIZE, fd) != SMV_EXTRAROMINFO_SIZE) + return (WRONG_FORMAT); + + ptr += 3; // zero bytes + movie->ROMCRC32 = Read32(ptr); + strncpy(movie->ROMName, (char *) ptr, 23); + + return (SUCCESS); +} + +static void write_movie_header (FILE *fd, SMovie *movie) +{ + uint8 buf[SMV_HEADER_SIZE], *ptr = buf; + + ZeroMemory(buf, sizeof(buf)); + + Write32(SMV_MAGIC, ptr); + Write32(SMV_VERSION, ptr); + Write32(movie->MovieId, ptr); + Write32(movie->RerecordCount, ptr); + Write32(movie->MaxFrame, ptr); + Write8(movie->ControllersMask, ptr); + Write8(movie->Opts, ptr); + ptr++; + Write8(movie->SyncFlags, ptr); + Write32(movie->SaveStateOffset, ptr); + Write32(movie->ControllerDataOffset, ptr); + Write32(movie->MaxSample, ptr); + Write8(movie->PortType[0], ptr); + Write8(movie->PortType[1], ptr); + for (int p = 0; p < 2; p++) + { + for (int i = 0; i < 4; i++) + Write8(movie->PortIDs[p][i], ptr); + } + + size_t ignore; + ignore = fwrite(buf, 1, SMV_HEADER_SIZE, fd); +} + +static void write_movie_extrarominfo (FILE *fd, SMovie *movie) +{ + uint8 buf[SMV_EXTRAROMINFO_SIZE], *ptr = buf; + + Write8(0, ptr); + Write8(0, ptr); + Write8(0, ptr); + Write32(movie->ROMCRC32, ptr); + strncpy((char *) ptr, movie->ROMName, 23); + + size_t ignore; + ignore = fwrite(buf, 1, SMV_EXTRAROMINFO_SIZE, fd); +} + +static void change_state (MovieState new_state) +{ + if (new_state == Movie.State) + return; + + if (Movie.State == MOVIE_STATE_RECORD) + flush_movie(); + + if (new_state == MOVIE_STATE_NONE) + { + truncate_movie(); + fclose(Movie.File); + Movie.File = NULL; + + if (S9xMoviePlaying() || S9xMovieRecording()) + restore_previous_settings(); + } + + Movie.State = new_state; +} + +void S9xMovieFreeze (uint8 **buf, uint32 *size) +{ + if (!S9xMovieActive()) + return; + + uint32 size_needed; + uint8 *ptr; + + size_needed = sizeof(Movie.MovieId) + sizeof(Movie.CurrentFrame) + sizeof(Movie.MaxFrame) + sizeof(Movie.CurrentSample) + sizeof(Movie.MaxSample); + size_needed += (uint32) (Movie.BytesPerSample * (Movie.MaxSample + 1)); + *size = size_needed; + + *buf = new uint8[size_needed]; + ptr = *buf; + if (!ptr) + return; + + Write32(Movie.MovieId, ptr); + Write32(Movie.CurrentFrame, ptr); + Write32(Movie.MaxFrame, ptr); + Write32(Movie.CurrentSample, ptr); + Write32(Movie.MaxSample, ptr); + + memcpy(ptr, Movie.InputBuffer, Movie.BytesPerSample * (Movie.MaxSample + 1)); +} + +int S9xMovieUnfreeze (uint8 *buf, uint32 size) +{ + if (!S9xMovieActive()) + return (FILE_NOT_FOUND); + + if (size < sizeof(Movie.MovieId) + sizeof(Movie.CurrentFrame) + sizeof(Movie.MaxFrame) + sizeof(Movie.CurrentSample) + sizeof(Movie.MaxSample)) + return (WRONG_FORMAT); + + uint8 *ptr = buf; + + uint32 movie_id = Read32(ptr); + uint32 current_frame = Read32(ptr); + uint32 max_frame = Read32(ptr); + uint32 current_sample = Read32(ptr); + uint32 max_sample = Read32(ptr); + uint32 space_needed = (Movie.BytesPerSample * (max_sample + 1)); + + if (current_frame > max_frame || current_sample > max_sample || space_needed > size) + return (WRONG_MOVIE_SNAPSHOT); + + if (Settings.WrongMovieStateProtection) + if (movie_id != Movie.MovieId) + if (max_frame < Movie.MaxFrame || max_sample < Movie.MaxSample || memcmp(Movie.InputBuffer, ptr, space_needed)) + return (WRONG_MOVIE_SNAPSHOT); + + if (!Movie.ReadOnly) + { + change_state(MOVIE_STATE_RECORD); + + Movie.CurrentFrame = current_frame; + Movie.MaxFrame = max_frame; + Movie.CurrentSample = current_sample; + Movie.MaxSample = max_sample; + Movie.RerecordCount++; + + store_movie_settings(); + + reserve_buffer_space(space_needed); + memcpy(Movie.InputBuffer, ptr, space_needed); + + flush_movie(); + fseek(Movie.File, Movie.ControllerDataOffset + (Movie.BytesPerSample * (Movie.CurrentSample + 1)), SEEK_SET); + } + else + { + if (current_frame > Movie.MaxFrame || current_sample > Movie.MaxSample || memcmp(Movie.InputBuffer, ptr, space_needed)) + return (SNAPSHOT_INCONSISTENT); + + change_state(MOVIE_STATE_PLAY); + + Movie.CurrentFrame = current_frame; + Movie.CurrentSample = current_sample; + } + + Movie.InputBufferPtr = Movie.InputBuffer + (Movie.BytesPerSample * Movie.CurrentSample); + read_frame_controller_data(true); + + return (SUCCESS); +} + +int S9xMovieOpen (const char *filename, bool8 read_only) +{ + FILE *fd; + STREAM stream; + int result; + int fn; + + if (!(fd = fopen(filename, "rb+"))) + { + if (!(fd = fopen(filename, "rb"))) + return (FILE_NOT_FOUND); + else + read_only = TRUE; + } + + change_state(MOVIE_STATE_NONE); + + result = read_movie_header(fd, &Movie); + if (result != SUCCESS) + { + fclose(fd); + return (result); + } + + read_movie_extrarominfo(fd, &Movie); + + fn = dup(fileno(fd)); + fclose(fd); + + store_previous_settings(); + restore_movie_settings(); + + lseek(fn, Movie.SaveStateOffset, SEEK_SET); + stream = REOPEN_STREAM(fn, "rb"); + if (!stream) + return (FILE_NOT_FOUND); + + if (Movie.Opts & MOVIE_OPT_FROM_RESET) + { + S9xReset(); + reset_controllers(); + result = (READ_STREAM(Memory.SRAM, 0x20000, stream) == 0x20000) ? SUCCESS : WRONG_FORMAT; + } + else + result = S9xUnfreezeFromStream(stream); + + CLOSE_STREAM(stream); + + if (result != SUCCESS) + return (result); + + if (!(fd = fopen(filename, "rb+"))) + { + if (!(fd = fopen(filename, "rb"))) + return (FILE_NOT_FOUND); + else + read_only = TRUE; + } + + if (fseek(fd, Movie.ControllerDataOffset, SEEK_SET)) + return (WRONG_FORMAT); + + Movie.File = fd; + Movie.BytesPerSample = bytes_per_sample(); + Movie.InputBufferPtr = Movie.InputBuffer; + reserve_buffer_space(Movie.BytesPerSample * (Movie.MaxSample + 1)); + + size_t ignore; + ignore = fread(Movie.InputBufferPtr, 1, Movie.BytesPerSample * (Movie.MaxSample + 1), fd); + + // read "baseline" controller data + if (Movie.MaxSample && Movie.MaxFrame) + read_frame_controller_data(true); + + Movie.CurrentFrame = 0; + Movie.CurrentSample = 0; + Movie.ReadOnly = read_only; + strncpy(Movie.Filename, filename, PATH_MAX + 1); + Movie.Filename[PATH_MAX] = 0; + + change_state(MOVIE_STATE_PLAY); + + S9xUpdateFrameCounter(-1); + + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_REPLAY); + + return (SUCCESS); +} + +int S9xMovieCreate (const char *filename, uint8 controllers_mask, uint8 opts, const wchar_t *metadata, int metadata_length) +{ + FILE *fd; + STREAM stream; + int fn; + + if (controllers_mask == 0) + return (WRONG_FORMAT); + + if (!(fd = fopen(filename, "wb"))) + return (FILE_NOT_FOUND); + + if (metadata_length > MOVIE_MAX_METADATA) + metadata_length = MOVIE_MAX_METADATA; + + change_state(MOVIE_STATE_NONE); + + store_previous_settings(); + store_movie_settings(); + + Movie.MovieId = (uint32) time(NULL); + Movie.RerecordCount = 0; + Movie.MaxFrame = 0; + Movie.MaxSample = 0; + Movie.SaveStateOffset = SMV_HEADER_SIZE + (sizeof(uint16) * metadata_length) + SMV_EXTRAROMINFO_SIZE; + Movie.ControllerDataOffset = 0; + Movie.ControllersMask = controllers_mask; + Movie.Opts = opts; + Movie.SyncFlags = MOVIE_SYNC_DATA_EXISTS | MOVIE_SYNC_HASROMINFO; + + write_movie_header(fd, &Movie); + + // convert wchar_t metadata string/array to a uint16 array + // XXX: UTF-8 is much better... + if (metadata_length > 0) + { + uint8 meta_buf[sizeof(uint16) * MOVIE_MAX_METADATA]; + for (int i = 0; i < metadata_length; i++) + { + uint16 c = (uint16) metadata[i]; + meta_buf[i * 2] = (uint8) (c & 0xff); + meta_buf[i * 2 + 1] = (uint8) ((c >> 8) & 0xff); + } + + size_t ignore; + ignore = fwrite(meta_buf, sizeof(uint16), metadata_length, fd); + } + + Movie.ROMCRC32 = Memory.ROMCRC32; + strncpy(Movie.ROMName, Memory.RawROMName, 23); + + write_movie_extrarominfo(fd, &Movie); + + fn = dup(fileno(fd)); + fclose(fd); + + stream = REOPEN_STREAM(fn, "ab"); + if (!stream) + return (FILE_NOT_FOUND); + + if (opts & MOVIE_OPT_FROM_RESET) + { + S9xReset(); + reset_controllers(); + WRITE_STREAM(Memory.SRAM, 0x20000, stream); + } + else + S9xFreezeToStream(stream); + + CLOSE_STREAM(stream); + + if (!(fd = fopen(filename, "rb+"))) + return (FILE_NOT_FOUND); + + fseek(fd, 0, SEEK_END); + Movie.ControllerDataOffset = (uint32) ftell(fd); + + // 16-byte align the controller input, for hex-editing friendliness if nothing else + while (Movie.ControllerDataOffset % 16) + { + fputc(0xcc, fd); // arbitrary + Movie.ControllerDataOffset++; + } + + // write "baseline" controller data + Movie.File = fd; + Movie.BytesPerSample = bytes_per_sample(); + Movie.InputBufferPtr = Movie.InputBuffer; + write_frame_controller_data(); + + Movie.CurrentFrame = 0; + Movie.CurrentSample = 0; + Movie.ReadOnly = false; + strncpy(Movie.Filename, filename, PATH_MAX + 1); + Movie.Filename[PATH_MAX] = 0; + + change_state(MOVIE_STATE_RECORD); + + S9xUpdateFrameCounter(-1); + + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_RECORD); + + return (SUCCESS); +} + +int S9xMovieGetInfo (const char *filename, struct MovieInfo *info) +{ + FILE *fd; + SMovie local_movie; + int metadata_length; + int result, i; + + flush_movie(); + + ZeroMemory(info, sizeof(*info)); + + if (!(fd = fopen(filename, "rb"))) + return (FILE_NOT_FOUND); + + result = read_movie_header(fd, &local_movie); + if (result != SUCCESS) + return (result); + + info->TimeCreated = (time_t) local_movie.MovieId; + info->Version = local_movie.Version; + info->Opts = local_movie.Opts; + info->SyncFlags = local_movie.SyncFlags; + info->ControllersMask = local_movie.ControllersMask; + info->RerecordCount = local_movie.RerecordCount; + info->LengthFrames = local_movie.MaxFrame; + info->LengthSamples = local_movie.MaxSample; + info->PortType[0] = local_movie.PortType[0]; + info->PortType[1] = local_movie.PortType[1]; + + if (local_movie.SaveStateOffset > SMV_HEADER_SIZE) + { + uint8 meta_buf[sizeof(uint16) * MOVIE_MAX_METADATA]; + int curRomInfoSize = (local_movie.SyncFlags & MOVIE_SYNC_HASROMINFO) ? SMV_EXTRAROMINFO_SIZE : 0; + + metadata_length = ((int) local_movie.SaveStateOffset - SMV_HEADER_SIZE - curRomInfoSize) / sizeof(uint16); + metadata_length = (metadata_length >= MOVIE_MAX_METADATA) ? MOVIE_MAX_METADATA - 1 : metadata_length; + metadata_length = (int) fread(meta_buf, sizeof(uint16), metadata_length, fd); + + for (i = 0; i < metadata_length; i++) + { + uint16 c = meta_buf[i * 2] | (meta_buf[i * 2 + 1] << 8); + info->Metadata[i] = (wchar_t) c; + } + + info->Metadata[i] = '\0'; + } + else + info->Metadata[0] = '\0'; + + read_movie_extrarominfo(fd, &local_movie); + + info->ROMCRC32 = local_movie.ROMCRC32; + strncpy(info->ROMName, local_movie.ROMName, 23); + + fclose(fd); + + if (access(filename, W_OK)) + info->ReadOnly = true; + + return (SUCCESS); +} + +void S9xMovieUpdate (bool addFrame) +{ + switch (Movie.State) + { + case MOVIE_STATE_PLAY: + { + if (Movie.CurrentFrame >= Movie.MaxFrame || Movie.CurrentSample >= Movie.MaxSample) + { + change_state(MOVIE_STATE_NONE); + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_END); + return; + } + else + { + if (addFrame) + S9xUpdateFrameCounter(); + else + if (SKIPPED_POLLING_PORT_TYPE(Movie.PortType[0]) && SKIPPED_POLLING_PORT_TYPE(Movie.PortType[1])) + return; + + read_frame_controller_data(addFrame); + Movie.CurrentSample++; + if (addFrame) + Movie.CurrentFrame++; + } + + break; + } + + case MOVIE_STATE_RECORD: + { + if (addFrame) + S9xUpdateFrameCounter(); + else + if (SKIPPED_POLLING_PORT_TYPE(Movie.PortType[0]) && SKIPPED_POLLING_PORT_TYPE(Movie.PortType[1])) + return; + + write_frame_controller_data(); + Movie.MaxSample = ++Movie.CurrentSample; + if (addFrame) + Movie.MaxFrame = ++Movie.CurrentFrame; + + size_t ignore; + ignore = fwrite((Movie.InputBufferPtr - Movie.BytesPerSample), 1, Movie.BytesPerSample, Movie.File); + + break; + } + + default: + { + if (addFrame) + S9xUpdateFrameCounter(); + + break; + } + } +} + +void S9xMovieUpdateOnReset (void) +{ + if (Movie.State == MOVIE_STATE_RECORD) + { + reserve_buffer_space((uint32) (Movie.InputBufferPtr + Movie.BytesPerSample - Movie.InputBuffer)); + memset(Movie.InputBufferPtr, 0xFF, Movie.BytesPerSample); + Movie.InputBufferPtr += Movie.BytesPerSample; + Movie.MaxSample = ++Movie.CurrentSample; + Movie.MaxFrame = ++Movie.CurrentFrame; + + size_t ignore; + ignore = fwrite((Movie.InputBufferPtr - Movie.BytesPerSample), 1, Movie.BytesPerSample, Movie.File); + } +} + +void S9xMovieInit (void) +{ + ZeroMemory(&Movie, sizeof(Movie)); + Movie.State = MOVIE_STATE_NONE; +} + +void S9xMovieStop (bool8 suppress_message) +{ + if (Movie.State != MOVIE_STATE_NONE) + { + change_state(MOVIE_STATE_NONE); + + if (!suppress_message) + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_STOP); + } +} + +void S9xMovieShutdown (void) +{ + if (S9xMovieActive()) + S9xMovieStop(TRUE); +} + +bool8 S9xMovieActive (void) +{ + return (Movie.State != MOVIE_STATE_NONE); +} + +bool8 S9xMoviePlaying (void) +{ + return (Movie.State == MOVIE_STATE_PLAY); +} + +bool8 S9xMovieRecording (void) +{ + return (Movie.State == MOVIE_STATE_RECORD); +} + +uint8 S9xMovieControllers (void) +{ + return (Movie.ControllersMask); +} + +bool8 S9xMovieReadOnly (void) +{ + if (!S9xMovieActive()) + return (FALSE); + return (Movie.ReadOnly); +} + +uint32 S9xMovieGetId (void) +{ + if (!S9xMovieActive()) + return (0); + return (Movie.MovieId); +} + +uint32 S9xMovieGetLength (void) +{ + if (!S9xMovieActive()) + return (0); + return (Movie.MaxFrame); +} + +uint32 S9xMovieGetFrameCounter (void) +{ + if (!S9xMovieActive()) + return (0); + return (Movie.CurrentFrame); +} + +void S9xMovieToggleRecState (void) +{ + Movie.ReadOnly = !Movie.ReadOnly; + + if (Movie.ReadOnly) + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, "Movie is now read-only."); + else + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, "Movie is now read+write."); +} + +void S9xMovieToggleFrameDisplay (void) +{ + Settings.DisplayMovieFrame = !Settings.DisplayMovieFrame; + S9xReRefresh(); +} + +void S9xUpdateFrameCounter (int offset) +{ + extern bool8 pad_read; + + offset++; + + if (!Settings.DisplayMovieFrame) + *GFX.FrameDisplayString = 0; + else + if (Movie.State == MOVIE_STATE_RECORD) + sprintf(GFX.FrameDisplayString, "Recording frame: %d%s", + max(0, (int) (Movie.CurrentFrame + offset)), pad_read || !Settings.MovieNotifyIgnored ? "" : " (ignored)"); + else + if (Movie.State == MOVIE_STATE_PLAY) + sprintf(GFX.FrameDisplayString, "Playing frame: %d / %d", + max(0, (int) (Movie.CurrentFrame + offset)), Movie.MaxFrame); +#ifdef NETPLAY_SUPPORT + else + if (Settings.NetPlay) + sprintf(GFX.FrameDisplayString, "%s frame: %d", Settings.NetPlayServer ? "Server" : "Client", + max(0, (int) (NetPlay.FrameCount + offset))); +#endif +} diff --git a/plugins/snes9x_gx/source/snes9x/movie.h b/plugins/snes9x_gx/source/snes9x/movie.h new file mode 100644 index 00000000..f1fb2bb0 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/movie.h @@ -0,0 +1,254 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _MOVIE_H_ +#define _MOVIE_H_ + +#define MOVIE_OPT_FROM_SNAPSHOT 0 +#define MOVIE_OPT_FROM_RESET (1 << 0) +#define MOVIE_OPT_PAL (1 << 1) +#define MOVIE_OPT_NOSAVEDATA (1 << 2) +#define MOVIE_SYNC_DATA_EXISTS 0x01 +#define MOVIE_SYNC_OBSOLETE 0x02 +#define MOVIE_SYNC_LEFTRIGHT 0x04 +#define MOVIE_SYNC_VOLUMEENVX 0x08 +#define MOVIE_SYNC_FAKEMUTE 0x10 +#define MOVIE_SYNC_SYNCSOUND 0x20 +#define MOVIE_SYNC_HASROMINFO 0x40 +#define MOVIE_SYNC_NOCPUSHUTDOWN 0x80 +#define MOVIE_MAX_METADATA 512 + +#define CONTROLLER_DATA_SIZE 2 +#define MOUSE_DATA_SIZE 5 +#define SCOPE_DATA_SIZE 6 +#define JUSTIFIER_DATA_SIZE 11 + +struct MovieInfo +{ + time_t TimeCreated; + uint32 Version; + uint32 LengthFrames; + uint32 LengthSamples; + uint32 RerecordCount; + uint8 Opts; + uint8 ControllersMask; + uint8 SyncFlags; + bool8 ReadOnly; + uint8 PortType[2]; + wchar_t Metadata[MOVIE_MAX_METADATA]; + uint32 ROMCRC32; + char ROMName[23]; +}; + +// methods used by the user-interface code +int S9xMovieOpen (const char *, bool8); +int S9xMovieCreate (const char *, uint8, uint8, const wchar_t *, int); +int S9xMovieGetInfo (const char *, struct MovieInfo *); +void S9xMovieStop (bool8); +void S9xMovieToggleRecState (void); +void S9xMovieToggleFrameDisplay (void); +const char * S9xChooseMovieFilename (bool8); + +// methods used by the emulation +void S9xMovieInit (void); +void S9xMovieShutdown (void); +void S9xMovieUpdate (bool a = true); +void S9xMovieUpdateOnReset (void); +void S9xUpdateFrameCounter (int o = 0); +void S9xMovieFreeze (uint8 **, uint32 *); +int S9xMovieUnfreeze (uint8 *, uint32); + +// accessor functions +bool8 S9xMovieActive (void); +bool8 S9xMoviePlaying (void); +bool8 S9xMovieRecording (void); +bool8 S9xMovieReadOnly (void); +uint8 S9xMovieControllers (void); +uint32 S9xMovieGetId (void); +uint32 S9xMovieGetLength (void); +uint32 S9xMovieGetFrameCounter (void); + +uint16 MovieGetJoypad (int); +void MovieSetJoypad (int, uint16); +bool MovieGetMouse (int, uint8 d[MOUSE_DATA_SIZE]); +void MovieSetMouse (int, uint8 d[MOUSE_DATA_SIZE], bool); +bool MovieGetScope (int, uint8 d[SCOPE_DATA_SIZE]); +void MovieSetScope (int, uint8 d[SCOPE_DATA_SIZE]); +bool MovieGetJustifier (int, uint8 d[JUSTIFIER_DATA_SIZE]); +void MovieSetJustifier (int, uint8 d[JUSTIFIER_DATA_SIZE]); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/obc1.cpp b/plugins/snes9x_gx/source/snes9x/obc1.cpp new file mode 100644 index 00000000..9fe98de5 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/obc1.cpp @@ -0,0 +1,276 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" + + +uint8 S9xGetOBC1 (uint16 Address) +{ + switch (Address) + { + case 0x7ff0: + return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2)]); + + case 0x7ff1: + return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 1]); + + case 0x7ff2: + return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 2]); + + case 0x7ff3: + return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 3]); + + case 0x7ff4: + return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address >> 2) + 0x200]); + } + + return (Memory.OBC1RAM[Address - 0x6000]); +} + +void S9xSetOBC1 (uint8 Byte, uint16 Address) +{ + switch (Address) + { + case 0x7ff0: + Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2)] = Byte; + break; + + case 0x7ff1: + Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 1] = Byte; + break; + + case 0x7ff2: + Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 2] = Byte; + break; + + case 0x7ff3: + Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 3] = Byte; + break; + + case 0x7ff4: + { + uint8 Temp; + Temp = Memory.OBC1RAM[OBC1.basePtr + (OBC1.address >> 2) + 0x200]; + Temp = (Temp & ~(3 << OBC1.shift)) | ((Byte & 3) << OBC1.shift); + Memory.OBC1RAM[OBC1.basePtr + (OBC1.address >> 2) + 0x200] = Temp; + break; + } + + case 0x7ff5: + if (Byte & 1) + OBC1.basePtr = 0x1800; + else + OBC1.basePtr = 0x1c00; + break; + + case 0x7ff6: + OBC1.address = Byte & 0x7f; + OBC1.shift = (Byte & 3) << 1; + break; + } + + Memory.OBC1RAM[Address - 0x6000] = Byte; +} + +void S9xResetOBC1 (void) +{ + for (int i = 0; i <= 0x1fff; i++) + Memory.OBC1RAM[i] = 0xff; + + if (Memory.OBC1RAM[0x1ff5] & 1) + OBC1.basePtr = 0x1800; + else + OBC1.basePtr = 0x1c00; + + OBC1.address = Memory.OBC1RAM[0x1ff6] & 0x7f; + OBC1.shift = (Memory.OBC1RAM[0x1ff6] & 3) << 1; +} + +uint8 * S9xGetBasePointerOBC1 (uint16 Address) +{ + if (Address >= 0x7ff0 && Address <= 0x7ff6) + return (NULL); + return (Memory.OBC1RAM - 0x6000); +} + +uint8 * S9xGetMemPointerOBC1 (uint16 Address) +{ + if (Address >= 0x7ff0 && Address <= 0x7ff6) + return (NULL); + return (Memory.OBC1RAM + Address - 0x6000); +} diff --git a/plugins/snes9x_gx/source/snes9x/obc1.h b/plugins/snes9x_gx/source/snes9x/obc1.h new file mode 100644 index 00000000..836850b7 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/obc1.h @@ -0,0 +1,196 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _OBC1_H_ +#define _OBC1_H_ + +struct SOBC1 +{ + uint16 address; + uint16 basePtr; + uint16 shift; +}; + +extern struct SOBC1 OBC1; + +void S9xSetOBC1 (uint8, uint16); +uint8 S9xGetOBC1 (uint16); +void S9xResetOBC1 (void); +uint8 * S9xGetBasePointerOBC1 (uint16); +uint8 * S9xGetMemPointerOBC1 (uint16); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/pixform.h b/plugins/snes9x_gx/source/snes9x/pixform.h new file mode 100644 index 00000000..1760899c --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/pixform.h @@ -0,0 +1,407 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _PIXFORM_H_ +#define _PIXFORM_H_ + +#ifdef GFX_MULTI_FORMAT + +enum { RGB565, RGB555, BGR565, BGR555, GBR565, GBR555, RGB5551 }; + +#define BUILD_PIXEL(R, G, B) ((*GFX.BuildPixel) (R, G, B)) +#define BUILD_PIXEL2(R, G, B) ((*GFX.BuildPixel2) (R, G, B)) +#define DECOMPOSE_PIXEL(PIX, R, G, B) ((*GFX.DecomposePixel) (PIX, R, G, B)) + +extern uint32 MAX_RED; +extern uint32 MAX_GREEN; +extern uint32 MAX_BLUE; +extern uint32 RED_LOW_BIT_MASK; +extern uint32 GREEN_LOW_BIT_MASK; +extern uint32 BLUE_LOW_BIT_MASK; +extern uint32 RED_HI_BIT_MASK; +extern uint32 GREEN_HI_BIT_MASK; +extern uint32 BLUE_HI_BIT_MASK; +extern uint32 FIRST_COLOR_MASK; +extern uint32 SECOND_COLOR_MASK; +extern uint32 THIRD_COLOR_MASK; +extern uint32 ALPHA_BITS_MASK; +extern uint32 GREEN_HI_BIT; +extern uint32 RGB_LOW_BITS_MASK; +extern uint32 RGB_HI_BITS_MASK; +extern uint32 RGB_HI_BITS_MASKx2; +extern uint32 RGB_REMOVE_LOW_BITS_MASK; +extern uint32 FIRST_THIRD_COLOR_MASK; +extern uint32 TWO_LOW_BITS_MASK; +extern uint32 HIGH_BITS_SHIFTED_TWO_MASK; +extern uint32 SPARE_RGB_BIT_MASK; + +#endif + +/* RGB565 format */ +#define BUILD_PIXEL_RGB565(R, G, B) (((int) (R) << 11) | ((int) (G) << 6) | (int) (B)) +#define BUILD_PIXEL2_RGB565(R, G, B) (((int) (R) << 11) | ((int) (G) << 5) | (int) (B)) +#define DECOMPOSE_PIXEL_RGB565(PIX, R, G, B) { (R) = (PIX) >> 11; (G) = ((PIX) >> 6) & 0x1f; (B) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_RGB565 (1 << 5) + +#define MAX_RED_RGB565 31 +#define MAX_GREEN_RGB565 63 +#define MAX_BLUE_RGB565 31 +#define RED_LOW_BIT_MASK_RGB565 0x0800 +#define GREEN_LOW_BIT_MASK_RGB565 0x0020 +#define BLUE_LOW_BIT_MASK_RGB565 0x0001 +#define RED_HI_BIT_MASK_RGB565 0x8000 +#define GREEN_HI_BIT_MASK_RGB565 0x0400 +#define BLUE_HI_BIT_MASK_RGB565 0x0010 +#define FIRST_COLOR_MASK_RGB565 0xF800 +#define SECOND_COLOR_MASK_RGB565 0x07E0 +#define THIRD_COLOR_MASK_RGB565 0x001F +#define ALPHA_BITS_MASK_RGB565 0x0000 + +/* RGB555 format */ +#define BUILD_PIXEL_RGB555(R, G, B) (((int) (R) << 10) | ((int) (G) << 5) | (int) (B)) +#define BUILD_PIXEL2_RGB555(R, G, B) (((int) (R) << 10) | ((int) (G) << 5) | (int) (B)) +#define DECOMPOSE_PIXEL_RGB555(PIX, R, G, B) { (R) = (PIX) >> 10; (G) = ((PIX) >> 5) & 0x1f; (B) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_RGB555 (1 << 15) + +#define MAX_RED_RGB555 31 +#define MAX_GREEN_RGB555 31 +#define MAX_BLUE_RGB555 31 +#define RED_LOW_BIT_MASK_RGB555 0x0400 +#define GREEN_LOW_BIT_MASK_RGB555 0x0020 +#define BLUE_LOW_BIT_MASK_RGB555 0x0001 +#define RED_HI_BIT_MASK_RGB555 0x4000 +#define GREEN_HI_BIT_MASK_RGB555 0x0200 +#define BLUE_HI_BIT_MASK_RGB555 0x0010 +#define FIRST_COLOR_MASK_RGB555 0x7C00 +#define SECOND_COLOR_MASK_RGB555 0x03E0 +#define THIRD_COLOR_MASK_RGB555 0x001F +#define ALPHA_BITS_MASK_RGB555 0x0000 + +/* BGR565 format */ +#define BUILD_PIXEL_BGR565(R, G, B) (((int) (B) << 11) | ((int) (G) << 6) | (int) (R)) +#define BUILD_PIXEL2_BGR565(R, G, B) (((int) (B) << 11) | ((int) (G) << 5) | (int) (R)) +#define DECOMPOSE_PIXEL_BGR565(PIX, R, G, B) { (B) = (PIX) >> 11; (G) = ((PIX) >> 6) & 0x1f; (R) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_BGR565 (1 << 5) + +#define MAX_RED_BGR565 31 +#define MAX_GREEN_BGR565 63 +#define MAX_BLUE_BGR565 31 +#define RED_LOW_BIT_MASK_BGR565 0x0001 +#define GREEN_LOW_BIT_MASK_BGR565 0x0040 +#define BLUE_LOW_BIT_MASK_BGR565 0x0800 +#define RED_HI_BIT_MASK_BGR565 0x0010 +#define GREEN_HI_BIT_MASK_BGR565 0x0400 +#define BLUE_HI_BIT_MASK_BGR565 0x8000 +#define FIRST_COLOR_MASK_BGR565 0xF800 +#define SECOND_COLOR_MASK_BGR565 0x07E0 +#define THIRD_COLOR_MASK_BGR565 0x001F +#define ALPHA_BITS_MASK_BGR565 0x0000 + +/* BGR555 format */ +#define BUILD_PIXEL_BGR555(R, G, B) (((int) (B) << 10) | ((int) (G) << 5) | (int) (R)) +#define BUILD_PIXEL2_BGR555(R, G, B) (((int) (B) << 10) | ((int) (G) << 5) | (int) (R)) +#define DECOMPOSE_PIXEL_BGR555(PIX, R, G, B) { (B) = (PIX) >> 10; (G) = ((PIX) >> 5) & 0x1f; (R) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_BGR555 (1 << 15) + +#define MAX_RED_BGR555 31 +#define MAX_GREEN_BGR555 31 +#define MAX_BLUE_BGR555 31 +#define RED_LOW_BIT_MASK_BGR555 0x0001 +#define GREEN_LOW_BIT_MASK_BGR555 0x0020 +#define BLUE_LOW_BIT_MASK_BGR555 0x0400 +#define RED_HI_BIT_MASK_BGR555 0x0010 +#define GREEN_HI_BIT_MASK_BGR555 0x0200 +#define BLUE_HI_BIT_MASK_BGR555 0x4000 +#define FIRST_COLOR_MASK_BGR555 0x7C00 +#define SECOND_COLOR_MASK_BGR555 0x03E0 +#define THIRD_COLOR_MASK_BGR555 0x001F +#define ALPHA_BITS_MASK_BGR555 0x0000 + +/* GBR565 format */ +#define BUILD_PIXEL_GBR565(R, G, B) (((int) (G) << 11) | ((int) (B) << 6) | (int) (R)) +#define BUILD_PIXEL2_GBR565(R, G, B) (((int) (G) << 11) | ((int) (B) << 5) | (int) (R)) +#define DECOMPOSE_PIXEL_GBR565(PIX, R, G, B) { (G) = (PIX) >> 11; (B) = ((PIX) >> 6) & 0x1f; (R) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_GBR565 (1 << 5) + +#define MAX_RED_GBR565 31 +#define MAX_GREEN_GBR565 31 +#define MAX_BLUE_GBR565 63 +#define RED_LOW_BIT_MASK_GBR565 0x0001 +#define GREEN_LOW_BIT_MASK_GBR565 0x0800 +#define BLUE_LOW_BIT_MASK_GBR565 0x0040 +#define RED_HI_BIT_MASK_GBR565 0x0010 +#define GREEN_HI_BIT_MASK_GBR565 0x8000 +#define BLUE_HI_BIT_MASK_GBR565 0x0400 +#define FIRST_COLOR_MASK_GBR565 0xF800 +#define SECOND_COLOR_MASK_GBR565 0x07E0 +#define THIRD_COLOR_MASK_GBR565 0x001F +#define ALPHA_BITS_MASK_GBR565 0x0000 + +/* GBR555 format */ +#define BUILD_PIXEL_GBR555(R, G, B) (((int) (G) << 10) | ((int) (B) << 5) | (int) (R)) +#define BUILD_PIXEL2_GBR555(R, G, B) (((int) (G) << 10) | ((int) (B) << 5) | (int) (R)) +#define DECOMPOSE_PIXEL_GBR555(PIX, R, G, B) { (G) = (PIX) >> 10; (B) = ((PIX) >> 5) & 0x1f; (R) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_GBR555 (1 << 15) + +#define MAX_RED_GBR555 31 +#define MAX_GREEN_GBR555 31 +#define MAX_BLUE_GBR555 31 +#define RED_LOW_BIT_MASK_GBR555 0x0001 +#define GREEN_LOW_BIT_MASK_GBR555 0x0400 +#define BLUE_LOW_BIT_MASK_GBR555 0x0020 +#define RED_HI_BIT_MASK_GBR555 0x0010 +#define GREEN_HI_BIT_MASK_GBR555 0x4000 +#define BLUE_HI_BIT_MASK_GBR555 0x0200 +#define FIRST_COLOR_MASK_GBR555 0x7C00 +#define SECOND_COLOR_MASK_GBR555 0x03E0 +#define THIRD_COLOR_MASK_GBR555 0x001F +#define ALPHA_BITS_MASK_GBR555 0x0000 + +/* RGB5551 format */ +#define BUILD_PIXEL_RGB5551(R, G, B) (((int) (R) << 11) | ((int) (G) << 6) | (int) ((B) << 1) | 1) +#define BUILD_PIXEL2_RGB5551(R, G, B) (((int) (R) << 11) | ((int) (G) << 6) | (int) ((B) << 1) | 1) +#define DECOMPOSE_PIXEL_RGB5551(PIX, R, G, B) { (R) = (PIX) >> 11; (G) = ((PIX) >> 6) & 0x1f; (B) = ((PIX) >> 1) & 0x1f; } +#define SPARE_RGB_BIT_MASK_RGB5551 (1) + +#define MAX_RED_RGB5551 31 +#define MAX_GREEN_RGB5551 31 +#define MAX_BLUE_RGB5551 31 +#define RED_LOW_BIT_MASK_RGB5551 0x0800 +#define GREEN_LOW_BIT_MASK_RGB5551 0x0040 +#define BLUE_LOW_BIT_MASK_RGB5551 0x0002 +#define RED_HI_BIT_MASK_RGB5551 0x8000 +#define GREEN_HI_BIT_MASK_RGB5551 0x0400 +#define BLUE_HI_BIT_MASK_RGB5551 0x0020 +#define FIRST_COLOR_MASK_RGB5551 0xf800 +#define SECOND_COLOR_MASK_RGB5551 0x07c0 +#define THIRD_COLOR_MASK_RGB5551 0x003e +#define ALPHA_BITS_MASK_RGB5551 0x0001 + +#ifndef GFX_MULTI_FORMAT + +#define CONCAT(X, Y) X##Y + +// C pre-processor needs a two stage macro define to enable it to concat +// to macro names together to form the name of another macro. +#define BUILD_PIXEL_D(F, R, G, B) CONCAT(BUILD_PIXEL_,F) (R, G, B) +#define BUILD_PIXEL2_D(F, R, G, B) CONCAT(BUILD_PIXEL2_,F) (R, G, B) +#define DECOMPOSE_PIXEL_D(F, PIX, R, G, B) CONCAT(DECOMPOSE_PIXEL_,F) (PIX, R, G, B) + +#define BUILD_PIXEL(R, G, B) BUILD_PIXEL_D(PIXEL_FORMAT, R, G, B) +#define BUILD_PIXEL2(R, G, B) BUILD_PIXEL2_D(PIXEL_FORMAT, R, G, B) +#define DECOMPOSE_PIXEL(PIX, R, G, B) DECOMPOSE_PIXEL_D(PIXEL_FORMAT, PIX, R, G, B) + +#define MAX_RED_D(F) CONCAT(MAX_RED_, F) +#define MAX_GREEN_D(F) CONCAT(MAX_GREEN_, F) +#define MAX_BLUE_D(F) CONCAT(MAX_BLUE_, F) +#define RED_LOW_BIT_MASK_D(F) CONCAT(RED_LOW_BIT_MASK_, F) +#define GREEN_LOW_BIT_MASK_D(F) CONCAT(GREEN_LOW_BIT_MASK_, F) +#define BLUE_LOW_BIT_MASK_D(F) CONCAT(BLUE_LOW_BIT_MASK_, F) +#define RED_HI_BIT_MASK_D(F) CONCAT(RED_HI_BIT_MASK_, F) +#define GREEN_HI_BIT_MASK_D(F) CONCAT(GREEN_HI_BIT_MASK_, F) +#define BLUE_HI_BIT_MASK_D(F) CONCAT(BLUE_HI_BIT_MASK_, F) +#define FIRST_COLOR_MASK_D(F) CONCAT(FIRST_COLOR_MASK_, F) +#define SECOND_COLOR_MASK_D(F) CONCAT(SECOND_COLOR_MASK_, F) +#define THIRD_COLOR_MASK_D(F) CONCAT(THIRD_COLOR_MASK_, F) +#define ALPHA_BITS_MASK_D(F) CONCAT(ALPHA_BITS_MASK_, F) + +#define MAX_RED MAX_RED_D(PIXEL_FORMAT) +#define MAX_GREEN MAX_GREEN_D(PIXEL_FORMAT) +#define MAX_BLUE MAX_BLUE_D(PIXEL_FORMAT) +#define RED_LOW_BIT_MASK RED_LOW_BIT_MASK_D(PIXEL_FORMAT) +#define GREEN_LOW_BIT_MASK GREEN_LOW_BIT_MASK_D(PIXEL_FORMAT) +#define BLUE_LOW_BIT_MASK BLUE_LOW_BIT_MASK_D(PIXEL_FORMAT) +#define RED_HI_BIT_MASK RED_HI_BIT_MASK_D(PIXEL_FORMAT) +#define GREEN_HI_BIT_MASK GREEN_HI_BIT_MASK_D(PIXEL_FORMAT) +#define BLUE_HI_BIT_MASK BLUE_HI_BIT_MASK_D(PIXEL_FORMAT) +#define FIRST_COLOR_MASK FIRST_COLOR_MASK_D(PIXEL_FORMAT) +#define SECOND_COLOR_MASK SECOND_COLOR_MASK_D(PIXEL_FORMAT) +#define THIRD_COLOR_MASK THIRD_COLOR_MASK_D(PIXEL_FORMAT) +#define ALPHA_BITS_MASK ALPHA_BITS_MASK_D(PIXEL_FORMAT) + +#define GREEN_HI_BIT ((MAX_GREEN + 1) >> 1) +#define RGB_LOW_BITS_MASK (RED_LOW_BIT_MASK | GREEN_LOW_BIT_MASK | BLUE_LOW_BIT_MASK) +#define RGB_HI_BITS_MASK (RED_HI_BIT_MASK | GREEN_HI_BIT_MASK | BLUE_HI_BIT_MASK) +#define RGB_HI_BITS_MASKx2 ((RED_HI_BIT_MASK | GREEN_HI_BIT_MASK | BLUE_HI_BIT_MASK) << 1) +#define RGB_REMOVE_LOW_BITS_MASK (~RGB_LOW_BITS_MASK) +#define FIRST_THIRD_COLOR_MASK (FIRST_COLOR_MASK | THIRD_COLOR_MASK) +#define TWO_LOW_BITS_MASK (RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 1)) +#define HIGH_BITS_SHIFTED_TWO_MASK (((FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) & ~TWO_LOW_BITS_MASK ) >> 2) + +#endif + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/port.h b/plugins/snes9x_gx/source/snes9x/port.h new file mode 100644 index 00000000..b9bed24c --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/port.h @@ -0,0 +1,362 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _PORT_H_ +#define _PORT_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#ifndef GEKKO +#include <memory.h> +#endif +#include <time.h> +#include <string.h> +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif +#include <sys/types.h> + +#ifdef __WIN32__ +#define NOMINMAX +#include <windows.h> +#endif + +#define GFX_MULTI_FORMAT + +#ifdef __WIN32__ +//#define RIGHTSHIFT_IS_SAR +#define RIGHTSHIFT_int8_IS_SAR +#define RIGHTSHIFT_int16_IS_SAR +#define RIGHTSHIFT_int32_IS_SAR +#define SNES_JOY_READ_CALLBACKS +#endif + +#ifdef __MACOSX__ +#undef GFX_MULTI_FORMAT +#define PIXEL_FORMAT RGB555 +#endif + +#ifndef snes9x_types_defined +#define snes9x_types_defined +typedef unsigned char bool8; +#ifdef HAVE_STDINT_H +#include <stdint.h> +typedef intptr_t pint; +typedef int8_t int8; +typedef uint8_t uint8; +typedef int16_t int16; +typedef uint16_t uint16; +typedef int32_t int32; +typedef uint32_t uint32; +typedef int64_t int64; +typedef uint64_t uint64; +#else // HAVE_STDINT_H +#ifdef __WIN32__ +typedef intptr_t pint; +#else // __WIN32__ +#ifdef PTR_NOT_INT +typedef long pint; +#else +typedef int pint; +#endif +#endif // __WIN32__ +#ifdef __WIN32__ +#ifdef __BORLANDC__ +#include <systypes.h> +#else +typedef signed char int8; +typedef unsigned char uint8; +typedef signed short int16; +typedef unsigned short uint16; +#ifndef WSAAP +// winsock2.h typedefs int32 as well +typedef signed int int32; +#endif +typedef unsigned int uint32; +#endif +typedef unsigned char uint8_t; +typedef signed __int64 int64; +typedef unsigned __int64 uint64; +typedef int socklen_t; +#else // __WIN32__ +typedef signed char int8; +typedef unsigned char uint8; +typedef signed short int16; +typedef unsigned short uint16; +typedef signed int int32; +typedef unsigned int uint32; +#ifdef __GNUC__ +// long long is not part of ISO C++ +__extension__ +#endif +typedef long long int64; +typedef unsigned long long uint64; +#endif // __WIN32__ +#endif // HAVE_STDINT_H +#endif // snes9x_types_defined + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#define START_EXTERN_C extern "C" { +#define END_EXTERN_C } + +#ifndef __WIN32__ +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif +#define _MAX_DRIVE 1 +#define _MAX_DIR PATH_MAX +#define _MAX_FNAME PATH_MAX +#define _MAX_EXT PATH_MAX +#define _MAX_PATH PATH_MAX +#else +#ifndef PATH_MAX +#define PATH_MAX _MAX_PATH +#endif +#endif + +#ifndef __WIN32__ +#define ZeroMemory(a, b) memset((a), 0, (b)) +void _splitpath (const char *, char *, char *, char *, char *); +void _makepath (char *, const char *, const char *, const char *, const char *); +#define S9xDisplayString DisplayStringFromBottom +#else +#define snprintf _snprintf +#define strcasecmp stricmp +#define strncasecmp strnicmp +void WinDisplayStringFromBottom(const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap); +#define S9xDisplayString WinDisplayStringFromBottom +void SetInfoDlgColor(unsigned char, unsigned char, unsigned char); +#define SET_UI_COLOR(r,g,b) SetInfoDlgColor(r,g,b) +#endif + +#ifdef __DJGPP +#define SLASH_STR "\\" +#define SLASH_CHAR '\\' +#else +#define SLASH_STR "/" +#define SLASH_CHAR '/' +#endif + +#ifndef SIG_PF +#define SIG_PF void (*) (int) +#endif + +#ifdef __linux +#define TITLE "Snes9x: Linux" +#define SYS_CONFIG_FILE "/etc/snes9x/snes9x.conf" +#endif + +#ifndef TITLE +#define TITLE "Snes9x" +#endif + +#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__) || defined(__alpha__) || defined(__MIPSEL__) || defined(_M_IX86) || defined(_M_X64) +#define LSB_FIRST +#define FAST_LSB_WORD_ACCESS +#else +#define MSB_FIRST +#endif + +#ifdef FAST_LSB_WORD_ACCESS +#define READ_WORD(s) (*(uint16 *) (s)) +#define READ_3WORD(s) (*(uint32 *) (s) & 0x00ffffff) +#define READ_DWORD(s) (*(uint32 *) (s)) +#define WRITE_WORD(s, d) *(uint16 *) (s) = (d) +#define WRITE_3WORD(s, d) *(uint16 *) (s) = (uint16) (d), *((uint8 *) (s) + 2) = (uint8) ((d) >> 16) +#define WRITE_DWORD(s, d) *(uint32 *) (s) = (d) +#else +#define READ_WORD(s) (*(uint8 *) (s) | (*((uint8 *) (s) + 1) << 8)) +#define READ_3WORD(s) (*(uint8 *) (s) | (*((uint8 *) (s) + 1) << 8) | (*((uint8 *) (s) + 2) << 16)) +#define READ_DWORD(s) (*(uint8 *) (s) | (*((uint8 *) (s) + 1) << 8) | (*((uint8 *) (s) + 2) << 16) | (*((uint8 *) (s) + 3) << 24)) +#define WRITE_WORD(s, d) *(uint8 *) (s) = (uint8) (d), *((uint8 *) (s) + 1) = (uint8) ((d) >> 8) +#define WRITE_3WORD(s, d) *(uint8 *) (s) = (uint8) (d), *((uint8 *) (s) + 1) = (uint8) ((d) >> 8), *((uint8 *) (s) + 2) = (uint8) ((d) >> 16) +#define WRITE_DWORD(s, d) *(uint8 *) (s) = (uint8) (d), *((uint8 *) (s) + 1) = (uint8) ((d) >> 8), *((uint8 *) (s) + 2) = (uint8) ((d) >> 16), *((uint8 *) (s) + 3) = (uint8) ((d) >> 24) +#endif + +#define SWAP_WORD(s) (s) = (((s) & 0xff) << 8) | (((s) & 0xff00) >> 8) +#define SWAP_DWORD(s) (s) = (((s) & 0xff) << 24) | (((s) & 0xff00) << 8) | (((s) & 0xff0000) >> 8) | (((s) & 0xff000000) >> 24) + +#include "pixform.h" + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/ppu.cpp b/plugins/snes9x_gx/source/snes9x/ppu.cpp new file mode 100644 index 00000000..898c6f41 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/ppu.cpp @@ -0,0 +1,2223 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "dma.h" +#include "apu/apu.h" +#include "fxemu.h" +#include "sdd1.h" +#include "srtc.h" +#include "controls.h" +#include "movie.h" +#include "display.h" +#ifdef NETPLAY_SUPPORT +#include "netplay.h" +#endif +#ifdef DEBUGGER +#include "debug.h" +#include "missing.h" +#endif + +extern uint8 *HDMAMemPointers[8]; + + +static inline void S9xLatchCounters (bool force) +{ + if (force || (Memory.FillRAM[0x4213] & 0x80)) + { + // Latch h and v counters, like the gun + #ifdef DEBUGGER + missing.h_v_latch = 1; + #endif + #if 0 // #ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PCAtOpcodeStart; + #endif + + PPU.HVBeamCounterLatched = 1; + PPU.VBeamPosLatched = (uint16) CPU.V_Counter; + + // From byuu: + // All dots are 4 cycles long, except dots 322 and 326. dots 322 and 326 are 6 cycles long. + // This holds true for all scanlines except scanline 240 on non-interlace odd frames. + // The reason for this is because this scanline is only 1360 cycles long, + // instead of 1364 like all other scanlines. + // This makes the effective range of hscan_pos 0-339 at all times. + int32 hc = CPU.Cycles; + + if (Timings.H_Max == Timings.H_Max_Master) // 1364 + { + if (hc >= 1292) + hc -= (ONE_DOT_CYCLE / 2); + if (hc >= 1308) + hc -= (ONE_DOT_CYCLE / 2); + } + + PPU.HBeamPosLatched = (uint16) (hc / ONE_DOT_CYCLE); + + Memory.FillRAM[0x213f] |= 0x40; + } + + if (CPU.V_Counter > PPU.GunVLatch || (CPU.V_Counter == PPU.GunVLatch && CPU.Cycles >= PPU.GunHLatch * ONE_DOT_CYCLE)) + PPU.GunVLatch = 1000; +} + +static inline void S9xTryGunLatch (bool force) +{ + if (CPU.V_Counter > PPU.GunVLatch || (CPU.V_Counter == PPU.GunVLatch && CPU.Cycles >= PPU.GunHLatch * ONE_DOT_CYCLE)) + { + if (force || (Memory.FillRAM[0x4213] & 0x80)) + { + #ifdef DEBUGGER + missing.h_v_latch = 1; + #endif + #if 0 // #ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PCAtOpcodeStart; + #endif + + PPU.HVBeamCounterLatched = 1; + PPU.VBeamPosLatched = (uint16) PPU.GunVLatch; + PPU.HBeamPosLatched = (uint16) PPU.GunHLatch; + + Memory.FillRAM[0x213f] |= 0x40; + } + + PPU.GunVLatch = 1000; + } +} + +void S9xCheckMissingHTimerPosition (int32 hc) +{ + if (PPU.HTimerPosition == hc) + { + if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) + S9xSetIRQ(PPU_IRQ_SOURCE); + else + if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) + S9xSetIRQ(PPU_IRQ_SOURCE); + } +} + +void S9xCheckMissingHTimerHalt (int32 hc_from, int32 range) +{ + if ((PPU.HTimerPosition >= hc_from) && (PPU.HTimerPosition < (hc_from + range))) + { + if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) + CPU.IRQPending = 1; + else + if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) + CPU.IRQPending = 1; + } +} + +void S9xCheckMissingHTimerRange (int32 hc_from, int32 range) +{ + if ((PPU.HTimerPosition >= hc_from) && (PPU.HTimerPosition < (hc_from + range))) + { + if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) + S9xSetIRQ(PPU_IRQ_SOURCE); + else + if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) + S9xSetIRQ(PPU_IRQ_SOURCE); + } +} + +void S9xUpdateHVTimerPosition (void) +{ + if (PPU.HTimerEnabled) + { + #ifdef DEBUGGER + missing.hirq_pos = PPU.IRQHBeamPos; + #endif + if (PPU.IRQHBeamPos != 0) + { + // IRQ_read + PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE; + if (Timings.H_Max == Timings.H_Max_Master) // 1364 + { + if (PPU.IRQHBeamPos > 322) + PPU.HTimerPosition += (ONE_DOT_CYCLE / 2); + if (PPU.IRQHBeamPos > 326) + PPU.HTimerPosition += (ONE_DOT_CYCLE / 2); + } + + PPU.HTimerPosition += 14; + // /IRQ + PPU.HTimerPosition += 4; + // after CPU executing + PPU.HTimerPosition += 6; + } + else + PPU.HTimerPosition = 10 + 4 + 6; + } + else + PPU.HTimerPosition = 10 + 4 + 6; + + PPU.VTimerPosition = PPU.IRQVBeamPos; + + if ((PPU.HTimerPosition >= Timings.H_Max) && (PPU.IRQHBeamPos < 340)) + { + PPU.HTimerPosition -= Timings.H_Max; + PPU.VTimerPosition++; + // FIXME + if (PPU.VTimerPosition >= Timings.V_Max) + PPU.VTimerPosition = 0; + } + + if (PPU.HTimerPosition < CPU.Cycles) + { + switch (CPU.WhichEvent) + { + case HC_IRQ_1_3_EVENT: + CPU.WhichEvent = HC_HDMA_START_EVENT; + CPU.NextEvent = Timings.HDMAStart; + break; + + case HC_IRQ_3_5_EVENT: + CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT; + CPU.NextEvent = Timings.H_Max; + break; + + case HC_IRQ_5_7_EVENT: + CPU.WhichEvent = HC_HDMA_INIT_EVENT; + CPU.NextEvent = Timings.HDMAInit; + break; + + case HC_IRQ_7_9_EVENT: + CPU.WhichEvent = HC_RENDER_EVENT; + CPU.NextEvent = Timings.RenderPos; + break; + + case HC_IRQ_9_A_EVENT: + CPU.WhichEvent = HC_WRAM_REFRESH_EVENT; + CPU.NextEvent = Timings.WRAMRefreshPos; + break; + + case HC_IRQ_A_1_EVENT: + CPU.WhichEvent = HC_HBLANK_START_EVENT; + CPU.NextEvent = Timings.HBlankStart; + break; + } + } + else + if ((PPU.HTimerPosition < CPU.NextEvent) || (!(CPU.WhichEvent & 1) && (PPU.HTimerPosition == CPU.NextEvent))) + { + CPU.NextEvent = PPU.HTimerPosition; + + switch (CPU.WhichEvent) + { + case HC_HDMA_START_EVENT: + CPU.WhichEvent = HC_IRQ_1_3_EVENT; + break; + + case HC_HCOUNTER_MAX_EVENT: + CPU.WhichEvent = HC_IRQ_3_5_EVENT; + break; + + case HC_HDMA_INIT_EVENT: + CPU.WhichEvent = HC_IRQ_5_7_EVENT; + break; + + case HC_RENDER_EVENT: + CPU.WhichEvent = HC_IRQ_7_9_EVENT; + break; + + case HC_WRAM_REFRESH_EVENT: + CPU.WhichEvent = HC_IRQ_9_A_EVENT; + break; + + case HC_HBLANK_START_EVENT: + CPU.WhichEvent = HC_IRQ_A_1_EVENT; + break; + } + } + else + { + switch (CPU.WhichEvent) + { + case HC_IRQ_1_3_EVENT: + CPU.WhichEvent = HC_HDMA_START_EVENT; + CPU.NextEvent = Timings.HDMAStart; + break; + + case HC_IRQ_3_5_EVENT: + CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT; + CPU.NextEvent = Timings.H_Max; + break; + + case HC_IRQ_5_7_EVENT: + CPU.WhichEvent = HC_HDMA_INIT_EVENT; + CPU.NextEvent = Timings.HDMAInit; + break; + + case HC_IRQ_7_9_EVENT: + CPU.WhichEvent = HC_RENDER_EVENT; + CPU.NextEvent = Timings.RenderPos; + break; + + case HC_IRQ_9_A_EVENT: + CPU.WhichEvent = HC_WRAM_REFRESH_EVENT; + CPU.NextEvent = Timings.WRAMRefreshPos; + break; + + case HC_IRQ_A_1_EVENT: + CPU.WhichEvent = HC_HBLANK_START_EVENT; + CPU.NextEvent = Timings.HBlankStart; + break; + } + } + +#ifdef DEBUGGER + S9xTraceFormattedMessage("--- IRQ settings: H:%d V:%d (%04d, %03d)", PPU.HTimerEnabled, PPU.VTimerEnabled, PPU.HTimerPosition, PPU.VTimerPosition); +#endif +} + +void S9xFixColourBrightness (void) +{ + IPPU.XB = mul_brightness[PPU.Brightness]; + + for (int i = 0; i < 256; i++) + { + IPPU.Red[i] = IPPU.XB[(PPU.CGDATA[i]) & 0x1f]; + IPPU.Green[i] = IPPU.XB[(PPU.CGDATA[i] >> 5) & 0x1f]; + IPPU.Blue[i] = IPPU.XB[(PPU.CGDATA[i] >> 10) & 0x1f]; + IPPU.ScreenColors[i] = BUILD_PIXEL(IPPU.Red[i], IPPU.Green[i], IPPU.Blue[i]); + } +} + +void S9xSetPPU (uint8 Byte, uint16 Address) +{ + // MAP_PPU: $2000-$3FFF + + if (CPU.InDMAorHDMA) + { + if (CPU.CurrentDMAorHDMAChannel >= 0 && DMA[CPU.CurrentDMAorHDMAChannel].ReverseTransfer) + { + // S9xSetPPU() is called to write to DMA[].AAddress + if ((Address & 0xff00) == 0x2100) + { + // Cannot access to Address Bus B ($2100-$21ff) via (H)DMA + return; + } + else + { + // 0x2000-0x3FFF is connected to Address Bus A + // SA1, SuperFX and SRTC are mapped here + // I don't bother for now... + return; + } + } + else + { + // S9xSetPPU() is called to read from $21xx + // Take care of DMA wrapping + if (Address > 0x21ff) + Address = 0x2100 + (Address & 0xff); + } + } + +#ifdef DEBUGGER + if (CPU.InHDMA) + S9xTraceFormattedMessage("--- HDMA PPU %04X -> %02X", Address, Byte); +#endif + + if ((Address & 0xffc0) == 0x2140) // APUIO0, APUIO1, APUIO2, APUIO3 + // write_port will run the APU until given clock before writing value + S9xAPUWritePort(Address & 3, Byte); + else + if (Address <= 0x2183) + { + switch (Address) + { + case 0x2100: // INIDISP + if (Byte != Memory.FillRAM[0x2100]) + { + FLUSH_REDRAW(); + + if (PPU.Brightness != (Byte & 0xf)) + { + IPPU.ColorsChanged = TRUE; + IPPU.DirectColourMapsNeedRebuild = TRUE; + PPU.Brightness = Byte & 0xf; + S9xFixColourBrightness(); + if (PPU.Brightness > IPPU.MaxBrightness) + IPPU.MaxBrightness = PPU.Brightness; + } + + if ((Memory.FillRAM[0x2100] & 0x80) != (Byte & 0x80)) + { + IPPU.ColorsChanged = TRUE; + PPU.ForcedBlanking = (Byte >> 7) & 1; + } + } + + if ((Memory.FillRAM[0x2100] & 0x80) && CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) + { + PPU.OAMAddr = PPU.SavedOAMAddr; + + uint8 tmp = 0; + if (PPU.OAMPriorityRotation) + tmp = (PPU.OAMAddr & 0xfe) >> 1; + if ((PPU.OAMFlip & 1) || PPU.FirstSprite != tmp) + { + PPU.FirstSprite = tmp; + IPPU.OBJChanged = TRUE; + } + + PPU.OAMFlip = 0; + } + + break; + + case 0x2101: // OBSEL + if (Byte != Memory.FillRAM[0x2101]) + { + FLUSH_REDRAW(); + PPU.OBJNameBase = (Byte & 3) << 14; + PPU.OBJNameSelect = ((Byte >> 3) & 3) << 13; + PPU.OBJSizeSelect = (Byte >> 5) & 7; + IPPU.OBJChanged = TRUE; + } + + break; + + case 0x2102: // OAMADDL + PPU.OAMAddr = ((Memory.FillRAM[0x2103] & 1) << 8) | Byte; + PPU.OAMFlip = 2; + PPU.OAMReadFlip = 0; + PPU.SavedOAMAddr = PPU.OAMAddr; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; + IPPU.OBJChanged = TRUE; + #ifdef DEBUGGER + missing.sprite_priority_rotation = 1; + #endif + } + + break; + + case 0x2103: // OAMADDH + PPU.OAMAddr = ((Byte & 1) << 8) | Memory.FillRAM[0x2102]; + PPU.OAMPriorityRotation = (Byte & 0x80) ? 1 : 0; + if (PPU.OAMPriorityRotation) + { + if (PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; + IPPU.OBJChanged = TRUE; + #ifdef DEBUGGER + missing.sprite_priority_rotation = 1; + #endif + } + } + else + { + if (PPU.FirstSprite != 0) + { + PPU.FirstSprite = 0; + IPPU.OBJChanged = TRUE; + #ifdef DEBUGGER + missing.sprite_priority_rotation = 1; + #endif + } + } + + PPU.OAMFlip = 0; + PPU.OAMReadFlip = 0; + PPU.SavedOAMAddr = PPU.OAMAddr; + + break; + + case 0x2104: // OAMDATA + REGISTER_2104(Byte); + break; + + case 0x2105: // BGMODE + if (Byte != Memory.FillRAM[0x2105]) + { + FLUSH_REDRAW(); + PPU.BG[0].BGSize = (Byte >> 4) & 1; + PPU.BG[1].BGSize = (Byte >> 5) & 1; + PPU.BG[2].BGSize = (Byte >> 6) & 1; + PPU.BG[3].BGSize = (Byte >> 7) & 1; + PPU.BGMode = Byte & 7; + // BJ: BG3Priority only takes effect if BGMode == 1 and the bit is set + PPU.BG3Priority = ((Byte & 0x0f) == 0x09); + IPPU.Interlace = Memory.FillRAM[0x2133] & 1; + #ifdef DEBUGGER + missing.modes[PPU.BGMode] = 1; + #endif + } + + break; + + case 0x2106: // MOSAIC + if (Byte != Memory.FillRAM[0x2106]) + { + FLUSH_REDRAW(); + PPU.MosaicStart = CPU.V_Counter; + if (PPU.MosaicStart > PPU.ScreenHeight) + PPU.MosaicStart = 0; + PPU.Mosaic = (Byte >> 4) + 1; + PPU.BGMosaic[0] = (Byte & 1); + PPU.BGMosaic[1] = (Byte & 2); + PPU.BGMosaic[2] = (Byte & 4); + PPU.BGMosaic[3] = (Byte & 8); + #ifdef DEBUGGER + if ((Byte & 0xf0) && (Byte & 0x0f)) + missing.mosaic = 1; + #endif + } + + break; + + case 0x2107: // BG1SC + if (Byte != Memory.FillRAM[0x2107]) + { + FLUSH_REDRAW(); + PPU.BG[0].SCSize = Byte & 3; + PPU.BG[0].SCBase = (Byte & 0x7c) << 8; + } + + break; + + case 0x2108: // BG2SC + if (Byte != Memory.FillRAM[0x2108]) + { + FLUSH_REDRAW(); + PPU.BG[1].SCSize = Byte & 3; + PPU.BG[1].SCBase = (Byte & 0x7c) << 8; + } + + break; + + case 0x2109: // BG3SC + if (Byte != Memory.FillRAM[0x2109]) + { + FLUSH_REDRAW(); + PPU.BG[2].SCSize = Byte & 3; + PPU.BG[2].SCBase = (Byte & 0x7c) << 8; + } + + break; + + case 0x210a: // BG4SC + if (Byte != Memory.FillRAM[0x210a]) + { + FLUSH_REDRAW(); + PPU.BG[3].SCSize = Byte & 3; + PPU.BG[3].SCBase = (Byte & 0x7c) << 8; + } + + break; + + case 0x210b: // BG12NBA + if (Byte != Memory.FillRAM[0x210b]) + { + FLUSH_REDRAW(); + PPU.BG[0].NameBase = (Byte & 7) << 12; + PPU.BG[1].NameBase = ((Byte >> 4) & 7) << 12; + } + + break; + + case 0x210c: // BG34NBA + if (Byte != Memory.FillRAM[0x210c]) + { + FLUSH_REDRAW(); + PPU.BG[2].NameBase = (Byte & 7) << 12; + PPU.BG[3].NameBase = ((Byte >> 4) & 7) << 12; + } + + break; + + case 0x210d: // BG1HOFS, M7HOFS + PPU.BG[0].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[0].HOffset >> 8) & 7); + PPU.M7HOFS = (Byte << 8) | PPU.M7byte; + PPU.BGnxOFSbyte = Byte; + PPU.M7byte = Byte; + break; + + case 0x210e: // BG1VOFS, M7VOFS + PPU.BG[0].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.M7VOFS = (Byte << 8) | PPU.M7byte; + PPU.BGnxOFSbyte = Byte; + PPU.M7byte = Byte; + break; + + case 0x210f: // BG2HOFS + PPU.BG[1].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[1].HOffset >> 8) & 7); + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2110: // BG2VOFS + PPU.BG[1].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2111: // BG3HOFS + PPU.BG[2].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[2].HOffset >> 8) & 7); + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2112: // BG3VOFS + PPU.BG[2].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2113: // BG4HOFS + PPU.BG[3].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[3].HOffset >> 8) & 7); + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2114: // BG4VOFS + PPU.BG[3].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2115: // VMAIN + PPU.VMA.High = (Byte & 0x80) == 0 ? FALSE : TRUE; + switch (Byte & 3) + { + case 0: PPU.VMA.Increment = 1; break; + case 1: PPU.VMA.Increment = 32; break; + case 2: PPU.VMA.Increment = 128; break; + case 3: PPU.VMA.Increment = 128; break; + } + + if (Byte & 0x0c) + { + static uint16 Shift[4] = { 0, 5, 6, 7 }; + static uint16 IncCount[4] = { 0, 32, 64, 128 }; + + uint8 i = (Byte & 0x0c) >> 2; + PPU.VMA.FullGraphicCount = IncCount[i]; + PPU.VMA.Mask1 = IncCount[i] * 8 - 1; + PPU.VMA.Shift = Shift[i]; + #ifdef DEBUGGER + missing.vram_full_graphic_inc = (Byte & 0x0c) >> 2; + #endif + } + else + PPU.VMA.FullGraphicCount = 0; + #ifdef DEBUGGER + if (Byte & 3) + missing.vram_inc = Byte & 3; + #endif + break; + + case 0x2116: // VMADDL + PPU.VMA.Address &= 0xff00; + PPU.VMA.Address |= Byte; + #ifdef CORRECT_VRAM_READS + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff)); + } + else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff)); + #else + IPPU.FirstVRAMRead = TRUE; + #endif + break; + + case 0x2117: // VMADDH + PPU.VMA.Address &= 0x00ff; + PPU.VMA.Address |= Byte << 8; + #ifdef CORRECT_VRAM_READS + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff)); + } + else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff)); + #else + IPPU.FirstVRAMRead = TRUE; + #endif + break; + + case 0x2118: // VMDATAL + #ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; + #endif + REGISTER_2118(Byte); + break; + + case 0x2119: // VMDATAH + #ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; + #endif + REGISTER_2119(Byte); + break; + + case 0x211a: // M7SEL + if (Byte != Memory.FillRAM[0x211a]) + { + FLUSH_REDRAW(); + PPU.Mode7Repeat = Byte >> 6; + if (PPU.Mode7Repeat == 1) + PPU.Mode7Repeat = 0; + PPU.Mode7VFlip = (Byte & 2) >> 1; + PPU.Mode7HFlip = Byte & 1; + } + + break; + + case 0x211b: // M7A + PPU.MatrixA = PPU.M7byte | (Byte << 8); + PPU.Need16x8Mulitply = TRUE; + PPU.M7byte = Byte; + break; + + case 0x211c: // M7B + PPU.MatrixB = PPU.M7byte | (Byte << 8); + PPU.Need16x8Mulitply = TRUE; + PPU.M7byte = Byte; + break; + + case 0x211d: // M7C + PPU.MatrixC = PPU.M7byte | (Byte << 8); + PPU.M7byte = Byte; + break; + + case 0x211e: // M7D + PPU.MatrixD = PPU.M7byte | (Byte << 8); + PPU.M7byte = Byte; + break; + + case 0x211f: // M7X + PPU.CentreX = PPU.M7byte | (Byte << 8); + PPU.M7byte = Byte; + break; + + case 0x2120: // M7Y + PPU.CentreY = PPU.M7byte | (Byte << 8); + PPU.M7byte = Byte; + break; + + case 0x2121: // CGADD + PPU.CGFLIP = 0; + PPU.CGFLIPRead = 0; + PPU.CGADD = Byte; + break; + + case 0x2122: // CGDATA + REGISTER_2122(Byte); + break; + + case 0x2123: // W12SEL + if (Byte != Memory.FillRAM[0x2123]) + { + FLUSH_REDRAW(); + PPU.ClipWindow1Enable[0] = !!(Byte & 0x02); + PPU.ClipWindow1Enable[1] = !!(Byte & 0x20); + PPU.ClipWindow2Enable[0] = !!(Byte & 0x08); + PPU.ClipWindow2Enable[1] = !!(Byte & 0x80); + PPU.ClipWindow1Inside[0] = !(Byte & 0x01); + PPU.ClipWindow1Inside[1] = !(Byte & 0x10); + PPU.ClipWindow2Inside[0] = !(Byte & 0x04); + PPU.ClipWindow2Inside[1] = !(Byte & 0x40); + PPU.RecomputeClipWindows = TRUE; + #ifdef DEBUGGER + if (Byte & 0x80) + missing.window2[1] = 1; + if (Byte & 0x20) + missing.window1[1] = 1; + if (Byte & 0x08) + missing.window2[0] = 1; + if (Byte & 0x02) + missing.window1[0] = 1; + #endif + } + + break; + + case 0x2124: // W34SEL + if (Byte != Memory.FillRAM[0x2124]) + { + FLUSH_REDRAW(); + PPU.ClipWindow1Enable[2] = !!(Byte & 0x02); + PPU.ClipWindow1Enable[3] = !!(Byte & 0x20); + PPU.ClipWindow2Enable[2] = !!(Byte & 0x08); + PPU.ClipWindow2Enable[3] = !!(Byte & 0x80); + PPU.ClipWindow1Inside[2] = !(Byte & 0x01); + PPU.ClipWindow1Inside[3] = !(Byte & 0x10); + PPU.ClipWindow2Inside[2] = !(Byte & 0x04); + PPU.ClipWindow2Inside[3] = !(Byte & 0x40); + PPU.RecomputeClipWindows = TRUE; + #ifdef DEBUGGER + if (Byte & 0x80) + missing.window2[3] = 1; + if (Byte & 0x20) + missing.window1[3] = 1; + if (Byte & 0x08) + missing.window2[2] = 1; + if (Byte & 0x02) + missing.window1[2] = 1; + #endif + } + + break; + + case 0x2125: // WOBJSEL + if (Byte != Memory.FillRAM[0x2125]) + { + FLUSH_REDRAW(); + PPU.ClipWindow1Enable[4] = !!(Byte & 0x02); + PPU.ClipWindow1Enable[5] = !!(Byte & 0x20); + PPU.ClipWindow2Enable[4] = !!(Byte & 0x08); + PPU.ClipWindow2Enable[5] = !!(Byte & 0x80); + PPU.ClipWindow1Inside[4] = !(Byte & 0x01); + PPU.ClipWindow1Inside[5] = !(Byte & 0x10); + PPU.ClipWindow2Inside[4] = !(Byte & 0x04); + PPU.ClipWindow2Inside[5] = !(Byte & 0x40); + PPU.RecomputeClipWindows = TRUE; + #ifdef DEBUGGER + if (Byte & 0x80) + missing.window2[5] = 1; + if (Byte & 0x20) + missing.window1[5] = 1; + if (Byte & 0x08) + missing.window2[4] = 1; + if (Byte & 0x02) + missing.window1[4] = 1; + #endif + } + + break; + + case 0x2126: // WH0 + if (Byte != Memory.FillRAM[0x2126]) + { + FLUSH_REDRAW(); + PPU.Window1Left = Byte; + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x2127: // WH1 + if (Byte != Memory.FillRAM[0x2127]) + { + FLUSH_REDRAW(); + PPU.Window1Right = Byte; + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x2128: // WH2 + if (Byte != Memory.FillRAM[0x2128]) + { + FLUSH_REDRAW(); + PPU.Window2Left = Byte; + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x2129: // WH3 + if (Byte != Memory.FillRAM[0x2129]) + { + FLUSH_REDRAW(); + PPU.Window2Right = Byte; + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x212a: // WBGLOG + if (Byte != Memory.FillRAM[0x212a]) + { + FLUSH_REDRAW(); + PPU.ClipWindowOverlapLogic[0] = (Byte & 0x03); + PPU.ClipWindowOverlapLogic[1] = (Byte & 0x0c) >> 2; + PPU.ClipWindowOverlapLogic[2] = (Byte & 0x30) >> 4; + PPU.ClipWindowOverlapLogic[3] = (Byte & 0xc0) >> 6; + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x212b: // WOBJLOG + if (Byte != Memory.FillRAM[0x212b]) + { + FLUSH_REDRAW(); + PPU.ClipWindowOverlapLogic[4] = (Byte & 0x03); + PPU.ClipWindowOverlapLogic[5] = (Byte & 0x0c) >> 2; + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x212c: // TM + if (Byte != Memory.FillRAM[0x212c]) + { + FLUSH_REDRAW(); + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x212d: // TS + if (Byte != Memory.FillRAM[0x212d]) + { + FLUSH_REDRAW(); + PPU.RecomputeClipWindows = TRUE; + #ifdef DEBUGGER + if (Byte & 0x1f) + missing.subscreen = 1; + #endif + } + + break; + + case 0x212e: // TMW + if (Byte != Memory.FillRAM[0x212e]) + { + FLUSH_REDRAW(); + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x212f: // TSW + if (Byte != Memory.FillRAM[0x212f]) + { + FLUSH_REDRAW(); + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x2130: // CGWSEL + if (Byte != Memory.FillRAM[0x2130]) + { + FLUSH_REDRAW(); + PPU.RecomputeClipWindows = TRUE; + #ifdef DEBUGGER + if ((Byte & 1) && (PPU.BGMode == 3 || PPU.BGMode == 4 || PPU.BGMode == 7)) + missing.direct = 1; + #endif + } + + break; + + case 0x2131: // CGADSUB + if (Byte != Memory.FillRAM[0x2131]) + { + FLUSH_REDRAW(); + #ifdef DEBUGGER + if (Byte & 0x80) + { + if (Memory.FillRAM[0x2130] & 0x02) + missing.subscreen_sub = 1; + else + missing.fixed_colour_sub = 1; + } + else + { + if (Memory.FillRAM[0x2130] & 0x02) + missing.subscreen_add = 1; + else + missing.fixed_colour_add = 1; + } + #endif + } + + break; + + case 0x2132: // COLDATA + if (Byte != Memory.FillRAM[0x2132]) + { + FLUSH_REDRAW(); + if (Byte & 0x80) + PPU.FixedColourBlue = Byte & 0x1f; + if (Byte & 0x40) + PPU.FixedColourGreen = Byte & 0x1f; + if (Byte & 0x20) + PPU.FixedColourRed = Byte & 0x1f; + } + + break; + + case 0x2133: // SETINI + if (Byte != Memory.FillRAM[0x2133]) + { + if ((Memory.FillRAM[0x2133] ^ Byte) & 8) + { + FLUSH_REDRAW(); + IPPU.PseudoHires = Byte & 8; + } + + if (Byte & 0x04) + { + PPU.ScreenHeight = SNES_HEIGHT_EXTENDED; + if (IPPU.DoubleHeightPixels) + IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; + else + IPPU.RenderedScreenHeight = PPU.ScreenHeight; + #ifdef DEBUGGER + missing.lines_239 = 1; + #endif + } + else + PPU.ScreenHeight = SNES_HEIGHT; + + if ((Memory.FillRAM[0x2133] ^ Byte) & 3) + { + FLUSH_REDRAW(); + if ((Memory.FillRAM[0x2133] ^ Byte) & 2) + IPPU.OBJChanged = TRUE; + IPPU.Interlace = Byte & 1; + IPPU.InterlaceOBJ = Byte & 2; + } + #ifdef DEBUGGER + if (Byte & 0x40) + missing.mode7_bgmode = 1; + if (Byte & 0x08) + missing.pseudo_512 = 1; + if (Byte & 0x02) + missing.sprite_double_height = 1; + if (Byte & 0x01) + missing.interlace = 1; + #endif + } + + break; + + case 0x2134: // MPYL + case 0x2135: // MPYM + case 0x2136: // MPYH + case 0x2137: // SLHV + case 0x2138: // OAMDATAREAD + case 0x2139: // VMDATALREAD + case 0x213a: // VMDATAHREAD + case 0x213b: // CGDATAREAD + case 0x213c: // OPHCT + case 0x213d: // OPVCT + case 0x213e: // STAT77 + case 0x213f: // STAT78 + return; + + case 0x2180: // WMDATA + if (!CPU.InWRAMDMAorHDMA) + REGISTER_2180(Byte); + break; + + case 0x2181: // WMADDL + if (!CPU.InWRAMDMAorHDMA) + { + PPU.WRAM &= 0x1ff00; + PPU.WRAM |= Byte; + } + + break; + + case 0x2182: // WMADDM + if (!CPU.InWRAMDMAorHDMA) + { + PPU.WRAM &= 0x100ff; + PPU.WRAM |= Byte << 8; + } + + break; + + case 0x2183: // WMADDH + if (!CPU.InWRAMDMAorHDMA) + { + PPU.WRAM &= 0x0ffff; + PPU.WRAM |= Byte << 16; + PPU.WRAM &= 0x1ffff; + } + + break; + } + } + else + { + if (Settings.SuperFX && Address >= 0x3000 && Address <= 0x32ff) + { + S9xSetSuperFX(Byte, Address); + return; + } + else + if (Settings.SA1 && Address >= 0x2200) + { + if (Address <= 0x23ff) + S9xSetSA1(Byte, Address); + else + Memory.FillRAM[Address] = Byte; + return; + } + else + if (Settings.BS && Address >= 0x2188 && Address <= 0x219f) + S9xSetBSXPPU(Byte, Address); + else + if (Settings.SRTC && Address == 0x2801) + S9xSetSRTC(Byte, Address); + #ifdef DEBUGGER + else + { + missing.unknownppu_write = Address; + if (Settings.TraceUnknownRegisters) + { + sprintf(String, "Unknown register write: $%02X->$%04X\n", Byte, Address); + S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String); + } + } + #endif + } + + Memory.FillRAM[Address] = Byte; +} + +uint8 S9xGetPPU (uint16 Address) +{ + // MAP_PPU: $2000-$3FFF + + if (Address < 0x2100) + return (OpenBus); + + if (CPU.InDMAorHDMA) + { + if (CPU.CurrentDMAorHDMAChannel >= 0 && !DMA[CPU.CurrentDMAorHDMAChannel].ReverseTransfer) + { + // S9xGetPPU() is called to read from DMA[].AAddress + if ((Address & 0xff00) == 0x2100) + // Cannot access to Address Bus B ($2100-$21FF) via (H)DMA + return (OpenBus); + else + // $2200-$3FFF are connected to Address Bus A + // SA1, SuperFX and SRTC are mapped here + // I don't bother for now... + return (OpenBus); + } + else + { + // S9xGetPPU() is called to write to $21xx + // Take care of DMA wrapping + if (Address > 0x21ff) + Address = 0x2100 + (Address & 0xff); + } + } + + if ((Address & 0xffc0) == 0x2140) // APUIO0, APUIO1, APUIO2, APUIO3 + // read_port will run the APU until given APU time before reading value + return (S9xAPUReadPort(Address & 3)); + else + if (Address <= 0x2183) + { + uint8 byte; + + switch (Address) + { + case 0x2104: // OAMDATA + case 0x2105: // BGMODE + case 0x2106: // MOSAIC + case 0x2108: // BG2SC + case 0x2109: // BG3SC + case 0x210a: // BG4SC + case 0x2114: // BG4VOFS + case 0x2115: // VMAIN + case 0x2116: // VMADDL + case 0x2118: // VMDATAL + case 0x2119: // VMDATAH + case 0x211a: // M7SEL + case 0x2124: // W34SEL + case 0x2125: // WOBJSEL + case 0x2126: // WH0 + case 0x2128: // WH2 + case 0x2129: // WH3 + case 0x212a: // WBGLOG + return (PPU.OpenBus1); + + case 0x2134: // MPYL + case 0x2135: // MPYM + case 0x2136: // MPYH + if (PPU.Need16x8Mulitply) + { + int32 r = (int32) PPU.MatrixA * (int32) (PPU.MatrixB >> 8); + Memory.FillRAM[0x2134] = (uint8) r; + Memory.FillRAM[0x2135] = (uint8) (r >> 8); + Memory.FillRAM[0x2136] = (uint8) (r >> 16); + PPU.Need16x8Mulitply = FALSE; + } + #ifdef DEBUGGER + missing.matrix_multiply = 1; + #endif + return (PPU.OpenBus1 = Memory.FillRAM[Address]); + + case 0x2137: // SLHV + S9xLatchCounters(0); + return (OpenBus); + + case 0x2138: // OAMDATAREAD + if (PPU.OAMAddr & 0x100) + { + if (!(PPU.OAMFlip & 1)) + byte = PPU.OAMData[(PPU.OAMAddr & 0x10f) << 1]; + else + { + byte = PPU.OAMData[((PPU.OAMAddr & 0x10f) << 1) + 1]; + PPU.OAMAddr = (PPU.OAMAddr + 1) & 0x1ff; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; + IPPU.OBJChanged = TRUE; + #ifdef DEBUGGER + missing.sprite_priority_rotation = 1; + #endif + } + } + } + else + { + if (!(PPU.OAMFlip & 1)) + byte = PPU.OAMData[PPU.OAMAddr << 1]; + else + { + byte = PPU.OAMData[(PPU.OAMAddr << 1) + 1]; + ++PPU.OAMAddr; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; + IPPU.OBJChanged = TRUE; + #ifdef DEBUGGER + missing.sprite_priority_rotation = 1; + #endif + } + } + } + + PPU.OAMFlip ^= 1; + #ifdef DEBUGGER + missing.oam_read = 1; + #endif + return (PPU.OpenBus1 = byte); + + case 0x2139: // VMDATALREAD + #ifdef CORRECT_VRAM_READS + byte = IPPU.VRAMReadBuffer & 0xff; + if (!PPU.VMA.High) + { + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff)); + } + else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff)); + + PPU.VMA.Address += PPU.VMA.Increment; + } + #else + if (IPPU.FirstVRAMRead) + byte = Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]; + else + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address - 1; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + byte = Memory.VRAM[((address << 1) - 2) & 0xffff]; + } + else + byte = Memory.VRAM[((PPU.VMA.Address << 1) - 2) & 0xffff]; + + if (!PPU.VMA.High) + { + PPU.VMA.Address += PPU.VMA.Increment; + IPPU.FirstVRAMRead = FALSE; + } + #endif + #ifdef DEBUGGER + missing.vram_read = 1; + #endif + return (PPU.OpenBus1 = byte); + + case 0x213a: // VMDATAHREAD + #ifdef CORRECT_VRAM_READS + byte = (IPPU.VRAMReadBuffer >> 8) & 0xff; + if (PPU.VMA.High) + { + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff)); + } + else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff)); + + PPU.VMA.Address += PPU.VMA.Increment; + } + #else + if (IPPU.FirstVRAMRead) + byte = Memory.VRAM[((PPU.VMA.Address << 1) + 1) & 0xffff]; + else + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address - 1; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + byte = Memory.VRAM[((address << 1) - 1) & 0xffff]; + } + else + byte = Memory.VRAM[((PPU.VMA.Address << 1) - 1) & 0xffff]; + + if (PPU.VMA.High) + { + PPU.VMA.Address += PPU.VMA.Increment; + IPPU.FirstVRAMRead = FALSE; + } + #endif + #ifdef DEBUGGER + missing.vram_read = 1; + #endif + return (PPU.OpenBus1 = byte); + + case 0x213b: // CGDATAREAD + if (PPU.CGFLIPRead) + byte = (PPU.OpenBus2 & 0x80) | ((PPU.CGDATA[PPU.CGADD++] >> 8) & 0x7f); + else + byte = PPU.CGDATA[PPU.CGADD] & 0xff; + PPU.CGFLIPRead ^= 1; + #ifdef DEBUGGER + missing.cgram_read = 1; + #endif + return (PPU.OpenBus2 = byte); + + case 0x213c: // OPHCT + S9xTryGunLatch(false); + if (PPU.HBeamFlip) + byte = (PPU.OpenBus2 & 0xfe) | ((PPU.HBeamPosLatched >> 8) & 0x01); + else + byte = (uint8) PPU.HBeamPosLatched; + PPU.HBeamFlip ^= 1; + #ifdef DEBUGGER + missing.h_counter_read = 1; + #endif + return (PPU.OpenBus2 = byte); + + case 0x213d: // OPVCT + S9xTryGunLatch(false); + if (PPU.VBeamFlip) + byte = (PPU.OpenBus2 & 0xfe) | ((PPU.VBeamPosLatched >> 8) & 0x01); + else + byte = (uint8) PPU.VBeamPosLatched; + PPU.VBeamFlip ^= 1; + #ifdef DEBUGGER + missing.v_counter_read = 1; + #endif + return (PPU.OpenBus2 = byte); + + case 0x213e: // STAT77 + FLUSH_REDRAW(); + byte = (PPU.OpenBus1 & 0x10) | PPU.RangeTimeOver | Model->_5C77; + return (PPU.OpenBus1 = byte); + + case 0x213f: // STAT78 + S9xTryGunLatch(false); + PPU.VBeamFlip = PPU.HBeamFlip = 0; + byte = (PPU.OpenBus2 & 0x20) | (Memory.FillRAM[0x213f] & 0xc0) | (Settings.PAL ? 0x10 : 0) | Model->_5C78; + Memory.FillRAM[0x213f] &= ~0x40; + return (PPU.OpenBus2 = byte); + + case 0x2180: // WMDATA + if (!CPU.InWRAMDMAorHDMA) + { + byte = Memory.RAM[PPU.WRAM++]; + PPU.WRAM &= 0x1ffff; + } + else + byte = OpenBus; + #ifdef DEBUGGER + missing.wram_read = 1; + #endif + return (byte); + + default: + return (OpenBus); + } + } + else + { + if (Settings.SuperFX && Address >= 0x3000 && Address <= 0x32ff) + return (S9xGetSuperFX(Address)); + else + if (Settings.SA1 && Address >= 0x2200) + return (S9xGetSA1(Address)); + else + if (Settings.BS && Address >= 0x2188 && Address <= 0x219f) + return (S9xGetBSXPPU(Address)); + else + if (Settings.SRTC && Address == 0x2800) + return (S9xGetSRTC(Address)); + else + switch (Address) + { + case 0x21c2: + if (Model->_5C77 == 2) + return (0x20); + return (OpenBus); + + case 0x21c3: + if (Model->_5C77 == 2) + return (0); + return (OpenBus); + + default: + return (OpenBus); + } + } +} + +void S9xSetCPU (uint8 Byte, uint16 Address) +{ + if (Address < 0x4200) + { + switch (Address) + { + case 0x4016: // JOYSER0 + S9xSetJoypadLatch(Byte & 1); + break; + + case 0x4017: // JOYSER1 + return; + + default: + break; + } + } + else + if ((Address & 0xff80) == 0x4300) + { + if (CPU.InDMAorHDMA) + return; + + int d = (Address >> 4) & 0x7; + + switch (Address & 0xf) + { + case 0x0: // 0x43x0: DMAPx + DMA[d].ReverseTransfer = (Byte & 0x80) ? TRUE : FALSE; + DMA[d].HDMAIndirectAddressing = (Byte & 0x40) ? TRUE : FALSE; + DMA[d].UnusedBit43x0 = (Byte & 0x20) ? TRUE : FALSE; + DMA[d].AAddressDecrement = (Byte & 0x10) ? TRUE : FALSE; + DMA[d].AAddressFixed = (Byte & 0x08) ? TRUE : FALSE; + DMA[d].TransferMode = (Byte & 7); + return; + + case 0x1: // 0x43x1: BBADx + DMA[d].BAddress = Byte; + return; + + case 0x2: // 0x43x2: A1TxL + DMA[d].AAddress &= 0xff00; + DMA[d].AAddress |= Byte; + return; + + case 0x3: // 0x43x3: A1TxH + DMA[d].AAddress &= 0xff; + DMA[d].AAddress |= Byte << 8; + return; + + case 0x4: // 0x43x4: A1Bx + DMA[d].ABank = Byte; + HDMAMemPointers[d] = NULL; + return; + + case 0x5: // 0x43x5: DASxL + DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff00; + DMA[d].DMACount_Or_HDMAIndirectAddress |= Byte; + HDMAMemPointers[d] = NULL; + return; + + case 0x6: // 0x43x6: DASxH + DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff; + DMA[d].DMACount_Or_HDMAIndirectAddress |= Byte << 8; + HDMAMemPointers[d] = NULL; + return; + + case 0x7: // 0x43x7: DASBx + DMA[d].IndirectBank = Byte; + HDMAMemPointers[d] = NULL; + return; + + case 0x8: // 0x43x8: A2AxL + DMA[d].Address &= 0xff00; + DMA[d].Address |= Byte; + HDMAMemPointers[d] = NULL; + return; + + case 0x9: // 0x43x9: A2AxH + DMA[d].Address &= 0xff; + DMA[d].Address |= Byte << 8; + HDMAMemPointers[d] = NULL; + return; + + case 0xa: // 0x43xa: NLTRx + if (Byte & 0x7f) + { + DMA[d].LineCount = Byte & 0x7f; + DMA[d].Repeat = !(Byte & 0x80); + } + else + { + DMA[d].LineCount = 128; + DMA[d].Repeat = !!(Byte & 0x80); + } + + return; + + case 0xb: // 0x43xb: ????x + case 0xf: // 0x43xf: mirror of 0x43xb + DMA[d].UnknownByte = Byte; + return; + + default: + break; + } + } + else + { + uint16 pos; + + switch (Address) + { + case 0x4200: // NMITIMEN + if (Byte & 0x20) + { + PPU.VTimerEnabled = TRUE; + #ifdef DEBUGGER + missing.virq = 1; + missing.virq_pos = PPU.IRQVBeamPos; + #endif + } + else + PPU.VTimerEnabled = FALSE; + + if (Byte & 0x10) + { + PPU.HTimerEnabled = TRUE; + #ifdef DEBUGGER + missing.hirq = 1; + missing.hirq_pos = PPU.IRQHBeamPos; + #endif + } + else + PPU.HTimerEnabled = FALSE; + + S9xUpdateHVTimerPosition(); + + // The case that IRQ will trigger in an instruction such as STA $4200. + // FIXME: not true but good enough for Snes9x, I think. + S9xCheckMissingHTimerRange(CPU.PrevCycles, CPU.Cycles - CPU.PrevCycles); + + if (!(Byte & 0x30)) + S9xClearIRQ(PPU_IRQ_SOURCE); + + // NMI can trigger immediately during VBlank as long as NMI_read ($4210) wasn't cleard. + if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) && + (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) && (Memory.FillRAM[0x4210] & 0x80)) + { + // FIXME: triggered at HC+=6, checked just before the final CPU cycle, + // then, when to call S9xOpcode_NMI()? + CPU.Flags |= NMI_FLAG; + Timings.NMITriggerPos = CPU.Cycles + 6 + 6; + } + + break; + + case 0x4201: // WRIO + if ((Byte & 0x80) == 0 && (Memory.FillRAM[0x4213] & 0x80) == 0x80) + S9xLatchCounters(1); + else + S9xTryGunLatch((Byte & 0x80) ? true : false); + Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = Byte; + break; + + case 0x4202: // WRMPYA + break; + + case 0x4203: // WRMPYB + { + uint32 res = Memory.FillRAM[0x4202] * Byte; + // FIXME: The update occurs 8 machine cycles after $4203 is set. + Memory.FillRAM[0x4216] = (uint8) res; + Memory.FillRAM[0x4217] = (uint8) (res >> 8); + break; + } + + case 0x4204: // WRDIVL + case 0x4205: // WRDIVH + break; + + case 0x4206: // WRDIVB + { + uint16 a = Memory.FillRAM[0x4204] + (Memory.FillRAM[0x4205] << 8); + uint16 div = Byte ? a / Byte : 0xffff; + uint16 rem = Byte ? a % Byte : a; + // FIXME: The update occurs 16 machine cycles after $4206 is set. + Memory.FillRAM[0x4214] = (uint8) div; + Memory.FillRAM[0x4215] = div >> 8; + Memory.FillRAM[0x4216] = (uint8) rem; + Memory.FillRAM[0x4217] = rem >> 8; + break; + } + + case 0x4207: // HTIMEL + pos = PPU.IRQHBeamPos; + PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff00) | Byte; + if (PPU.IRQHBeamPos != pos) + S9xUpdateHVTimerPosition(); + #ifdef DEBUGGER + missing.hirq_pos = PPU.IRQHBeamPos; + #endif + break; + + case 0x4208: // HTIMEH + pos = PPU.IRQHBeamPos; + PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff) | ((Byte & 1) << 8); + if (PPU.IRQHBeamPos != pos) + S9xUpdateHVTimerPosition(); + #ifdef DEBUGGER + missing.hirq_pos = PPU.IRQHBeamPos; + #endif + break; + + case 0x4209: // VTIMEL + pos = PPU.IRQVBeamPos; + PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff00) | Byte; + if (PPU.IRQVBeamPos != pos) + S9xUpdateHVTimerPosition(); + #ifdef DEBUGGER + missing.virq_pos = PPU.IRQVBeamPos; + #endif + break; + + case 0x420a: // VTIMEH + pos = PPU.IRQVBeamPos; + PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff) | ((Byte & 1) << 8); + if (PPU.IRQVBeamPos != pos) + S9xUpdateHVTimerPosition(); + #ifdef DEBUGGER + missing.virq_pos = PPU.IRQVBeamPos; + #endif + break; + + case 0x420b: // MDMAEN + if (CPU.InDMAorHDMA) + return; + // XXX: Not quite right... + if (Byte) + CPU.Cycles += Timings.DMACPUSync; + if (Byte & 0x01) + S9xDoDMA(0); + if (Byte & 0x02) + S9xDoDMA(1); + if (Byte & 0x04) + S9xDoDMA(2); + if (Byte & 0x08) + S9xDoDMA(3); + if (Byte & 0x10) + S9xDoDMA(4); + if (Byte & 0x20) + S9xDoDMA(5); + if (Byte & 0x40) + S9xDoDMA(6); + if (Byte & 0x80) + S9xDoDMA(7); + #ifdef DEBUGGER + missing.dma_this_frame = Byte; + missing.dma_channels = Byte; + #endif + break; + + case 0x420c: // HDMAEN + if (CPU.InDMAorHDMA) + return; + if (Settings.DisableHDMA) + Byte = 0; + Memory.FillRAM[0x420c] = Byte; + // Yoshi's Island, Genjyu Ryodan, Mortal Kombat, Tales of Phantasia + PPU.HDMA = Byte & ~PPU.HDMAEnded; + #ifdef DEBUGGER + missing.hdma_this_frame |= Byte; + missing.hdma_channels |= Byte; + #endif + break; + + case 0x420d: // MEMSEL + if ((Byte & 1) != (Memory.FillRAM[0x420d] & 1)) + { + if (Byte & 1) + { + CPU.FastROMSpeed = ONE_CYCLE; + #ifdef DEBUGGER + missing.fast_rom = 1; + #endif + } + else + CPU.FastROMSpeed = SLOW_ONE_CYCLE; + } + + break; + + case 0x4210: // RDNMI + #if 0 + Memory.FillRAM[0x4210] = Model->_5A22; + #endif + return; + + case 0x4211: // TIMEUP + #if 0 + S9xClearIRQ(PPU_IRQ_SOURCE); + #endif + return; + + case 0x4212: // HVBJOY + case 0x4213: // RDIO + case 0x4214: // RDDIVL + case 0x4215: // RDDIVH + case 0x4216: // RDMPYL + case 0x4217: // RDMPYH + case 0x4218: // JOY1L + case 0x4219: // JOY1H + case 0x421a: // JOY2L + case 0x421b: // JOY2H + case 0x421c: // JOY3L + case 0x421d: // JOY3H + case 0x421e: // JOY4L + case 0x421f: // JOY4H + return; + + default: + if (Settings.SPC7110 && Address >= 0x4800) + S9xSetSPC7110(Byte, Address); + else + if (Settings.SDD1 && Address >= 0x4804 && Address <= 0x4807) + S9xSetSDD1MemoryMap(Address - 0x4804, Byte & 7); + break; + } + } + + Memory.FillRAM[Address] = Byte; +} + +uint8 S9xGetCPU (uint16 Address) +{ + if (Address < 0x4200) + { + #ifdef SNES_JOY_READ_CALLBACKS + extern bool8 pad_read; + if (Address == 0x4016 || Address == 0x4017) + { + S9xOnSNESPadRead(); + pad_read = TRUE; + } + #endif + + switch (Address) + { + case 0x4016: // JOYSER0 + case 0x4017: // JOYSER1 + return (S9xReadJOYSERn(Address)); + + default: + return (OpenBus); + } + } + else + if ((Address & 0xff80) == 0x4300) + { + if (CPU.InDMAorHDMA) + return (OpenBus); + + int d = (Address >> 4) & 0x7; + + switch (Address & 0xf) + { + case 0x0: // 0x43x0: DMAPx + return ((DMA[d].ReverseTransfer ? 0x80 : 0) | + (DMA[d].HDMAIndirectAddressing ? 0x40 : 0) | + (DMA[d].UnusedBit43x0 ? 0x20 : 0) | + (DMA[d].AAddressDecrement ? 0x10 : 0) | + (DMA[d].AAddressFixed ? 0x08 : 0) | + (DMA[d].TransferMode & 7)); + + case 0x1: // 0x43x1: BBADx + return (DMA[d].BAddress); + + case 0x2: // 0x43x2: A1TxL + return (DMA[d].AAddress & 0xff); + + case 0x3: // 0x43x3: A1TxH + return (DMA[d].AAddress >> 8); + + case 0x4: // 0x43x4: A1Bx + return (DMA[d].ABank); + + case 0x5: // 0x43x5: DASxL + return (DMA[d].DMACount_Or_HDMAIndirectAddress & 0xff); + + case 0x6: // 0x43x6: DASxH + return (DMA[d].DMACount_Or_HDMAIndirectAddress >> 8); + + case 0x7: // 0x43x7: DASBx + return (DMA[d].IndirectBank); + + case 0x8: // 0x43x8: A2AxL + return (DMA[d].Address & 0xff); + + case 0x9: // 0x43x9: A2AxH + return (DMA[d].Address >> 8); + + case 0xa: // 0x43xa: NLTRx + return (DMA[d].LineCount ^ (DMA[d].Repeat ? 0x00 : 0x80)); + + case 0xb: // 0x43xb: ????x + case 0xf: // 0x43xf: mirror of 0x43xb + return (DMA[d].UnknownByte); + + default: + return (OpenBus); + } + } + else + { + uint8 byte; + + switch (Address) + { + case 0x4210: // RDNMI + #ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; + #endif + byte = Memory.FillRAM[0x4210]; + Memory.FillRAM[0x4210] = Model->_5A22; + return ((byte & 0x80) | (OpenBus & 0x70) | Model->_5A22); + + case 0x4211: // TIMEUP + byte = (CPU.IRQActive & PPU_IRQ_SOURCE) ? 0x80 : 0; + S9xClearIRQ(PPU_IRQ_SOURCE); + return (byte | (OpenBus & 0x7f)); + + case 0x4212: // HVBJOY + #ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; + #endif + return (REGISTER_4212() | (OpenBus & 0x3e)); + + case 0x4213: // RDIO + return (Memory.FillRAM[0x4213]); + + case 0x4214: // RDDIVL + case 0x4215: // RDDIVH + case 0x4216: // RDMPYL + case 0x4217: // RDMPYH + return (Memory.FillRAM[Address]); + + case 0x4218: // JOY1L + case 0x4219: // JOY1H + case 0x421a: // JOY2L + case 0x421b: // JOY2H + case 0x421c: // JOY3L + case 0x421d: // JOY3H + case 0x421e: // JOY4L + case 0x421f: // JOY4H + #ifdef SNES_JOY_READ_CALLBACKS + extern bool8 pad_read; + if (Memory.FillRAM[0x4200] & 1) + { + S9xOnSNESPadRead(); + pad_read = TRUE; + } + #endif + return (Memory.FillRAM[Address]); + + default: + if (Settings.SPC7110 && Address >= 0x4800) + return (S9xGetSPC7110(Address)); + if (Settings.SDD1 && Address >= 0x4800 && Address <= 0x4807) + return (Memory.FillRAM[Address]); + return (OpenBus); + } + } +} + +void S9xResetPPU (void) +{ + S9xSoftResetPPU(); + S9xControlsReset(); + PPU.M7HOFS = 0; + PPU.M7VOFS = 0; + PPU.M7byte = 0; +} + +void S9xSoftResetPPU (void) +{ + S9xControlsSoftReset(); + + PPU.VMA.High = 0; + PPU.VMA.Increment = 1; + PPU.VMA.Address = 0; + PPU.VMA.FullGraphicCount = 0; + PPU.VMA.Shift = 0; + + PPU.WRAM = 0; + + for (int c = 0; c < 4; c++) + { + PPU.BG[c].SCBase = 0; + PPU.BG[c].HOffset = 0; + PPU.BG[c].VOffset = 0; + PPU.BG[c].BGSize = 0; + PPU.BG[c].NameBase = 0; + PPU.BG[c].SCSize = 0; + } + + PPU.BGMode = 0; + PPU.BG3Priority = 0; + + PPU.CGFLIP = 0; + PPU.CGFLIPRead = 0; + PPU.CGADD = 0; + + for (int c = 0; c < 256; c++) + { + IPPU.Red[c] = (c & 7) << 2; + IPPU.Green[c] = ((c >> 3) & 7) << 2; + IPPU.Blue[c] = ((c >> 6) & 2) << 3; + PPU.CGDATA[c] = IPPU.Red[c] | (IPPU.Green[c] << 5) | (IPPU.Blue[c] << 10); + } + + for (int c = 0; c < 128; c++) + { + PPU.OBJ[c].HPos = 0; + PPU.OBJ[c].VPos = 0; + PPU.OBJ[c].HFlip = 0; + PPU.OBJ[c].VFlip = 0; + PPU.OBJ[c].Name = 0; + PPU.OBJ[c].Priority = 0; + PPU.OBJ[c].Palette = 0; + PPU.OBJ[c].Size = 0; + } + + PPU.OBJThroughMain = FALSE; + PPU.OBJThroughSub = FALSE; + PPU.OBJAddition = FALSE; + PPU.OBJNameBase = 0; + PPU.OBJNameSelect = 0; + PPU.OBJSizeSelect = 0; + + PPU.OAMAddr = 0; + PPU.SavedOAMAddr = 0; + PPU.OAMPriorityRotation = 0; + PPU.OAMFlip = 0; + PPU.OAMReadFlip = 0; + PPU.OAMTileAddress = 0; + PPU.OAMWriteRegister = 0; + ZeroMemory(PPU.OAMData, 512 + 32); + + PPU.FirstSprite = 0; + PPU.LastSprite = 127; + PPU.RangeTimeOver = 0; + + PPU.HTimerEnabled = FALSE; + PPU.VTimerEnabled = FALSE; + PPU.HTimerPosition = Timings.H_Max + 1; + PPU.VTimerPosition = Timings.V_Max + 1; + PPU.IRQHBeamPos = 0x1ff; + PPU.IRQVBeamPos = 0x1ff; + + PPU.HBeamFlip = 0; + PPU.VBeamFlip = 0; + PPU.HBeamPosLatched = 0; + PPU.VBeamPosLatched = 0; + PPU.GunHLatch = 0; + PPU.GunVLatch = 1000; + PPU.HVBeamCounterLatched = 0; + + PPU.Mode7HFlip = FALSE; + PPU.Mode7VFlip = FALSE; + PPU.Mode7Repeat = 0; + PPU.MatrixA = 0; + PPU.MatrixB = 0; + PPU.MatrixC = 0; + PPU.MatrixD = 0; + PPU.CentreX = 0; + PPU.CentreY = 0; + + PPU.Mosaic = 0; + PPU.BGMosaic[0] = FALSE; + PPU.BGMosaic[1] = FALSE; + PPU.BGMosaic[2] = FALSE; + PPU.BGMosaic[3] = FALSE; + + PPU.Window1Left = 1; + PPU.Window1Right = 0; + PPU.Window2Left = 1; + PPU.Window2Right = 0; + PPU.RecomputeClipWindows = TRUE; + + for (int c = 0; c < 6; c++) + { + PPU.ClipCounts[c] = 0; + PPU.ClipWindowOverlapLogic[c] = CLIP_OR; + PPU.ClipWindow1Enable[c] = FALSE; + PPU.ClipWindow2Enable[c] = FALSE; + PPU.ClipWindow1Inside[c] = TRUE; + PPU.ClipWindow2Inside[c] = TRUE; + } + + PPU.ForcedBlanking = TRUE; + + PPU.FixedColourRed = 0; + PPU.FixedColourGreen = 0; + PPU.FixedColourBlue = 0; + PPU.Brightness = 0; + PPU.ScreenHeight = SNES_HEIGHT; + + PPU.Need16x8Mulitply = FALSE; + PPU.BGnxOFSbyte = 0; + + PPU.HDMA = 0; + PPU.HDMAEnded = 0; + + PPU.OpenBus1 = 0; + PPU.OpenBus2 = 0; + + for (int c = 0; c < 2; c++) + memset(&IPPU.Clip[c], 0, sizeof(struct ClipData)); + IPPU.ColorsChanged = TRUE; + IPPU.OBJChanged = TRUE; + IPPU.DirectColourMapsNeedRebuild = TRUE; + ZeroMemory(IPPU.TileCached[TILE_2BIT], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT], MAX_4BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_8BIT], MAX_8BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_2BIT_EVEN], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_2BIT_ODD], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT_EVEN], MAX_4BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT_ODD], MAX_4BIT_TILES); +#ifdef CORRECT_VRAM_READS + IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better? +#else + IPPU.FirstVRAMRead = FALSE; +#endif + IPPU.Interlace = FALSE; + IPPU.InterlaceOBJ = FALSE; + IPPU.DoubleWidthPixels = FALSE; + IPPU.DoubleHeightPixels = FALSE; + IPPU.CurrentLine = 0; + IPPU.PreviousLine = 0; + IPPU.XB = NULL; + for (int c = 0; c < 256; c++) + IPPU.ScreenColors[c] = c; + IPPU.MaxBrightness = 0; + IPPU.RenderThisFrame = TRUE; + IPPU.RenderedScreenWidth = SNES_WIDTH; + IPPU.RenderedScreenHeight = SNES_HEIGHT; + IPPU.FrameCount = 0; + IPPU.RenderedFramesCount = 0; + IPPU.DisplayedRenderedFrameCount = 0; + IPPU.SkippedFrames = 0; + IPPU.FrameSkip = 0; + + S9xFixColourBrightness(); + + for (int c = 0; c < 0x8000; c += 0x100) + memset(&Memory.FillRAM[c], c >> 8, 0x100); + ZeroMemory(&Memory.FillRAM[0x2100], 0x100); + ZeroMemory(&Memory.FillRAM[0x4200], 0x100); + ZeroMemory(&Memory.FillRAM[0x4000], 0x100); + // For BS Suttehakkun 2... + ZeroMemory(&Memory.FillRAM[0x1000], 0x1000); + + Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = 0xff; +} diff --git a/plugins/snes9x_gx/source/snes9x/ppu.h b/plugins/snes9x_gx/source/snes9x/ppu.h new file mode 100644 index 00000000..7f20e897 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/ppu.h @@ -0,0 +1,752 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _PPU_H_ +#define _PPU_H_ + +#define FIRST_VISIBLE_LINE 1 + +#define TILE_2BIT 0 +#define TILE_4BIT 1 +#define TILE_8BIT 2 +#define TILE_2BIT_EVEN 3 +#define TILE_2BIT_ODD 4 +#define TILE_4BIT_EVEN 5 +#define TILE_4BIT_ODD 6 + +#define MAX_2BIT_TILES 4096 +#define MAX_4BIT_TILES 2048 +#define MAX_8BIT_TILES 1024 + +#define CLIP_OR 0 +#define CLIP_AND 1 +#define CLIP_XOR 2 +#define CLIP_XNOR 3 + +#define PPU_IRQ_SOURCE (1 << 1) +#define GSU_IRQ_SOURCE (1 << 2) +#define SA1_IRQ_SOURCE (1 << 7) +#define SA1_DMA_IRQ_SOURCE (1 << 5) + +struct ClipData +{ + uint8 Count; + uint8 DrawMode[6]; + uint16 Left[6]; + uint16 Right[6]; +}; + +struct InternalPPU +{ + struct ClipData Clip[2][6]; + bool8 ColorsChanged; + bool8 OBJChanged; + bool8 DirectColourMapsNeedRebuild; + uint8 *TileCache[7]; + uint8 *TileCached[7]; +#ifdef CORRECT_VRAM_READS + uint16 VRAMReadBuffer; +#else + bool8 FirstVRAMRead; +#endif + bool8 Interlace; + bool8 InterlaceOBJ; + bool8 PseudoHires; + bool8 DoubleWidthPixels; + bool8 DoubleHeightPixels; + int CurrentLine; + int PreviousLine; + uint8 *XB; + uint32 Red[256]; + uint32 Green[256]; + uint32 Blue[256]; + uint16 ScreenColors[256]; + uint8 MaxBrightness; + bool8 RenderThisFrame; + int RenderedScreenWidth; + int RenderedScreenHeight; + uint32 FrameCount; + uint32 RenderedFramesCount; + uint32 DisplayedRenderedFrameCount; + uint32 TotalEmulatedFrames; + uint32 SkippedFrames; + uint32 FrameSkip; +}; + +struct SOBJ +{ + int16 HPos; + uint16 VPos; + uint8 HFlip; + uint8 VFlip; + uint16 Name; + uint8 Priority; + uint8 Palette; + uint8 Size; +}; + +struct SPPU +{ + struct + { + bool8 High; + uint8 Increment; + uint16 Address; + uint16 Mask1; + uint16 FullGraphicCount; + uint16 Shift; + } VMA; + + uint32 WRAM; + + struct + { + uint16 SCBase; + uint16 HOffset; + uint16 VOffset; + uint8 BGSize; + uint16 NameBase; + uint16 SCSize; + } BG[4]; + + uint8 BGMode; + uint8 BG3Priority; + + bool8 CGFLIP; + uint8 CGFLIPRead; + uint8 CGADD; + uint16 CGDATA[256]; + + struct SOBJ OBJ[128]; + bool8 OBJThroughMain; + bool8 OBJThroughSub; + bool8 OBJAddition; + uint16 OBJNameBase; + uint16 OBJNameSelect; + uint8 OBJSizeSelect; + + uint16 OAMAddr; + uint16 SavedOAMAddr; + uint8 OAMPriorityRotation; + uint8 OAMFlip; + uint8 OAMReadFlip; + uint16 OAMTileAddress; + uint16 OAMWriteRegister; + uint8 OAMData[512 + 32]; + + uint8 FirstSprite; + uint8 LastSprite; + uint8 RangeTimeOver; + + bool8 HTimerEnabled; + bool8 VTimerEnabled; + short HTimerPosition; + short VTimerPosition; + uint16 IRQHBeamPos; + uint16 IRQVBeamPos; + + uint8 HBeamFlip; + uint8 VBeamFlip; + uint16 HBeamPosLatched; + uint16 VBeamPosLatched; + uint16 GunHLatch; + uint16 GunVLatch; + uint8 HVBeamCounterLatched; + + bool8 Mode7HFlip; + bool8 Mode7VFlip; + uint8 Mode7Repeat; + short MatrixA; + short MatrixB; + short MatrixC; + short MatrixD; + short CentreX; + short CentreY; + short M7HOFS; + short M7VOFS; + + uint8 Mosaic; + uint8 MosaicStart; + bool8 BGMosaic[4]; + + uint8 Window1Left; + uint8 Window1Right; + uint8 Window2Left; + uint8 Window2Right; + bool8 RecomputeClipWindows; + uint8 ClipCounts[6]; + uint8 ClipWindowOverlapLogic[6]; + uint8 ClipWindow1Enable[6]; + uint8 ClipWindow2Enable[6]; + bool8 ClipWindow1Inside[6]; + bool8 ClipWindow2Inside[6]; + + bool8 ForcedBlanking; + + uint8 FixedColourRed; + uint8 FixedColourGreen; + uint8 FixedColourBlue; + uint8 Brightness; + uint16 ScreenHeight; + + bool8 Need16x8Mulitply; + uint8 BGnxOFSbyte; + uint8 M7byte; + + uint8 HDMA; + uint8 HDMAEnded; + + uint8 OpenBus1; + uint8 OpenBus2; +}; + +extern uint16 SignExtend[2]; +extern struct SPPU PPU; +extern struct InternalPPU IPPU; + +void S9xResetPPU (void); +void S9xSoftResetPPU (void); +void S9xSetPPU (uint8, uint16); +uint8 S9xGetPPU (uint16); +void S9xSetCPU (uint8, uint16); +uint8 S9xGetCPU (uint16); +void S9xUpdateHVTimerPosition (void); +void S9xCheckMissingHTimerPosition (int32); +void S9xCheckMissingHTimerRange (int32, int32); +void S9xCheckMissingHTimerHalt (int32, int32); +void S9xFixColourBrightness (void); +void S9xDoAutoJoypad (void); + +#include "gfx.h" +#include "memmap.h" + +typedef struct +{ + uint8 _5C77; + uint8 _5C78; + uint8 _5A22; +} SnesModel; + +extern SnesModel *Model; +extern SnesModel M1SNES; +extern SnesModel M2SNES; + +#define MAX_5C77_VERSION 0x01 +#define MAX_5C78_VERSION 0x03 +#define MAX_5A22_VERSION 0x02 + +static inline void FLUSH_REDRAW (void) +{ + if (IPPU.PreviousLine != IPPU.CurrentLine) + S9xUpdateScreen(); +} + +static inline void REGISTER_2104 (uint8 Byte) +{ + if (PPU.OAMAddr & 0x100) + { + int addr = ((PPU.OAMAddr & 0x10f) << 1) + (PPU.OAMFlip & 1); + if (Byte != PPU.OAMData[addr]) + { + FLUSH_REDRAW(); + PPU.OAMData[addr] = Byte; + IPPU.OBJChanged = TRUE; + + // X position high bit, and sprite size (x4) + struct SOBJ *pObj = &PPU.OBJ[(addr & 0x1f) * 4]; + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 0) & 1]; + pObj++->Size = Byte & 2; + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 2) & 1]; + pObj++->Size = Byte & 8; + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 4) & 1]; + pObj++->Size = Byte & 32; + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 6) & 1]; + pObj->Size = Byte & 128; + } + + PPU.OAMFlip ^= 1; + if (!(PPU.OAMFlip & 1)) + { + ++PPU.OAMAddr; + PPU.OAMAddr &= 0x1ff; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; + IPPU.OBJChanged = TRUE; + } + } + else + { + if (PPU.OAMPriorityRotation && (PPU.OAMAddr & 1)) + IPPU.OBJChanged = TRUE; + } + } + else + if (!(PPU.OAMFlip & 1)) + { + PPU.OAMWriteRegister &= 0xff00; + PPU.OAMWriteRegister |= Byte; + PPU.OAMFlip |= 1; + if (PPU.OAMPriorityRotation && (PPU.OAMAddr & 1)) + IPPU.OBJChanged = TRUE; + } + else + { + PPU.OAMWriteRegister &= 0x00ff; + uint8 lowbyte = (uint8) (PPU.OAMWriteRegister); + uint8 highbyte = Byte; + PPU.OAMWriteRegister |= Byte << 8; + + int addr = (PPU.OAMAddr << 1); + if (lowbyte != PPU.OAMData[addr] || highbyte != PPU.OAMData[addr + 1]) + { + FLUSH_REDRAW(); + PPU.OAMData[addr] = lowbyte; + PPU.OAMData[addr + 1] = highbyte; + IPPU.OBJChanged = TRUE; + if (addr & 2) + { + // Tile + PPU.OBJ[addr = PPU.OAMAddr >> 1].Name = PPU.OAMWriteRegister & 0x1ff; + // priority, h and v flip. + PPU.OBJ[addr].Palette = (highbyte >> 1) & 7; + PPU.OBJ[addr].Priority = (highbyte >> 4) & 3; + PPU.OBJ[addr].HFlip = (highbyte >> 6) & 1; + PPU.OBJ[addr].VFlip = (highbyte >> 7) & 1; + } + else + { + // X position (low) + PPU.OBJ[addr = PPU.OAMAddr >> 1].HPos &= 0xff00; + PPU.OBJ[addr].HPos |= lowbyte; + // Sprite Y position + PPU.OBJ[addr].VPos = highbyte; + } + } + + PPU.OAMFlip &= ~1; + ++PPU.OAMAddr; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; + IPPU.OBJChanged = TRUE; + } + } +} + +// This code is correct, however due to Snes9x's inaccurate timings, some games might be broken by this chage. :( +#ifdef DEBUGGER +#define CHECK_INBLANK() \ + if (!PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) \ + { \ + printf("Invalid VRAM acess at (%04d, %04d) blank:%d\n", CPU.Cycles, CPU.V_Counter, PPU.ForcedBlanking); \ + if (Settings.BlockInvalidVRAMAccess) \ + return; \ + } +#else +#define CHECK_INBLANK() \ + if (Settings.BlockInvalidVRAMAccess && !PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) \ + return; +#endif + +static inline void REGISTER_2118 (uint8 Byte) +{ + CHECK_INBLANK(); + + uint32 address; + + if (PPU.VMA.FullGraphicCount) + { + uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; + address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff; + Memory.VRAM[address] = Byte; + } + else + Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xffff] = Byte; + + IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + + if (!PPU.VMA.High) + { + #ifdef DEBUGGER + if (Settings.TraceVRAM && !CPU.InDMAorHDMA) + printf("VRAM write byte: $%04X (%d, %d)\n", PPU.VMA.Address, Memory.FillRAM[0x2115] & 3, (Memory.FillRAM[0x2115] & 0x0c) >> 2); + #endif + PPU.VMA.Address += PPU.VMA.Increment; + } +} + +static inline void REGISTER_2119 (uint8 Byte) +{ + CHECK_INBLANK(); + + uint32 address; + + if (PPU.VMA.FullGraphicCount) + { + uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; + address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xffff; + Memory.VRAM[address] = Byte; + } + else + Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xffff] = Byte; + + IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + + if (PPU.VMA.High) + { + #ifdef DEBUGGER + if (Settings.TraceVRAM && !CPU.InDMAorHDMA) + printf("VRAM write word: $%04X (%d, %d)\n", PPU.VMA.Address, Memory.FillRAM[0x2115] & 3, (Memory.FillRAM[0x2115] & 0x0c) >> 2); + #endif + PPU.VMA.Address += PPU.VMA.Increment; + } +} + +static inline void REGISTER_2118_tile (uint8 Byte) +{ + CHECK_INBLANK(); + + uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; + uint32 address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff; + + Memory.VRAM[address] = Byte; + + IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + + if (!PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +} + +static inline void REGISTER_2119_tile (uint8 Byte) +{ + CHECK_INBLANK(); + + uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; + uint32 address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xffff; + + Memory.VRAM[address] = Byte; + + IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + + if (PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +} + +static inline void REGISTER_2118_linear (uint8 Byte) +{ + CHECK_INBLANK(); + + uint32 address; + + Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xffff] = Byte; + + IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + + if (!PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +} + +static inline void REGISTER_2119_linear (uint8 Byte) +{ + CHECK_INBLANK(); + + uint32 address; + + Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xffff] = Byte; + + IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + + if (PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +} + +static inline void REGISTER_2122 (uint8 Byte) +{ + if (PPU.CGFLIP) + { + if ((Byte & 0x7f) != (PPU.CGDATA[PPU.CGADD] >> 8)) + { + FLUSH_REDRAW(); + PPU.CGDATA[PPU.CGADD] &= 0x00ff; + PPU.CGDATA[PPU.CGADD] |= (Byte & 0x7f) << 8; + IPPU.ColorsChanged = TRUE; + IPPU.Blue[PPU.CGADD] = IPPU.XB[(Byte >> 2) & 0x1f]; + IPPU.Green[PPU.CGADD] = IPPU.XB[(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f]; + IPPU.ScreenColors[PPU.CGADD] = (uint16) BUILD_PIXEL(IPPU.Red[PPU.CGADD], IPPU.Green[PPU.CGADD], IPPU.Blue[PPU.CGADD]); + } + + PPU.CGADD++; + } + else + { + if (Byte != (uint8) (PPU.CGDATA[PPU.CGADD] & 0xff)) + { + FLUSH_REDRAW(); + PPU.CGDATA[PPU.CGADD] &= 0x7f00; + PPU.CGDATA[PPU.CGADD] |= Byte; + IPPU.ColorsChanged = TRUE; + IPPU.Red[PPU.CGADD] = IPPU.XB[Byte & 0x1f]; + IPPU.Green[PPU.CGADD] = IPPU.XB[(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f]; + IPPU.ScreenColors[PPU.CGADD] = (uint16) BUILD_PIXEL(IPPU.Red[PPU.CGADD], IPPU.Green[PPU.CGADD], IPPU.Blue[PPU.CGADD]); + } + } + + PPU.CGFLIP ^= 1; +} + +static inline void REGISTER_2180 (uint8 Byte) +{ + Memory.RAM[PPU.WRAM++] = Byte; + PPU.WRAM &= 0x1ffff; +} + +static inline uint8 REGISTER_4212 (void) +{ + uint8 byte = 0; + + if ((CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) && (CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE + 3)) + byte = 1; + if ((CPU.Cycles < Timings.HBlankEnd) || (CPU.Cycles >= Timings.HBlankStart)) + byte |= 0x40; + if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) + byte |= 0x80; + + return (byte); +} + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/reader.cpp b/plugins/snes9x_gx/source/snes9x/reader.cpp new file mode 100644 index 00000000..fa7ba1ec --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/reader.cpp @@ -0,0 +1,353 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +// Abstract the details of reading from zip files versus FILE *'s. + +#include <string> +#ifdef UNZIP_SUPPORT +#include "unzip.h" +#endif +#include "snes9x.h" +#include "reader.h" + + +// Generic constructor/destructor + +Reader::Reader (void) +{ + return; +} + +Reader::~Reader (void) +{ + return; +} + +// Generic getline function, based on gets. Reimlpement if you can do better. + +char * Reader::getline (void) +{ + bool eof; + std::string ret; + + ret = getline(eof); + if (ret.size() == 0 && eof) + return (NULL); + + return (strdup(ret.c_str())); +} + +std::string Reader::getline (bool &eof) +{ + char buf[1024]; + std::string ret; + + eof = false; + ret.clear(); + + do + { + if (gets(buf, sizeof(buf)) == NULL) + { + eof = true; + break; + } + + ret.append(buf); + } + while (*ret.rbegin() != '\n'); + + return (ret); +} + +// snes9x.h STREAM reader + +fReader::fReader (STREAM f) +{ + fp = f; +} + +fReader::~fReader (void) +{ + return; +} + +int fReader::get_char (void) +{ + return (GETC_STREAM(fp)); +} + +char * fReader::gets (char *buf, size_t len) +{ + return (GETS_STREAM(buf, len, fp)); +} + +size_t fReader::read (char *buf, size_t len) +{ + return (READ_STREAM(buf, len, fp)); +} + +// unzip reader + +#ifdef UNZIP_SUPPORT + +unzReader::unzReader (unzFile &v) +{ + file = v; + head = NULL; + numbytes = 0; +} + +unzReader::~unzReader (void) +{ + return; +} + +int unzReader::get_char (void) +{ + unsigned char c; + + if (numbytes <= 0) + { + numbytes = unzReadCurrentFile(file, buffer, unz_BUFFSIZ); + if (numbytes <= 0) + return (EOF); + head = buffer; + } + + c = *head; + head++; + numbytes--; + + return ((int) c); +} + +char * unzReader::gets (char *buf, size_t len) +{ + size_t i; + int c; + + for (i = 0; i < len - 1; i++) + { + c = get_char(); + if (c == EOF) + { + if (i == 0) + return (NULL); + break; + } + + buf[i] = (char) c; + if (buf[i] == '\n') + break; + } + + buf[i] = '\0'; + + return (buf); +} + +size_t unzReader::read (char *buf, size_t len) +{ + if (len == 0) + return (len); + + if (len <= numbytes) + { + memcpy(buf, head, len); + numbytes -= len; + head += len; + return (len); + } + + size_t numread = 0; + if (numbytes > 0) + { + memcpy(buf, head, numbytes); + numread += numbytes; + head = NULL; + numbytes = 0; + } + + int l = unzReadCurrentFile(file, buf + numread, len - numread); + if (l > 0) + numread += l; + + return (numread); +} + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/reader.h b/plugins/snes9x_gx/source/snes9x/reader.h new file mode 100644 index 00000000..2019cc1a --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/reader.h @@ -0,0 +1,228 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _READER_H_ +#define _READER_H_ + +class Reader +{ + public: + Reader (void); + virtual ~Reader (void); + virtual int get_char (void) = 0; + virtual char * gets (char *, size_t) = 0; + virtual char * getline (void); // free() when done + virtual std::string getline (bool &); + virtual size_t read (char *, size_t) = 0; +}; + +class fReader : public Reader +{ + public: + fReader (STREAM); + virtual ~fReader (void); + virtual int get_char (void); + virtual char * gets (char *, size_t); + virtual size_t read (char *, size_t); + + private: + STREAM fp; +}; + +#ifdef UNZIP_SUPPORT + +#define unz_BUFFSIZ 1024 + +class unzReader : public Reader +{ + public: + unzReader (unzFile &); + virtual ~unzReader (void); + virtual int get_char (void); + virtual char * gets (char *, size_t); + virtual size_t read (char *, size_t); + + private: + unzFile file; + char buffer[unz_BUFFSIZ]; + char *head; + size_t numbytes; +}; + +#endif + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/sa1.cpp b/plugins/snes9x_gx/source/snes9x/sa1.cpp new file mode 100644 index 00000000..df28bace --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/sa1.cpp @@ -0,0 +1,1136 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" + +uint8 SA1OpenBus; + +static void S9xSA1Reset (void); +static void S9xSA1SetBWRAMMemMap (uint8); +static void S9xSetSA1MemMap (uint32, uint8); +static void S9xSA1CharConv2 (void); +static void S9xSA1DMA (void); +static void S9xSA1ReadVariableLengthData (bool8, bool8); + + +void S9xSA1Init (void) +{ + SA1.IRQActive = FALSE; + SA1.WaitingForInterrupt = FALSE; + SA1.Waiting = FALSE; + SA1.Flags = 0; + SA1.Executing = FALSE; + memset(&Memory.FillRAM[0x2200], 0, 0x200); + Memory.FillRAM[0x2200] = 0x20; + Memory.FillRAM[0x2220] = 0x00; + Memory.FillRAM[0x2221] = 0x01; + Memory.FillRAM[0x2222] = 0x02; + Memory.FillRAM[0x2223] = 0x03; + Memory.FillRAM[0x2228] = 0xff; + SA1.op1 = 0; + SA1.op2 = 0; + SA1.arithmetic_op = 0; + SA1.sum = 0; + SA1.overflow = FALSE; + SA1.S9xOpcodes = NULL; +} + +static void S9xSA1Reset (void) +{ + SA1Registers.PBPC = 0; + SA1Registers.PB = 0; + SA1Registers.PCw = Memory.FillRAM[0x2203] | (Memory.FillRAM[0x2204] << 8); + SA1Registers.D.W = 0; + SA1Registers.DB = 0; + SA1Registers.SH = 1; + SA1Registers.SL = 0xFF; + SA1Registers.XH = 0; + SA1Registers.YH = 0; + SA1Registers.P.W = 0; + + SA1.ShiftedPB = 0; + SA1.ShiftedDB = 0; + SA1SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation); + SA1ClearFlags(Decimal); + + SA1.WaitingForInterrupt = FALSE; + SA1.PCBase = NULL; + S9xSA1SetPCBase(SA1Registers.PBPC); + SA1.S9xOpcodes = S9xSA1OpcodesM1X1; + SA1.S9xOpLengths = S9xOpLengthsM1X1; + + S9xSA1UnpackStatus(); + S9xSA1FixCycles(); + SA1.Executing = TRUE; + SA1.BWRAM = Memory.SRAM; + Memory.FillRAM[0x2225] = 0; +} + +static void S9xSA1SetBWRAMMemMap (uint8 val) +{ + if (val & 0x80) + { + for (int c = 0; c < 0x400; c += 16) + { + SA1.Map[c + 6] = SA1.Map[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; + SA1.Map[c + 7] = SA1.Map[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; + SA1.WriteMap[c + 6] = SA1.WriteMap[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; + SA1.WriteMap[c + 7] = SA1.WriteMap[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; + } + + SA1.BWRAM = Memory.SRAM + (val & 0x7f) * 0x2000 / 4; + } + else + { + for (int c = 0; c < 0x400; c += 16) + { + SA1.Map[c + 6] = SA1.Map[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM; + SA1.Map[c + 7] = SA1.Map[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM; + SA1.WriteMap[c + 6] = SA1.WriteMap[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM; + SA1.WriteMap[c + 7] = SA1.WriteMap[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM; + } + + SA1.BWRAM = Memory.SRAM + (val & 7) * 0x2000; + } +} + +void S9xSA1PostLoadState (void) +{ + SA1.ShiftedPB = (uint32) SA1Registers.PB << 16; + SA1.ShiftedDB = (uint32) SA1Registers.DB << 16; + + S9xSA1SetPCBase(SA1Registers.PBPC); + S9xSA1UnpackStatus(); + S9xSA1FixCycles(); + SA1.VirtualBitmapFormat = (Memory.FillRAM[0x223f] & 0x80) ? 2 : 4; + Memory.BWRAM = Memory.SRAM + (Memory.FillRAM[0x2224] & 7) * 0x2000; + S9xSA1SetBWRAMMemMap(Memory.FillRAM[0x2225]); + + SA1.Waiting = (Memory.FillRAM[0x2200] & 0x60) != 0; + SA1.Executing = !SA1.Waiting; +} + +void S9xSA1ExecuteDuringSleep (void) +{ +#if 0 + if (SA1.Executing) + { + while (CPU.Cycles < CPU.NextEvent) + { + S9xSA1MainLoop(); + CPU.Cycles += TWO_CYCLES * 2; + } + } +#endif +} + +static void S9xSetSA1MemMap (uint32 which1, uint8 map) +{ + int start = which1 * 0x100 + 0xc00; + int start2 = which1 * 0x200; + + if (which1 >= 2) + start2 += 0x400; + + for (int c = 0; c < 0x100; c += 16) + { + uint8 *block = &Memory.ROM[(map & 7) * 0x100000 + (c << 12)]; + for (int i = c; i < c + 16; i++) + Memory.Map[start + i] = SA1.Map[start + i] = block; + } + + for (int c = 0; c < 0x200; c += 16) + { + uint8 *block = &Memory.ROM[(map & 7) * 0x100000 + (c << 11) - 0x8000]; + for (int i = c + 8; i < c + 16; i++) + Memory.Map[start2 + i] = SA1.Map[start2 + i] = block; + } +} + +uint8 S9xGetSA1 (uint32 address) +{ + switch (address) + { + case 0x2300: + return ((uint8) ((Memory.FillRAM[0x2209] & 0x5f) | (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE)))); + + case 0x2301: + return ((Memory.FillRAM[0x2200] & 0xf) | (Memory.FillRAM[0x2301] & 0xf0)); + + case 0x2306: + return ((uint8) SA1.sum); + + case 0x2307: + return ((uint8) (SA1.sum >> 8)); + + case 0x2308: + return ((uint8) (SA1.sum >> 16)); + + case 0x2309: + return ((uint8) (SA1.sum >> 24)); + + case 0x230a: + return ((uint8) (SA1.sum >> 32)); + + case 0x230c: + return (Memory.FillRAM[0x230c]); + + case 0x230d: + { + uint8 byte = Memory.FillRAM[0x230d]; + + if (Memory.FillRAM[0x2258] & 0x80) + S9xSA1ReadVariableLengthData(TRUE, FALSE); + + return (byte); + } + + default: + //printf("R: %04x\n", address); + break; + } + + return (Memory.FillRAM[address]); +} + +void S9xSetSA1 (uint8 byte, uint32 address) +{ + switch (address) + { + case 0x2200: + SA1.Waiting = (byte & 0x60) != 0; + //SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; + + if (!(byte & 0x20) && (Memory.FillRAM[0x2200] & 0x20)) + S9xSA1Reset(); + + if (byte & 0x80) + { + Memory.FillRAM[0x2301] |= 0x80; + if (Memory.FillRAM[0x220a] & 0x80) + { + SA1.Flags |= IRQ_FLAG; + SA1.IRQActive |= SNES_IRQ_SOURCE; + SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; + } + } + + if (byte & 0x10) + { + Memory.FillRAM[0x2301] |= 0x10; + if (Memory.FillRAM[0x220a] & 0x10) + { + SA1.Flags |= NMI_FLAG; + SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; + } + } + + break; + + case 0x2201: + if (((byte ^ Memory.FillRAM[0x2201]) & 0x80) && (Memory.FillRAM[0x2300] & byte & 0x80)) + S9xSetIRQ(SA1_IRQ_SOURCE); + + if (((byte ^ Memory.FillRAM[0x2201]) & 0x20) && (Memory.FillRAM[0x2300] & byte & 0x20)) + S9xSetIRQ(SA1_DMA_IRQ_SOURCE); + + break; + + case 0x2202: + if (byte & 0x80) + { + Memory.FillRAM[0x2300] &= ~0x80; + S9xClearIRQ(SA1_IRQ_SOURCE); + } + + if (byte & 0x20) + { + Memory.FillRAM[0x2300] &= ~0x20; + S9xClearIRQ(SA1_DMA_IRQ_SOURCE); + } + + break; + + case 0x2203: + //printf("SA1 reset vector: %04x\n", byte | (Memory.FillRAM[0x2204] << 8)); + break; + + case 0x2204: + //printf("SA1 reset vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2203]); + break; + + case 0x2205: + //printf("SA1 NMI vector: %04x\n", byte | (Memory.FillRAM[0x2206] << 8)); + break; + + case 0x2206: + //printf("SA1 NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2205]); + break; + + case 0x2207: + //printf("SA1 IRQ vector: %04x\n", byte | (Memory.FillRAM[0x2208] << 8)); + break; + + case 0x2208: + //printf("SA1 IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2207]); + break; + + case 0x2209: + Memory.FillRAM[0x2209] = byte; + + if (byte & 0x80) + Memory.FillRAM[0x2300] |= 0x80; + + if (byte & Memory.FillRAM[0x2201] & 0x80) + S9xSetIRQ(SA1_IRQ_SOURCE); + + break; + + case 0x220a: + if (((byte ^ Memory.FillRAM[0x220a]) & 0x80) && (Memory.FillRAM[0x2301] & byte & 0x80)) + { + SA1.Flags |= IRQ_FLAG; + SA1.IRQActive |= SNES_IRQ_SOURCE; + //SA1.Executing = !SA1.Waiting; + } + + if (((byte ^ Memory.FillRAM[0x220a]) & 0x40) && (Memory.FillRAM[0x2301] & byte & 0x40)) + { + SA1.Flags |= IRQ_FLAG; + SA1.IRQActive |= TIMER_IRQ_SOURCE; + //SA1.Executing = !SA1.Waiting; + } + + if (((byte ^ Memory.FillRAM[0x220a]) & 0x20) && (Memory.FillRAM[0x2301] & byte & 0x20)) + { + SA1.Flags |= IRQ_FLAG; + SA1.IRQActive |= DMA_IRQ_SOURCE; + //SA1.Executing = !SA1.Waiting; + } + + if (((byte ^ Memory.FillRAM[0x220a]) & 0x10) && (Memory.FillRAM[0x2301] & byte & 0x10)) + { + SA1.Flags |= NMI_FLAG; + //SA1.Executing = !SA1.Waiting; + } + + break; + + case 0x220b: + if (byte & 0x80) + { + SA1.IRQActive &= ~SNES_IRQ_SOURCE; + Memory.FillRAM[0x2301] &= ~0x80; + } + + if (byte & 0x40) + { + SA1.IRQActive &= ~TIMER_IRQ_SOURCE; + Memory.FillRAM[0x2301] &= ~0x40; + } + + if (byte & 0x20) + { + SA1.IRQActive &= ~DMA_IRQ_SOURCE; + Memory.FillRAM[0x2301] &= ~0x20; + } + + if (byte & 0x10) + Memory.FillRAM[0x2301] &= ~0x10; + + if (!SA1.IRQActive) + SA1.Flags &= ~IRQ_FLAG; + + break; + + case 0x220c: + //printf("SNES NMI vector: %04x\n", byte | (Memory.FillRAM[0x220d] << 8)); + break; + + case 0x220d: + //printf("SNES NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220c]); + break; + + case 0x220e: + //printf("SNES IRQ vector: %04x\n", byte | (Memory.FillRAM[0x220f] << 8)); + break; + + case 0x220f: + //printf("SNES IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220e]); + break; + + case 0x2210: + #if 0 + printf("Timer %s\n", (byte & 0x80) ? "linear" : "HV"); + printf("Timer H-IRQ %s\n", (byte & 1) ? "enabled" : "disabled"); + printf("Timer V-IRQ %s\n", (byte & 2) ? "enabled" : "disabled"); + #endif + break; + + case 0x2211: + //printf("Timer reset\n"); + break; + + case 0x2212: + //printf("H-Timer %04x\n", byte | (Memory.FillRAM[0x2213] << 8)); + break; + + case 0x2213: + //printf("H-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2212]); + break; + + case 0x2214: + //printf("V-Timer %04x\n", byte | (Memory.FillRAM[0x2215] << 8)); + break; + + case 0x2215: + //printf("V-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2214]); + break; + + case 0x2220: + case 0x2221: + case 0x2222: + case 0x2223: + //printf("MMC: %02x\n", byte); + S9xSetSA1MemMap(address - 0x2220, byte); + break; + + case 0x2224: + //printf("BWRAM image SNES %02x -> 0x6000\n", byte); + Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000; + break; + + case 0x2225: + //printf("BWRAM image SA1 %02x -> 0x6000 (%02x)\n", byte, Memory.FillRAM[0x2225]); + if (byte != Memory.FillRAM[0x2225]) + S9xSA1SetBWRAMMemMap(byte); + break; + + case 0x2226: + //printf("BW-RAM SNES write %s\n", (byte & 0x80) ? "enabled" : "disabled"); + break; + + case 0x2227: + //printf("BW-RAM SA1 write %s\n", (byte & 0x80) ? "enabled" : "disabled"); + break; + + case 0x2228: + //printf("BW-RAM write protect area %02x\n", byte); + break; + + case 0x2229: + //printf("I-RAM SNES write protect area %02x\n", byte); + break; + + case 0x222a: + //printf("I-RAM SA1 write protect area %02x\n", byte); + break; + + case 0x2230: + #if 0 + printf("SA1 DMA %s\n", (byte & 0x80) ? "enabled" : "disabled"); + printf("DMA priority %s\n", (byte & 0x40) ? "DMA" : "SA1"); + printf("DMA %s\n", (byte & 0x20) ? "char conv" : "normal"); + printf("DMA type %s\n", (byte & 0x10) ? "BW-RAM -> I-RAM" : "SA1 -> I-RAM"); + printf("DMA distination %s\n", (byte & 4) ? "BW-RAM" : "I-RAM"); + printf("DMA source %s\n", DMAsource[byte & 3]); + #endif + break; + + case 0x2231: + if (byte & 0x80) + SA1.in_char_dma = FALSE; + #if 0 + printf("CHDEND %s\n", (byte & 0x80) ? "complete" : "incomplete"); + printf("DMA colour mode %d\n", byte & 3); + printf("virtual VRAM width %d\n", (byte >> 2) & 7); + #endif + break; + + case 0x2232: + case 0x2233: + case 0x2234: + Memory.FillRAM[address] = byte; + #if 0 + printf("DMA source start %06x\n", Memory.FillRAM[0x2232] | (Memory.FillRAM[0x2233] << 8) | (Memory.FillRAM[0x2234] << 16)); + #endif + break; + + case 0x2235: + Memory.FillRAM[0x2235] = byte; + break; + + case 0x2236: + Memory.FillRAM[0x2236] = byte; + + if ((Memory.FillRAM[0x2230] & 0xa4) == 0x80) // Normal DMA to I-RAM + S9xSA1DMA(); + else + if ((Memory.FillRAM[0x2230] & 0xb0) == 0xb0) + { + Memory.FillRAM[0x2300] |= 0x20; + if (Memory.FillRAM[0x2201] & 0x20) + S9xSetIRQ(SA1_DMA_IRQ_SOURCE); + SA1.in_char_dma = TRUE; + } + + break; + + case 0x2237: + Memory.FillRAM[0x2237] = byte; + + if ((Memory.FillRAM[0x2230] & 0xa4) == 0x84) // Normal DMA to BW-RAM + S9xSA1DMA(); + #if 0 + printf("DMA dest address %06x\n", Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8) | (Memory.FillRAM[0x2237] << 16)); + #endif + break; + + case 0x2238: + case 0x2239: + Memory.FillRAM[address] = byte; + #if 0 + printf("DMA length %04x\n", Memory.FillRAM[0x2238] | (Memory.FillRAM[0x2239] << 8)); + #endif + break; + + case 0x223f: + //printf("virtual VRAM depth %d\n", (byte & 0x80) ? 2 : 4); + SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4; + break; + + case 0x2240: + case 0x2241: + case 0x2242: + case 0x2243: + case 0x2244: + case 0x2245: + case 0x2246: + case 0x2247: + case 0x2248: + case 0x2249: + case 0x224a: + case 0x224b: + case 0x224c: + case 0x224d: + case 0x224e: + #if 0 + if (!(SA1.Flags & TRACE_FLAG)) + { + TraceSA1(); + Trace(); + } + #endif + Memory.FillRAM[address] = byte; + break; + + case 0x224f: + Memory.FillRAM[0x224f] = byte; + + if ((Memory.FillRAM[0x2230] & 0xb0) == 0xa0) // Char conversion 2 DMA enabled + { + memmove(&Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16, &Memory.FillRAM[0x2240], 16); + SA1.in_char_dma = (SA1.in_char_dma + 1) & 7; + if ((SA1.in_char_dma & 3) == 0) + S9xSA1CharConv2(); + } + + break; + + case 0x2250: + if (byte & 2) + SA1.sum = 0; + SA1.arithmetic_op = byte & 3; + break; + + case 0x2251: + SA1.op1 = (SA1.op1 & 0xff00) | byte; + break; + + case 0x2252: + SA1.op1 = (SA1.op1 & 0xff) | (byte << 8); + break; + + case 0x2253: + SA1.op2 = (SA1.op2 & 0xff00) | byte; + break; + + case 0x2254: + SA1.op2 = (SA1.op2 & 0xff) | (byte << 8); + + switch (SA1.arithmetic_op) + { + case 0: // multiply + SA1.sum = SA1.op1 * SA1.op2; + break; + + case 1: // divide + if (SA1.op2 == 0) + SA1.sum = SA1.op1 << 16; + else + SA1.sum = (SA1.op1 / (int) ((uint16) SA1.op2)) | ((SA1.op1 % (int) ((uint16) SA1.op2)) << 16); + break; + + case 2: // cumulative sum + default: + SA1.sum += SA1.op1 * SA1.op2; + if (SA1.sum & ((int64) 0xffffff << 32)) + SA1.overflow = TRUE; + break; + } + + break; + + case 0x2258: // Variable bit-field length/auto inc/start. + Memory.FillRAM[0x2258] = byte; + S9xSA1ReadVariableLengthData(TRUE, FALSE); + return; + + case 0x2259: // Variable bit-field start address + case 0x225a: + case 0x225b: + Memory.FillRAM[address] = byte; + // XXX: ??? + SA1.variable_bit_pos = 0; + S9xSA1ReadVariableLengthData(FALSE, TRUE); + return; + + default: + //printf("W: %02x->%04x\n", byte, address); + break; + } + + if (address >= 0x2200 && address <= 0x22ff) + Memory.FillRAM[address] = byte; +} + +static void S9xSA1CharConv2 (void) +{ + uint32 dest = Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8); + uint32 offset = (SA1.in_char_dma & 7) ? 0 : 1; + int depth = (Memory.FillRAM[0x2231] & 3) == 0 ? 8 : (Memory.FillRAM[0x2231] & 3) == 1 ? 4 : 2; + int bytes_per_char = 8 * depth; + uint8 *p = &Memory.FillRAM[0x3000] + (dest & 0x7ff) + offset * bytes_per_char; + uint8 *q = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + offset * 64; + + switch (depth) + { + case 2: + for (int l = 0; l < 8; l++, q += 8) + { + for (int b = 0; b < 8; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + } + + p += 2; + } + + break; + + case 4: + for (int l = 0; l < 8; l++, q += 8) + { + for (int b = 0; b < 8; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); + } + + p += 2; + } + + break; + + case 8: + for (int l = 0; l < 8; l++, q += 8) + { + for (int b = 0; b < 8; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); + *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); + *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); + *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); + *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); + } + + p += 2; + } + + break; + } +} + +static void S9xSA1DMA (void) +{ + uint32 src = Memory.FillRAM[0x2232] | (Memory.FillRAM[0x2233] << 8) | (Memory.FillRAM[0x2234] << 16); + uint32 dst = Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8) | (Memory.FillRAM[0x2237] << 16); + uint32 len = Memory.FillRAM[0x2238] | (Memory.FillRAM[0x2239] << 8); + uint8 *s, *d; + + switch (Memory.FillRAM[0x2230] & 3) + { + case 0: // ROM + s = SA1.Map[((src & 0xffffff) >> MEMMAP_SHIFT)]; + if (s >= (uint8 *) CMemory::MAP_LAST) + s += (src & 0xffff); + else + s = Memory.ROM + (src & 0xffff); + break; + + case 1: // BW-RAM + src &= Memory.SRAMMask; + len &= Memory.SRAMMask; + s = Memory.SRAM + src; + break; + + default: + case 2: + src &= 0x3ff; + len &= 0x3ff; + s = &Memory.FillRAM[0x3000] + src; + break; + } + + if (Memory.FillRAM[0x2230] & 4) + { + dst &= Memory.SRAMMask; + len &= Memory.SRAMMask; + d = Memory.SRAM + dst; + } + else + { + dst &= 0x3ff; + len &= 0x3ff; + d = &Memory.FillRAM[0x3000] + dst; + } + + memmove(d, s, len); + Memory.FillRAM[0x2301] |= 0x20; + + if (Memory.FillRAM[0x220a] & 0x20) + { + SA1.Flags |= IRQ_FLAG; + SA1.IRQActive |= DMA_IRQ_SOURCE; + //SA1.Executing = !SA1.Waiting; + } +} + +static void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift) +{ + uint32 addr = Memory.FillRAM[0x2259] | (Memory.FillRAM[0x225a] << 8) | (Memory.FillRAM[0x225b] << 16); + uint8 shift = Memory.FillRAM[0x2258] & 15; + + if (no_shift) + shift = 0; + else + if (shift == 0) + shift = 16; + + uint8 s = shift + SA1.variable_bit_pos; + + if (s >= 16) + { + addr += (s >> 4) << 1; + s &= 15; + } + + uint32 data = S9xSA1GetWord(addr) | (S9xSA1GetWord(addr + 2) << 16); + + data >>= s; + Memory.FillRAM[0x230c] = (uint8) data; + Memory.FillRAM[0x230d] = (uint8) (data >> 8); + + if (inc) + { + SA1.variable_bit_pos = (SA1.variable_bit_pos + shift) & 15; + Memory.FillRAM[0x2259] = (uint8) addr; + Memory.FillRAM[0x225a] = (uint8) (addr >> 8); + Memory.FillRAM[0x225b] = (uint8) (addr >> 16); + } +} + +uint8 S9xSA1GetByte (uint32 address) +{ + uint8 *GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT]; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + return (*(GetAddress + (address & 0xffff))); + + switch ((pint) GetAddress) + { + case CMemory::MAP_PPU: + return (S9xGetSA1(address & 0xffff)); + + case CMemory::MAP_LOROM_SRAM: + case CMemory::MAP_SA1RAM: + return (*(Memory.SRAM + (address & 0xffff))); + + case CMemory::MAP_BWRAM: + return (*(SA1.BWRAM + ((address & 0x7fff) - 0x6000))); + + case CMemory::MAP_BWRAM_BITMAP: + address -= 0x600000; + if (SA1.VirtualBitmapFormat == 2) + return ((Memory.SRAM[(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); + else + return ((Memory.SRAM[(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); + + case CMemory::MAP_BWRAM_BITMAP2: + address = (address & 0xffff) - 0x6000; + if (SA1.VirtualBitmapFormat == 2) + return ((SA1.BWRAM[(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); + else + return ((SA1.BWRAM[(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); + + default: + return (SA1OpenBus); + } +} + +uint16 S9xSA1GetWord (uint32 address, s9xwrap_t w) +{ + PC_t a; + + SA1OpenBus = S9xSA1GetByte(address); + + switch (w) + { + case WRAP_PAGE: + a.xPBPC = address; + a.B.xPCl++; + return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8)); + + case WRAP_BANK: + a.xPBPC = address; + a.W.xPC++; + return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8)); + + case WRAP_NONE: + default: + return (SA1OpenBus | (S9xSA1GetByte(address + 1) << 8)); + } +} + +void S9xSA1SetByte (uint8 byte, uint32 address) +{ + uint8 *SetAddress = SA1.WriteMap[(address & 0xffffff) >> MEMMAP_SHIFT]; + + if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + { + *(SetAddress + (address & 0xffff)) = byte; + return; + } + + switch ((pint) SetAddress) + { + case CMemory::MAP_PPU: + S9xSetSA1(byte, address & 0xffff); + return; + + case CMemory::MAP_LOROM_SRAM: + case CMemory::MAP_SA1RAM: + *(Memory.SRAM + (address & 0xffff)) = byte; + return; + + case CMemory::MAP_BWRAM: + *(SA1.BWRAM + ((address & 0x7fff) - 0x6000)) = byte; + return; + + case CMemory::MAP_BWRAM_BITMAP: + address -= 0x600000; + if (SA1.VirtualBitmapFormat == 2) + { + uint8 *ptr = &Memory.SRAM[(address >> 2) & 0xffff]; + *ptr &= ~(3 << ((address & 3) << 1)); + *ptr |= (byte & 3) << ((address & 3) << 1); + } + else + { + uint8 *ptr = &Memory.SRAM[(address >> 1) & 0xffff]; + *ptr &= ~(15 << ((address & 1) << 2)); + *ptr |= (byte & 15) << ((address & 1) << 2); + } + + return; + + case CMemory::MAP_BWRAM_BITMAP2: + address = (address & 0xffff) - 0x6000; + if (SA1.VirtualBitmapFormat == 2) + { + uint8 *ptr = &SA1.BWRAM[(address >> 2) & 0xffff]; + *ptr &= ~(3 << ((address & 3) << 1)); + *ptr |= (byte & 3) << ((address & 3) << 1); + } + else + { + uint8 *ptr = &SA1.BWRAM[(address >> 1) & 0xffff]; + *ptr &= ~(15 << ((address & 1) << 2)); + *ptr |= (byte & 15) << ((address & 1) << 2); + } + + return; + + default: + return; + } +} + +void S9xSA1SetWord (uint16 Word, uint32 address, enum s9xwrap_t w, enum s9xwriteorder_t o) +{ + PC_t a; + + if (!o) + S9xSA1SetByte((uint8) Word, address); + + switch (w) + { + case WRAP_PAGE: + a.xPBPC = address; + a.B.xPCl++; + S9xSA1SetByte(Word >> 8, a.xPBPC); + break; + + case WRAP_BANK: + a.xPBPC = address; + a.W.xPC++; + S9xSA1SetByte(Word >> 8, a.xPBPC); + break; + + case WRAP_NONE: + default: + S9xSA1SetByte(Word >> 8, address + 1); + break; + } + + if (o) + S9xSA1SetByte((uint8) Word, address); +} + +void S9xSA1SetPCBase (uint32 address) +{ + SA1Registers.PBPC = address & 0xffffff; + SA1.ShiftedPB = address & 0xff0000; + + uint8 *GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT]; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { + SA1.PCBase = GetAddress; + return; + } + + switch ((pint) GetAddress) + { + case CMemory::MAP_LOROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + SA1.PCBase = NULL; + else + SA1.PCBase = (Memory.SRAM + ((((address & 0xff0000) >> 1) | (address & 0x7fff)) & Memory.SRAMMask)) - (address & 0xffff); + return; + + case CMemory::MAP_HIROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + SA1.PCBase = NULL; + else + SA1.PCBase = (Memory.SRAM + (((address & 0x7fff) - 0x6000 + ((address & 0xf0000) >> 3)) & Memory.SRAMMask)) - (address & 0xffff); + return; + + case CMemory::MAP_BWRAM: + SA1.PCBase = SA1.BWRAM - 0x6000 - (address & 0x8000); + return; + + case CMemory::MAP_SA1RAM: + SA1.PCBase = Memory.SRAM; + return; + + default: + SA1.PCBase = NULL; + return; + } +} + diff --git a/plugins/snes9x_gx/source/snes9x/sa1.h b/plugins/snes9x_gx/source/snes9x/sa1.h new file mode 100644 index 00000000..7849c8c8 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/sa1.h @@ -0,0 +1,323 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _SA1_H_ +#define _SA1_H_ + +struct SSA1Registers +{ + uint8 DB; + pair P; + pair A; + pair D; + pair S; + pair X; + pair Y; + PC_t PC; +}; + +struct SSA1 +{ + struct SOpcodes *S9xOpcodes; + uint8 *S9xOpLengths; + uint8 _Carry; + uint8 _Zero; + uint8 _Negative; + uint8 _Overflow; + bool8 CPUExecuting; + uint32 ShiftedPB; + uint32 ShiftedDB; + + uint32 Flags; + uint8 *PCBase; + bool8 IRQActive; + bool8 Waiting; + bool8 WaitingForInterrupt; + uint32 WaitAddress; + uint32 WaitCounter; + uint32 PBPCAtOpcodeStart; + uint8 *WaitByteAddress1; + uint8 *WaitByteAddress2; + + uint8 *Map[MEMMAP_NUM_BLOCKS]; + uint8 *WriteMap[MEMMAP_NUM_BLOCKS]; + uint8 *BWRAM; + + bool8 Executing; + bool8 overflow; + bool8 in_char_dma; + int16 op1; + int16 op2; + int32 arithmetic_op; + int64 sum; + uint8 VirtualBitmapFormat; + uint8 variable_bit_pos; +}; + +#define SA1CheckCarry() (SA1._Carry) +#define SA1CheckZero() (SA1._Zero == 0) +#define SA1CheckIRQ() (SA1Registers.PL & IRQ) +#define SA1CheckDecimal() (SA1Registers.PL & Decimal) +#define SA1CheckIndex() (SA1Registers.PL & IndexFlag) +#define SA1CheckMemory() (SA1Registers.PL & MemoryFlag) +#define SA1CheckOverflow() (SA1._Overflow) +#define SA1CheckNegative() (SA1._Negative & 0x80) +#define SA1CheckEmulation() (SA1Registers.P.W & Emulation) + +#define SA1SetFlags(f) (SA1Registers.P.W |= (f)) +#define SA1ClearFlags(f) (SA1Registers.P.W &= ~(f)) +#define SA1CheckFlag(f) (SA1Registers.PL & (f)) + +extern struct SSA1Registers SA1Registers; +extern struct SSA1 SA1; +extern uint8 SA1OpenBus; +extern struct SOpcodes S9xSA1OpcodesM1X1[256]; +extern struct SOpcodes S9xSA1OpcodesM1X0[256]; +extern struct SOpcodes S9xSA1OpcodesM0X1[256]; +extern struct SOpcodes S9xSA1OpcodesM0X0[256]; +extern uint8 S9xOpLengthsM1X1[256]; +extern uint8 S9xOpLengthsM1X0[256]; +extern uint8 S9xOpLengthsM0X1[256]; +extern uint8 S9xOpLengthsM0X0[256]; + +uint8 S9xSA1GetByte (uint32); +void S9xSA1SetByte (uint8, uint32); +uint16 S9xSA1GetWord (uint32, enum s9xwrap_t w = WRAP_NONE); +void S9xSA1SetWord (uint16, uint32, enum s9xwrap_t w = WRAP_NONE, enum s9xwriteorder_t o = WRITE_01); +void S9xSA1SetPCBase (uint32); +uint8 S9xGetSA1 (uint32); +void S9xSetSA1 (uint8, uint32); +void S9xSA1Init (void); +void S9xSA1MainLoop (void); +void S9xSA1ExecuteDuringSleep (void); +void S9xSA1PostLoadState (void); + +#define SNES_IRQ_SOURCE (1 << 7) +#define TIMER_IRQ_SOURCE (1 << 6) +#define DMA_IRQ_SOURCE (1 << 5) + +static inline void S9xSA1UnpackStatus (void) +{ + SA1._Zero = (SA1Registers.PL & Zero) == 0; + SA1._Negative = (SA1Registers.PL & Negative); + SA1._Carry = (SA1Registers.PL & Carry); + SA1._Overflow = (SA1Registers.PL & Overflow) >> 6; +} + +static inline void S9xSA1PackStatus (void) +{ + SA1Registers.PL &= ~(Zero | Negative | Carry | Overflow); + SA1Registers.PL |= SA1._Carry | ((SA1._Zero == 0) << 1) | (SA1._Negative & 0x80) | (SA1._Overflow << 6); +} + +static inline void S9xSA1FixCycles (void) +{ + if (SA1CheckEmulation()) + { + SA1.S9xOpcodes = S9xSA1OpcodesM1X1; + SA1.S9xOpLengths = S9xOpLengthsM1X1; + } + else + if (SA1CheckMemory()) + { + if (SA1CheckIndex()) + { + SA1.S9xOpcodes = S9xSA1OpcodesM1X1; + SA1.S9xOpLengths = S9xOpLengthsM1X1; + } + else + { + SA1.S9xOpcodes = S9xSA1OpcodesM1X0; + SA1.S9xOpLengths = S9xOpLengthsM1X0; + } + } + else + { + if (SA1CheckIndex()) + { + SA1.S9xOpcodes = S9xSA1OpcodesM0X1; + SA1.S9xOpLengths = S9xOpLengthsM0X1; + } + else + { + SA1.S9xOpcodes = S9xSA1OpcodesM0X0; + SA1.S9xOpLengths = S9xOpLengthsM0X0; + } + } +} + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/sa1cpu.cpp b/plugins/snes9x_gx/source/snes9x/sa1cpu.cpp new file mode 100644 index 00000000..e5093617 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/sa1cpu.cpp @@ -0,0 +1,303 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" + +#define CPU SA1 +#define ICPU SA1 +#define Registers SA1Registers +#define OpenBus SA1OpenBus +#define S9xGetByte S9xSA1GetByte +#define S9xGetWord S9xSA1GetWord +#define S9xSetByte S9xSA1SetByte +#define S9xSetWord S9xSA1SetWord +#define S9xSetPCBase S9xSA1SetPCBase +#define S9xOpcodesM1X1 S9xSA1OpcodesM1X1 +#define S9xOpcodesM1X0 S9xSA1OpcodesM1X0 +#define S9xOpcodesM0X1 S9xSA1OpcodesM0X1 +#define S9xOpcodesM0X0 S9xSA1OpcodesM0X0 +#define S9xOpcodesE1 S9xSA1OpcodesE1 +#define S9xOpcodesSlow S9xSA1OpcodesSlow +#define S9xOpcode_IRQ S9xSA1Opcode_IRQ +#define S9xOpcode_NMI S9xSA1Opcode_NMI +#define S9xUnpackStatus S9xSA1UnpackStatus +#define S9xPackStatus S9xSA1PackStatus +#define S9xFixCycles S9xSA1FixCycles +#define Immediate8 SA1Immediate8 +#define Immediate16 SA1Immediate16 +#define Relative SA1Relative +#define RelativeLong SA1RelativeLong +#define Absolute SA1Absolute +#define AbsoluteLong SA1AbsoluteLong +#define AbsoluteIndirect SA1AbsoluteIndirect +#define AbsoluteIndirectLong SA1AbsoluteIndirectLong +#define AbsoluteIndexedIndirect SA1AbsoluteIndexedIndirect +#define Direct SA1Direct +#define DirectIndirectIndexed SA1DirectIndirectIndexed +#define DirectIndirectIndexedLong SA1DirectIndirectIndexedLong +#define DirectIndexedIndirect SA1DirectIndexedIndirect +#define DirectIndexedX SA1DirectIndexedX +#define DirectIndexedY SA1DirectIndexedY +#define AbsoluteIndexedX SA1AbsoluteIndexedX +#define AbsoluteIndexedY SA1AbsoluteIndexedY +#define AbsoluteLongIndexedX SA1AbsoluteLongIndexedX +#define DirectIndirect SA1DirectIndirect +#define DirectIndirectLong SA1DirectIndirectLong +#define StackRelative SA1StackRelative +#define StackRelativeIndirectIndexed SA1StackRelativeIndirectIndexed + +//#undef CPU_SHUTDOWN +#define SA1_OPCODES + +#include "cpuops.cpp" + + +void S9xSA1MainLoop (void) +{ + if (SA1.Flags & NMI_FLAG) + { + if (Memory.FillRAM[0x2200] & 0x10) + { + SA1.Flags &= ~NMI_FLAG; + Memory.FillRAM[0x2301] |= 0x10; + + if (SA1.WaitingForInterrupt) + { + SA1.WaitingForInterrupt = FALSE; + SA1Registers.PCw++; + } + + S9xSA1Opcode_NMI(); + } + } + + if (SA1.Flags & IRQ_FLAG) + { + if (SA1.IRQActive) + { + if (SA1.WaitingForInterrupt) + { + SA1.WaitingForInterrupt = FALSE; + SA1Registers.PCw++; + } + + if (!SA1CheckFlag(IRQ)) + S9xSA1Opcode_IRQ(); + } + else + SA1.Flags &= ~IRQ_FLAG; + } + + for (int i = 0; i < 3 && SA1.Executing; i++) + { + #ifdef DEBUGGER + if (SA1.Flags & TRACE_FLAG) + S9xSA1Trace(); + #endif + + #ifdef CPU_SHUTDOWN + SA1.PBPCAtOpcodeStart = SA1Registers.PBPC; + #endif + + register uint8 Op; + register struct SOpcodes *Opcodes; + + if (SA1.PCBase) + { + SA1OpenBus = Op = SA1.PCBase[Registers.PCw]; + Opcodes = SA1.S9xOpcodes; + } + else + { + Op = S9xSA1GetByte(Registers.PBPC); + Opcodes = S9xOpcodesSlow; + } + + if ((SA1Registers.PCw & MEMMAP_MASK) + SA1.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE) + { + uint32 oldPC = SA1Registers.PBPC; + S9xSA1SetPCBase(SA1Registers.PBPC); + SA1Registers.PBPC = oldPC; + Opcodes = S9xSA1OpcodesSlow; + } + + Registers.PCw++; + (*Opcodes[Op].S9xOpcode)(); + } +} + diff --git a/plugins/snes9x_gx/source/snes9x/sar.h b/plugins/snes9x_gx/source/snes9x/sar.h new file mode 100644 index 00000000..f53de57a --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/sar.h @@ -0,0 +1,223 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _SAR_H_ +#define _SAR_H_ + +#ifdef RIGHTSHIFT_IS_SAR +#define SAR(b, n) ((b) >> (n)) +#else + +static inline int8 SAR (const int8 b, const int n) +{ +#ifndef RIGHTSHIFT_int8_IS_SAR + if (b < 0) + return ((b >> n) | (-1 << (8 - n))); +#endif + return (b >> n); +} + +static inline int16 SAR (const int16 b, const int n) +{ +#ifndef RIGHTSHIFT_int16_IS_SAR + if (b < 0) + return ((b >> n) | (-1 << (16 - n))); +#endif + return (b >> n); +} + +static inline int32 SAR (const int32 b, const int n) +{ +#ifndef RIGHTSHIFT_int32_IS_SAR + if (b < 0) + return ((b >> n) | (-1 << (32 - n))); +#endif + return (b >> n); +} + +static inline int64 SAR (const int64 b, const int n) +{ +#ifndef RIGHTSHIFT_int64_IS_SAR + if (b < 0) + return ((b >> n) | (-1 << (64 - n))); +#endif + return (b >> n); +} + +#endif + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/screenshot.cpp b/plugins/snes9x_gx/source/snes9x/screenshot.cpp new file mode 100644 index 00000000..ec8f7503 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/screenshot.cpp @@ -0,0 +1,315 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifdef HAVE_LIBPNG +#include <png.h> +#endif +#include "snes9x.h" +#include "memmap.h" +#include "display.h" +#include "screenshot.h" + + +bool8 S9xDoScreenshot (int width, int height) +{ + Settings.TakeScreenshot = FALSE; + +#ifdef HAVE_LIBPNG + FILE *fp; + png_structp png_ptr; + png_infop info_ptr; + png_color_8 sig_bit; + int imgwidth, imgheight; + const char *fname; + + fname = S9xGetFilenameInc(".png", SCREENSHOT_DIR); + + fp = fopen(fname, "wb"); + if (!fp) + { + S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); + return (FALSE); + } + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + { + fclose(fp); + remove(fname); + S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); + return (FALSE); + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + fclose(fp); + remove(fname); + S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); + return (FALSE); + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + remove(fname); + S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); + return (FALSE); + } + + imgwidth = width; + imgheight = height; + + if (Settings.StretchScreenshots == 1) + { + if (width > SNES_WIDTH && height <= SNES_HEIGHT_EXTENDED) + imgheight = height << 1; + } + else + if (Settings.StretchScreenshots == 2) + { + if (width <= SNES_WIDTH) + imgwidth = width << 1; + if (height <= SNES_HEIGHT_EXTENDED) + imgheight = height << 1; + } + + png_init_io(png_ptr, fp); + + png_set_IHDR(png_ptr, info_ptr, imgwidth, imgheight, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + sig_bit.red = 5; + sig_bit.green = 5; + sig_bit.blue = 5; + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + png_set_shift(png_ptr, &sig_bit); + + png_write_info(png_ptr, info_ptr); + + png_set_packing(png_ptr); + + png_byte *row_pointer = new png_byte[png_get_rowbytes(png_ptr, info_ptr)]; + uint16 *screen = GFX.Screen; + + for (int y = 0; y < height; y++, screen += GFX.RealPPL) + { + png_byte *rowpix = row_pointer; + + for (int x = 0; x < width; x++) + { + uint32 r, g, b; + + DECOMPOSE_PIXEL(screen[x], r, g, b); + + *(rowpix++) = r; + *(rowpix++) = g; + *(rowpix++) = b; + + if (imgwidth != width) + { + *(rowpix++) = r; + *(rowpix++) = g; + *(rowpix++) = b; + } + } + + png_write_row(png_ptr, row_pointer); + if (imgheight != height) + png_write_row(png_ptr, row_pointer); + } + + delete [] row_pointer; + + png_write_end(png_ptr, info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + + fclose(fp); + + fprintf(stderr, "%s saved.\n", fname); + + const char *base = S9xBasename(fname); + sprintf(String, "Saved screenshot %s", base); + S9xMessage(S9X_INFO, 0, String); + + return (TRUE); +#else + fprintf(stderr, "Screenshot support not available (libpng was not found at build time).\n"); + return (FALSE); +#endif +} diff --git a/plugins/snes9x_gx/source/snes9x/screenshot.h b/plugins/snes9x_gx/source/snes9x/screenshot.h new file mode 100644 index 00000000..6839ba09 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/screenshot.h @@ -0,0 +1,183 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _SCREENSHOT_H_ +#define _SCREENSHOT_H_ + +bool8 S9xDoScreenshot (int, int); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/sdd1.cpp b/plugins/snes9x_gx/source/snes9x/sdd1.cpp new file mode 100644 index 00000000..40cd4c9b --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/sdd1.cpp @@ -0,0 +1,211 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "sdd1.h" +#include "display.h" + + +void S9xSetSDD1MemoryMap (uint32 bank, uint32 value) +{ + bank = 0xc00 + bank * 0x100; + value = value * 1024 * 1024; + + for (int c = 0; c < 0x100; c += 16) + { + uint8 *block = &Memory.ROM[value + (c << 12)]; + for (int i = c; i < c + 16; i++) + Memory.Map[i + bank] = block; + } +} + +void S9xResetSDD1 (void) +{ + memset(&Memory.FillRAM[0x4800], 0, 4); + for (int i = 0; i < 4; i++) + { + Memory.FillRAM[0x4804 + i] = i; + S9xSetSDD1MemoryMap(i, i); + } +} + +void S9xSDD1PostLoadState (void) +{ + for (int i = 0; i < 4; i++) + S9xSetSDD1MemoryMap(i, Memory.FillRAM[0x4804 + i]); +} diff --git a/plugins/snes9x_gx/source/snes9x/sdd1.h b/plugins/snes9x_gx/source/snes9x/sdd1.h new file mode 100644 index 00000000..7419b5ba --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/sdd1.h @@ -0,0 +1,185 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _SDD1_H_ +#define _SDD1_H_ + +void S9xSetSDD1MemoryMap (uint32, uint32); +void S9xResetSDD1 (void); +void S9xSDD1PostLoadState (void); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/sdd1emu.cpp b/plugins/snes9x_gx/source/snes9x/sdd1emu.cpp new file mode 100644 index 00000000..c4f4d36b --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/sdd1emu.cpp @@ -0,0 +1,503 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + +/* S-DD1 decompressor + * + * Based on code and documentation by Andreas Naive, who deserves a great deal + * of thanks and credit for figuring this out. + * + * Andreas says: + * The author is greatly indebted with The Dumper, without whose help and + * patience providing him with real S-DD1 data the research had never been + * possible. He also wish to note that in the very beggining of his research, + * Neviksti had done some steps in the right direction. By last, the author is + * indirectly indebted to all the people that worked and contributed in the + * S-DD1 issue in the past. + */ + + +#include "port.h" +#include "sdd1emu.h" + +static int valid_bits; +static uint16 in_stream; +static uint8 *in_buf; +static uint8 bit_ctr[8]; +static uint8 context_states[32]; +static int context_MPS[32]; +static int bitplane_type; +static int high_context_bits; +static int low_context_bits; +static int prev_bits[8]; + +static struct { + uint8 code_size; + uint8 MPS_next; + uint8 LPS_next; +} evolution_table[] = { + /* 0 */ { 0,25,25}, + /* 1 */ { 0, 2, 1}, + /* 2 */ { 0, 3, 1}, + /* 3 */ { 0, 4, 2}, + /* 4 */ { 0, 5, 3}, + /* 5 */ { 1, 6, 4}, + /* 6 */ { 1, 7, 5}, + /* 7 */ { 1, 8, 6}, + /* 8 */ { 1, 9, 7}, + /* 9 */ { 2,10, 8}, + /* 10 */ { 2,11, 9}, + /* 11 */ { 2,12,10}, + /* 12 */ { 2,13,11}, + /* 13 */ { 3,14,12}, + /* 14 */ { 3,15,13}, + /* 15 */ { 3,16,14}, + /* 16 */ { 3,17,15}, + /* 17 */ { 4,18,16}, + /* 18 */ { 4,19,17}, + /* 19 */ { 5,20,18}, + /* 20 */ { 5,21,19}, + /* 21 */ { 6,22,20}, + /* 22 */ { 6,23,21}, + /* 23 */ { 7,24,22}, + /* 24 */ { 7,24,23}, + /* 25 */ { 0,26, 1}, + /* 26 */ { 1,27, 2}, + /* 27 */ { 2,28, 4}, + /* 28 */ { 3,29, 8}, + /* 29 */ { 4,30,12}, + /* 30 */ { 5,31,16}, + /* 31 */ { 6,32,18}, + /* 32 */ { 7,24,22} +}; + +static uint8 run_table[128] = { + 128, 64, 96, 32, 112, 48, 80, 16, 120, 56, 88, 24, 104, 40, 72, + 8, 124, 60, 92, 28, 108, 44, 76, 12, 116, 52, 84, 20, 100, 36, + 68, 4, 126, 62, 94, 30, 110, 46, 78, 14, 118, 54, 86, 22, 102, + 38, 70, 6, 122, 58, 90, 26, 106, 42, 74, 10, 114, 50, 82, 18, + 98, 34, 66, 2, 127, 63, 95, 31, 111, 47, 79, 15, 119, 55, 87, + 23, 103, 39, 71, 7, 123, 59, 91, 27, 107, 43, 75, 11, 115, 51, + 83, 19, 99, 35, 67, 3, 125, 61, 93, 29, 109, 45, 77, 13, 117, + 53, 85, 21, 101, 37, 69, 5, 121, 57, 89, 25, 105, 41, 73, 9, + 113, 49, 81, 17, 97, 33, 65, 1 +}; + +static inline uint8 GetCodeword(int bits){ + uint8 tmp; + + if(!valid_bits){ + in_stream|=*(in_buf++); + valid_bits=8; + } + in_stream<<=1; + valid_bits--; + in_stream^=0x8000; + if(in_stream&0x8000) return 0x80+(1<<bits); + tmp=(in_stream>>8) | (0x7f>>bits); + in_stream<<=bits; + valid_bits-=bits; + if(valid_bits<0){ + in_stream |= (*(in_buf++))<<(-valid_bits); + valid_bits+=8; + } + return run_table[tmp]; +} + +static inline uint8 GolombGetBit(int code_size){ + if(!bit_ctr[code_size]) bit_ctr[code_size]=GetCodeword(code_size); + bit_ctr[code_size]--; + if(bit_ctr[code_size]==0x80){ + bit_ctr[code_size]=0; + return 2; /* secret code for 'last zero'. ones are always last. */ + } + return (bit_ctr[code_size]==0)?1:0; +} + +static inline uint8 ProbGetBit(uint8 context){ + uint8 state=context_states[context]; + uint8 bit=GolombGetBit(evolution_table[state].code_size); + + if(bit&1){ + context_states[context]=evolution_table[state].LPS_next; + if(state<2){ + context_MPS[context]^=1; + return context_MPS[context]; /* just inverted, so just return it */ + } else{ + return context_MPS[context]^1; /* we know bit is 1, so use a constant */ + } + } else if(bit){ + context_states[context]=evolution_table[state].MPS_next; + /* zero here, zero there, no difference so drop through. */ + } + return context_MPS[context]; /* we know bit is 0, so don't bother xoring */ +} + +static inline uint8 GetBit(uint8 cur_bitplane){ + uint8 bit; + + bit=ProbGetBit(((cur_bitplane&1)<<4) + | ((prev_bits[cur_bitplane]&high_context_bits)>>5) + | (prev_bits[cur_bitplane]&low_context_bits)); + + prev_bits[cur_bitplane] <<= 1; + prev_bits[cur_bitplane] |= bit; + return bit; +} + +void SDD1_decompress(uint8 *out, uint8 *in, int len){ + uint8 bit, i, plane; + uint8 byte1, byte2; + + if(len==0) len=0x10000; + + bitplane_type=in[0]>>6; + + switch(in[0]&0x30){ + case 0x00: + high_context_bits=0x01c0; + low_context_bits =0x0001; + break; + case 0x10: + high_context_bits=0x0180; + low_context_bits =0x0001; + break; + case 0x20: + high_context_bits=0x00c0; + low_context_bits =0x0001; + break; + case 0x30: + high_context_bits=0x0180; + low_context_bits =0x0003; + break; + } + + in_stream=(in[0]<<11) | (in[1]<<3); + valid_bits=5; + in_buf=in+2; + memset(bit_ctr, 0, sizeof(bit_ctr)); + memset(context_states, 0, sizeof(context_states)); + memset(context_MPS, 0, sizeof(context_MPS)); + memset(prev_bits, 0, sizeof(prev_bits)); + + switch(bitplane_type){ + case 0: + while(1) { + for(byte1=byte2=0, bit=0x80; bit; bit>>=1){ + if(GetBit(0)) byte1 |= bit; + if(GetBit(1)) byte2 |= bit; + } + *(out++)=byte1; + if(!--len) return; + *(out++)=byte2; + if(!--len) return; + } + break; + case 1: + i=plane=0; + while(1) { + for(byte1=byte2=0, bit=0x80; bit; bit>>=1){ + if(GetBit(plane)) byte1 |= bit; + if(GetBit(plane+1)) byte2 |= bit; + } + *(out++)=byte1; + if(!--len) return; + *(out++)=byte2; + if(!--len) return; + if(!(i+=32)) plane = (plane+2)&7; + } + break; + case 2: + i=plane=0; + while(1) { + for(byte1=byte2=0, bit=0x80; bit; bit>>=1){ + if(GetBit(plane)) byte1 |= bit; + if(GetBit(plane+1)) byte2 |= bit; + } + *(out++)=byte1; + if(!--len) return; + *(out++)=byte2; + if(!--len) return; + if(!(i+=32)) plane ^= 2; + } + break; + case 3: + do { + for(byte1=plane=0, bit=1; bit; bit<<=1, plane++){ + if(GetBit(plane)) byte1 |= bit; + } + *(out++)=byte1; + } while(--len); + break; + } +} + +#if 0 +static uint8 cur_plane; +static uint8 num_bits; +static uint8 next_byte; + +void SDD1_init(uint8 *in){ + bitplane_type=in[0]>>6; + + switch(in[0]&0x30){ + case 0x00: + high_context_bits=0x01c0; + low_context_bits =0x0001; + break; + case 0x10: + high_context_bits=0x0180; + low_context_bits =0x0001; + break; + case 0x20: + high_context_bits=0x00c0; + low_context_bits =0x0001; + break; + case 0x30: + high_context_bits=0x0180; + low_context_bits =0x0003; + break; + } + + in_stream=(in[0]<<11) | (in[1]<<3); + valid_bits=5; + in_buf=in+2; + memset(bit_ctr, 0, sizeof(bit_ctr)); + memset(context_states, 0, sizeof(context_states)); + memset(context_MPS, 0, sizeof(context_MPS)); + memset(prev_bits, 0, sizeof(prev_bits)); + + cur_plane=0; + num_bits=0; +} + +uint8 SDD1_get_byte(void){ + uint8 bit; + uint8 byte=0; + + switch(bitplane_type){ + case 0: + num_bits+=16; + if(num_bits&16){ + next_byte=0; + for(bit=0x80; bit; bit>>=1){ + if(GetBit(0)) byte |= bit; + if(GetBit(1)) next_byte |= bit; + } + return byte; + } else { + return next_byte; + } + + case 1: + num_bits+=16; + if(num_bits&16){ + next_byte=0; + for(bit=0x80; bit; bit>>=1){ + if(GetBit(cur_plane)) byte |= bit; + if(GetBit(cur_plane+1)) next_byte |= bit; + } + return byte; + } else { + if(!num_bits) cur_plane = (cur_plane+2)&7; + return next_byte; + } + + case 2: + num_bits+=16; + if(num_bits&16){ + next_byte=0; + for(bit=0x80; bit; bit>>=1){ + if(GetBit(cur_plane)) byte |= bit; + if(GetBit(cur_plane+1)) next_byte |= bit; + } + return byte; + } else { + if(!num_bits) cur_plane ^= 2; + return next_byte; + } + + case 3: + for(cur_plane=0, bit=1; bit; bit<<=1, cur_plane++){ + if(GetBit(cur_plane)) byte |= bit; + } + return byte; + + default: + /* should never happen */ + return 0; + } +} +#endif diff --git a/plugins/snes9x_gx/source/snes9x/sdd1emu.h b/plugins/snes9x_gx/source/snes9x/sdd1emu.h new file mode 100644 index 00000000..5722b4b6 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/sdd1emu.h @@ -0,0 +1,183 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _SDD1EMU_H_ +#define _SDD1EMU_H_ + +void SDD1_decompress (uint8 *, uint8 *, int); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/seta.cpp b/plugins/snes9x_gx/source/snes9x/seta.cpp new file mode 100644 index 00000000..e7fd24c9 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/seta.cpp @@ -0,0 +1,193 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "seta.h" + +uint8 (*GetSETA) (uint32) = &S9xGetST010; +void (*SetSETA) (uint32, uint8) = &S9xSetST010; + + +uint8 S9xGetSetaDSP (uint32 Address) +{ + return (GetSETA(Address)); +} + +void S9xSetSetaDSP (uint8 Byte, uint32 Address) +{ + SetSETA (Address, Byte); +} diff --git a/plugins/snes9x_gx/source/snes9x/seta.h b/plugins/snes9x_gx/source/snes9x/seta.h new file mode 100644 index 00000000..ee49097c --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/seta.h @@ -0,0 +1,238 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _SETA_H_ +#define _SETA_H_ + +#define ST_010 0x01 +#define ST_011 0x02 +#define ST_018 0x03 + +struct SST010 +{ + uint8 input_params[16]; + uint8 output_params[16]; + uint8 op_reg; + uint8 execute; + bool8 control_enable; +}; + +struct SST011 +{ + bool8 waiting4command; + uint8 status; + uint8 command; + uint32 in_count; + uint32 in_index; + uint32 out_count; + uint32 out_index; + uint8 parameters[512]; + uint8 output[512]; +}; + +struct SST018 +{ + bool8 waiting4command; + uint8 status; + uint8 part_command; + uint8 pass; + uint32 command; + uint32 in_count; + uint32 in_index; + uint32 out_count; + uint32 out_index; + uint8 parameters[512]; + uint8 output[512]; +}; + +extern struct SST010 ST010; +extern struct SST011 ST011; +extern struct SST018 ST018; + +uint8 S9xGetST010 (uint32); +void S9xSetST010 (uint32, uint8); +uint8 S9xGetST011 (uint32); +void S9xSetST011 (uint32, uint8); +uint8 S9xGetST018 (uint32); +void S9xSetST018 (uint8, uint32); +uint8 S9xGetSetaDSP (uint32); +void S9xSetSetaDSP (uint8, uint32); + +extern uint8 (*GetSETA) (uint32); +extern void (*SetSETA) (uint32, uint8); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/seta010.cpp b/plugins/snes9x_gx/source/snes9x/seta010.cpp new file mode 100644 index 00000000..45cf8779 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/seta010.cpp @@ -0,0 +1,863 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include <math.h> +#include "snes9x.h" +#include "memmap.h" +#include "seta.h" + +static const int16 ST010_SinTable[256] = +{ + 0x0000, 0x0324, 0x0648, 0x096a, 0x0c8c, 0x0fab, 0x12c8, 0x15e2, + 0x18f9, 0x1c0b, 0x1f1a, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, + 0x30fb, 0x33df, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, + 0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, + 0x5a82, 0x5cb3, 0x5ed7, 0x60eb, 0x62f1, 0x64e8, 0x66cf, 0x68a6, + 0x6a6d, 0x6c23, 0x6dc9, 0x6f5e, 0x70e2, 0x7254, 0x73b5, 0x7504, + 0x7641, 0x776b, 0x7884, 0x7989, 0x7a7c, 0x7b5c, 0x7c29, 0x7ce3, + 0x7d89, 0x7e1d, 0x7e9c, 0x7f09, 0x7f61, 0x7fa6, 0x7fd8, 0x7ff5, + 0x7fff, 0x7ff5, 0x7fd8, 0x7fa6, 0x7f61, 0x7f09, 0x7e9c, 0x7e1d, + 0x7d89, 0x7ce3, 0x7c29, 0x7b5c, 0x7a7c, 0x7989, 0x7884, 0x776b, + 0x7641, 0x7504, 0x73b5, 0x7254, 0x70e2, 0x6f5e, 0x6dc9, 0x6c23, + 0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f1, 0x60eb, 0x5ed7, 0x5cb3, + 0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, + 0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33df, + 0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f1a, 0x1c0b, + 0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8c, 0x096a, 0x0648, 0x0324, + 0x0000, -0x0324, -0x0648, -0x096b, -0x0c8c, -0x0fab, -0x12c8, -0x15e2, + -0x18f9, -0x1c0b, -0x1f1a, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11, + -0x30fb, -0x33df, -0x36ba, -0x398d, -0x3c56, -0x3f17, -0x41ce, -0x447a, + -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842, + -0x5a82, -0x5cb3, -0x5ed7, -0x60ec, -0x62f1, -0x64e8, -0x66cf, -0x68a6, + -0x6a6d, -0x6c23, -0x6dc9, -0x6f5e, -0x70e2, -0x7254, -0x73b5, -0x7504, + -0x7641, -0x776b, -0x7884, -0x7989, -0x7a7c, -0x7b5c, -0x7c29, -0x7ce3, + -0x7d89, -0x7e1d, -0x7e9c, -0x7f09, -0x7f61, -0x7fa6, -0x7fd8, -0x7ff5, + -0x7fff, -0x7ff5, -0x7fd8, -0x7fa6, -0x7f61, -0x7f09, -0x7e9c, -0x7e1d, + -0x7d89, -0x7ce3, -0x7c29, -0x7b5c, -0x7a7c, -0x7989, -0x7883, -0x776b, + -0x7641, -0x7504, -0x73b5, -0x7254, -0x70e2, -0x6f5e, -0x6dc9, -0x6c23, + -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f1, -0x60eb, -0x5ed7, -0x5cb3, + -0x5a82, -0x5842, -0x55f5, -0x539a, -0x5133, -0x4ebf, -0x4c3f, -0x49b3, + -0x471c, -0x447a, -0x41cd, -0x3f17, -0x3c56, -0x398c, -0x36b9, -0x33de, + -0x30fb, -0x2e10, -0x2b1f, -0x2826, -0x2527, -0x2223, -0x1f19, -0x1c0b, + -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324 +}; + +static const uint8 ST010_ArcTan[32][32] = +{ + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, + { 0x80, 0xa0, 0xad, 0xb3, 0xb6, 0xb8, 0xb9, 0xba, 0xbb, 0xbb, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf }, + { 0x80, 0x93, 0xa0, 0xa8, 0xad, 0xb0, 0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd }, + { 0x80, 0x8d, 0x98, 0xa0, 0xa6, 0xaa, 0xad, 0xb0, 0xb1, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb7, 0xb8, + 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc }, + { 0x80, 0x8a, 0x93, 0x9a, 0xa0, 0xa5, 0xa8, 0xab, 0xad, 0xaf, 0xb0, 0xb2, 0xb3, 0xb4, 0xb5, 0xb5, + 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb }, + { 0x80, 0x88, 0x90, 0x96, 0x9b, 0xa0, 0xa4, 0xa7, 0xa9, 0xab, 0xad, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, + 0xb4, 0xb4, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9 }, + { 0x80, 0x87, 0x8d, 0x93, 0x98, 0x9c, 0xa0, 0xa3, 0xa6, 0xa8, 0xaa, 0xac, 0xad, 0xae, 0xb0, 0xb0, + 0xb1, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8 }, + { 0x80, 0x86, 0x8b, 0x90, 0x95, 0x99, 0x9d, 0xa0, 0xa3, 0xa5, 0xa7, 0xa9, 0xaa, 0xac, 0xad, 0xae, + 0xaf, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7 }, + { 0x80, 0x85, 0x8a, 0x8f, 0x93, 0x97, 0x9a, 0x9d, 0xa0, 0xa2, 0xa5, 0xa6, 0xa8, 0xaa, 0xab, 0xac, + 0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5 }, + { 0x80, 0x85, 0x89, 0x8d, 0x91, 0x95, 0x98, 0x9b, 0x9e, 0xa0, 0xa0, 0xa4, 0xa6, 0xa7, 0xa9, 0xaa, + 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4 }, + { 0x80, 0x84, 0x88, 0x8c, 0x90, 0x93, 0x96, 0x99, 0x9b, 0x9e, 0xa0, 0xa2, 0xa4, 0xa5, 0xa7, 0xa8, + 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3 }, + { 0x80, 0x84, 0x87, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5, 0xa6, + 0xa7, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2 }, + { 0x80, 0x83, 0x87, 0x8a, 0x8d, 0x90, 0x93, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1 }, + { 0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x94, 0x96, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa2, 0xa3, + 0xa4, 0xa5, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xb0 }, + { 0x80, 0x83, 0x86, 0x89, 0x8b, 0x8e, 0x90, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa1, + 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf }, + { 0x80, 0x83, 0x85, 0x88, 0x8b, 0x8d, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9b, 0x9d, 0x9f, 0xa0, + 0xa1, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae }, + { 0x80, 0x83, 0x85, 0x88, 0x8a, 0x8c, 0x8f, 0x91, 0x93, 0x95, 0x97, 0x99, 0x9a, 0x9c, 0x9d, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa5, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xab, 0xac, 0xad }, + { 0x80, 0x82, 0x85, 0x87, 0x89, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x97, 0x99, 0x9b, 0x9c, 0x9d, + 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac }, + { 0x80, 0x82, 0x85, 0x87, 0x89, 0x8b, 0x8d, 0x8f, 0x91, 0x93, 0x95, 0x96, 0x98, 0x99, 0x9b, 0x9c, + 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab }, + { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x9a, 0x9b, + 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa }, + { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x99, 0x9a, + 0x9b, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9 }, + { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8f, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x99, + 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8 }, + { 0x80, 0x82, 0x84, 0x86, 0x87, 0x89, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x98, + 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7 }, + { 0x80, 0x82, 0x84, 0x85, 0x87, 0x89, 0x8a, 0x8c, 0x8e, 0x8f, 0x91, 0x92, 0x94, 0x95, 0x96, 0x98, + 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6 }, + { 0x80, 0x82, 0x83, 0x85, 0x87, 0x88, 0x8a, 0x8c, 0x8d, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5 }, + { 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4 }, + { 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x89, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x95, + 0x96, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4 }, + { 0x80, 0x82, 0x83, 0x85, 0x86, 0x87, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93, 0x95, + 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2, 0xa3 }, + { 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x89, 0x8a, 0x8b, 0x8d, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2 }, + { 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x88, 0x8a, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa1 }, + { 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8b, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93, + 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1 }, + { 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0 } +}; + +// Mode 7 scaling constants for all raster lines +static const int16 ST010_M7Scale[176] = +{ + 0x0380, 0x0325, 0x02da, 0x029c, 0x0268, 0x023b, 0x0215, 0x01f3, + 0x01d5, 0x01bb, 0x01a3, 0x018e, 0x017b, 0x016a, 0x015a, 0x014b, + 0x013e, 0x0132, 0x0126, 0x011c, 0x0112, 0x0109, 0x0100, 0x00f8, + 0x00f0, 0x00e9, 0x00e3, 0x00dc, 0x00d6, 0x00d1, 0x00cb, 0x00c6, + 0x00c1, 0x00bd, 0x00b8, 0x00b4, 0x00b0, 0x00ac, 0x00a8, 0x00a5, + 0x00a2, 0x009e, 0x009b, 0x0098, 0x0095, 0x0093, 0x0090, 0x008d, + 0x008b, 0x0088, 0x0086, 0x0084, 0x0082, 0x0080, 0x007e, 0x007c, + 0x007a, 0x0078, 0x0076, 0x0074, 0x0073, 0x0071, 0x006f, 0x006e, + 0x006c, 0x006b, 0x0069, 0x0068, 0x0067, 0x0065, 0x0064, 0x0063, + 0x0062, 0x0060, 0x005f, 0x005e, 0x005d, 0x005c, 0x005b, 0x005a, + 0x0059, 0x0058, 0x0057, 0x0056, 0x0055, 0x0054, 0x0053, 0x0052, + 0x0051, 0x0051, 0x0050, 0x004f, 0x004e, 0x004d, 0x004d, 0x004c, + 0x004b, 0x004b, 0x004a, 0x0049, 0x0048, 0x0048, 0x0047, 0x0047, + 0x0046, 0x0045, 0x0045, 0x0044, 0x0044, 0x0043, 0x0042, 0x0042, + 0x0041, 0x0041, 0x0040, 0x0040, 0x003f, 0x003f, 0x003e, 0x003e, + 0x003d, 0x003d, 0x003c, 0x003c, 0x003b, 0x003b, 0x003a, 0x003a, + 0x003a, 0x0039, 0x0039, 0x0038, 0x0038, 0x0038, 0x0037, 0x0037, + 0x0036, 0x0036, 0x0036, 0x0035, 0x0035, 0x0035, 0x0034, 0x0034, + 0x0034, 0x0033, 0x0033, 0x0033, 0x0032, 0x0032, 0x0032, 0x0031, + 0x0031, 0x0031, 0x0030, 0x0030, 0x0030, 0x0030, 0x002f, 0x002f, + 0x002f, 0x002e, 0x002e, 0x002e, 0x002e, 0x002d, 0x002d, 0x002d, + 0x002d, 0x002c, 0x002c, 0x002c, 0x002c, 0x002b, 0x002b, 0x002b +}; + +#ifndef PI +#define PI 3.1415926535897932384626433832795 +#endif + +#define ST010_WORD(offset) (Memory.SRAM[offset + 1] << 8) | Memory.SRAM[offset] + + +static int16 ST010_Sin (int16 Theta) +{ + return (ST010_SinTable[(Theta >> 8) & 0xff]); +} + +static int16 ST010_Cos (int16 Theta) +{ + return (ST010_SinTable[((Theta + 0x4000) >> 8) & 0xff]); +} + +static void ST010_OP01 (int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &Quadrant, int16 &Theta) +{ + if ((x0 < 0) && (y0 < 0)) + { + x1 = -x0; + y1 = -y0; + Quadrant = -0x8000; + } + else + if (x0 < 0) + { + x1 = y0; + y1 = -x0; + Quadrant = -0x4000; + } + else + if (y0 < 0) + { + x1 = -y0; + y1 = x0; + Quadrant = 0x4000; + } + else + { + x1 = x0; + y1 = y0; + Quadrant = 0x0000; + } + + while ((x1 > 0x1f) || (y1 > 0x1f)) + { + if (x1 > 1) + x1 >>= 1; + if (y1 > 1) + y1 >>= 1; + } + + if (y1 == 0) + Quadrant += 0x4000; + + Theta = (ST010_ArcTan[y1][x1] << 8) ^ Quadrant; +} + +static void ST010_Scale (int16 Multiplier, int16 X0, int16 Y0, int32 &X1, int32 &Y1) +{ + X1 = X0 * Multiplier << 1; + Y1 = Y0 * Multiplier << 1; +} + +static void ST010_Multiply (int16 Multiplicand, int16 Multiplier, int32 &Product) +{ + Product = Multiplicand * Multiplier << 1; +} + +static void ST010_Rotate (int16 Theta, int16 X0, int16 Y0, int16 &X1, int16 &Y1) +{ + X1 = (Y0 * ST010_Sin(Theta) >> 15) + (X0 * ST010_Cos(Theta) >> 15); + Y1 = (Y0 * ST010_Cos(Theta) >> 15) - (X0 * ST010_Sin(Theta) >> 15); +} + +static void ST010_SortDrivers (uint16 Positions, uint16 Places[32], uint16 Drivers[32]) +{ + bool Sorted; + uint16 Temp; + + if (Positions > 1) + { + do + { + Sorted = true; + + for (int i = 0; i < Positions - 1; i++) + { + if (Places[i] < Places[i + 1]) + { + Temp = Places[i + 1]; + Places[i + 1] = Places[i]; + Places[i] = Temp; + + Temp = Drivers[i + 1]; + Drivers[i + 1] = Drivers[i]; + Drivers[i] = Temp; + + Sorted = false; + } + } + + Positions--; + } + while (!Sorted); + } +} + +/* +static void SETA_Distance (int16 Y0, int16 X0, int16 &Distance) +{ + if (X0 < 0) + X0 = -X0; + if (Y0 < 0) + Y0 = -Y0; + + Distance = ((X0 * 0x7af0) + 0x4000) >> 15; +} +*/ + +uint8 S9xGetST010 (uint32 Address) +{ + if (!(Address & 0x80000)) + return (0x80); + + if ((Address & 0xFFF) == 0x20) + return (ST010.op_reg); + + if ((Address & 0xFFF) == 0x21) + return (ST010.execute); + + return (Memory.SRAM[Address & Memory.SRAMMask]); +} + +void S9xSetST010 (uint32 Address, uint8 Byte) +{ + if (!(Address & 0x80000)) + { + ST010.control_enable = TRUE; + return; + } + +#ifdef DEBUGGER + printf("Write %06X:%02X\n", Address, Byte); +#endif + + if ((Address & 0xFFF) == 0x20 && ST010.control_enable) + ST010.op_reg = Byte; + + if ((Address & 0xFFF) == 0x21 && ST010.control_enable) + ST010.execute = Byte; + else + Memory.SRAM[Address & Memory.SRAMMask] = Byte; + + if (ST010.execute & 0x80) + { + switch (ST010.op_reg) + { + // Sorts Driver Placements + // + // Input + // 0x0024-0x0025 : Positions + // 0x0040-0x007f : Places + // 0x0080-0x00ff : Drivers + // Output + // 0x0040-0x007f : Places + // 0x0080-0x00ff : Drivers + // + case 0x02: + { + #ifdef FAST_LSB_WORD_ACCESS + ST010_SortDrivers(*(uint16 *) (Memory.SRAM + 0x0024), (uint16 *) (Memory.SRAM + 0x0040), (uint16 *) (Memory.SRAM + 0x0080)); + #else + uint16 Places[32]; + uint16 Positions = ST010_WORD(0x0024); + int Pos, Offset; + + Offset = 0; + + for (Pos = 0; Pos < Positions; Pos++) + { + Places[Pos] = ST010_WORD(0x0040 + Offset); + Offset += 2; + } + + ST010_SortDrivers(Positions, Places, (uint16 *) (Memory.SRAM + 0x0080)); + + Offset = 0; + + for (Pos = 0; Pos < Positions; Pos++) + { + Memory.SRAM[0x0040 + Offset] = (uint8) (Places[Pos]); + Memory.SRAM[0x0041 + Offset] = (uint8) (Places[Pos] >> 8); + Offset += 2; + } + #endif + break; + } + + // Two Dimensional Coordinate Scale + // + // Input + // 0x0000-0x0001 : X0 (signed) + // 0x0002-0x0003 : Y0 (signed) + // 0x0004-0x0005 : Multiplier (signed) + // Output + // 0x0010-0x0013 : X1 (signed) + // 0x0014-0x0017 : Y1 (signed) + // + case 0x03: + { + #ifdef FAST_LSB_WORD_ACCESS + ST010_Scale(*(int16 *) &Memory.SRAM[0x0004], *(int16 *) &Memory.SRAM[0x0000], *(int16 *) &Memory.SRAM[0x0002], (int32 &) Memory.SRAM[0x0010], (int32 &) Memory.SRAM[0x0014]); + #else + int32 x1, y1; + + ST010_Scale(ST010_WORD(0x0004), ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1); + + Memory.SRAM[0x0010] = (uint8) (x1); + Memory.SRAM[0x0011] = (uint8) (x1 >> 8); + Memory.SRAM[0x0012] = (uint8) (x1 >> 16); + Memory.SRAM[0x0013] = (uint8) (x1 >> 24); + Memory.SRAM[0x0014] = (uint8) (y1); + Memory.SRAM[0x0015] = (uint8) (y1 >> 8); + Memory.SRAM[0x0016] = (uint8) (y1 >> 16); + Memory.SRAM[0x0017] = (uint8) (y1 >> 24); + #endif + break; + } + + // 16-bit Multiplication + // + // Input + // 0x0000-0x0001 : Multiplcand (signed) + // 0x0002-0x0003 : Multiplier (signed) + // Output + // 0x0010-0x0013 : Product (signed) + // + case 0x06: + { + #ifdef FAST_LSB_WORD_ACCESS + ST010_Multiply(*(int16 *) &Memory.SRAM[0x0000], *(int16 *) &Memory.SRAM[0x0002], (int32 &) Memory.SRAM[0x0010]); + #else + int32 Product; + + ST010_Multiply(ST010_WORD(0x0000), ST010_WORD(0x0002), Product); + + Memory.SRAM[0x0010] = (uint8) (Product); + Memory.SRAM[0x0011] = (uint8) (Product >> 8); + Memory.SRAM[0x0012] = (uint8) (Product >> 16); + Memory.SRAM[0x0013] = (uint8) (Product >> 24); + #endif + break; + } + + // Mode 7 Raster Data Calculation + // + // Input + // 0x0000-0x0001 : Angle (signed) + // Output + // 0x00f0-0x024f : Mode 7 Matrix A + // 0x0250-0x03af : Mode 7 Matrix B + // 0x03b0-0x050f : Mode 7 Matrix C + // 0x0510-0x066f : Mode 7 Matrix D + // + case 0x07: + { + int16 data; + int32 offset = 0; + int16 Theta = ST010_WORD(0x0000); + + for (int32 line = 0; line < 176; line++) + { + // Calculate Mode 7 Matrix A/D data + data = ST010_M7Scale[line] * ST010_Cos(Theta) >> 15; + + Memory.SRAM[0x00f0 + offset] = (uint8) (data); + Memory.SRAM[0x00f1 + offset] = (uint8) (data >> 8); + Memory.SRAM[0x0510 + offset] = (uint8) (data); + Memory.SRAM[0x0511 + offset] = (uint8) (data >> 8); + + // Calculate Mode 7 Matrix B/C data + data = ST010_M7Scale[line] * ST010_Sin(Theta) >> 15; + + Memory.SRAM[0x0250 + offset] = (uint8) (data); + Memory.SRAM[0x0251 + offset] = (uint8) (data >> 8); + + if (data) + data = ~data; + + Memory.SRAM[0x03b0 + offset] = (uint8) (data); + Memory.SRAM[0x03b1 + offset] = (uint8) (data >> 8); + + offset += 2; + } + + // Shift Angle for use with Lookup table + Memory.SRAM[0x00] = Memory.SRAM[0x01]; + Memory.SRAM[0x01] = 0x00; + + break; + } + + // Two dimensional Coordinate Rotation + // + // Input + // 0x0000-0x0001 : X0 (signed) + // 0x0002-0x0003 : Y0 (signed) + // 0x0004-0x0005 : Angle (signed) + // Output + // 0x0010-0x0011 : X1 (signed) + // 0x0012-0x0013 : Y1 (signed) + // + case 0x08: + { + #ifdef FAST_LSB_WORD_ACCESS + ST010_Rotate(*(int16 *) &Memory.SRAM[0x0004], *(int16 *) &Memory.SRAM[0x0000], *(int16 *) &Memory.SRAM[0x0002], (int16 &) Memory.SRAM[0x0010], (int16 &) Memory.SRAM[0x0012]); + #else + int16 x1, y1; + + ST010_Rotate(ST010_WORD(0x0004), ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1); + + Memory.SRAM[0x0010] = (uint8) (x1); + Memory.SRAM[0x0011] = (uint8) (x1 >> 8); + Memory.SRAM[0x0012] = (uint8) (y1); + Memory.SRAM[0x0013] = (uint8) (y1 >> 8); + #endif + break; + } + + // Input + // 0x0000-0x0001 : DX (signed) + // 0x0002-0x0003 : DY (signed) + // Output + // 0x0010-0x0011 : Angle (signed) + // + case 0x01: + { + Memory.SRAM[0x0006] = Memory.SRAM[0x0002]; + Memory.SRAM[0x0007] = Memory.SRAM[0x0003]; + + #ifdef FAST_LSB_WORD_ACCESS + ST010_OP01(*(int16 *) &Memory.SRAM[0x0000], *(int16 *) &Memory.SRAM[0x0002], (int16 &) Memory.SRAM[0x0000], (int16 &) Memory.SRAM[0x0002], (int16 &) Memory.SRAM[0x0004], (int16 &) Memory.SRAM[0x0010]); + #else + int16 x1, y1, Quadrant, Theta; + + ST010_OP01(ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1, Quadrant, Theta); + + Memory.SRAM[0x0000] = (uint8) (x1); + Memory.SRAM[0x0001] = (uint8) (x1 >> 8); + Memory.SRAM[0x0002] = (uint8) (y1); + Memory.SRAM[0x0003] = (uint8) (y1 >> 8); + Memory.SRAM[0x0004] = (uint8) (Quadrant); + Memory.SRAM[0x0005] = (uint8) (Quadrant >> 8); + Memory.SRAM[0x0010] = (uint8) (Theta); + Memory.SRAM[0x0011] = (uint8) (Theta >> 8); + #endif + break; + } + + // calculate the vector length of (x, y) + case 0x04: + { + int16 square, x, y; + #ifdef FAST_LSB_WORD_ACCESS + x = *((int16 *) Memory.SRAM); + y = *((int16 *) &Memory.SRAM[2]); + #else + x = Memory.SRAM[0] | (Memory.SRAM[1] << 8); + y = Memory.SRAM[2] | (Memory.SRAM[3] << 8); + #endif + square = (int16) sqrt((double) (y * y + x * x)); + //SETA_Distance(x, y, square); + + #ifdef FAST_LSB_WORD_ACCESS + *((int16 *) &Memory.SRAM[0x10]) = square; + #else + Memory.SRAM[0x10] = (uint8) (square); + Memory.SRAM[0x11] = (uint8) (square >> 8); + #endif + break; + } + + // calculate AI orientation based on specific guidelines + case 0x05: + { + int32 dx, dy; + int16 a1, b1, c1; + uint16 o1; + bool wrap = false; + + // target (x, y) coordinates + int16 ypos_max = ST010_WORD(0x00C0); + int16 xpos_max = ST010_WORD(0x00C2); + + // current coordinates and direction + int32 ypos = Memory.SRAM[0xC4] | (Memory.SRAM[0xC5] << 8) | (Memory.SRAM[0xC6] << 16) | (Memory.SRAM[0xC7] << 24); + int32 xpos = Memory.SRAM[0xC8] | (Memory.SRAM[0xC9] << 8) | (Memory.SRAM[0xCA] << 16) | (Memory.SRAM[0xCB] << 24); + uint16 rot = Memory.SRAM[0xCC] | (Memory.SRAM[0xCD] << 8); + + // physics + uint16 speed = ST010_WORD(0x00D4); + uint16 accel = ST010_WORD(0x00D6); + uint16 speed_max = ST010_WORD(0x00D8); + + // special condition acknowledgment + int16 system = ST010_WORD(0x00DA); + int16 flags = ST010_WORD(0x00DC); + + // new target coordinates + int16 ypos_new = ST010_WORD(0x00DE); + int16 xpos_new = ST010_WORD(0x00E0); + + // mask upper bit + xpos_new &= 0x7FFF; + + // get the current distance + dx = xpos_max - (xpos >> 16); + dy = ypos_max - (ypos >> 16); + + // quirk: clear and move in9 + Memory.SRAM[0xD2] = 0xFF; + Memory.SRAM[0xD3] = 0xFF; + Memory.SRAM[0xDA] = 0; + Memory.SRAM[0xDB] = 0; + + // grab the target angle + ST010_OP01(dy, dx, a1, b1, c1, (int16 &) o1); + + // check for wrapping + //if ((o1 < 0x6000 && rot > 0xA000) || (rot < 0x6000 && o1 > 0xA000)) + //if (o1 < rot) + if (abs(o1 - rot) > 0x8000) + { + o1 += 0x8000; + rot += 0x8000; + wrap = true; + } + //o1 = 0x0000; + //rot = 0xFF00; + + uint16 old_speed; + + old_speed = speed; + + // special case + if (abs(o1 - rot) == 0x8000) + speed = 0x100; + // slow down for sharp curves + else + if (abs(o1 - rot) >= 0x1000) + { + uint32 slow = abs(o1 - rot); + slow >>= 4; // scaling + speed -= slow; + } + // otherwise accelerate + else + { + speed += accel; + if (speed > speed_max) + { + // clip speed + speed = speed_max; + } + } + + // prevent negative/positive overflow + if (abs(old_speed - speed) > 0x8000) + { + if (old_speed < speed) + speed = 0; + else + speed = 0xff00; + } + + // adjust direction by so many degrees + // be careful of negative adjustments + if ((o1 > rot && (o1 - rot) > 0x80) || (o1 < rot && (rot - o1) >= 0x80)) + { + if (o1 < rot) + rot -= 0x280; + else + if (o1 > rot) + rot += 0x280; + } + + // turn off wrapping + if (wrap) + rot -= 0x8000; + + // now check the distances (store for later) + dx = (xpos_max << 16) - xpos; + dy = (ypos_max << 16) - ypos; + dx >>= 16; + dy >>= 16; + + // if we're in so many units of the target, signal it + if ((system && (dy <= 6 && dy >= -8) && (dx <= 126 && dx >= -128)) || (!system && (dx <= 6 && dx >= -8) && (dy <= 126 && dy >= -128))) + { + // announce our new destination and flag it + xpos_max = xpos_new & 0x7FFF; + ypos_max = ypos_new; + flags |= 0x08; + } + + // update position + xpos -= (ST010_Cos(rot) * 0x400 >> 15) * (speed >> 8) << 1; + ypos -= (ST010_Sin(rot) * 0x400 >> 15) * (speed >> 8) << 1; + + // quirk: mask upper byte + xpos &= 0x1FFFFFFF; + ypos &= 0x1FFFFFFF; + + Memory.SRAM[0x00C0] = (uint8) (ypos_max); + Memory.SRAM[0x00C1] = (uint8) (ypos_max >> 8); + Memory.SRAM[0x00C2] = (uint8) (xpos_max); + Memory.SRAM[0x00C3] = (uint8) (xpos_max >> 8); + Memory.SRAM[0x00C4] = (uint8) (ypos); + Memory.SRAM[0x00C5] = (uint8) (ypos >> 8); + Memory.SRAM[0x00C6] = (uint8) (ypos >> 16); + Memory.SRAM[0x00C7] = (uint8) (ypos >> 24); + Memory.SRAM[0x00C8] = (uint8) (xpos); + Memory.SRAM[0x00C9] = (uint8) (xpos >> 8); + Memory.SRAM[0x00CA] = (uint8) (xpos >> 16); + Memory.SRAM[0x00CB] = (uint8) (xpos >> 24); + Memory.SRAM[0x00CC] = (uint8) (rot); + Memory.SRAM[0x00CD] = (uint8) (rot >> 8); + Memory.SRAM[0x00D4] = (uint8) (speed); + Memory.SRAM[0x00D5] = (uint8) (speed >> 8); + Memory.SRAM[0x00DC] = (uint8) (flags); + Memory.SRAM[0x00DD] = (uint8) (flags >> 8); + + break; + } + + default: + #ifdef DEBUGGER + printf("Unknown Op\n"); + #endif + break; + } + + // lower signal: op processed + ST010.op_reg = 0; + ST010.execute = 0; + } +} diff --git a/plugins/snes9x_gx/source/snes9x/seta011.cpp b/plugins/snes9x_gx/source/snes9x/seta011.cpp new file mode 100644 index 00000000..b49a8b8b --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/seta011.cpp @@ -0,0 +1,309 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "seta.h" + +static uint8 board[9][9]; // shougi playboard +static int line = 0; // line counter + + +uint8 S9xGetST011 (uint32 Address) +{ + uint8 t; + uint16 address = (uint16) Address & 0xFFFF; + + line++; + + // status check + if (address == 0x01) + t = 0xFF; + else + t = Memory.SRAM[address]; // read directly from s-ram + +#ifdef DEBUGGER + if (address < 0x150) + printf("ST011 R: %06X %02X\n", Address, t); +#endif + + return (t); +} + +void S9xSetST011 (uint32 Address, uint8 Byte) +{ + static bool reset = false; + uint16 address = (uint16) Address & 0xFFFF; + + line++; + + if (!reset) + { + // bootup values + ST011.waiting4command = true; + reset = true; + } + +#ifdef DEBUGGER + if (address < 0x150) + printf("ST011 W: %06X %02X\n", Address, Byte); +#endif + + Memory.SRAM[address] = Byte; + + // op commands/data goes through this address + if (address == 0x00) + { + // check for new commands + if (ST011.waiting4command) + { + ST011.waiting4command = false; + ST011.command = Byte; + ST011.in_index = 0; + ST011.out_index = 0; + + switch (ST011.command) + { + case 0x01: ST011.in_count = 12 * 10 + 8; break; + case 0x02: ST011.in_count = 4; break; + case 0x04: ST011.in_count = 0; break; + case 0x05: ST011.in_count = 0; break; + case 0x06: ST011.in_count = 0; break; + case 0x07: ST011.in_count = 0; break; + case 0x0E: ST011.in_count = 0; break; + default: ST011.waiting4command = true; break; + } + } + else + { + ST011.parameters[ST011.in_index] = Byte; + ST011.in_index++; + } + } + + if (ST011.in_count == ST011.in_index) + { + // actually execute the command + ST011.waiting4command = true; + ST011.out_index = 0; + + switch (ST011.command) + { + // unknown: download playboard + case 0x01: + // 9x9 board data: top to bottom, left to right + // Values represent piece types and ownership + for (int lcv = 0; lcv < 9; lcv++) + memcpy(board[lcv], ST011.parameters + lcv * 10, 9 * 1); + break; + + // unknown + case 0x02: + break; + + // unknown + case 0x04: + // outputs + Memory.SRAM[0x12C] = 0x00; + //Memory.SRAM[0x12D] = 0x00; + Memory.SRAM[0x12E] = 0x00; + break; + + // unknown + case 0x05: + // outputs + Memory.SRAM[0x12C] = 0x00; + //Memory.SRAM[0x12D] = 0x00; + Memory.SRAM[0x12E] = 0x00; + break; + + // unknown + case 0x06: + break; + + case 0x07: + break; + + // unknown + case 0x0E: + // outputs + Memory.SRAM[0x12C] = 0x00; + Memory.SRAM[0x12D] = 0x00; + break; + } + } +} diff --git a/plugins/snes9x_gx/source/snes9x/seta018.cpp b/plugins/snes9x_gx/source/snes9x/seta018.cpp new file mode 100644 index 00000000..24efb5c8 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/seta018.cpp @@ -0,0 +1,353 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "seta.h" + +static int line; // line counter + + +uint8 S9xGetST018 (uint32 Address) +{ + uint8 t = 0; + uint16 address = (uint16) Address & 0xFFFF; + + line++; + + // these roles may be flipped + // op output + if (address == 0x3804) + { + if (ST018.out_count) + { + t = (uint8) ST018.output[ST018.out_index]; + ST018.out_index++; + if (ST018.out_count == ST018.out_index) + ST018.out_count = 0; + } + else + t = 0x81; + } + // status register + else + if (address == 0x3800) + t = ST018.status; + +#ifdef DEBUGGER + printf("ST018 R: %06X %02X\n", Address, t); +#endif + + return (t); +} + +void S9xSetST018 (uint8 Byte, uint32 Address) +{ + static bool reset = false; + uint16 address = (uint16) Address & 0xFFFF; + +#ifdef DEBUGGER + printf("ST018 W: %06X %02X\n", Address, Byte); +#endif + + line++; + + if (!reset) + { + // bootup values + ST018.waiting4command = true; + ST018.part_command = 0; + reset = true; + } + + Memory.SRAM[address] = Byte; + + // default status for now + ST018.status = 0x00; + + // op data goes through this address + if (address == 0x3804) + { + // check for new commands: 3 bytes length + if (ST018.waiting4command && ST018.part_command == 2) + { + ST018.waiting4command = false; + ST018.in_index = 0; + ST018.out_index = 0; + ST018.part_command = 0; // 3-byte commands + ST018.pass = 0; // data streams into the chip + ST018.command <<= 8; + ST018.command |= Byte; + + switch (ST018.command & 0xFFFFFF) + { + case 0x0100: ST018.in_count = 0; break; + case 0xFF00: ST018.in_count = 0; break; + default: ST018.waiting4command = true; break; + } + } + else + if (ST018.waiting4command) + { + // 3-byte commands + ST018.part_command++; + ST018.command <<= 8; + ST018.command |= Byte; + } + } + // extra parameters + else + if (address == 0x3802) + { + ST018.parameters[ST018.in_index] = Byte; + ST018.in_index++; + } + + if (ST018.in_count == ST018.in_index) + { + // qctually execute the command + ST018.waiting4command = true; + ST018.in_index = 0; + ST018.out_index = 0; + + switch (ST018.command) + { + // hardware check? + case 0x0100: + ST018.waiting4command = false; + ST018.pass++; + + if (ST018.pass == 1) + { + ST018.in_count = 1; + ST018.out_count = 2; + + // Overload's research + ST018.output[0x00] = 0x81; + ST018.output[0x01] = 0x81; + } + else + { + //ST018.in_count = 1; + ST018.out_count = 3; + + // no reason to change this + //ST018.output[0x00] = 0x81; + //ST018.output[0x01] = 0x81; + ST018.output[0x02] = 0x81; + + // done processing requests + if (ST018.pass == 3) + ST018.waiting4command = true; + } + + break; + + // unknown: feels like a security detection + // format identical to 0x0100 + case 0xFF00: + ST018.waiting4command = false; + ST018.pass++; + + if (ST018.pass == 1) + { + ST018.in_count = 1; + ST018.out_count = 2; + + // Overload's research + ST018.output[0x00] = 0x81; + ST018.output[0x01] = 0x81; + } + else + { + //ST018.in_count = 1; + ST018.out_count = 3; + + // no reason to change this + //ST018.output[0x00] = 0x81; + //ST018.output[0x01] = 0x81; + ST018.output[0x02] = 0x81; + + // done processing requests + if (ST018.pass == 3) + ST018.waiting4command = true; + } + + break; + } + } +} diff --git a/plugins/snes9x_gx/source/snes9x/snapshot.cpp b/plugins/snes9x_gx/source/snes9x/snapshot.cpp new file mode 100644 index 00000000..13934f04 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/snapshot.cpp @@ -0,0 +1,2250 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#include <assert.h> +#include "snes9x.h" +#include "memmap.h" +#include "dma.h" +#include "apu/apu.h" +#include "fxinst.h" +#include "fxemu.h" +#include "sdd1.h" +#include "srtc.h" +#include "snapshot.h" +#include "controls.h" +#include "movie.h" +#include "display.h" +#include "language.h" + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +typedef struct +{ + int offset; + int offset2; + int size; + int type; + uint16 debuted_in; + uint16 deleted_in; + const char *name; +} FreezeData; + +enum +{ + INT_V, + uint8_ARRAY_V, + uint16_ARRAY_V, + uint32_ARRAY_V, + uint8_INDIR_ARRAY_V, + uint16_INDIR_ARRAY_V, + uint32_INDIR_ARRAY_V, + POINTER_V +}; + +#define COUNT(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0])) +#define Offset(field, structure) ((int) (((char *) (&(((structure) NULL)->field))) - ((char *) NULL))) +#define OFFSET(f) Offset(f, STRUCT *) +#define DUMMY(f) Offset(f, struct Obsolete *) +#define DELETED(f) (-1) + +#define INT_ENTRY(save_version_introduced, field) \ +{ \ + OFFSET(field), \ + 0, \ + sizeof(((STRUCT *) NULL)->field), \ + INT_V, \ + save_version_introduced, \ + 9999, \ + #field \ +} + +#define ARRAY_ENTRY(save_version_introduced, field, count, elemType) \ +{ \ + OFFSET(field), \ + 0, \ + count, \ + elemType, \ + save_version_introduced, \ + 9999, \ + #field \ +} + +#define POINTER_ENTRY(save_version_introduced, field, relativeToField) \ +{ \ + OFFSET(field), \ + OFFSET(relativeToField), \ + 4, \ + POINTER_V, \ + save_version_introduced, \ + 9999, \ + #field \ +} + +#define OBSOLETE_INT_ENTRY(save_version_introduced, save_version_removed, field) \ +{ \ + DUMMY(field), \ + 0, \ + sizeof(((struct Obsolete *) NULL)->field), \ + INT_V, \ + save_version_introduced, \ + save_version_removed, \ + #field \ +} + +#define OBSOLETE_ARRAY_ENTRY(save_version_introduced, save_version_removed, field, count, elemType) \ +{ \ + DUMMY(field), \ + 0, \ + count, \ + elemType, \ + save_version_introduced, \ + save_version_removed, \ + #field \ +} + +#define OBSOLETE_POINTER_ENTRY(save_version_introduced, save_version_removed, field, relativeToField) \ +{ \ + DUMMY(field), \ + DUMMY(relativeToField), \ + 4, \ + POINTER_V, \ + save_version_introduced, \ + save_version_removed, \ + #field \ +} + +#define DELETED_INT_ENTRY(save_version_introduced, save_version_removed, field, size) \ +{ \ + DELETED(field), \ + 0, \ + size, \ + INT_V, \ + save_version_introduced, \ + save_version_removed, \ + #field \ +} + +#define DELETED_ARRAY_ENTRY(save_version_introduced, save_version_removed, field, count, elemType) \ +{ \ + DELETED(field), \ + 0, \ + count, \ + elemType, \ + save_version_introduced, \ + save_version_removed, \ + #field \ +} + +#define DELETED_POINTER_ENTRY(save_version_introduced, save_version_removed, field, relativeToField) \ +{ \ + DELETED(field), \ + DELETED(relativeToField), \ + 4, \ + POINTER_V, \ + save_version_introduced, \ + save_version_removed, \ + #field \ +} + +struct SDMASnapshot +{ + struct SDMA dma[8]; +}; + +struct SnapshotMovieInfo +{ + uint32 MovieInputDataSize; +}; + +struct SnapshotScreenshotInfo +{ + uint16 Width; + uint16 Height; + uint8 Interlaced; + uint8 Data[MAX_SNES_WIDTH * MAX_SNES_HEIGHT * 3]; +}; + +static struct Obsolete +{ + uint8 reserved; +} Obsolete; + +#define STRUCT struct SCPUState + +static FreezeData SnapCPU[] = +{ + INT_ENTRY(6, Cycles), + INT_ENTRY(6, PrevCycles), + INT_ENTRY(6, V_Counter), + INT_ENTRY(6, Flags), + INT_ENTRY(6, IRQActive), + INT_ENTRY(6, IRQPending), + INT_ENTRY(6, MemSpeed), + INT_ENTRY(6, MemSpeedx2), + INT_ENTRY(6, FastROMSpeed), + INT_ENTRY(6, InDMA), + INT_ENTRY(6, InHDMA), + INT_ENTRY(6, InDMAorHDMA), + INT_ENTRY(6, InWRAMDMAorHDMA), + INT_ENTRY(6, HDMARanInDMA), + INT_ENTRY(6, WhichEvent), + INT_ENTRY(6, NextEvent), + INT_ENTRY(6, WaitingForInterrupt), + INT_ENTRY(6, WaitAddress), + INT_ENTRY(6, WaitCounter), + INT_ENTRY(6, PBPCAtOpcodeStart) +}; + +#undef STRUCT +#define STRUCT struct SRegisters + +static FreezeData SnapRegisters[] = +{ + INT_ENTRY(6, PB), + INT_ENTRY(6, DB), + INT_ENTRY(6, P.W), + INT_ENTRY(6, A.W), + INT_ENTRY(6, D.W), + INT_ENTRY(6, S.W), + INT_ENTRY(6, X.W), + INT_ENTRY(6, Y.W), + INT_ENTRY(6, PCw) +}; + +#undef STRUCT +#define STRUCT struct SPPU + +static FreezeData SnapPPU[] = +{ + INT_ENTRY(6, VMA.High), + INT_ENTRY(6, VMA.Increment), + INT_ENTRY(6, VMA.Address), + INT_ENTRY(6, VMA.Mask1), + INT_ENTRY(6, VMA.FullGraphicCount), + INT_ENTRY(6, VMA.Shift), + INT_ENTRY(6, WRAM), +#define O(N) \ + INT_ENTRY(6, BG[N].SCBase), \ + INT_ENTRY(6, BG[N].HOffset), \ + INT_ENTRY(6, BG[N].VOffset), \ + INT_ENTRY(6, BG[N].BGSize), \ + INT_ENTRY(6, BG[N].NameBase), \ + INT_ENTRY(6, BG[N].SCSize) + O(0), O(1), O(2), O(3), +#undef O + INT_ENTRY(6, BGMode), + INT_ENTRY(6, BG3Priority), + INT_ENTRY(6, CGFLIP), + INT_ENTRY(6, CGFLIPRead), + INT_ENTRY(6, CGADD), + ARRAY_ENTRY(6, CGDATA, 256, uint16_ARRAY_V), +#define O(N) \ + INT_ENTRY(6, OBJ[N].HPos), \ + INT_ENTRY(6, OBJ[N].VPos), \ + INT_ENTRY(6, OBJ[N].HFlip), \ + INT_ENTRY(6, OBJ[N].VFlip), \ + INT_ENTRY(6, OBJ[N].Name), \ + INT_ENTRY(6, OBJ[N].Priority), \ + INT_ENTRY(6, OBJ[N].Palette), \ + INT_ENTRY(6, OBJ[N].Size) + O( 0), O( 1), O( 2), O( 3), O( 4), O( 5), O( 6), O( 7), + O( 8), O( 9), O( 10), O( 11), O( 12), O( 13), O( 14), O( 15), + O( 16), O( 17), O( 18), O( 19), O( 20), O( 21), O( 22), O( 23), + O( 24), O( 25), O( 26), O( 27), O( 28), O( 29), O( 30), O( 31), + O( 32), O( 33), O( 34), O( 35), O( 36), O( 37), O( 38), O( 39), + O( 40), O( 41), O( 42), O( 43), O( 44), O( 45), O( 46), O( 47), + O( 48), O( 49), O( 50), O( 51), O( 52), O( 53), O( 54), O( 55), + O( 56), O( 57), O( 58), O( 59), O( 60), O( 61), O( 62), O( 63), + O( 64), O( 65), O( 66), O( 67), O( 68), O( 69), O( 70), O( 71), + O( 72), O( 73), O( 74), O( 75), O( 76), O( 77), O( 78), O( 79), + O( 80), O( 81), O( 82), O( 83), O( 84), O( 85), O( 86), O( 87), + O( 88), O( 89), O( 90), O( 91), O( 92), O( 93), O( 94), O( 95), + O( 96), O( 97), O( 98), O( 99), O(100), O(101), O(102), O(103), + O(104), O(105), O(106), O(107), O(108), O(109), O(110), O(111), + O(112), O(113), O(114), O(115), O(116), O(117), O(118), O(119), + O(120), O(121), O(122), O(123), O(124), O(125), O(126), O(127), +#undef O + INT_ENTRY(6, OBJThroughMain), + INT_ENTRY(6, OBJThroughSub), + INT_ENTRY(6, OBJAddition), + INT_ENTRY(6, OBJNameBase), + INT_ENTRY(6, OBJNameSelect), + INT_ENTRY(6, OBJSizeSelect), + INT_ENTRY(6, OAMAddr), + INT_ENTRY(6, SavedOAMAddr), + INT_ENTRY(6, OAMPriorityRotation), + INT_ENTRY(6, OAMFlip), + INT_ENTRY(6, OAMReadFlip), + INT_ENTRY(6, OAMTileAddress), + INT_ENTRY(6, OAMWriteRegister), + ARRAY_ENTRY(6, OAMData, 512 + 32, uint8_ARRAY_V), + INT_ENTRY(6, FirstSprite), + INT_ENTRY(6, LastSprite), + INT_ENTRY(6, HTimerEnabled), + INT_ENTRY(6, VTimerEnabled), + INT_ENTRY(6, HTimerPosition), + INT_ENTRY(6, VTimerPosition), + INT_ENTRY(6, IRQHBeamPos), + INT_ENTRY(6, IRQVBeamPos), + INT_ENTRY(6, HBeamFlip), + INT_ENTRY(6, VBeamFlip), + INT_ENTRY(6, HBeamPosLatched), + INT_ENTRY(6, VBeamPosLatched), + INT_ENTRY(6, GunHLatch), + INT_ENTRY(6, GunVLatch), + INT_ENTRY(6, HVBeamCounterLatched), + INT_ENTRY(6, Mode7HFlip), + INT_ENTRY(6, Mode7VFlip), + INT_ENTRY(6, Mode7Repeat), + INT_ENTRY(6, MatrixA), + INT_ENTRY(6, MatrixB), + INT_ENTRY(6, MatrixC), + INT_ENTRY(6, MatrixD), + INT_ENTRY(6, CentreX), + INT_ENTRY(6, CentreY), + INT_ENTRY(6, M7HOFS), + INT_ENTRY(6, M7VOFS), + INT_ENTRY(6, Mosaic), + INT_ENTRY(6, MosaicStart), + ARRAY_ENTRY(6, BGMosaic, 4, uint8_ARRAY_V), + INT_ENTRY(6, Window1Left), + INT_ENTRY(6, Window1Right), + INT_ENTRY(6, Window2Left), + INT_ENTRY(6, Window2Right), + INT_ENTRY(6, RecomputeClipWindows), +#define O(N) \ + INT_ENTRY(6, ClipCounts[N]), \ + INT_ENTRY(6, ClipWindowOverlapLogic[N]), \ + INT_ENTRY(6, ClipWindow1Enable[N]), \ + INT_ENTRY(6, ClipWindow2Enable[N]), \ + INT_ENTRY(6, ClipWindow1Inside[N]), \ + INT_ENTRY(6, ClipWindow2Inside[N]) + O(0), O(1), O(2), O(3), O(4), O(5), +#undef O + INT_ENTRY(6, ForcedBlanking), + INT_ENTRY(6, FixedColourRed), + INT_ENTRY(6, FixedColourGreen), + INT_ENTRY(6, FixedColourBlue), + INT_ENTRY(6, Brightness), + INT_ENTRY(6, ScreenHeight), + INT_ENTRY(6, Need16x8Mulitply), + INT_ENTRY(6, BGnxOFSbyte), + INT_ENTRY(6, M7byte), + INT_ENTRY(6, HDMA), + INT_ENTRY(6, HDMAEnded), + INT_ENTRY(6, OpenBus1), + INT_ENTRY(6, OpenBus2) +}; + +#undef STRUCT +#define STRUCT struct SDMASnapshot + +static FreezeData SnapDMA[] = +{ +#define O(N) \ + INT_ENTRY(6, dma[N].ReverseTransfer), \ + INT_ENTRY(6, dma[N].HDMAIndirectAddressing), \ + INT_ENTRY(6, dma[N].UnusedBit43x0), \ + INT_ENTRY(6, dma[N].AAddressFixed), \ + INT_ENTRY(6, dma[N].AAddressDecrement), \ + INT_ENTRY(6, dma[N].TransferMode), \ + INT_ENTRY(6, dma[N].BAddress), \ + INT_ENTRY(6, dma[N].AAddress), \ + INT_ENTRY(6, dma[N].ABank), \ + INT_ENTRY(6, dma[N].DMACount_Or_HDMAIndirectAddress), \ + INT_ENTRY(6, dma[N].IndirectBank), \ + INT_ENTRY(6, dma[N].Address), \ + INT_ENTRY(6, dma[N].Repeat), \ + INT_ENTRY(6, dma[N].LineCount), \ + INT_ENTRY(6, dma[N].UnknownByte), \ + INT_ENTRY(6, dma[N].DoTransfer) + O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7) +#undef O +}; + +#undef STRUCT +#define STRUCT struct SControlSnapshot + +static FreezeData SnapControls[] = +{ + INT_ENTRY(6, ver), + ARRAY_ENTRY(6, port1_read_idx, 2, uint8_ARRAY_V), + ARRAY_ENTRY(6, dummy1, 4, uint8_ARRAY_V), + ARRAY_ENTRY(6, port2_read_idx, 2, uint8_ARRAY_V), + ARRAY_ENTRY(6, dummy2, 4, uint8_ARRAY_V), + ARRAY_ENTRY(6, mouse_speed, 2, uint8_ARRAY_V), + INT_ENTRY(6, justifier_select), + ARRAY_ENTRY(6, dummy3, 8, uint8_ARRAY_V), + INT_ENTRY(6, pad_read), + INT_ENTRY(6, pad_read_last), + ARRAY_ENTRY(6, internal, 60, uint8_ARRAY_V) +}; + +#undef STRUCT +#define STRUCT struct STimings + +static FreezeData SnapTimings[] = +{ + INT_ENTRY(6, H_Max_Master), + INT_ENTRY(6, H_Max), + INT_ENTRY(6, V_Max_Master), + INT_ENTRY(6, V_Max), + INT_ENTRY(6, HBlankStart), + INT_ENTRY(6, HBlankEnd), + INT_ENTRY(6, HDMAInit), + INT_ENTRY(6, HDMAStart), + INT_ENTRY(6, NMITriggerPos), + INT_ENTRY(6, WRAMRefreshPos), + INT_ENTRY(6, RenderPos), + INT_ENTRY(6, InterlaceField), + INT_ENTRY(6, DMACPUSync), + INT_ENTRY(6, NMIDMADelay), + INT_ENTRY(6, IRQPendCount), + INT_ENTRY(6, APUSpeedup) +}; + +#undef STRUCT +#define STRUCT struct FxRegs_s + +static FreezeData SnapFX[] = +{ + ARRAY_ENTRY(6, avReg, 16, uint32_ARRAY_V), + INT_ENTRY(6, vColorReg), + INT_ENTRY(6, vPlotOptionReg), + INT_ENTRY(6, vStatusReg), + INT_ENTRY(6, vPrgBankReg), + INT_ENTRY(6, vRomBankReg), + INT_ENTRY(6, vRamBankReg), + INT_ENTRY(6, vCacheBaseReg), + INT_ENTRY(6, vCacheFlags), + INT_ENTRY(6, vLastRamAdr), + POINTER_ENTRY(6, pvDreg, avRegAddr), + POINTER_ENTRY(6, pvSreg, avRegAddr), + INT_ENTRY(6, vRomBuffer), + INT_ENTRY(6, vPipe), + INT_ENTRY(6, vPipeAdr), + INT_ENTRY(6, vSign), + INT_ENTRY(6, vZero), + INT_ENTRY(6, vCarry), + INT_ENTRY(6, vOverflow), + INT_ENTRY(6, vErrorCode), + INT_ENTRY(6, vIllegalAddress), + INT_ENTRY(6, bBreakPoint), + INT_ENTRY(6, vBreakPoint), + INT_ENTRY(6, vStepPoint), + INT_ENTRY(6, nRamBanks), + INT_ENTRY(6, nRomBanks), + INT_ENTRY(6, vMode), + INT_ENTRY(6, vPrevMode), + POINTER_ENTRY(6, pvScreenBase, pvRam), +#define O(N) \ + POINTER_ENTRY(6, apvScreen[N], pvRam) + O( 0), O( 1), O( 2), O( 3), O( 4), O( 5), O( 6), O( 7), + O( 8), O( 9), O( 10), O( 11), O( 12), O( 13), O( 14), O( 15), + O( 16), O( 17), O( 18), O( 19), O( 20), O( 21), O( 22), O( 23), + O( 24), O( 25), O( 26), O( 27), O( 28), O( 29), O( 30), O( 31), +#undef O + ARRAY_ENTRY(6, x, 32, uint32_ARRAY_V), + INT_ENTRY(6, vScreenHeight), + INT_ENTRY(6, vScreenRealHeight), + INT_ENTRY(6, vPrevScreenHeight), + INT_ENTRY(6, vScreenSize), + POINTER_ENTRY(6, pvRamBank, apvRamBank), + POINTER_ENTRY(6, pvRomBank, apvRomBank), + POINTER_ENTRY(6, pvPrgBank, apvRomBank), +#define O(N) \ + POINTER_ENTRY(6, apvRamBank[N], pvRam) + O(0), O(1), O(2), O(3), +#undef O + INT_ENTRY(6, bCacheActive), + POINTER_ENTRY(6, pvCache, pvRegisters), + ARRAY_ENTRY(6, avCacheBackup, 512, uint8_ARRAY_V), + INT_ENTRY(6, vCounter), + INT_ENTRY(6, vInstCount), + INT_ENTRY(6, vSCBRDirty) +}; + +#undef STRUCT +#define STRUCT struct SSA1 + +static FreezeData SnapSA1[] = +{ + INT_ENTRY(6, CPUExecuting), + INT_ENTRY(6, ShiftedPB), + INT_ENTRY(6, ShiftedDB), + INT_ENTRY(6, Flags), + INT_ENTRY(6, IRQActive), + INT_ENTRY(6, Waiting), + INT_ENTRY(6, WaitingForInterrupt), + INT_ENTRY(6, WaitAddress), + INT_ENTRY(6, WaitCounter), + INT_ENTRY(6, PBPCAtOpcodeStart), + INT_ENTRY(6, Executing), + INT_ENTRY(6, overflow), + INT_ENTRY(6, in_char_dma), + INT_ENTRY(6, op1), + INT_ENTRY(6, op2), + INT_ENTRY(6, arithmetic_op), + INT_ENTRY(6, sum), + INT_ENTRY(6, VirtualBitmapFormat), + INT_ENTRY(6, variable_bit_pos) +}; + +#undef STRUCT +#define STRUCT struct SSA1Registers + +static FreezeData SnapSA1Registers[] = +{ + INT_ENTRY(6, PB), + INT_ENTRY(6, DB), + INT_ENTRY(6, P.W), + INT_ENTRY(6, A.W), + INT_ENTRY(6, D.W), + INT_ENTRY(6, S.W), + INT_ENTRY(6, X.W), + INT_ENTRY(6, Y.W), + INT_ENTRY(6, PCw) +}; + +#undef STRUCT +#define STRUCT struct SDSP1 + +static FreezeData SnapDSP1[] = +{ + INT_ENTRY(6, waiting4command), + INT_ENTRY(6, first_parameter), + INT_ENTRY(6, command), + INT_ENTRY(6, in_count), + INT_ENTRY(6, in_index), + INT_ENTRY(6, out_count), + INT_ENTRY(6, out_index), + ARRAY_ENTRY(6, parameters, 512, uint8_ARRAY_V), + ARRAY_ENTRY(6, output, 512, uint8_ARRAY_V), + INT_ENTRY(6, CentreX), + INT_ENTRY(6, CentreY), + INT_ENTRY(6, VOffset), + INT_ENTRY(6, VPlane_C), + INT_ENTRY(6, VPlane_E), + INT_ENTRY(6, SinAas), + INT_ENTRY(6, CosAas), + INT_ENTRY(6, SinAzs), + INT_ENTRY(6, CosAzs), + INT_ENTRY(6, SinAZS), + INT_ENTRY(6, CosAZS), + INT_ENTRY(6, SecAZS_C1), + INT_ENTRY(6, SecAZS_E1), + INT_ENTRY(6, SecAZS_C2), + INT_ENTRY(6, SecAZS_E2), + INT_ENTRY(6, Nx), + INT_ENTRY(6, Ny), + INT_ENTRY(6, Nz), + INT_ENTRY(6, Gx), + INT_ENTRY(6, Gy), + INT_ENTRY(6, Gz), + INT_ENTRY(6, C_Les), + INT_ENTRY(6, E_Les), + INT_ENTRY(6, G_Les), +#define O(N) \ + ARRAY_ENTRY(6, matrixA[N], 3, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, matrixB[N], 3, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, matrixC[N], 3, uint16_ARRAY_V) + O(0), O(1), O(2), +#undef O + INT_ENTRY(6, Op00Multiplicand), + INT_ENTRY(6, Op00Multiplier), + INT_ENTRY(6, Op00Result), + INT_ENTRY(6, Op20Multiplicand), + INT_ENTRY(6, Op20Multiplier), + INT_ENTRY(6, Op20Result), + INT_ENTRY(6, Op10Coefficient), + INT_ENTRY(6, Op10Exponent), + INT_ENTRY(6, Op10CoefficientR), + INT_ENTRY(6, Op10ExponentR), + INT_ENTRY(6, Op04Angle), + INT_ENTRY(6, Op04Radius), + INT_ENTRY(6, Op04Sin), + INT_ENTRY(6, Op04Cos), + INT_ENTRY(6, Op0CA), + INT_ENTRY(6, Op0CX1), + INT_ENTRY(6, Op0CY1), + INT_ENTRY(6, Op0CX2), + INT_ENTRY(6, Op0CY2), + INT_ENTRY(6, Op02FX), + INT_ENTRY(6, Op02FY), + INT_ENTRY(6, Op02FZ), + INT_ENTRY(6, Op02LFE), + INT_ENTRY(6, Op02LES), + INT_ENTRY(6, Op02AAS), + INT_ENTRY(6, Op02AZS), + INT_ENTRY(6, Op02VOF), + INT_ENTRY(6, Op02VVA), + INT_ENTRY(6, Op02CX), + INT_ENTRY(6, Op02CY), + INT_ENTRY(6, Op0AVS), + INT_ENTRY(6, Op0AA), + INT_ENTRY(6, Op0AB), + INT_ENTRY(6, Op0AC), + INT_ENTRY(6, Op0AD), + INT_ENTRY(6, Op06X), + INT_ENTRY(6, Op06Y), + INT_ENTRY(6, Op06Z), + INT_ENTRY(6, Op06H), + INT_ENTRY(6, Op06V), + INT_ENTRY(6, Op06M), + INT_ENTRY(6, Op01m), + INT_ENTRY(6, Op01Zr), + INT_ENTRY(6, Op01Xr), + INT_ENTRY(6, Op01Yr), + INT_ENTRY(6, Op11m), + INT_ENTRY(6, Op11Zr), + INT_ENTRY(6, Op11Xr), + INT_ENTRY(6, Op11Yr), + INT_ENTRY(6, Op21m), + INT_ENTRY(6, Op21Zr), + INT_ENTRY(6, Op21Xr), + INT_ENTRY(6, Op21Yr), + INT_ENTRY(6, Op0DX), + INT_ENTRY(6, Op0DY), + INT_ENTRY(6, Op0DZ), + INT_ENTRY(6, Op0DF), + INT_ENTRY(6, Op0DL), + INT_ENTRY(6, Op0DU), + INT_ENTRY(6, Op1DX), + INT_ENTRY(6, Op1DY), + INT_ENTRY(6, Op1DZ), + INT_ENTRY(6, Op1DF), + INT_ENTRY(6, Op1DL), + INT_ENTRY(6, Op1DU), + INT_ENTRY(6, Op2DX), + INT_ENTRY(6, Op2DY), + INT_ENTRY(6, Op2DZ), + INT_ENTRY(6, Op2DF), + INT_ENTRY(6, Op2DL), + INT_ENTRY(6, Op2DU), + INT_ENTRY(6, Op03F), + INT_ENTRY(6, Op03L), + INT_ENTRY(6, Op03U), + INT_ENTRY(6, Op03X), + INT_ENTRY(6, Op03Y), + INT_ENTRY(6, Op03Z), + INT_ENTRY(6, Op13F), + INT_ENTRY(6, Op13L), + INT_ENTRY(6, Op13U), + INT_ENTRY(6, Op13X), + INT_ENTRY(6, Op13Y), + INT_ENTRY(6, Op13Z), + INT_ENTRY(6, Op23F), + INT_ENTRY(6, Op23L), + INT_ENTRY(6, Op23U), + INT_ENTRY(6, Op23X), + INT_ENTRY(6, Op23Y), + INT_ENTRY(6, Op23Z), + INT_ENTRY(6, Op14Zr), + INT_ENTRY(6, Op14Xr), + INT_ENTRY(6, Op14Yr), + INT_ENTRY(6, Op14U), + INT_ENTRY(6, Op14F), + INT_ENTRY(6, Op14L), + INT_ENTRY(6, Op14Zrr), + INT_ENTRY(6, Op14Xrr), + INT_ENTRY(6, Op14Yrr), + INT_ENTRY(6, Op0EH), + INT_ENTRY(6, Op0EV), + INT_ENTRY(6, Op0EX), + INT_ENTRY(6, Op0EY), + INT_ENTRY(6, Op0BX), + INT_ENTRY(6, Op0BY), + INT_ENTRY(6, Op0BZ), + INT_ENTRY(6, Op0BS), + INT_ENTRY(6, Op1BX), + INT_ENTRY(6, Op1BY), + INT_ENTRY(6, Op1BZ), + INT_ENTRY(6, Op1BS), + INT_ENTRY(6, Op2BX), + INT_ENTRY(6, Op2BY), + INT_ENTRY(6, Op2BZ), + INT_ENTRY(6, Op2BS), + INT_ENTRY(6, Op28X), + INT_ENTRY(6, Op28Y), + INT_ENTRY(6, Op28Z), + INT_ENTRY(6, Op28R), + INT_ENTRY(6, Op1CX), + INT_ENTRY(6, Op1CY), + INT_ENTRY(6, Op1CZ), + INT_ENTRY(6, Op1CXBR), + INT_ENTRY(6, Op1CYBR), + INT_ENTRY(6, Op1CZBR), + INT_ENTRY(6, Op1CXAR), + INT_ENTRY(6, Op1CYAR), + INT_ENTRY(6, Op1CZAR), + INT_ENTRY(6, Op1CX1), + INT_ENTRY(6, Op1CY1), + INT_ENTRY(6, Op1CZ1), + INT_ENTRY(6, Op1CX2), + INT_ENTRY(6, Op1CY2), + INT_ENTRY(6, Op1CZ2), + INT_ENTRY(6, Op0FRamsize), + INT_ENTRY(6, Op0FPass), + INT_ENTRY(6, Op2FUnknown), + INT_ENTRY(6, Op2FSize), + INT_ENTRY(6, Op08X), + INT_ENTRY(6, Op08Y), + INT_ENTRY(6, Op08Z), + INT_ENTRY(6, Op08Ll), + INT_ENTRY(6, Op08Lh), + INT_ENTRY(6, Op18X), + INT_ENTRY(6, Op18Y), + INT_ENTRY(6, Op18Z), + INT_ENTRY(6, Op18R), + INT_ENTRY(6, Op18D), + INT_ENTRY(6, Op38X), + INT_ENTRY(6, Op38Y), + INT_ENTRY(6, Op38Z), + INT_ENTRY(6, Op38R), + INT_ENTRY(6, Op38D) +}; + +#undef STRUCT +#define STRUCT struct SDSP2 + +static FreezeData SnapDSP2[] = +{ + INT_ENTRY(6, waiting4command), + INT_ENTRY(6, command), + INT_ENTRY(6, in_count), + INT_ENTRY(6, in_index), + INT_ENTRY(6, out_count), + INT_ENTRY(6, out_index), + ARRAY_ENTRY(6, parameters, 512, uint8_ARRAY_V), + ARRAY_ENTRY(6, output, 512, uint8_ARRAY_V), + INT_ENTRY(6, Op05HasLen), + INT_ENTRY(6, Op05Len), + INT_ENTRY(6, Op05Transparent), + INT_ENTRY(6, Op06HasLen), + INT_ENTRY(6, Op06Len), + INT_ENTRY(6, Op09Word1), + INT_ENTRY(6, Op09Word2), + INT_ENTRY(6, Op0DHasLen), + INT_ENTRY(6, Op0DOutLen), + INT_ENTRY(6, Op0DInLen) +}; + +#undef STRUCT +#define STRUCT struct SDSP4 + +static FreezeData SnapDSP4[] = +{ + INT_ENTRY(6, waiting4command), + INT_ENTRY(6, half_command), + INT_ENTRY(6, command), + INT_ENTRY(6, in_count), + INT_ENTRY(6, in_index), + INT_ENTRY(6, out_count), + INT_ENTRY(6, out_index), + ARRAY_ENTRY(6, parameters, 512, uint8_ARRAY_V), + ARRAY_ENTRY(6, output, 512, uint8_ARRAY_V), + INT_ENTRY(6, byte), + INT_ENTRY(6, address), + INT_ENTRY(6, Logic), + INT_ENTRY(6, lcv), + INT_ENTRY(6, distance), + INT_ENTRY(6, raster), + INT_ENTRY(6, segments), + INT_ENTRY(6, world_x), + INT_ENTRY(6, world_y), + INT_ENTRY(6, world_dx), + INT_ENTRY(6, world_dy), + INT_ENTRY(6, world_ddx), + INT_ENTRY(6, world_ddy), + INT_ENTRY(6, world_xenv), + INT_ENTRY(6, world_yofs), + INT_ENTRY(6, view_x1), + INT_ENTRY(6, view_y1), + INT_ENTRY(6, view_x2), + INT_ENTRY(6, view_y2), + INT_ENTRY(6, view_dx), + INT_ENTRY(6, view_dy), + INT_ENTRY(6, view_xofs1), + INT_ENTRY(6, view_yofs1), + INT_ENTRY(6, view_xofs2), + INT_ENTRY(6, view_yofs2), + INT_ENTRY(6, view_yofsenv), + INT_ENTRY(6, view_turnoff_x), + INT_ENTRY(6, view_turnoff_dx), + INT_ENTRY(6, viewport_cx), + INT_ENTRY(6, viewport_cy), + INT_ENTRY(6, viewport_left), + INT_ENTRY(6, viewport_right), + INT_ENTRY(6, viewport_top), + INT_ENTRY(6, viewport_bottom), + INT_ENTRY(6, sprite_x), + INT_ENTRY(6, sprite_y), + INT_ENTRY(6, sprite_attr), + INT_ENTRY(6, sprite_size), + INT_ENTRY(6, sprite_clipy), + INT_ENTRY(6, sprite_count), +#define O(N) \ + ARRAY_ENTRY(6, poly_clipLf[N], 2, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, poly_clipRt[N], 2, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, poly_ptr[N], 2, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, poly_raster[N], 2, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, poly_top[N], 2, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, poly_bottom[N], 2, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, poly_cx[N], 2, uint16_ARRAY_V) + O(0), O(1), +#undef O + ARRAY_ENTRY(6, poly_start, 2, uint16_ARRAY_V), + ARRAY_ENTRY(6, poly_plane, 2, uint16_ARRAY_V), + ARRAY_ENTRY(6, OAM_attr, 16, uint16_ARRAY_V), + INT_ENTRY(6, OAM_index), + INT_ENTRY(6, OAM_bits), + INT_ENTRY(6, OAM_RowMax), + ARRAY_ENTRY(6, OAM_Row, 32, uint16_ARRAY_V) +}; + +#undef STRUCT +#define STRUCT struct SST010 + +static FreezeData SnapST010[] = +{ + ARRAY_ENTRY(6, input_params, 16, uint8_ARRAY_V), + ARRAY_ENTRY(6, output_params, 16, uint8_ARRAY_V), + INT_ENTRY(6, op_reg), + INT_ENTRY(6, execute), + INT_ENTRY(6, control_enable) +}; + +#undef STRUCT +#define STRUCT struct SOBC1 + +static FreezeData SnapOBC1[] = +{ + INT_ENTRY(6, address), + INT_ENTRY(6, basePtr), + INT_ENTRY(6, shift) +}; + +#undef STRUCT +#define STRUCT struct SSPC7110Snapshot + +static FreezeData SnapSPC7110Snap[] = +{ + INT_ENTRY(6, r4801), + INT_ENTRY(6, r4802), + INT_ENTRY(6, r4803), + INT_ENTRY(6, r4804), + INT_ENTRY(6, r4805), + INT_ENTRY(6, r4806), + INT_ENTRY(6, r4807), + INT_ENTRY(6, r4808), + INT_ENTRY(6, r4809), + INT_ENTRY(6, r480a), + INT_ENTRY(6, r480b), + INT_ENTRY(6, r480c), + INT_ENTRY(6, r4811), + INT_ENTRY(6, r4812), + INT_ENTRY(6, r4813), + INT_ENTRY(6, r4814), + INT_ENTRY(6, r4815), + INT_ENTRY(6, r4816), + INT_ENTRY(6, r4817), + INT_ENTRY(6, r4818), + INT_ENTRY(6, r481x), + INT_ENTRY(6, r4814_latch), + INT_ENTRY(6, r4815_latch), + INT_ENTRY(6, r4820), + INT_ENTRY(6, r4821), + INT_ENTRY(6, r4822), + INT_ENTRY(6, r4823), + INT_ENTRY(6, r4824), + INT_ENTRY(6, r4825), + INT_ENTRY(6, r4826), + INT_ENTRY(6, r4827), + INT_ENTRY(6, r4828), + INT_ENTRY(6, r4829), + INT_ENTRY(6, r482a), + INT_ENTRY(6, r482b), + INT_ENTRY(6, r482c), + INT_ENTRY(6, r482d), + INT_ENTRY(6, r482e), + INT_ENTRY(6, r482f), + INT_ENTRY(6, r4830), + INT_ENTRY(6, r4831), + INT_ENTRY(6, r4832), + INT_ENTRY(6, r4833), + INT_ENTRY(6, r4834), + INT_ENTRY(6, dx_offset), + INT_ENTRY(6, ex_offset), + INT_ENTRY(6, fx_offset), + INT_ENTRY(6, r4840), + INT_ENTRY(6, r4841), + INT_ENTRY(6, r4842), + INT_ENTRY(6, rtc_state), + INT_ENTRY(6, rtc_mode), + INT_ENTRY(6, rtc_index), + INT_ENTRY(6, decomp_mode), + INT_ENTRY(6, decomp_offset), + ARRAY_ENTRY(6, decomp_buffer, SPC7110_DECOMP_BUFFER_SIZE, uint8_ARRAY_V), + INT_ENTRY(6, decomp_buffer_rdoffset), + INT_ENTRY(6, decomp_buffer_wroffset), + INT_ENTRY(6, decomp_buffer_length), +#define O(N) \ + INT_ENTRY(6, context[N].index), \ + INT_ENTRY(6, context[N].invert) + O( 0), O( 1), O( 2), O( 3), O( 4), O( 5), O( 6), O( 7), + O( 8), O( 9), O( 10), O( 11), O( 12), O( 13), O( 14), O( 15), + O( 16), O( 17), O( 18), O( 19), O( 20), O( 21), O( 22), O( 23), + O( 24), O( 25), O( 26), O( 27), O( 28), O( 29), O( 30), O( 31) +#undef O +}; + +#undef STRUCT +#define STRUCT struct SSRTCSnapshot + +static FreezeData SnapSRTCSnap[] = +{ + INT_ENTRY(6, rtc_mode), + INT_ENTRY(6, rtc_index) +}; + +#undef STRUCT +#define STRUCT struct SBSX + +static FreezeData SnapBSX[] = +{ + INT_ENTRY(6, dirty), + INT_ENTRY(6, dirty2), + INT_ENTRY(6, bootup), + INT_ENTRY(6, flash_enable), + INT_ENTRY(6, write_enable), + INT_ENTRY(6, read_enable), + INT_ENTRY(6, flash_command), + INT_ENTRY(6, old_write), + INT_ENTRY(6, new_write), + INT_ENTRY(6, out_index), + ARRAY_ENTRY(6, output, 32, uint8_ARRAY_V), + ARRAY_ENTRY(6, PPU, 32, uint8_ARRAY_V), + ARRAY_ENTRY(6, MMC, 16, uint8_ARRAY_V), + ARRAY_ENTRY(6, prevMMC, 16, uint8_ARRAY_V), + ARRAY_ENTRY(6, test2192, 32, uint8_ARRAY_V) +}; + +#undef STRUCT +#define STRUCT struct SnapshotScreenshotInfo + +static FreezeData SnapScreenshot[] = +{ + INT_ENTRY(6, Width), + INT_ENTRY(6, Height), + INT_ENTRY(6, Interlaced), + ARRAY_ENTRY(6, Data, MAX_SNES_WIDTH * MAX_SNES_HEIGHT * 3, uint8_ARRAY_V) +}; + +#undef STRUCT +#define STRUCT struct SnapshotMovieInfo + +static FreezeData SnapMovie[] = +{ + INT_ENTRY(6, MovieInputDataSize) +}; + +static int UnfreezeBlock (STREAM, const char *, uint8 *, int); +static int UnfreezeBlockCopy (STREAM, const char *, uint8 **, int); +static int UnfreezeStruct (STREAM, const char *, void *, FreezeData *, int, int); +static int UnfreezeStructCopy (STREAM, const char *, uint8 **, FreezeData *, int, int); +static void UnfreezeStructFromCopy (void *, FreezeData *, int, uint8 *, int); +static void FreezeBlock (STREAM, const char *, uint8 *, int); +static void FreezeStruct (STREAM, const char *, void *, FreezeData *, int); + + +void S9xResetSaveTimer (bool8 dontsave) +{ + static time_t t = -1; + + if (!Settings.DontSaveOopsSnapshot && !dontsave && t != -1 && time(NULL) - t > 300) + { + char filename[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + _splitpath(Memory.ROMFilename, drive, dir, def, ext); + sprintf(filename, "%s%s%s.%.*s", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, _MAX_EXT - 1, "oops"); + S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, SAVE_INFO_OOPS); + S9xFreezeGame(filename); + } + + t = time(NULL); +} + +bool8 S9xFreezeGame (const char *filename) +{ + STREAM stream = NULL; + + if (S9xOpenSnapshotFile(filename, FALSE, &stream)) + { + S9xFreezeToStream(stream); + S9xCloseSnapshotFile(stream); + + S9xResetSaveTimer(TRUE); + + const char *base = S9xBasename(filename); + if (S9xMovieActive()) + sprintf(String, MOVIE_INFO_SNAPSHOT " %s", base); + else + sprintf(String, SAVE_INFO_SNAPSHOT " %s", base); + + S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String); + + return (TRUE); + } + + return (FALSE); +} + +bool8 S9xUnfreezeGame (const char *filename) +{ + STREAM stream = NULL; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + const char *base = S9xBasename(filename); + + _splitpath(filename, drive, dir, def, ext); + S9xResetSaveTimer(!strcmp(ext, "oops") || !strcmp(ext, "oop") || !strcmp(ext, ".oops") || !strcmp(ext, ".oop")); + + if (S9xOpenSnapshotFile(filename, TRUE, &stream)) + { + int result; + + result = S9xUnfreezeFromStream(stream); + S9xCloseSnapshotFile(stream); + + if (result != SUCCESS) + { + switch (result) + { + case WRONG_FORMAT: + S9xMessage(S9X_ERROR, S9X_WRONG_FORMAT, SAVE_ERR_WRONG_FORMAT); + break; + + case WRONG_VERSION: + S9xMessage(S9X_ERROR, S9X_WRONG_VERSION, SAVE_ERR_WRONG_VERSION); + break; + + case WRONG_MOVIE_SNAPSHOT: + S9xMessage(S9X_ERROR, S9X_WRONG_MOVIE_SNAPSHOT, MOVIE_ERR_SNAPSHOT_WRONG_MOVIE); + break; + + case NOT_A_MOVIE_SNAPSHOT: + S9xMessage(S9X_ERROR, S9X_NOT_A_MOVIE_SNAPSHOT, MOVIE_ERR_SNAPSHOT_NOT_MOVIE); + break; + + case SNAPSHOT_INCONSISTENT: + S9xMessage(S9X_ERROR, S9X_SNAPSHOT_INCONSISTENT, MOVIE_ERR_SNAPSHOT_INCONSISTENT); + break; + + case FILE_NOT_FOUND: + default: + sprintf(String, SAVE_ERR_ROM_NOT_FOUND, base); + S9xMessage(S9X_ERROR, S9X_ROM_NOT_FOUND, String); + break; + } + + return (FALSE); + } + + if (S9xMovieActive()) + { + if (S9xMovieReadOnly()) + sprintf(String, MOVIE_INFO_REWIND " %s", base); + else + sprintf(String, MOVIE_INFO_RERECORD " %s", base); + } + else + sprintf(String, SAVE_INFO_LOAD " %s", base); + + S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String); + + return (TRUE); + } + + sprintf(String, SAVE_ERR_SAVE_NOT_FOUND, base); + S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String); + + return (FALSE); +} + +void S9xFreezeToStream (STREAM stream) +{ + char buffer[1024]; + uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE]; + + S9xSetSoundMute(TRUE); + + sprintf(buffer, "%s:%04d\n", SNAPSHOT_MAGIC, SNAPSHOT_VERSION); + WRITE_STREAM(buffer, strlen(buffer), stream); + + sprintf(buffer, "NAM:%06d:%s%c", (int) strlen(Memory.ROMFilename) + 1, Memory.ROMFilename, 0); + WRITE_STREAM(buffer, strlen(buffer) + 1, stream); + + FreezeStruct(stream, "CPU", &CPU, SnapCPU, COUNT(SnapCPU)); + + FreezeStruct(stream, "REG", &Registers, SnapRegisters, COUNT(SnapRegisters)); + + FreezeStruct(stream, "PPU", &PPU, SnapPPU, COUNT(SnapPPU)); + + struct SDMASnapshot dma_snap; + for (int d = 0; d < 8; d++) + dma_snap.dma[d] = DMA[d]; + FreezeStruct(stream, "DMA", &dma_snap, SnapDMA, COUNT(SnapDMA)); + + FreezeBlock (stream, "VRA", Memory.VRAM, 0x10000); + + FreezeBlock (stream, "RAM", Memory.RAM, 0x20000); + + FreezeBlock (stream, "SRA", Memory.SRAM, 0x20000); + + FreezeBlock (stream, "FIL", Memory.FillRAM, 0x8000); + + S9xAPUSaveState(soundsnapshot); + FreezeBlock (stream, "SND", soundsnapshot, SPC_SAVE_STATE_BLOCK_SIZE); + + struct SControlSnapshot ctl_snap; + S9xControlPreSaveState(&ctl_snap); + FreezeStruct(stream, "CTL", &ctl_snap, SnapControls, COUNT(SnapControls)); + + FreezeStruct(stream, "TIM", &Timings, SnapTimings, COUNT(SnapTimings)); + + if (Settings.SuperFX) + { + GSU.avRegAddr = (uint8 *) &GSU.avReg; + FreezeStruct(stream, "SFX", &GSU, SnapFX, COUNT(SnapFX)); + } + + if (Settings.SA1) + { + S9xSA1PackStatus(); + FreezeStruct(stream, "SA1", &SA1, SnapSA1, COUNT(SnapSA1)); + FreezeStruct(stream, "SAR", &SA1Registers, SnapSA1Registers, COUNT(SnapSA1Registers)); + } + + if (Settings.DSP == 1) + FreezeStruct(stream, "DP1", &DSP1, SnapDSP1, COUNT(SnapDSP1)); + + if (Settings.DSP == 2) + FreezeStruct(stream, "DP2", &DSP2, SnapDSP2, COUNT(SnapDSP2)); + + if (Settings.DSP == 4) + FreezeStruct(stream, "DP4", &DSP4, SnapDSP4, COUNT(SnapDSP4)); + + if (Settings.C4) + FreezeBlock (stream, "CX4", Memory.C4RAM, 8192); + + if (Settings.SETA == ST_010) + FreezeStruct(stream, "ST0", &ST010, SnapST010, COUNT(SnapST010)); + + if (Settings.OBC1) + { + FreezeStruct(stream, "OBC", &OBC1, SnapOBC1, COUNT(SnapOBC1)); + FreezeBlock (stream, "OBM", Memory.OBC1RAM, 8192); + } + + if (Settings.SPC7110) + { + S9xSPC7110PreSaveState(); + FreezeStruct(stream, "S71", &s7snap, SnapSPC7110Snap, COUNT(SnapSPC7110Snap)); + } + + if (Settings.SRTC) + { + S9xSRTCPreSaveState(); + FreezeStruct(stream, "SRT", &srtcsnap, SnapSRTCSnap, COUNT(SnapSRTCSnap)); + } + + if (Settings.SRTC || Settings.SPC7110RTC) + FreezeBlock (stream, "CLK", RTCData.reg, 20); + + if (Settings.BS) + FreezeStruct(stream, "BSX", &BSX, SnapBSX, COUNT(SnapBSX)); + + if (Settings.SnapshotScreenshots) + { + SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo; + + ssi->Width = min(IPPU.RenderedScreenWidth, MAX_SNES_WIDTH); + ssi->Height = min(IPPU.RenderedScreenHeight, MAX_SNES_HEIGHT); + ssi->Interlaced = GFX.DoInterlace; + + uint8 *rowpix = ssi->Data; + uint16 *screen = GFX.Screen; + + for (int y = 0; y < ssi->Height; y++, screen += GFX.RealPPL) + { + for (int x = 0; x < ssi->Width; x++) + { + uint32 r, g, b; + + DECOMPOSE_PIXEL(screen[x], r, g, b); + *(rowpix++) = r; + *(rowpix++) = g; + *(rowpix++) = b; + } + } + + memset(rowpix, 0, sizeof(ssi->Data) + ssi->Data - rowpix); + + FreezeStruct(stream, "SHO", ssi, SnapScreenshot, COUNT(SnapScreenshot)); + + delete ssi; + } + + if (S9xMovieActive()) + { + uint8 *movie_freeze_buf; + uint32 movie_freeze_size; + + S9xMovieFreeze(&movie_freeze_buf, &movie_freeze_size); + if (movie_freeze_buf) + { + struct SnapshotMovieInfo mi; + + mi.MovieInputDataSize = movie_freeze_size; + FreezeStruct(stream, "MOV", &mi, SnapMovie, COUNT(SnapMovie)); + FreezeBlock (stream, "MID", movie_freeze_buf, movie_freeze_size); + + delete [] movie_freeze_buf; + } + } + + S9xSetSoundMute(FALSE); + + delete [] soundsnapshot; +} + +int S9xUnfreezeFromStream (STREAM stream) +{ + int result = SUCCESS; + int version, len; + char buffer[PATH_MAX + 1]; + + len = strlen(SNAPSHOT_MAGIC) + 1 + 4 + 1; + if (READ_STREAM(buffer, len, stream) != len) + return (WRONG_FORMAT); + + if (strncmp(buffer, SNAPSHOT_MAGIC, strlen(SNAPSHOT_MAGIC)) != 0) + return (WRONG_FORMAT); + + version = atoi(&buffer[strlen(SNAPSHOT_MAGIC) + 1]); + if (version > SNAPSHOT_VERSION) + return (WRONG_VERSION); + + result = UnfreezeBlock(stream, "NAM", (uint8 *) buffer, PATH_MAX); + if (result != SUCCESS) + return (result); + + uint8 *local_cpu = NULL; + uint8 *local_registers = NULL; + uint8 *local_ppu = NULL; + uint8 *local_dma = NULL; + uint8 *local_vram = NULL; + uint8 *local_ram = NULL; + uint8 *local_sram = NULL; + uint8 *local_fillram = NULL; + uint8 *local_apu_sound = NULL; + uint8 *local_control_data = NULL; + uint8 *local_timing_data = NULL; + uint8 *local_superfx = NULL; + uint8 *local_sa1 = NULL; + uint8 *local_sa1_registers = NULL; + uint8 *local_dsp1 = NULL; + uint8 *local_dsp2 = NULL; + uint8 *local_dsp4 = NULL; + uint8 *local_cx4_data = NULL; + uint8 *local_st010 = NULL; + uint8 *local_obc1 = NULL; + uint8 *local_obc1_data = NULL; + uint8 *local_spc7110 = NULL; + uint8 *local_srtc = NULL; + uint8 *local_rtc_data = NULL; + uint8 *local_bsx_data = NULL; + uint8 *local_screenshot = NULL; + uint8 *local_movie_data = NULL; + + do + { + result = UnfreezeStructCopy(stream, "CPU", &local_cpu, SnapCPU, COUNT(SnapCPU), version); + if (result != SUCCESS) + break; + + result = UnfreezeStructCopy(stream, "REG", &local_registers, SnapRegisters, COUNT(SnapRegisters), version); + if (result != SUCCESS) + break; + + result = UnfreezeStructCopy(stream, "PPU", &local_ppu, SnapPPU, COUNT(SnapPPU), version); + if (result != SUCCESS) + break; + + result = UnfreezeStructCopy(stream, "DMA", &local_dma, SnapDMA, COUNT(SnapDMA), version); + if (result != SUCCESS) + break; + + result = UnfreezeBlockCopy (stream, "VRA", &local_vram, 0x10000); + if (result != SUCCESS) + break; + + result = UnfreezeBlockCopy (stream, "RAM", &local_ram, 0x20000); + if (result != SUCCESS) + break; + + result = UnfreezeBlockCopy (stream, "SRA", &local_sram, 0x20000); + if (result != SUCCESS) + break; + + result = UnfreezeBlockCopy (stream, "FIL", &local_fillram, 0x8000); + if (result != SUCCESS) + break; + + result = UnfreezeBlockCopy (stream, "SND", &local_apu_sound, SPC_SAVE_STATE_BLOCK_SIZE); + if (result != SUCCESS) + break; + + result = UnfreezeStructCopy(stream, "CTL", &local_control_data, SnapControls, COUNT(SnapControls), version); + if (result != SUCCESS) + break; + + result = UnfreezeStructCopy(stream, "TIM", &local_timing_data, SnapTimings, COUNT(SnapTimings), version); + if (result != SUCCESS) + break; + + result = UnfreezeStructCopy(stream, "SFX", &local_superfx, SnapFX, COUNT(SnapFX), version); + if (result != SUCCESS && Settings.SuperFX) + break; + + result = UnfreezeStructCopy(stream, "SA1", &local_sa1, SnapSA1, COUNT(SnapSA1), version); + if (result != SUCCESS && Settings.SA1) + break; + + result = UnfreezeStructCopy(stream, "SAR", &local_sa1_registers, SnapSA1Registers, COUNT(SnapSA1Registers), version); + if (result != SUCCESS && Settings.SA1) + break; + + result = UnfreezeStructCopy(stream, "DP1", &local_dsp1, SnapDSP1, COUNT(SnapDSP1), version); + if (result != SUCCESS && Settings.DSP == 1) + break; + + result = UnfreezeStructCopy(stream, "DP2", &local_dsp2, SnapDSP2, COUNT(SnapDSP2), version); + if (result != SUCCESS && Settings.DSP == 2) + break; + + result = UnfreezeStructCopy(stream, "DP4", &local_dsp4, SnapDSP4, COUNT(SnapDSP4), version); + if (result != SUCCESS && Settings.DSP == 4) + break; + + result = UnfreezeBlockCopy (stream, "CX4", &local_cx4_data, 8192); + if (result != SUCCESS && Settings.C4) + break; + + result = UnfreezeStructCopy(stream, "ST0", &local_st010, SnapST010, COUNT(SnapST010), version); + if (result != SUCCESS && Settings.SETA == ST_010) + break; + + result = UnfreezeStructCopy(stream, "OBC", &local_obc1, SnapOBC1, COUNT(SnapOBC1), version); + if (result != SUCCESS && Settings.OBC1) + break; + + result = UnfreezeBlockCopy (stream, "OBM", &local_obc1_data, 8192); + if (result != SUCCESS && Settings.OBC1) + break; + + result = UnfreezeStructCopy(stream, "S71", &local_spc7110, SnapSPC7110Snap, COUNT(SnapSPC7110Snap), version); + if (result != SUCCESS && Settings.SPC7110) + break; + + result = UnfreezeStructCopy(stream, "SRT", &local_srtc, SnapSRTCSnap, COUNT(SnapSRTCSnap), version); + if (result != SUCCESS && Settings.SRTC) + break; + + result = UnfreezeBlockCopy (stream, "CLK", &local_rtc_data, 20); + if (result != SUCCESS && (Settings.SRTC || Settings.SPC7110RTC)) + break; + + result = UnfreezeStructCopy(stream, "BSX", &local_bsx_data, SnapBSX, COUNT(SnapBSX), version); + if (result != SUCCESS && Settings.BS) + break; + + result = UnfreezeStructCopy(stream, "SHO", &local_screenshot, SnapScreenshot, COUNT(SnapScreenshot), version); + + SnapshotMovieInfo mi; + + result = UnfreezeStruct(stream, "MOV", &mi, SnapMovie, COUNT(SnapMovie), version); + if (result != SUCCESS) + { + if (S9xMovieActive()) + { + result = NOT_A_MOVIE_SNAPSHOT; + break; + } + } + else + { + result = UnfreezeBlockCopy(stream, "MID", &local_movie_data, mi.MovieInputDataSize); + if (result != SUCCESS) + { + if (S9xMovieActive()) + { + result = NOT_A_MOVIE_SNAPSHOT; + break; + } + } + + if (S9xMovieActive()) + { + result = S9xMovieUnfreeze(local_movie_data, mi.MovieInputDataSize); + if (result != SUCCESS) + break; + } + } + + result = SUCCESS; + } while (false); + + if (result == SUCCESS) + { + uint32 old_flags = CPU.Flags; + uint32 sa1_old_flags = SA1.Flags; + + S9xSetSoundMute(TRUE); + + S9xReset(); + + UnfreezeStructFromCopy(&CPU, SnapCPU, COUNT(SnapCPU), local_cpu, version); + + UnfreezeStructFromCopy(&Registers, SnapRegisters, COUNT(SnapRegisters), local_registers, version); + + UnfreezeStructFromCopy(&PPU, SnapPPU, COUNT(SnapPPU), local_ppu, version); + + struct SDMASnapshot dma_snap; + UnfreezeStructFromCopy(&dma_snap, SnapDMA, COUNT(SnapDMA), local_dma, version); + + memcpy(Memory.VRAM, local_vram, 0x10000); + + memcpy(Memory.RAM, local_ram, 0x20000); + + memcpy(Memory.SRAM, local_sram, 0x20000); + + memcpy(Memory.FillRAM, local_fillram, 0x8000); + + S9xAPULoadState(local_apu_sound); + + struct SControlSnapshot ctl_snap; + UnfreezeStructFromCopy(&ctl_snap, SnapControls, COUNT(SnapControls), local_control_data, version); + + UnfreezeStructFromCopy(&Timings, SnapTimings, COUNT(SnapTimings), local_timing_data, version); + + if (local_superfx) + { + GSU.avRegAddr = (uint8 *) &GSU.avReg; + UnfreezeStructFromCopy(&GSU, SnapFX, COUNT(SnapFX), local_superfx, version); + } + + if (local_sa1) + UnfreezeStructFromCopy(&SA1, SnapSA1, COUNT(SnapSA1), local_sa1, version); + + if (local_sa1_registers) + UnfreezeStructFromCopy(&SA1Registers, SnapSA1Registers, COUNT(SnapSA1Registers), local_sa1_registers, version); + + if (local_dsp1) + UnfreezeStructFromCopy(&DSP1, SnapDSP1, COUNT(SnapDSP1), local_dsp1, version); + + if (local_dsp2) + UnfreezeStructFromCopy(&DSP2, SnapDSP2, COUNT(SnapDSP2), local_dsp2, version); + + if (local_dsp4) + UnfreezeStructFromCopy(&DSP4, SnapDSP4, COUNT(SnapDSP4), local_dsp4, version); + + if (local_cx4_data) + memcpy(Memory.C4RAM, local_cx4_data, 8192); + + if (local_st010) + UnfreezeStructFromCopy(&ST010, SnapST010, COUNT(SnapST010), local_st010, version); + + if (local_obc1) + UnfreezeStructFromCopy(&OBC1, SnapOBC1, COUNT(SnapOBC1), local_obc1, version); + + if (local_obc1_data) + memcpy(Memory.OBC1RAM, local_obc1_data, 8192); + + if (local_spc7110) + UnfreezeStructFromCopy(&s7snap, SnapSPC7110Snap, COUNT(SnapSPC7110Snap), local_spc7110, version); + + if (local_srtc) + UnfreezeStructFromCopy(&srtcsnap, SnapSRTCSnap, COUNT(SnapSRTCSnap), local_srtc, version); + + if (local_rtc_data) + memcpy(RTCData.reg, local_rtc_data, 20); + + if (local_bsx_data) + UnfreezeStructFromCopy(&BSX, SnapBSX, COUNT(SnapBSX), local_bsx_data, version); + + CPU.Flags |= old_flags & (DEBUG_MODE_FLAG | TRACE_FLAG | SINGLE_STEP_FLAG | FRAME_ADVANCE_FLAG); + ICPU.ShiftedPB = Registers.PB << 16; + ICPU.ShiftedDB = Registers.DB << 16; + S9xSetPCBase(Registers.PBPC); + S9xUnpackStatus(); + S9xFixCycles(); + + for (int d = 0; d < 8; d++) + DMA[d] = dma_snap.dma[d]; + CPU.InDMA = CPU.InHDMA = FALSE; + CPU.InDMAorHDMA = CPU.InWRAMDMAorHDMA = FALSE; + CPU.HDMARanInDMA = 0; + + S9xFixColourBrightness(); + IPPU.ColorsChanged = TRUE; + IPPU.OBJChanged = TRUE; + IPPU.RenderThisFrame = TRUE; + + uint8 hdma_byte = Memory.FillRAM[0x420c]; + S9xSetCPU(hdma_byte, 0x420c); + + S9xControlPostLoadState(&ctl_snap); + + if (local_superfx) + { + GSU.pfPlot = fx_PlotTable[GSU.vMode]; + GSU.pfRpix = fx_PlotTable[GSU.vMode + 5]; + } + + if (local_sa1 && local_sa1_registers) + { + SA1.Flags |= sa1_old_flags & TRACE_FLAG; + S9xSA1PostLoadState(); + } + + if (Settings.SDD1) + S9xSDD1PostLoadState(); + + if (local_spc7110) + S9xSPC7110PostLoadState(version); + + if (local_srtc) + S9xSRTCPostLoadState(version); + + if (local_bsx_data) + S9xBSXPostLoadState(); + + if (local_movie_data) + { + // restore last displayed pad_read status + extern bool8 pad_read, pad_read_last; + bool8 pad_read_temp = pad_read; + + pad_read = pad_read_last; + S9xUpdateFrameCounter(-1); + pad_read = pad_read_temp; + } + + if (local_screenshot) + { + SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo; + + UnfreezeStructFromCopy(ssi, SnapScreenshot, COUNT(SnapScreenshot), local_screenshot, version); + + IPPU.RenderedScreenWidth = min(ssi->Width, IMAGE_WIDTH); + IPPU.RenderedScreenHeight = min(ssi->Height, IMAGE_HEIGHT); + const bool8 scaleDownX = IPPU.RenderedScreenWidth < ssi->Width; + const bool8 scaleDownY = IPPU.RenderedScreenHeight < ssi->Height && ssi->Height > SNES_HEIGHT_EXTENDED; + GFX.DoInterlace = Settings.SupportHiRes ? ssi->Interlaced : 0; + + uint8 *rowpix = ssi->Data; + uint16 *screen = GFX.Screen; + + for (int y = 0; y < IPPU.RenderedScreenHeight; y++, screen += GFX.RealPPL) + { + for (int x = 0; x < IPPU.RenderedScreenWidth; x++) + { + uint32 r, g, b; + + r = *(rowpix++); + g = *(rowpix++); + b = *(rowpix++); + + if (scaleDownX) + { + r = (r + *(rowpix++)) >> 1; + g = (g + *(rowpix++)) >> 1; + b = (b + *(rowpix++)) >> 1; + + if (x + x + 1 >= ssi->Width) + break; + } + + screen[x] = BUILD_PIXEL(r, g, b); + } + + if (scaleDownY) + { + rowpix += 3 * ssi->Width; + if (y + y + 1 >= ssi->Height) + break; + } + } + + // black out what we might have missed + for (uint32 y = IPPU.RenderedScreenHeight; y < (uint32) (IMAGE_HEIGHT); y++) + memset(GFX.Screen + y * GFX.RealPPL, 0, GFX.RealPPL * 2); + + delete ssi; + } + else + { + // couldn't load graphics, so black out the screen instead + //for (uint32 y = 0; y < (uint32) (IMAGE_HEIGHT); y++) + // memset(GFX.Screen + y * GFX.RealPPL, 0, GFX.RealPPL * 2); + } + + S9xSetSoundMute(FALSE); + } + + if (local_cpu) delete [] local_cpu; + if (local_registers) delete [] local_registers; + if (local_ppu) delete [] local_ppu; + if (local_dma) delete [] local_dma; + if (local_vram) delete [] local_vram; + if (local_ram) delete [] local_ram; + if (local_sram) delete [] local_sram; + if (local_fillram) delete [] local_fillram; + if (local_apu_sound) delete [] local_apu_sound; + if (local_control_data) delete [] local_control_data; + if (local_timing_data) delete [] local_timing_data; + if (local_superfx) delete [] local_superfx; + if (local_sa1) delete [] local_sa1; + if (local_sa1_registers) delete [] local_sa1_registers; + if (local_dsp1) delete [] local_dsp1; + if (local_dsp2) delete [] local_dsp2; + if (local_dsp4) delete [] local_dsp4; + if (local_cx4_data) delete [] local_cx4_data; + if (local_st010) delete [] local_st010; + if (local_obc1) delete [] local_obc1; + if (local_obc1_data) delete [] local_obc1_data; + if (local_spc7110) delete [] local_spc7110; + if (local_srtc) delete [] local_srtc; + if (local_rtc_data) delete [] local_rtc_data; + if (local_bsx_data) delete [] local_bsx_data; + if (local_screenshot) delete [] local_screenshot; + if (local_movie_data) delete [] local_movie_data; + + return (result); +} + +static int FreezeSize (int size, int type) +{ + switch (type) + { + case uint32_ARRAY_V: + case uint32_INDIR_ARRAY_V: + return (size * 4); + + case uint16_ARRAY_V: + case uint16_INDIR_ARRAY_V: + return (size * 2); + + default: + return (size); + } +} + +static void FreezeStruct (STREAM stream, const char *name, void *base, FreezeData *fields, int num_fields) +{ + int len = 0; + int i, j; + + for (i = 0; i < num_fields; i++) + { + if (SNAPSHOT_VERSION < fields[i].debuted_in) + { + fprintf(stderr, "%s[%p]: field has bad debuted_in value %d, > %d.", name, (void *) fields, fields[i].debuted_in, SNAPSHOT_VERSION); + continue; + } + + if (SNAPSHOT_VERSION < fields[i].deleted_in) + len += FreezeSize(fields[i].size, fields[i].type); + } + + uint8 *block = new uint8[len]; + uint8 *ptr = block; + uint8 *addr; + uint16 word; + uint32 dword; + int64 qaword; + int relativeAddr; + + for (i = 0; i < num_fields; i++) + { + if (SNAPSHOT_VERSION >= fields[i].deleted_in || SNAPSHOT_VERSION < fields[i].debuted_in) + continue; + + addr = (uint8 *) base + fields[i].offset; + + // determine real address of indirect-type fields + // (where the structure contains a pointer to an array rather than the array itself) + if (fields[i].type == uint8_INDIR_ARRAY_V || fields[i].type == uint16_INDIR_ARRAY_V || fields[i].type == uint32_INDIR_ARRAY_V) + addr = (uint8 *) (*((pint *) addr)); + + // convert pointer-type saves from absolute to relative pointers + if (fields[i].type == POINTER_V) + { + uint8 *pointer = (uint8 *) *((pint *) ((uint8 *) base + fields[i].offset)); + uint8 *relativeTo = (uint8 *) *((pint *) ((uint8 *) base + fields[i].offset2)); + relativeAddr = pointer - relativeTo; + addr = (uint8 *) &relativeAddr; + } + + switch (fields[i].type) + { + case INT_V: + case POINTER_V: + switch (fields[i].size) + { + case 1: + *ptr++ = *(addr); + break; + + case 2: + word = *((uint16 *) (addr)); + *ptr++ = (uint8) (word >> 8); + *ptr++ = (uint8) word; + break; + + case 4: + dword = *((uint32 *) (addr)); + *ptr++ = (uint8) (dword >> 24); + *ptr++ = (uint8) (dword >> 16); + *ptr++ = (uint8) (dword >> 8); + *ptr++ = (uint8) dword; + break; + + case 8: + qaword = *((int64 *) (addr)); + *ptr++ = (uint8) (qaword >> 56); + *ptr++ = (uint8) (qaword >> 48); + *ptr++ = (uint8) (qaword >> 40); + *ptr++ = (uint8) (qaword >> 32); + *ptr++ = (uint8) (qaword >> 24); + *ptr++ = (uint8) (qaword >> 16); + *ptr++ = (uint8) (qaword >> 8); + *ptr++ = (uint8) qaword; + break; + } + + break; + + case uint8_ARRAY_V: + case uint8_INDIR_ARRAY_V: + memmove(ptr, addr, fields[i].size); + ptr += fields[i].size; + + break; + + case uint16_ARRAY_V: + case uint16_INDIR_ARRAY_V: + for (j = 0; j < fields[i].size; j++) + { + word = *((uint16 *) (addr + j * 2)); + *ptr++ = (uint8) (word >> 8); + *ptr++ = (uint8) word; + } + + break; + + case uint32_ARRAY_V: + case uint32_INDIR_ARRAY_V: + for (j = 0; j < fields[i].size; j++) + { + dword = *((uint32 *) (addr + j * 4)); + *ptr++ = (uint8) (dword >> 24); + *ptr++ = (uint8) (dword >> 16); + *ptr++ = (uint8) (dword >> 8); + *ptr++ = (uint8) dword; + } + + break; + } + } + + FreezeBlock(stream, name, block, len); + delete [] block; +} + +static void FreezeBlock (STREAM stream, const char *name, uint8 *block, int size) +{ + char buffer[20]; + + // check if it fits in 6 digits. (letting it go over and using strlen isn't safe) + if (size <= 999999) + sprintf(buffer, "%s:%06d:", name, size); + else + { + // to make it fit, pack it in the bytes instead of as digits + sprintf(buffer, "%s:------:", name); + buffer[6] = (unsigned char) ((unsigned) size >> 24); + buffer[7] = (unsigned char) ((unsigned) size >> 16); + buffer[8] = (unsigned char) ((unsigned) size >> 8); + buffer[9] = (unsigned char) ((unsigned) size >> 0); + } + + buffer[11] = 0; + + WRITE_STREAM(buffer, 11, stream); + WRITE_STREAM(block, size, stream); +} + +static int UnfreezeBlock (STREAM stream, const char *name, uint8 *block, int size) +{ + char buffer[20]; + int len = 0, rem = 0; + long rewind = FIND_STREAM(stream); + + size_t l = READ_STREAM(buffer, 11, stream); + buffer[l] = 0; + + if (l != 11 || strncmp(buffer, name, 3) != 0 || buffer[3] != ':') + { + err: + fprintf(stdout, "absent: %s(%d); next: '%.11s'\n", name, size, buffer); + REVERT_STREAM(stream, FIND_STREAM(stream) - l, 0); + return (WRONG_FORMAT); + } + + if (buffer[4] == '-') + { + len = (((unsigned char) buffer[6]) << 24) + | (((unsigned char) buffer[7]) << 16) + | (((unsigned char) buffer[8]) << 8) + | (((unsigned char) buffer[9]) << 0); + } + else + len = atoi(buffer + 4); + + if (len <= 0) + goto err; + + if (len > size) + { + rem = len - size; + len = size; + } + + ZeroMemory(block, size); + + if (READ_STREAM(block, len, stream) != len) + { + REVERT_STREAM(stream, rewind, 0); + return (WRONG_FORMAT); + } + + if (rem) + { + char *junk = new char[rem]; + len = READ_STREAM(junk, rem, stream); + delete [] junk; + if (len != rem) + { + REVERT_STREAM(stream, rewind, 0); + return (WRONG_FORMAT); + } + } + + return (SUCCESS); +} + +static int UnfreezeBlockCopy (STREAM stream, const char *name, uint8 **block, int size) +{ + int result; + + *block = new uint8[size]; + + result = UnfreezeBlock(stream, name, *block, size); + if (result != SUCCESS) + { + delete [] (*block); + *block = NULL; + return (result); + } + + return (SUCCESS); +} + +static int UnfreezeStruct (STREAM stream, const char *name, void *base, FreezeData *fields, int num_fields, int version) +{ + int result; + uint8 *block = NULL; + + result = UnfreezeStructCopy(stream, name, &block, fields, num_fields, version); + if (result != SUCCESS) + { + if (block != NULL) + delete [] block; + return (result); + } + + UnfreezeStructFromCopy(base, fields, num_fields, block, version); + delete [] block; + + return (SUCCESS); +} + +static int UnfreezeStructCopy (STREAM stream, const char *name, uint8 **block, FreezeData *fields, int num_fields, int version) +{ + int len = 0; + + for (int i = 0; i < num_fields; i++) + { + if (version >= fields[i].debuted_in && version < fields[i].deleted_in) + len += FreezeSize(fields[i].size, fields[i].type); + } + + return (UnfreezeBlockCopy(stream, name, block, len)); +} + +static void UnfreezeStructFromCopy (void *sbase, FreezeData *fields, int num_fields, uint8 *block, int version) +{ + uint8 *ptr = block; + uint16 word; + uint32 dword; + int64 qaword; + uint8 *addr; + void *base; + int relativeAddr; + int i, j; + + for (i = 0; i < num_fields; i++) + { + if (version < fields[i].debuted_in || version >= fields[i].deleted_in) + continue; + + base = (SNAPSHOT_VERSION >= fields[i].deleted_in) ? ((void *) &Obsolete) : sbase; + addr = (uint8 *) base + fields[i].offset; + + if (fields[i].type == uint8_INDIR_ARRAY_V || fields[i].type == uint16_INDIR_ARRAY_V || fields[i].type == uint32_INDIR_ARRAY_V) + addr = (uint8 *) (*((pint *) addr)); + + switch (fields[i].type) + { + case INT_V: + case POINTER_V: + switch (fields[i].size) + { + case 1: + if (fields[i].offset < 0) + { + ptr++; + break; + } + + *(addr) = *ptr++; + break; + + case 2: + if (fields[i].offset < 0) + { + ptr += 2; + break; + } + + word = *ptr++ << 8; + word |= *ptr++; + *((uint16 *) (addr)) = word; + break; + + case 4: + if (fields[i].offset < 0) + { + ptr += 4; + break; + } + + dword = *ptr++ << 24; + dword |= *ptr++ << 16; + dword |= *ptr++ << 8; + dword |= *ptr++; + *((uint32 *) (addr)) = dword; + break; + + case 8: + if (fields[i].offset < 0) + { + ptr += 8; + break; + } + + qaword = (int64) *ptr++ << 56; + qaword |= (int64) *ptr++ << 48; + qaword |= (int64) *ptr++ << 40; + qaword |= (int64) *ptr++ << 32; + qaword |= (int64) *ptr++ << 24; + qaword |= (int64) *ptr++ << 16; + qaword |= (int64) *ptr++ << 8; + qaword |= (int64) *ptr++; + *((int64 *) (addr)) = qaword; + break; + + default: + assert(0); + break; + } + + break; + + case uint8_ARRAY_V: + case uint8_INDIR_ARRAY_V: + if (fields[i].offset >= 0) + memmove(addr, ptr, fields[i].size); + ptr += fields[i].size; + + break; + + case uint16_ARRAY_V: + case uint16_INDIR_ARRAY_V: + if (fields[i].offset < 0) + { + ptr += fields[i].size * 2; + break; + } + + for (j = 0; j < fields[i].size; j++) + { + word = *ptr++ << 8; + word |= *ptr++; + *((uint16 *) (addr + j * 2)) = word; + } + + break; + + case uint32_ARRAY_V: + case uint32_INDIR_ARRAY_V: + if (fields[i].offset < 0) + { + ptr += fields[i].size * 4; + break; + } + + for (j = 0; j < fields[i].size; j++) + { + dword = *ptr++ << 24; + dword |= *ptr++ << 16; + dword |= *ptr++ << 8; + dword |= *ptr++; + *((uint32 *) (addr + j * 4)) = dword; + } + + break; + } + + if (fields[i].type == POINTER_V) + { + relativeAddr = (int) *((pint *) ((uint8 *) base + fields[i].offset)); + uint8 *relativeTo = (uint8 *) *((pint *) ((uint8 *) base + fields[i].offset2)); + *((pint *) (addr)) = (pint) (relativeTo + relativeAddr); + } + } +} + +bool8 S9xSPCDump (const char *filename) +{ + FILE *fs; + uint8 buf[SNES_SPC::spc_file_size]; + size_t ignore; + + fs = fopen(filename, "wb"); + if (!fs) + return (FALSE); + + S9xSetSoundMute(TRUE); + + spc_core->init_header(buf); + spc_core->save_spc(buf); + + ignore = fwrite(buf, SNES_SPC::spc_file_size, 1, fs); + + fclose(fs); + + S9xSetSoundMute(FALSE); + + return (TRUE); +} + diff --git a/plugins/snes9x_gx/source/snes9x/snapshot.h b/plugins/snes9x_gx/source/snes9x/snapshot.h new file mode 100644 index 00000000..b3ead241 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/snapshot.h @@ -0,0 +1,199 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _SNAPSHOT_H_ +#define _SNAPSHOT_H_ + +#define SNAPSHOT_MAGIC "#!s9xsnp" +#define SNAPSHOT_VERSION 6 + +#define SUCCESS 1 +#define WRONG_FORMAT (-1) +#define WRONG_VERSION (-2) +#define FILE_NOT_FOUND (-3) +#define WRONG_MOVIE_SNAPSHOT (-4) +#define NOT_A_MOVIE_SNAPSHOT (-5) +#define SNAPSHOT_INCONSISTENT (-6) + +void S9xResetSaveTimer (bool8); +bool8 S9xFreezeGame (const char *); +bool8 S9xUnfreezeGame (const char *); +void S9xFreezeToStream (STREAM); +int S9xUnfreezeFromStream (STREAM); +bool8 S9xSPCDump (const char *); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/snes9x.h b/plugins/snes9x_gx/source/snes9x/snes9x.h new file mode 100644 index 00000000..a58be71f --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/snes9x.h @@ -0,0 +1,480 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _SNES9X_H_ +#define _SNES9X_H_ + +#ifndef VERSION +#define VERSION "1.53" +#endif + +#include "port.h" +#include "65c816.h" +#include "messages.h" + +#define S9X_ACCURACY_LEVEL 3 + +#ifdef ZLIB +#include <zlib.h> +#define STREAM gzFile +#define READ_STREAM(p, l, s) gzread(s, p, l) +#define WRITE_STREAM(p, l, s) gzwrite(s, p, l) +#define GETS_STREAM(p, l, s) gzgets(s, p, l) +#define GETC_STREAM(s) gzgetc(s) +#define OPEN_STREAM(f, m) gzopen(f, m) +#define REOPEN_STREAM(f, m) gzdopen(f, m) +#define FIND_STREAM(f) gztell(f) +#define REVERT_STREAM(f, o, s) gzseek(f, o, s) +#define CLOSE_STREAM(s) gzclose(s) +#else +#define STREAM FILE * +#define READ_STREAM(p, l, s) fread(p, 1, l, s) +#define WRITE_STREAM(p, l, s) fwrite(p, 1, l, s) +#define GETS_STREAM(p, l, s) fgets(p, l, s) +#define GETC_STREAM(s) fgetc(s) +#define OPEN_STREAM(f, m) fopen(f, m) +#define REOPEN_STREAM(f, m) fdopen(f, m) +#define FIND_STREAM(f) ftell(f) +#define REVERT_STREAM(f, o, s) fseek(f, o, s) +#define CLOSE_STREAM(s) fclose(s) +#endif + +#define SNES_WIDTH 256 +#define SNES_HEIGHT 224 +#define SNES_HEIGHT_EXTENDED 239 +#define MAX_SNES_WIDTH (SNES_WIDTH * 2) +#define MAX_SNES_HEIGHT (SNES_HEIGHT_EXTENDED * 2) +#define IMAGE_WIDTH (Settings.SupportHiRes ? MAX_SNES_WIDTH : SNES_WIDTH) +#define IMAGE_HEIGHT (Settings.SupportHiRes ? MAX_SNES_HEIGHT : SNES_HEIGHT_EXTENDED) + +#define NTSC_MASTER_CLOCK 21477272.0 +#define PAL_MASTER_CLOCK 21281370.0 + +#define SNES_MAX_NTSC_VCOUNTER 262 +#define SNES_MAX_PAL_VCOUNTER 312 +#define SNES_HCOUNTER_MAX 341 + +#define ONE_CYCLE 6 +#define SLOW_ONE_CYCLE 8 +#define TWO_CYCLES 12 +#define ONE_DOT_CYCLE 4 + +#define SNES_CYCLES_PER_SCANLINE (SNES_HCOUNTER_MAX * ONE_DOT_CYCLE) +#define SNES_SCANLINE_TIME (SNES_CYCLES_PER_SCANLINE / NTSC_MASTER_CLOCK) + +#define SNES_WRAM_REFRESH_HC_v1 530 +#define SNES_WRAM_REFRESH_HC_v2 538 +#define SNES_WRAM_REFRESH_CYCLES 40 + +#define SNES_HBLANK_START_HC 1096 // H=274 +#define SNES_HDMA_START_HC 1106 // FIXME: not true +#define SNES_HBLANK_END_HC 4 // H=1 +#define SNES_HDMA_INIT_HC 20 // FIXME: not true +#define SNES_RENDER_START_HC (48 * ONE_DOT_CYCLE) // FIXME: Snes9x renders a line at a time. + +#define SNES_TR_MASK (1 << 4) +#define SNES_TL_MASK (1 << 5) +#define SNES_X_MASK (1 << 6) +#define SNES_A_MASK (1 << 7) +#define SNES_RIGHT_MASK (1 << 8) +#define SNES_LEFT_MASK (1 << 9) +#define SNES_DOWN_MASK (1 << 10) +#define SNES_UP_MASK (1 << 11) +#define SNES_START_MASK (1 << 12) +#define SNES_SELECT_MASK (1 << 13) +#define SNES_Y_MASK (1 << 14) +#define SNES_B_MASK (1 << 15) + +#define DEBUG_MODE_FLAG (1 << 0) // debugger +#define TRACE_FLAG (1 << 1) // debugger +#define SINGLE_STEP_FLAG (1 << 2) // debugger +#define BREAK_FLAG (1 << 3) // debugger +#define NMI_FLAG (1 << 7) // CPU +#define IRQ_FLAG (1 << 11) // CPU +#define SCAN_KEYS_FLAG (1 << 4) // CPU +#define HALTED_FLAG (1 << 12) // APU +#define FRAME_ADVANCE_FLAG (1 << 9) + +#define ROM_NAME_LEN 23 +#define AUTO_FRAMERATE 200 + +struct SCPUState +{ + int32 Cycles; + int32 PrevCycles; + int32 V_Counter; + uint32 Flags; + uint8 *PCBase; + bool8 IRQActive; + int32 IRQPending; + int32 MemSpeed; + int32 MemSpeedx2; + int32 FastROMSpeed; + bool8 InDMA; + bool8 InHDMA; + bool8 InDMAorHDMA; + bool8 InWRAMDMAorHDMA; + uint8 HDMARanInDMA; + int32 CurrentDMAorHDMAChannel; + uint8 WhichEvent; + int32 NextEvent; + bool8 WaitingForInterrupt; + uint32 WaitAddress; + uint32 WaitCounter; + uint32 PBPCAtOpcodeStart; + uint32 AutoSaveTimer; + bool8 SRAMModified; +}; + +enum +{ + HC_HBLANK_START_EVENT = 1, + HC_IRQ_1_3_EVENT = 2, + HC_HDMA_START_EVENT = 3, + HC_IRQ_3_5_EVENT = 4, + HC_HCOUNTER_MAX_EVENT = 5, + HC_IRQ_5_7_EVENT = 6, + HC_HDMA_INIT_EVENT = 7, + HC_IRQ_7_9_EVENT = 8, + HC_RENDER_EVENT = 9, + HC_IRQ_9_A_EVENT = 10, + HC_WRAM_REFRESH_EVENT = 11, + HC_IRQ_A_1_EVENT = 12 +}; + +struct STimings +{ + int32 H_Max_Master; + int32 H_Max; + int32 V_Max_Master; + int32 V_Max; + int32 HBlankStart; + int32 HBlankEnd; + int32 HDMAInit; + int32 HDMAStart; + int32 NMITriggerPos; + int32 WRAMRefreshPos; + int32 RenderPos; + bool8 InterlaceField; + int32 DMACPUSync; // The cycles to synchronize DMA and CPU. Snes9x cannot emulate correctly. + int32 NMIDMADelay; // The delay of NMI trigger after DMA transfers. Snes9x cannot emulate correctly. + int32 IRQPendCount; // This value is just a hack, because Snes9x cannot emulate any events in an opcode. + int32 APUSpeedup; + bool8 APUAllowTimeOverflow; +}; + +struct SSettings +{ + bool8 TraceDMA; + bool8 TraceHDMA; + bool8 TraceVRAM; + bool8 TraceUnknownRegisters; + bool8 TraceDSP; + bool8 TraceHCEvent; + + bool8 SuperFX; + uint8 DSP; + bool8 SA1; + bool8 C4; + bool8 SDD1; + bool8 SPC7110; + bool8 SPC7110RTC; + bool8 OBC1; + uint8 SETA; + bool8 SRTC; + bool8 BS; + bool8 BSXItself; + bool8 BSXBootup; + bool8 MouseMaster; + bool8 SuperScopeMaster; + bool8 JustifierMaster; + bool8 MultiPlayer5Master; + + bool8 ForceLoROM; + bool8 ForceHiROM; + bool8 ForceHeader; + bool8 ForceNoHeader; + bool8 ForceInterleaved; + bool8 ForceInterleaved2; + bool8 ForceInterleaveGD24; + bool8 ForceNotInterleaved; + bool8 ForcePAL; + bool8 ForceNTSC; + bool8 PAL; + uint32 FrameTimePAL; + uint32 FrameTimeNTSC; + uint32 FrameTime; + + bool8 SoundSync; + bool8 SixteenBitSound; + uint32 SoundPlaybackRate; + uint32 SoundInputRate; + bool8 Stereo; + bool8 ReverseStereo; + bool8 Mute; + + bool8 SupportHiRes; + bool8 Transparency; + uint8 BG_Forced; + bool8 DisableGraphicWindows; + + bool8 DisplayFrameRate; + bool8 DisplayWatchedAddresses; + bool8 DisplayPressedKeys; + bool8 DisplayMovieFrame; + bool8 AutoDisplayMessages; + uint32 InitialInfoStringTimeout; + uint16 DisplayColor; + + bool8 Multi; + char CartAName[PATH_MAX + 1]; + char CartBName[PATH_MAX + 1]; + + bool8 DisableGameSpecificHacks; + bool8 ShutdownMaster; + bool8 Shutdown; + bool8 BlockInvalidVRAMAccessMaster; + bool8 BlockInvalidVRAMAccess; + bool8 DisableIRQ; + bool8 DisableHDMA; + int32 HDMATimingHack; + + bool8 ForcedPause; + bool8 Paused; + bool8 StopEmulation; + + uint32 SkipFrames; + uint32 TurboSkipFrames; + uint32 AutoMaxSkipFrames; + bool8 TurboMode; + uint32 HighSpeedSeek; + bool8 FrameAdvance; + + bool8 NetPlay; + bool8 NetPlayServer; + char ServerName[128]; + int Port; + + bool8 MovieTruncate; + bool8 MovieNotifyIgnored; + bool8 WrongMovieStateProtection; + bool8 DumpStreams; + int DumpStreamsMaxFrames; + + bool8 TakeScreenshot; + int8 StretchScreenshots; + bool8 SnapshotScreenshots; + + bool8 ApplyCheats; + bool8 NoPatch; + int32 AutoSaveDelay; + bool8 DontSaveOopsSnapshot; + bool8 UpAndDown; + + bool8 OpenGLEnable; +}; + +struct SSNESGameFixes +{ + uint8 SRAMInitialValue; + uint8 Uniracers; +}; + +enum +{ + PAUSE_NETPLAY_CONNECT = (1 << 0), + PAUSE_TOGGLE_FULL_SCREEN = (1 << 1), + PAUSE_EXIT = (1 << 2), + PAUSE_MENU = (1 << 3), + PAUSE_INACTIVE_WINDOW = (1 << 4), + PAUSE_WINDOW_ICONISED = (1 << 5), + PAUSE_RESTORE_GUI = (1 << 6), + PAUSE_FREEZE_FILE = (1 << 7) +}; + +void S9xSetPause(uint32); +void S9xClearPause(uint32); +void S9xExit(void); +void S9xMessage(int, int, const char *); + +extern struct SSettings Settings; +extern struct SCPUState CPU; +extern struct STimings Timings; +extern struct SSNESGameFixes SNESGameFixes; +extern char String[513]; + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/spc7110.cpp b/plugins/snes9x_gx/source/snes9x/spc7110.cpp new file mode 100644 index 00000000..5ead6581 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/spc7110.cpp @@ -0,0 +1,488 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + +/***** + * SPC7110 emulator - version 0.03 (2008-08-10) + * Copyright (c) 2008, byuu and neviksti + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * The software is provided "as is" and the author disclaims all warranties + * with regard to this software including all implied warranties of + * merchantibility and fitness, in no event shall the author be liable for + * any special, direct, indirect, or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether in an + * action of contract, negligence or other tortious action, arising out of + * or in connection with the use or performance of this software. + *****/ + + +#include <limits> + +#include "snes9x.h" +#include "memmap.h" +#include "srtc.h" +#include "display.h" + +#define memory_cartrom_size() Memory.CalculatedSize +#define memory_cartrom_read(a) Memory.ROM[(a)] +#define memory_cartrtc_read(a) RTCData.reg[(a)] +#define memory_cartrtc_write(a, b) { RTCData.reg[(a)] = (b); } +#define cartridge_info_spc7110rtc Settings.SPC7110RTC +#define cpu_regs_mdr OpenBus + +#define _SPC7110EMU_CPP_ + +#include <stdint.h> +#include "port.h" + +#include "spc7110emu.h" +#include "spc7110emu.cpp" + +SPC7110 s7emu; + +static void SetSPC7110SRAMMap (uint8); + + +void S9xInitSPC7110 (void) +{ + s7emu.power(); + memset(RTCData.reg, 0, 20); +} + +void S9xResetSPC7110 (void) +{ + s7emu.reset(); +} + +static void SetSPC7110SRAMMap (uint8 newstate) +{ + if (newstate & 0x80) + { + Memory.Map[0x006] = (uint8 *) Memory.MAP_HIROM_SRAM; + Memory.Map[0x007] = (uint8 *) Memory.MAP_HIROM_SRAM; + Memory.Map[0x306] = (uint8 *) Memory.MAP_HIROM_SRAM; + Memory.Map[0x307] = (uint8 *) Memory.MAP_HIROM_SRAM; + } + else + { + Memory.Map[0x006] = (uint8 *) Memory.MAP_RONLY_SRAM; + Memory.Map[0x007] = (uint8 *) Memory.MAP_RONLY_SRAM; + Memory.Map[0x306] = (uint8 *) Memory.MAP_RONLY_SRAM; + Memory.Map[0x307] = (uint8 *) Memory.MAP_RONLY_SRAM; + } +} + +uint8 * S9xGetBasePointerSPC7110 (uint32 address) +{ + uint32 i; + + switch (address & 0xf00000) + { + case 0xd00000: + i = s7emu.dx_offset; + break; + + case 0xe00000: + i = s7emu.ex_offset; + break; + + case 0xf00000: + i = s7emu.fx_offset; + break; + + default: + i = 0; + break; + } + + i += address & 0x0f0000; + + return (&Memory.ROM[i]); +} + +uint8 S9xGetSPC7110Byte (uint32 address) +{ + uint32 i; + + switch (address & 0xf00000) + { + case 0xd00000: + i = s7emu.dx_offset; + break; + + case 0xe00000: + i = s7emu.ex_offset; + break; + + case 0xf00000: + i = s7emu.fx_offset; + break; + + default: + i = 0; + break; + } + + i += address & 0x0fffff; + + return (Memory.ROM[i]); +} + +uint8 S9xGetSPC7110 (uint16 address) +{ + if (!Settings.SPC7110RTC && address > 0x483f) + return (OpenBus); + + return (s7emu.mmio_read(address)); +} + +void S9xSetSPC7110 (uint8 byte, uint16 address) +{ + if (!Settings.SPC7110RTC && address > 0x483f) + return; + + if (address == 0x4830) + SetSPC7110SRAMMap(byte); + + s7emu.mmio_write(address, byte); +} + +void S9xSPC7110PreSaveState (void) +{ + s7snap.r4801 = s7emu.r4801; + s7snap.r4802 = s7emu.r4802; + s7snap.r4803 = s7emu.r4803; + s7snap.r4804 = s7emu.r4804; + s7snap.r4805 = s7emu.r4805; + s7snap.r4806 = s7emu.r4806; + s7snap.r4807 = s7emu.r4807; + s7snap.r4808 = s7emu.r4808; + s7snap.r4809 = s7emu.r4809; + s7snap.r480a = s7emu.r480a; + s7snap.r480b = s7emu.r480b; + s7snap.r480c = s7emu.r480c; + + s7snap.r4811 = s7emu.r4811; + s7snap.r4812 = s7emu.r4812; + s7snap.r4813 = s7emu.r4813; + s7snap.r4814 = s7emu.r4814; + s7snap.r4815 = s7emu.r4815; + s7snap.r4816 = s7emu.r4816; + s7snap.r4817 = s7emu.r4817; + s7snap.r4818 = s7emu.r4818; + + s7snap.r481x = s7emu.r481x; + + s7snap.r4814_latch = s7emu.r4814_latch ? TRUE : FALSE; + s7snap.r4815_latch = s7emu.r4815_latch ? TRUE : FALSE; + + s7snap.r4820 = s7emu.r4820; + s7snap.r4821 = s7emu.r4821; + s7snap.r4822 = s7emu.r4822; + s7snap.r4823 = s7emu.r4823; + s7snap.r4824 = s7emu.r4824; + s7snap.r4825 = s7emu.r4825; + s7snap.r4826 = s7emu.r4826; + s7snap.r4827 = s7emu.r4827; + s7snap.r4828 = s7emu.r4828; + s7snap.r4829 = s7emu.r4829; + s7snap.r482a = s7emu.r482a; + s7snap.r482b = s7emu.r482b; + s7snap.r482c = s7emu.r482c; + s7snap.r482d = s7emu.r482d; + s7snap.r482e = s7emu.r482e; + s7snap.r482f = s7emu.r482f; + + s7snap.r4830 = s7emu.r4830; + s7snap.r4831 = s7emu.r4831; + s7snap.r4832 = s7emu.r4832; + s7snap.r4833 = s7emu.r4833; + s7snap.r4834 = s7emu.r4834; + + s7snap.dx_offset = (uint32) s7emu.dx_offset; + s7snap.ex_offset = (uint32) s7emu.ex_offset; + s7snap.fx_offset = (uint32) s7emu.fx_offset; + + s7snap.r4840 = s7emu.r4840; + s7snap.r4841 = s7emu.r4841; + s7snap.r4842 = s7emu.r4842; + + s7snap.rtc_state = (int32) s7emu.rtc_state; + s7snap.rtc_mode = (int32) s7emu.rtc_mode; + s7snap.rtc_index = (uint32) s7emu.rtc_index; + + s7snap.decomp_mode = (uint32) s7emu.decomp.decomp_mode; + s7snap.decomp_offset = (uint32) s7emu.decomp.decomp_offset; + + for (int i = 0; i < SPC7110_DECOMP_BUFFER_SIZE; i++) + s7snap.decomp_buffer[i] = s7emu.decomp.decomp_buffer[i]; + + s7snap.decomp_buffer_rdoffset = (uint32) s7emu.decomp.decomp_buffer_rdoffset; + s7snap.decomp_buffer_wroffset = (uint32) s7emu.decomp.decomp_buffer_wroffset; + s7snap.decomp_buffer_length = (uint32) s7emu.decomp.decomp_buffer_length; + + for (int i = 0; i < 32; i++) + { + s7snap.context[i].index = s7emu.decomp.context[i].index; + s7snap.context[i].invert = s7emu.decomp.context[i].invert; + } +} + +void S9xSPC7110PostLoadState (int version) +{ + s7emu.r4801 = s7snap.r4801; + s7emu.r4802 = s7snap.r4802; + s7emu.r4803 = s7snap.r4803; + s7emu.r4804 = s7snap.r4804; + s7emu.r4805 = s7snap.r4805; + s7emu.r4806 = s7snap.r4806; + s7emu.r4807 = s7snap.r4807; + s7emu.r4808 = s7snap.r4808; + s7emu.r4809 = s7snap.r4809; + s7emu.r480a = s7snap.r480a; + s7emu.r480b = s7snap.r480b; + s7emu.r480c = s7snap.r480c; + + s7emu.r4811 = s7snap.r4811; + s7emu.r4812 = s7snap.r4812; + s7emu.r4813 = s7snap.r4813; + s7emu.r4814 = s7snap.r4814; + s7emu.r4815 = s7snap.r4815; + s7emu.r4816 = s7snap.r4816; + s7emu.r4817 = s7snap.r4817; + s7emu.r4818 = s7snap.r4818; + + s7emu.r481x = s7snap.r481x; + + s7emu.r4814_latch = s7snap.r4814_latch ? true : false; + s7emu.r4815_latch = s7snap.r4815_latch ? true : false; + + s7emu.r4820 = s7snap.r4820; + s7emu.r4821 = s7snap.r4821; + s7emu.r4822 = s7snap.r4822; + s7emu.r4823 = s7snap.r4823; + s7emu.r4824 = s7snap.r4824; + s7emu.r4825 = s7snap.r4825; + s7emu.r4826 = s7snap.r4826; + s7emu.r4827 = s7snap.r4827; + s7emu.r4828 = s7snap.r4828; + s7emu.r4829 = s7snap.r4829; + s7emu.r482a = s7snap.r482a; + s7emu.r482b = s7snap.r482b; + s7emu.r482c = s7snap.r482c; + s7emu.r482d = s7snap.r482d; + s7emu.r482e = s7snap.r482e; + s7emu.r482f = s7snap.r482f; + + s7emu.r4830 = s7snap.r4830; + s7emu.r4831 = s7snap.r4831; + s7emu.r4832 = s7snap.r4832; + s7emu.r4833 = s7snap.r4833; + s7emu.r4834 = s7snap.r4834; + + s7emu.dx_offset = (unsigned) s7snap.dx_offset; + s7emu.ex_offset = (unsigned) s7snap.ex_offset; + s7emu.fx_offset = (unsigned) s7snap.fx_offset; + + s7emu.r4840 = s7snap.r4840; + s7emu.r4841 = s7snap.r4841; + s7emu.r4842 = s7snap.r4842; + + s7emu.rtc_state = (SPC7110::RTC_State) s7snap.rtc_state; + s7emu.rtc_mode = (SPC7110::RTC_Mode) s7snap.rtc_mode; + s7emu.rtc_index = (unsigned) s7snap.rtc_index; + + s7emu.decomp.decomp_mode = (unsigned) s7snap.decomp_mode; + s7emu.decomp.decomp_offset = (unsigned) s7snap.decomp_offset; + + for (int i = 0; i < SPC7110_DECOMP_BUFFER_SIZE; i++) + s7emu.decomp.decomp_buffer[i] = s7snap.decomp_buffer[i]; + + s7emu.decomp.decomp_buffer_rdoffset = (unsigned) s7snap.decomp_buffer_rdoffset; + s7emu.decomp.decomp_buffer_wroffset = (unsigned) s7snap.decomp_buffer_wroffset; + s7emu.decomp.decomp_buffer_length = (unsigned) s7snap.decomp_buffer_length; + + for (int i = 0; i < 32; i++) + { + s7emu.decomp.context[i].index = s7snap.context[i].index; + s7emu.decomp.context[i].invert = s7snap.context[i].invert; + } + + s7emu.update_time(0); +} diff --git a/plugins/snes9x_gx/source/snes9x/spc7110.h b/plugins/snes9x_gx/source/snes9x/spc7110.h new file mode 100644 index 00000000..7002b509 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/spc7110.h @@ -0,0 +1,275 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _SPC7110_H_ +#define _SPC7110_H_ + +#define SPC7110_DECOMP_BUFFER_SIZE 64 + +// for snapshot only +struct SSPC7110Snapshot +{ + uint8 r4801; + uint8 r4802; + uint8 r4803; + uint8 r4804; + uint8 r4805; + uint8 r4806; + uint8 r4807; + uint8 r4808; + uint8 r4809; + uint8 r480a; + uint8 r480b; + uint8 r480c; + + uint8 r4811; + uint8 r4812; + uint8 r4813; + uint8 r4814; + uint8 r4815; + uint8 r4816; + uint8 r4817; + uint8 r4818; + + uint8 r481x; + + bool8 r4814_latch; // bool + bool8 r4815_latch; // bool + + uint8 r4820; + uint8 r4821; + uint8 r4822; + uint8 r4823; + uint8 r4824; + uint8 r4825; + uint8 r4826; + uint8 r4827; + uint8 r4828; + uint8 r4829; + uint8 r482a; + uint8 r482b; + uint8 r482c; + uint8 r482d; + uint8 r482e; + uint8 r482f; + + uint8 r4830; + uint8 r4831; + uint8 r4832; + uint8 r4833; + uint8 r4834; + + uint32 dx_offset; // unsigned + uint32 ex_offset; // unsigned + uint32 fx_offset; // unsigned + + uint8 r4840; + uint8 r4841; + uint8 r4842; + + int32 rtc_state; // enum RTC_State + int32 rtc_mode; // enum RTC_Mode + uint32 rtc_index; // unsigned + + uint32 decomp_mode; // unsigned + uint32 decomp_offset; // unsigned + + uint8 decomp_buffer[SPC7110_DECOMP_BUFFER_SIZE]; + + uint32 decomp_buffer_rdoffset; // unsigned + uint32 decomp_buffer_wroffset; // unsigned + uint32 decomp_buffer_length; // unsigned + + struct ContextState + { + uint8 index; + uint8 invert; + } context[32]; +}; + +extern struct SSPC7110Snapshot s7snap; + +void S9xInitSPC7110 (void); +void S9xResetSPC7110 (void); +void S9xSPC7110PreSaveState (void); +void S9xSPC7110PostLoadState (int); +void S9xSetSPC7110 (uint8, uint16); +uint8 S9xGetSPC7110 (uint16); +uint8 S9xGetSPC7110Byte (uint32); +uint8 * S9xGetBasePointerSPC7110 (uint32); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/spc7110dec.cpp b/plugins/snes9x_gx/source/snes9x/spc7110dec.cpp new file mode 100644 index 00000000..65d55868 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/spc7110dec.cpp @@ -0,0 +1,529 @@ +/***** + * SPC7110 emulator - version 0.03 (2008-08-10) + * Copyright (c) 2008, byuu and neviksti + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * The software is provided "as is" and the author disclaims all warranties + * with regard to this software including all implied warranties of + * merchantibility and fitness, in no event shall the author be liable for + * any special, direct, indirect, or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether in an + * action of contract, negligence or other tortious action, arising out of + * or in connection with the use or performance of this software. + *****/ + + +#ifdef _SPC7110EMU_CPP_ + +uint8 SPC7110Decomp::read() { + if(decomp_buffer_length == 0) { + //decompress at least (decomp_buffer_size / 2) bytes to the buffer + switch(decomp_mode) { + case 0: mode0(false); break; + case 1: mode1(false); break; + case 2: mode2(false); break; + default: return 0x00; + } + } + + uint8 data = decomp_buffer[decomp_buffer_rdoffset++]; + decomp_buffer_rdoffset &= decomp_buffer_size - 1; + decomp_buffer_length--; + return data; +} + +void SPC7110Decomp::write(uint8 data) { + decomp_buffer[decomp_buffer_wroffset++] = data; + decomp_buffer_wroffset &= decomp_buffer_size - 1; + decomp_buffer_length++; +} + +uint8 SPC7110Decomp::dataread() { + unsigned size = memory_cartrom_size() - 0x100000; + while(decomp_offset >= size) decomp_offset -= size; + return memory_cartrom_read(0x100000 + decomp_offset++); +} + +void SPC7110Decomp::init(unsigned mode, unsigned offset, unsigned index) { + decomp_mode = mode; + decomp_offset = offset; + + decomp_buffer_rdoffset = 0; + decomp_buffer_wroffset = 0; + decomp_buffer_length = 0; + + //reset context states + for(unsigned i = 0; i < 32; i++) { + context[i].index = 0; + context[i].invert = 0; + } + + switch(decomp_mode) { + case 0: mode0(true); break; + case 1: mode1(true); break; + case 2: mode2(true); break; + } + + //decompress up to requested output data index + while(index--) read(); +} + +// + +void SPC7110Decomp::mode0(bool init) { + static uint8 val, in, span; + static int out, inverts, lps, in_count; + + if(init == true) { + out = inverts = lps = 0; + span = 0xff; + val = dataread(); + in = dataread(); + in_count = 8; + return; + } + + while(decomp_buffer_length < (decomp_buffer_size >> 1)) { + for(unsigned bit = 0; bit < 8; bit++) { + //get context + uint8 mask = (1 << (bit & 3)) - 1; + uint8 con = mask + ((inverts & mask) ^ (lps & mask)); + if(bit > 3) con += 15; + + //get prob and mps + unsigned prob = probability(con); + unsigned mps = (((out >> 15) & 1) ^ context[con].invert); + + //get bit + unsigned flag_lps; + if(val <= span - prob) { //mps + span = span - prob; + out = (out << 1) + mps; + flag_lps = 0; + } else { //lps + val = val - (span - (prob - 1)); + span = prob - 1; + out = (out << 1) + 1 - mps; + flag_lps = 1; + } + + //renormalize + unsigned shift = 0; + while(span < 0x7f) { + shift++; + + span = (span << 1) + 1; + val = (val << 1) + (in >> 7); + + in <<= 1; + if(--in_count == 0) { + in = dataread(); + in_count = 8; + } + } + + //update processing info + lps = (lps << 1) + flag_lps; + inverts = (inverts << 1) + context[con].invert; + + //update context state + if(flag_lps & toggle_invert(con)) context[con].invert ^= 1; + if(flag_lps) context[con].index = next_lps(con); + else if(shift) context[con].index = next_mps(con); + } + + //save byte + write(out); + } +} + +void SPC7110Decomp::mode1(bool init) { + static unsigned pixelorder[4], realorder[4]; + static uint8 in, val, span; + static int out, inverts, lps, in_count; + + if(init == true) { + for(unsigned i = 0; i < 4; i++) pixelorder[i] = i; + out = inverts = lps = 0; + span = 0xff; + val = dataread(); + in = dataread(); + in_count = 8; + return; + } + + while(decomp_buffer_length < (decomp_buffer_size >> 1)) { + for(unsigned pixel = 0; pixel < 8; pixel++) { + //get first symbol context + unsigned a = ((out >> (1 * 2)) & 3); + unsigned b = ((out >> (7 * 2)) & 3); + unsigned c = ((out >> (8 * 2)) & 3); + unsigned con = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c); + + //update pixel order + unsigned m, n; + for(m = 0; m < 4; m++) if(pixelorder[m] == a) break; + for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1]; + pixelorder[0] = a; + + //calculate the real pixel order + for(m = 0; m < 4; m++) realorder[m] = pixelorder[m]; + + //rotate reference pixel c value to top + for(m = 0; m < 4; m++) if(realorder[m] == c) break; + for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; + realorder[0] = c; + + //rotate reference pixel b value to top + for(m = 0; m < 4; m++) if(realorder[m] == b) break; + for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; + realorder[0] = b; + + //rotate reference pixel a value to top + for(m = 0; m < 4; m++) if(realorder[m] == a) break; + for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; + realorder[0] = a; + + //get 2 symbols + for(unsigned bit = 0; bit < 2; bit++) { + //get prob + unsigned prob = probability(con); + + //get symbol + unsigned flag_lps; + if(val <= span - prob) { //mps + span = span - prob; + flag_lps = 0; + } else { //lps + val = val - (span - (prob - 1)); + span = prob - 1; + flag_lps = 1; + } + + //renormalize + unsigned shift = 0; + while(span < 0x7f) { + shift++; + + span = (span << 1) + 1; + val = (val << 1) + (in >> 7); + + in <<= 1; + if(--in_count == 0) { + in = dataread(); + in_count = 8; + } + } + + //update processing info + lps = (lps << 1) + flag_lps; + inverts = (inverts << 1) + context[con].invert; + + //update context state + if(flag_lps & toggle_invert(con)) context[con].invert ^= 1; + if(flag_lps) context[con].index = next_lps(con); + else if(shift) context[con].index = next_mps(con); + + //get next context + con = 5 + (con << 1) + ((lps ^ inverts) & 1); + } + + //get pixel + b = realorder[(lps ^ inverts) & 3]; + out = (out << 2) + b; + } + + //turn pixel data into bitplanes + unsigned data = morton_2x8(out); + write(data >> 8); + write(data >> 0); + } +} + +void SPC7110Decomp::mode2(bool init) { + static unsigned pixelorder[16], realorder[16]; + static uint8 bitplanebuffer[16], buffer_index; + static uint8 in, val, span; + static int out0, out1, inverts, lps, in_count; + + if(init == true) { + for(unsigned i = 0; i < 16; i++) pixelorder[i] = i; + buffer_index = 0; + out0 = out1 = inverts = lps = 0; + span = 0xff; + val = dataread(); + in = dataread(); + in_count = 8; + return; + } + + while(decomp_buffer_length < (decomp_buffer_size >> 1)) { + for(unsigned pixel = 0; pixel < 8; pixel++) { + //get first symbol context + unsigned a = ((out0 >> (0 * 4)) & 15); + unsigned b = ((out0 >> (7 * 4)) & 15); + unsigned c = ((out1 >> (0 * 4)) & 15); + unsigned con = 0; + unsigned refcon = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c); + + //update pixel order + unsigned m, n; + for(m = 0; m < 16; m++) if(pixelorder[m] == a) break; + for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1]; + pixelorder[0] = a; + + //calculate the real pixel order + for(m = 0; m < 16; m++) realorder[m] = pixelorder[m]; + + //rotate reference pixel c value to top + for(m = 0; m < 16; m++) if(realorder[m] == c) break; + for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; + realorder[0] = c; + + //rotate reference pixel b value to top + for(m = 0; m < 16; m++) if(realorder[m] == b) break; + for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; + realorder[0] = b; + + //rotate reference pixel a value to top + for(m = 0; m < 16; m++) if(realorder[m] == a) break; + for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; + realorder[0] = a; + + //get 4 symbols + for(unsigned bit = 0; bit < 4; bit++) { + //get prob + unsigned prob = probability(con); + + //get symbol + unsigned flag_lps; + if(val <= span - prob) { //mps + span = span - prob; + flag_lps = 0; + } else { //lps + val = val - (span - (prob - 1)); + span = prob - 1; + flag_lps = 1; + } + + //renormalize + unsigned shift = 0; + while(span < 0x7f) { + shift++; + + span = (span << 1) + 1; + val = (val << 1) + (in >> 7); + + in <<= 1; + if(--in_count == 0) { + in = dataread(); + in_count = 8; + } + } + + //update processing info + lps = (lps << 1) + flag_lps; + unsigned invertbit = context[con].invert; + inverts = (inverts << 1) + invertbit; + + //update context state + if(flag_lps & toggle_invert(con)) context[con].invert ^= 1; + if(flag_lps) context[con].index = next_lps(con); + else if(shift) context[con].index = next_mps(con); + + //get next context + con = mode2_context_table[con][flag_lps ^ invertbit] + (con == 1 ? refcon : 0); + } + + //get pixel + b = realorder[(lps ^ inverts) & 0x0f]; + out1 = (out1 << 4) + ((out0 >> 28) & 0x0f); + out0 = (out0 << 4) + b; + } + + //convert pixel data into bitplanes + unsigned data = morton_4x8(out0); + write(data >> 24); + write(data >> 16); + bitplanebuffer[buffer_index++] = data >> 8; + bitplanebuffer[buffer_index++] = data >> 0; + + if(buffer_index == 16) { + for(unsigned i = 0; i < 16; i++) write(bitplanebuffer[i]); + buffer_index = 0; + } + } +} + +// + +const uint8 SPC7110Decomp::evolution_table[53][4] = { +//{ prob, nextlps, nextmps, toggle invert }, + + { 0x5a, 1, 1, 1 }, + { 0x25, 6, 2, 0 }, + { 0x11, 8, 3, 0 }, + { 0x08, 10, 4, 0 }, + { 0x03, 12, 5, 0 }, + { 0x01, 15, 5, 0 }, + + { 0x5a, 7, 7, 1 }, + { 0x3f, 19, 8, 0 }, + { 0x2c, 21, 9, 0 }, + { 0x20, 22, 10, 0 }, + { 0x17, 23, 11, 0 }, + { 0x11, 25, 12, 0 }, + { 0x0c, 26, 13, 0 }, + { 0x09, 28, 14, 0 }, + { 0x07, 29, 15, 0 }, + { 0x05, 31, 16, 0 }, + { 0x04, 32, 17, 0 }, + { 0x03, 34, 18, 0 }, + { 0x02, 35, 5, 0 }, + + { 0x5a, 20, 20, 1 }, + { 0x48, 39, 21, 0 }, + { 0x3a, 40, 22, 0 }, + { 0x2e, 42, 23, 0 }, + { 0x26, 44, 24, 0 }, + { 0x1f, 45, 25, 0 }, + { 0x19, 46, 26, 0 }, + { 0x15, 25, 27, 0 }, + { 0x11, 26, 28, 0 }, + { 0x0e, 26, 29, 0 }, + { 0x0b, 27, 30, 0 }, + { 0x09, 28, 31, 0 }, + { 0x08, 29, 32, 0 }, + { 0x07, 30, 33, 0 }, + { 0x05, 31, 34, 0 }, + { 0x04, 33, 35, 0 }, + { 0x04, 33, 36, 0 }, + { 0x03, 34, 37, 0 }, + { 0x02, 35, 38, 0 }, + { 0x02, 36, 5, 0 }, + + { 0x58, 39, 40, 1 }, + { 0x4d, 47, 41, 0 }, + { 0x43, 48, 42, 0 }, + { 0x3b, 49, 43, 0 }, + { 0x34, 50, 44, 0 }, + { 0x2e, 51, 45, 0 }, + { 0x29, 44, 46, 0 }, + { 0x25, 45, 24, 0 }, + + { 0x56, 47, 48, 1 }, + { 0x4f, 47, 49, 0 }, + { 0x47, 48, 50, 0 }, + { 0x41, 49, 51, 0 }, + { 0x3c, 50, 52, 0 }, + { 0x37, 51, 43, 0 }, +}; + +const uint8 SPC7110Decomp::mode2_context_table[32][2] = { +//{ next 0, next 1 }, + + { 1, 2 }, + + { 3, 8 }, + { 13, 14 }, + + { 15, 16 }, + { 17, 18 }, + { 19, 20 }, + { 21, 22 }, + { 23, 24 }, + { 25, 26 }, + { 25, 26 }, + { 25, 26 }, + { 25, 26 }, + { 25, 26 }, + { 27, 28 }, + { 29, 30 }, + + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + + { 31, 31 }, +}; + +uint8 SPC7110Decomp::probability (unsigned n) { return evolution_table[context[n].index][0]; } +uint8 SPC7110Decomp::next_lps (unsigned n) { return evolution_table[context[n].index][1]; } +uint8 SPC7110Decomp::next_mps (unsigned n) { return evolution_table[context[n].index][2]; } +bool SPC7110Decomp::toggle_invert(unsigned n) { return evolution_table[context[n].index][3]; } + +unsigned SPC7110Decomp::morton_2x8(unsigned data) { + //reverse morton lookup: de-interleave two 8-bit values + //15, 13, 11, 9, 7, 5, 3, 1 -> 15- 8 + //14, 12, 10, 8, 6, 4, 2, 0 -> 7- 0 + return morton16[0][(data >> 0) & 255] + morton16[1][(data >> 8) & 255]; +} + +unsigned SPC7110Decomp::morton_4x8(unsigned data) { + //reverse morton lookup: de-interleave four 8-bit values + //31, 27, 23, 19, 15, 11, 7, 3 -> 31-24 + //30, 26, 22, 18, 14, 10, 6, 2 -> 23-16 + //29, 25, 21, 17, 13, 9, 5, 1 -> 15- 8 + //28, 24, 20, 16, 12, 8, 4, 0 -> 7- 0 + return morton32[0][(data >> 0) & 255] + morton32[1][(data >> 8) & 255] + + morton32[2][(data >> 16) & 255] + morton32[3][(data >> 24) & 255]; +} + +// + +void SPC7110Decomp::reset() { + //mode 3 is invalid; this is treated as a special case to always return 0x00 + //set to mode 3 so that reading decomp port before starting first decomp will return 0x00 + decomp_mode = 3; + + decomp_buffer_rdoffset = 0; + decomp_buffer_wroffset = 0; + decomp_buffer_length = 0; +} + +SPC7110Decomp::SPC7110Decomp() { + decomp_buffer = new uint8_t[decomp_buffer_size]; + reset(); + + //initialize reverse morton lookup tables + for(unsigned i = 0; i < 256; i++) { + #define map(x, y) (((i >> x) & 1) << y) + //2x8-bit + morton16[1][i] = map(7, 15) + map(6, 7) + map(5, 14) + map(4, 6) + + map(3, 13) + map(2, 5) + map(1, 12) + map(0, 4); + morton16[0][i] = map(7, 11) + map(6, 3) + map(5, 10) + map(4, 2) + + map(3, 9) + map(2, 1) + map(1, 8) + map(0, 0); + //4x8-bit + morton32[3][i] = map(7, 31) + map(6, 23) + map(5, 15) + map(4, 7) + + map(3, 30) + map(2, 22) + map(1, 14) + map(0, 6); + morton32[2][i] = map(7, 29) + map(6, 21) + map(5, 13) + map(4, 5) + + map(3, 28) + map(2, 20) + map(1, 12) + map(0, 4); + morton32[1][i] = map(7, 27) + map(6, 19) + map(5, 11) + map(4, 3) + + map(3, 26) + map(2, 18) + map(1, 10) + map(0, 2); + morton32[0][i] = map(7, 25) + map(6, 17) + map(5, 9) + map(4, 1) + + map(3, 24) + map(2, 16) + map(1, 8) + map(0, 0); + #undef map + } +} + +SPC7110Decomp::~SPC7110Decomp() { + delete[] decomp_buffer; +} + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/spc7110dec.h b/plugins/snes9x_gx/source/snes9x/spc7110dec.h new file mode 100644 index 00000000..3a9c7ce3 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/spc7110dec.h @@ -0,0 +1,67 @@ +/***** + * SPC7110 emulator - version 0.03 (2008-08-10) + * Copyright (c) 2008, byuu and neviksti + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * The software is provided "as is" and the author disclaims all warranties + * with regard to this software including all implied warranties of + * merchantibility and fitness, in no event shall the author be liable for + * any special, direct, indirect, or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether in an + * action of contract, negligence or other tortious action, arising out of + * or in connection with the use or performance of this software. + *****/ + + +#ifndef _SPC7110DEC_H_ +#define _SPC7110DEC_H_ + +class SPC7110Decomp { +public: + uint8 read(); + void init(unsigned mode, unsigned offset, unsigned index); + void reset(); + + SPC7110Decomp(); + ~SPC7110Decomp(); + + unsigned decomp_mode; + unsigned decomp_offset; + + //read() will spool chunks half the size of decomp_buffer_size + enum { decomp_buffer_size = SPC7110_DECOMP_BUFFER_SIZE }; //must be >= 64, and must be a power of two + uint8 *decomp_buffer; + unsigned decomp_buffer_rdoffset; + unsigned decomp_buffer_wroffset; + unsigned decomp_buffer_length; + + void write(uint8 data); + uint8 dataread(); + + void mode0(bool init); + void mode1(bool init); + void mode2(bool init); + + static const uint8 evolution_table[53][4]; + static const uint8 mode2_context_table[32][2]; + + struct ContextState { + uint8 index; + uint8 invert; + } context[32]; + + uint8 probability(unsigned n); + uint8 next_lps(unsigned n); + uint8 next_mps(unsigned n); + bool toggle_invert(unsigned n); + + unsigned morton16[2][256]; + unsigned morton32[4][256]; + unsigned morton_2x8(unsigned data); + unsigned morton_4x8(unsigned data); +}; + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/spc7110emu.cpp b/plugins/snes9x_gx/source/snes9x/spc7110emu.cpp new file mode 100644 index 00000000..69b3e7d5 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/spc7110emu.cpp @@ -0,0 +1,647 @@ +/***** + * SPC7110 emulator - version 0.03 (2008-08-10) + * Copyright (c) 2008, byuu and neviksti + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * The software is provided "as is" and the author disclaims all warranties + * with regard to this software including all implied warranties of + * merchantibility and fitness, in no event shall the author be liable for + * any special, direct, indirect, or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether in an + * action of contract, negligence or other tortious action, arising out of + * or in connection with the use or performance of this software. + *****/ + + +#ifdef _SPC7110EMU_CPP_ + +#include "spc7110dec.cpp" + +const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + +void SPC7110::power() { + reset(); +} + +void SPC7110::reset() { + r4801 = 0x00; + r4802 = 0x00; + r4803 = 0x00; + r4804 = 0x00; + r4805 = 0x00; + r4806 = 0x00; + r4807 = 0x00; + r4808 = 0x00; + r4809 = 0x00; + r480a = 0x00; + r480b = 0x00; + r480c = 0x00; + + decomp.reset(); + + r4811 = 0x00; + r4812 = 0x00; + r4813 = 0x00; + r4814 = 0x00; + r4815 = 0x00; + r4816 = 0x00; + r4817 = 0x00; + r4818 = 0x00; + + r481x = 0x00; + r4814_latch = false; + r4815_latch = false; + + r4820 = 0x00; + r4821 = 0x00; + r4822 = 0x00; + r4823 = 0x00; + r4824 = 0x00; + r4825 = 0x00; + r4826 = 0x00; + r4827 = 0x00; + r4828 = 0x00; + r4829 = 0x00; + r482a = 0x00; + r482b = 0x00; + r482c = 0x00; + r482d = 0x00; + r482e = 0x00; + r482f = 0x00; + + r4830 = 0x00; + mmio_write(0x4831, 0); + mmio_write(0x4832, 1); + mmio_write(0x4833, 2); + r4834 = 0x00; + + r4840 = 0x00; + r4841 = 0x00; + r4842 = 0x00; + + if(cartridge_info_spc7110rtc) { + rtc_state = RTCS_Inactive; + rtc_mode = RTCM_Linear; + rtc_index = 0; + } +} + +unsigned SPC7110::datarom_addr(unsigned addr) { + unsigned size = memory_cartrom_size() - 0x100000; + while(addr >= size) addr -= size; + return addr + 0x100000; +} + +unsigned SPC7110::data_pointer() { return r4811 + (r4812 << 8) + (r4813 << 16); } +unsigned SPC7110::data_adjust() { return r4814 + (r4815 << 8); } +unsigned SPC7110::data_increment() { return r4816 + (r4817 << 8); } +void SPC7110::set_data_pointer(unsigned addr) { r4811 = addr; r4812 = addr >> 8; r4813 = addr >> 16; } +void SPC7110::set_data_adjust(unsigned addr) { r4814 = addr; r4815 = addr >> 8; } + +void SPC7110::update_time(int offset) { + time_t rtc_time + = (memory_cartrtc_read(16) << 0) + | (memory_cartrtc_read(17) << 8) + | (memory_cartrtc_read(18) << 16) + | (memory_cartrtc_read(19) << 24); + time_t current_time = time(0) - offset; + + //sizeof(time_t) is platform-dependent; though memory::cartrtc needs to be platform-agnostic. + //yet platforms with 32-bit signed time_t will overflow every ~68 years. handle this by + //accounting for overflow at the cost of 1-bit precision (to catch underflow). this will allow + //memory::cartrtc timestamp to remain valid for up to ~34 years from the last update, even if + //time_t overflows. calculation should be valid regardless of number representation, time_t size, + //or whether time_t is signed or unsigned. + time_t diff + = (current_time >= rtc_time) + ? (current_time - rtc_time) + : (std::numeric_limits<time_t>::max() - rtc_time + current_time + 1); //compensate for overflow + if(diff > std::numeric_limits<time_t>::max() / 2) diff = 0; //compensate for underflow + + bool update = true; + if(memory_cartrtc_read(13) & 1) update = false; //do not update if CR0 timer disable flag is set + if(memory_cartrtc_read(15) & 3) update = false; //do not update if CR2 timer disable flags are set + + if(diff > 0 && update == true) { + unsigned second = memory_cartrtc_read( 0) + memory_cartrtc_read( 1) * 10; + unsigned minute = memory_cartrtc_read( 2) + memory_cartrtc_read( 3) * 10; + unsigned hour = memory_cartrtc_read( 4) + memory_cartrtc_read( 5) * 10; + unsigned day = memory_cartrtc_read( 6) + memory_cartrtc_read( 7) * 10; + unsigned month = memory_cartrtc_read( 8) + memory_cartrtc_read( 9) * 10; + unsigned year = memory_cartrtc_read(10) + memory_cartrtc_read(11) * 10; + unsigned weekday = memory_cartrtc_read(12); + + day--; + month--; + year += (year >= 90) ? 1900 : 2000; //range = 1990-2089 + + second += diff; + while(second >= 60) { + second -= 60; + + minute++; + if(minute < 60) continue; + minute = 0; + + hour++; + if(hour < 24) continue; + hour = 0; + + day++; + weekday = (weekday + 1) % 7; + unsigned days = months[month % 12]; + if(days == 28) { + bool leapyear = false; + if((year % 4) == 0) { + leapyear = true; + if((year % 100) == 0 && (year % 400) != 0) leapyear = false; + } + if(leapyear) days++; + } + if(day < days) continue; + day = 0; + + month++; + if(month < 12) continue; + month = 0; + + year++; + } + + day++; + month++; + year %= 100; + + memory_cartrtc_write( 0, second % 10); + memory_cartrtc_write( 1, second / 10); + memory_cartrtc_write( 2, minute % 10); + memory_cartrtc_write( 3, minute / 10); + memory_cartrtc_write( 4, hour % 10); + memory_cartrtc_write( 5, hour / 10); + memory_cartrtc_write( 6, day % 10); + memory_cartrtc_write( 7, day / 10); + memory_cartrtc_write( 8, month % 10); + memory_cartrtc_write( 9, month / 10); + memory_cartrtc_write(10, year % 10); + memory_cartrtc_write(11, (year / 10) % 10); + memory_cartrtc_write(12, weekday % 7); + } + + memory_cartrtc_write(16, current_time >> 0); + memory_cartrtc_write(17, current_time >> 8); + memory_cartrtc_write(18, current_time >> 16); + memory_cartrtc_write(19, current_time >> 24); +} + +uint8 SPC7110::mmio_read(unsigned addr) { + addr &= 0xffff; + + switch(addr) { + //================== + //decompression unit + //================== + + case 0x4800: { + uint16 counter = (r4809 + (r480a << 8)); + counter--; + r4809 = counter; + r480a = counter >> 8; + return decomp.read(); + } + case 0x4801: return r4801; + case 0x4802: return r4802; + case 0x4803: return r4803; + case 0x4804: return r4804; + case 0x4805: return r4805; + case 0x4806: return r4806; + case 0x4807: return r4807; + case 0x4808: return r4808; + case 0x4809: return r4809; + case 0x480a: return r480a; + case 0x480b: return r480b; + case 0x480c: { + uint8 status = r480c; + r480c &= 0x7f; + return status; + } + + //============== + //data port unit + //============== + + case 0x4810: { + if(r481x != 0x07) return 0x00; + + unsigned addr = data_pointer(); + unsigned adjust = data_adjust(); + if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend + + unsigned adjustaddr = addr; + if(r4818 & 2) { + adjustaddr += adjust; + set_data_adjust(adjust + 1); + } + + uint8 data = memory_cartrom_read(datarom_addr(adjustaddr)); + if(!(r4818 & 2)) { + unsigned increment = (r4818 & 1) ? data_increment() : 1; + if(r4818 & 4) increment = (int16)increment; //16-bit sign extend + + if((r4818 & 16) == 0) { + set_data_pointer(addr + increment); + } else { + set_data_adjust(adjust + increment); + } + } + + return data; + } + case 0x4811: return r4811; + case 0x4812: return r4812; + case 0x4813: return r4813; + case 0x4814: return r4814; + case 0x4815: return r4815; + case 0x4816: return r4816; + case 0x4817: return r4817; + case 0x4818: return r4818; + case 0x481a: { + if(r481x != 0x07) return 0x00; + + unsigned addr = data_pointer(); + unsigned adjust = data_adjust(); + if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend + + uint8 data = memory_cartrom_read(datarom_addr(addr + adjust)); + if((r4818 & 0x60) == 0x60) { + if((r4818 & 16) == 0) { + set_data_pointer(addr + adjust); + } else { + set_data_adjust(adjust + adjust); + } + } + + return data; + } + + //========= + //math unit + //========= + + case 0x4820: return r4820; + case 0x4821: return r4821; + case 0x4822: return r4822; + case 0x4823: return r4823; + case 0x4824: return r4824; + case 0x4825: return r4825; + case 0x4826: return r4826; + case 0x4827: return r4827; + case 0x4828: return r4828; + case 0x4829: return r4829; + case 0x482a: return r482a; + case 0x482b: return r482b; + case 0x482c: return r482c; + case 0x482d: return r482d; + case 0x482e: return r482e; + case 0x482f: { + uint8 status = r482f; + r482f &= 0x7f; + return status; + } + + //=================== + //memory mapping unit + //=================== + + case 0x4830: return r4830; + case 0x4831: return r4831; + case 0x4832: return r4832; + case 0x4833: return r4833; + case 0x4834: return r4834; + + //==================== + //real-time clock unit + //==================== + + case 0x4840: return r4840; + case 0x4841: { + if(rtc_state == RTCS_Inactive || rtc_state == RTCS_ModeSelect) return 0x00; + + r4842 = 0x80; + uint8 data = memory_cartrtc_read(rtc_index); + rtc_index = (rtc_index + 1) & 15; + return data; + } + case 0x4842: { + uint8 status = r4842; + r4842 &= 0x7f; + return status; + } + } + + return cpu_regs_mdr; +} + +void SPC7110::mmio_write(unsigned addr, uint8 data) { + addr &= 0xffff; + + switch(addr) { + //================== + //decompression unit + //================== + + case 0x4801: r4801 = data; break; + case 0x4802: r4802 = data; break; + case 0x4803: r4803 = data; break; + case 0x4804: r4804 = data; break; + case 0x4805: r4805 = data; break; + case 0x4806: { + r4806 = data; + + unsigned table = (r4801 + (r4802 << 8) + (r4803 << 16)); + unsigned index = (r4804 << 2); + //unsigned length = (r4809 + (r480a << 8)); + unsigned addr = datarom_addr(table + index); + unsigned mode = (memory_cartrom_read(addr + 0)); + unsigned offset = (memory_cartrom_read(addr + 1) << 16) + + (memory_cartrom_read(addr + 2) << 8) + + (memory_cartrom_read(addr + 3) << 0); + + decomp.init(mode, offset, (r4805 + (r4806 << 8)) << mode); + r480c = 0x80; + } break; + + case 0x4807: r4807 = data; break; + case 0x4808: r4808 = data; break; + case 0x4809: r4809 = data; break; + case 0x480a: r480a = data; break; + case 0x480b: r480b = data; break; + + //============== + //data port unit + //============== + + case 0x4811: r4811 = data; r481x |= 0x01; break; + case 0x4812: r4812 = data; r481x |= 0x02; break; + case 0x4813: r4813 = data; r481x |= 0x04; break; + case 0x4814: { + r4814 = data; + r4814_latch = true; + if(!r4815_latch) break; + if(!(r4818 & 2)) break; + if(r4818 & 0x10) break; + + if((r4818 & 0x60) == 0x20) { + unsigned increment = data_adjust() & 0xff; + if(r4818 & 8) increment = (int8)increment; //8-bit sign extend + set_data_pointer(data_pointer() + increment); + } else if((r4818 & 0x60) == 0x40) { + unsigned increment = data_adjust(); + if(r4818 & 8) increment = (int16)increment; //16-bit sign extend + set_data_pointer(data_pointer() + increment); + } + } break; + case 0x4815: { + r4815 = data; + r4815_latch = true; + if(!r4814_latch) break; + if(!(r4818 & 2)) break; + if(r4818 & 0x10) break; + + if((r4818 & 0x60) == 0x20) { + unsigned increment = data_adjust() & 0xff; + if(r4818 & 8) increment = (int8)increment; //8-bit sign extend + set_data_pointer(data_pointer() + increment); + } else if((r4818 & 0x60) == 0x40) { + unsigned increment = data_adjust(); + if(r4818 & 8) increment = (int16)increment; //16-bit sign extend + set_data_pointer(data_pointer() + increment); + } + } break; + case 0x4816: r4816 = data; break; + case 0x4817: r4817 = data; break; + case 0x4818: { + if(r481x != 0x07) break; + + r4818 = data; + r4814_latch = r4815_latch = false; + } break; + + //========= + //math unit + //========= + + case 0x4820: r4820 = data; break; + case 0x4821: r4821 = data; break; + case 0x4822: r4822 = data; break; + case 0x4823: r4823 = data; break; + case 0x4824: r4824 = data; break; + case 0x4825: { + r4825 = data; + + if(r482e & 1) { + //signed 16-bit x 16-bit multiplication + int16 r0 = (int16)(r4824 + (r4825 << 8)); + int16 r1 = (int16)(r4820 + (r4821 << 8)); + + signed result = r0 * r1; + r4828 = result; + r4829 = result >> 8; + r482a = result >> 16; + r482b = result >> 24; + } else { + //unsigned 16-bit x 16-bit multiplication + uint16 r0 = (uint16)(r4824 + (r4825 << 8)); + uint16 r1 = (uint16)(r4820 + (r4821 << 8)); + + unsigned result = r0 * r1; + r4828 = result; + r4829 = result >> 8; + r482a = result >> 16; + r482b = result >> 24; + } + + r482f = 0x80; + } break; + case 0x4826: r4826 = data; break; + case 0x4827: { + r4827 = data; + + if(r482e & 1) { + //signed 32-bit x 16-bit division + int32 dividend = (int32)(r4820 + (r4821 << 8) + (r4822 << 16) + (r4823 << 24)); + int16 divisor = (int16)(r4826 + (r4827 << 8)); + + int32 quotient; + int16 remainder; + + if(divisor) { + quotient = (int32)(dividend / divisor); + remainder = (int32)(dividend % divisor); + } else { + //illegal division by zero + quotient = 0; + remainder = dividend & 0xffff; + } + + r4828 = quotient; + r4829 = quotient >> 8; + r482a = quotient >> 16; + r482b = quotient >> 24; + + r482c = remainder; + r482d = remainder >> 8; + } else { + //unsigned 32-bit x 16-bit division + uint32 dividend = (uint32)(r4820 + (r4821 << 8) + (r4822 << 16) + (r4823 << 24)); + uint16 divisor = (uint16)(r4826 + (r4827 << 8)); + + uint32 quotient; + uint16 remainder; + + if(divisor) { + quotient = (uint32)(dividend / divisor); + remainder = (uint16)(dividend % divisor); + } else { + //illegal division by zero + quotient = 0; + remainder = dividend & 0xffff; + } + + r4828 = quotient; + r4829 = quotient >> 8; + r482a = quotient >> 16; + r482b = quotient >> 24; + + r482c = remainder; + r482d = remainder >> 8; + } + + r482f = 0x80; + } break; + + case 0x482e: { + //reset math unit + r4820 = r4821 = r4822 = r4823 = 0; + r4824 = r4825 = r4826 = r4827 = 0; + r4828 = r4829 = r482a = r482b = 0; + r482c = r482d = 0; + + r482e = data; + } break; + + //=================== + //memory mapping unit + //=================== + + case 0x4830: r4830 = data; break; + + case 0x4831: { + r4831 = data; + dx_offset = datarom_addr((data & 7) * 0x100000); + } break; + + case 0x4832: { + r4832 = data; + ex_offset = datarom_addr((data & 7) * 0x100000); + } break; + + case 0x4833: { + r4833 = data; + fx_offset = datarom_addr((data & 7) * 0x100000); + } break; + + case 0x4834: r4834 = data; break; + + //==================== + //real-time clock unit + //==================== + + case 0x4840: { + r4840 = data; + if(!(r4840 & 1)) { + //disable RTC + rtc_state = RTCS_Inactive; + update_time(); + } else { + //enable RTC + r4842 = 0x80; + rtc_state = RTCS_ModeSelect; + } + } break; + + case 0x4841: { + r4841 = data; + + switch(rtc_state) { + case RTCS_ModeSelect: { + if(data == RTCM_Linear || data == RTCM_Indexed) { + r4842 = 0x80; + rtc_state = RTCS_IndexSelect; + rtc_mode = (RTC_Mode)data; + rtc_index = 0; + } + } break; + + case RTCS_IndexSelect: { + r4842 = 0x80; + rtc_index = data & 15; + if(rtc_mode == RTCM_Linear) rtc_state = RTCS_Write; + } break; + + case RTCS_Write: { + r4842 = 0x80; + + //control register 0 + if(rtc_index == 13) { + //increment second counter + if(data & 2) update_time(+1); + + //round minute counter + if(data & 8) { + update_time(); + + unsigned second = memory_cartrtc_read( 0) + memory_cartrtc_read( 1) * 10; + //clear seconds + memory_cartrtc_write(0, 0); + memory_cartrtc_write(1, 0); + + if(second >= 30) update_time(+60); + } + } + + //control register 2 + if(rtc_index == 15) { + //disable timer and clear second counter + if((data & 1) && !(memory_cartrtc_read(15) & 1)) { + update_time(); + + //clear seconds + memory_cartrtc_write(0, 0); + memory_cartrtc_write(1, 0); + } + + //disable timer + if((data & 2) && !(memory_cartrtc_read(15) & 2)) { + update_time(); + } + } + + memory_cartrtc_write(rtc_index, data & 15); + rtc_index = (rtc_index + 1) & 15; + } break; + + case RTCS_Inactive: { + } break; + } //switch(rtc_state) + } break; + } +} + +SPC7110::SPC7110() { +} + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/spc7110emu.h b/plugins/snes9x_gx/source/snes9x/spc7110emu.h new file mode 100644 index 00000000..5f66fecc --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/spc7110emu.h @@ -0,0 +1,136 @@ +/***** + * SPC7110 emulator - version 0.03 (2008-08-10) + * Copyright (c) 2008, byuu and neviksti + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * The software is provided "as is" and the author disclaims all warranties + * with regard to this software including all implied warranties of + * merchantibility and fitness, in no event shall the author be liable for + * any special, direct, indirect, or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether in an + * action of contract, negligence or other tortious action, arising out of + * or in connection with the use or performance of this software. + *****/ + + +#ifndef _SPC7110EMU_H_ +#define _SPC7110EMU_H_ + +#include "spc7110dec.h" + +class SPC7110 { +public: + void init(); + void enable(); + void power(); + void reset(); + + unsigned datarom_addr(unsigned addr); + + unsigned data_pointer(); + unsigned data_adjust(); + unsigned data_increment(); + void set_data_pointer(unsigned addr); + void set_data_adjust(unsigned addr); + + void update_time(int offset = 0); + time_t create_time(); + + uint8 mmio_read (unsigned addr); + void mmio_write(unsigned addr, uint8 data); + + uint8 read (unsigned addr); + void write(unsigned addr, uint8 data); + + //spc7110decomp + void decomp_init(); + uint8 decomp_read(); + + SPC7110(); + + //================== + //decompression unit + //================== + uint8 r4801; //compression table low + uint8 r4802; //compression table high + uint8 r4803; //compression table bank + uint8 r4804; //compression table index + uint8 r4805; //decompression buffer index low + uint8 r4806; //decompression buffer index high + uint8 r4807; //??? + uint8 r4808; //??? + uint8 r4809; //compression length low + uint8 r480a; //compression length high + uint8 r480b; //decompression control register + uint8 r480c; //decompression status + + SPC7110Decomp decomp; + + //============== + //data port unit + //============== + uint8 r4811; //data pointer low + uint8 r4812; //data pointer high + uint8 r4813; //data pointer bank + uint8 r4814; //data adjust low + uint8 r4815; //data adjust high + uint8 r4816; //data increment low + uint8 r4817; //data increment high + uint8 r4818; //data port control register + + uint8 r481x; + + bool r4814_latch; + bool r4815_latch; + + //========= + //math unit + //========= + uint8 r4820; //16-bit multiplicand B0, 32-bit dividend B0 + uint8 r4821; //16-bit multiplicand B1, 32-bit dividend B1 + uint8 r4822; //32-bit dividend B2 + uint8 r4823; //32-bit dividend B3 + uint8 r4824; //16-bit multiplier B0 + uint8 r4825; //16-bit multiplier B1 + uint8 r4826; //16-bit divisor B0 + uint8 r4827; //16-bit divisor B1 + uint8 r4828; //32-bit product B0, 32-bit quotient B0 + uint8 r4829; //32-bit product B1, 32-bit quotient B1 + uint8 r482a; //32-bit product B2, 32-bit quotient B2 + uint8 r482b; //32-bit product B3, 32-bit quotient B3 + uint8 r482c; //16-bit remainder B0 + uint8 r482d; //16-bit remainder B1 + uint8 r482e; //math control register + uint8 r482f; //math status + + //=================== + //memory mapping unit + //=================== + uint8 r4830; //SRAM write enable + uint8 r4831; //$[d0-df]:[0000-ffff] mapping + uint8 r4832; //$[e0-ef]:[0000-ffff] mapping + uint8 r4833; //$[f0-ff]:[0000-ffff] mapping + uint8 r4834; //??? + + unsigned dx_offset; + unsigned ex_offset; + unsigned fx_offset; + + //==================== + //real-time clock unit + //==================== + uint8 r4840; //RTC latch + uint8 r4841; //RTC index/data port + uint8 r4842; //RTC status + + enum RTC_State { RTCS_Inactive, RTCS_ModeSelect, RTCS_IndexSelect, RTCS_Write } rtc_state; + enum RTC_Mode { RTCM_Linear = 0x03, RTCM_Indexed = 0x0c } rtc_mode; + unsigned rtc_index; + + static const unsigned months[12]; +}; + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/srtc.cpp b/plugins/snes9x_gx/source/snes9x/srtc.cpp new file mode 100644 index 00000000..ca7b91c5 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/srtc.cpp @@ -0,0 +1,245 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + +/***** + * S-RTC emulation code + * Copyright (c) byuu + *****/ + + +#include <limits> + +#include "snes9x.h" +#include "memmap.h" +#include "srtc.h" +#include "display.h" + +#define memory_cartrtc_read(a) RTCData.reg[(a)] +#define memory_cartrtc_write(a, b) { RTCData.reg[(a)] = (b); } +#define cpu_regs_mdr OpenBus + +static inline unsigned max (unsigned a, unsigned b) +{ + return ((a > b) ? a : b); +} + +static inline unsigned min (unsigned a, unsigned b) +{ + return ((a < b) ? a : b); +} + +#define _SRTCEMU_CPP_ + +#include "srtcemu.h" +#include "srtcemu.cpp" + +static SRTC srtcemu; + + +void S9xInitSRTC (void) +{ + srtcemu.power(); + memset(RTCData.reg, 0, 20); +} + +void S9xResetSRTC (void) +{ + srtcemu.reset(); +} + +void S9xSetSRTC (uint8 data, uint16 address) +{ + srtcemu.mmio_write(address, data); +} + +uint8 S9xGetSRTC (uint16 address) +{ + return (srtcemu.mmio_read(address)); +} + +void S9xSRTCPreSaveState (void) +{ + srtcsnap.rtc_mode = (int32) srtcemu.rtc_mode; + srtcsnap.rtc_index = (int32) srtcemu.rtc_index; +} + +void S9xSRTCPostLoadState (int) +{ + srtcemu.rtc_mode = (SRTC::RTC_Mode) srtcsnap.rtc_mode; + srtcemu.rtc_index = (signed) srtcsnap.rtc_index; + + srtcemu.update_time(); +} diff --git a/plugins/snes9x_gx/source/snes9x/srtc.h b/plugins/snes9x_gx/source/snes9x/srtc.h new file mode 100644 index 00000000..8bc441cb --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/srtc.h @@ -0,0 +1,203 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _SRTC_H_ +#define _SRTC_H_ + +struct SRTCData +{ + uint8 reg[20]; +}; + +// for snapshot only +struct SSRTCSnapshot +{ + int32 rtc_mode; // enum RTC_Mode + int32 rtc_index; // signed +}; + +extern struct SRTCData RTCData; +extern struct SSRTCSnapshot srtcsnap; + +void S9xInitSRTC (void); +void S9xResetSRTC (void); +void S9xSRTCPreSaveState (void); +void S9xSRTCPostLoadState (int); +void S9xSetSRTC (uint8, uint16); +uint8 S9xGetSRTC (uint16); + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/srtcemu.cpp b/plugins/snes9x_gx/source/snes9x/srtcemu.cpp new file mode 100644 index 00000000..969b966e --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/srtcemu.cpp @@ -0,0 +1,225 @@ +/***** + * S-RTC emulation code + * Copyright (c) byuu + *****/ + + +#ifdef _SRTCEMU_CPP_ + +const unsigned SRTC::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + +void SRTC::power() { + reset(); +} + +void SRTC::reset() { + rtc_mode = RTCM_Read; + rtc_index = -1; + update_time(); +} + +void SRTC::update_time() { + time_t rtc_time + = (memory_cartrtc_read(16) << 0) + | (memory_cartrtc_read(17) << 8) + | (memory_cartrtc_read(18) << 16) + | (memory_cartrtc_read(19) << 24); + time_t current_time = time(0); + + //sizeof(time_t) is platform-dependent; though memory::cartrtc needs to be platform-agnostic. + //yet platforms with 32-bit signed time_t will overflow every ~68 years. handle this by + //accounting for overflow at the cost of 1-bit precision (to catch underflow). this will allow + //memory::cartrtc timestamp to remain valid for up to ~34 years from the last update, even if + //time_t overflows. calculation should be valid regardless of number representation, time_t size, + //or whether time_t is signed or unsigned. + time_t diff + = (current_time >= rtc_time) + ? (current_time - rtc_time) + : (std::numeric_limits<time_t>::max() - rtc_time + current_time + 1); //compensate for overflow + if(diff > std::numeric_limits<time_t>::max() / 2) diff = 0; //compensate for underflow + + if(diff > 0) { + unsigned second = memory_cartrtc_read( 0) + memory_cartrtc_read( 1) * 10; + unsigned minute = memory_cartrtc_read( 2) + memory_cartrtc_read( 3) * 10; + unsigned hour = memory_cartrtc_read( 4) + memory_cartrtc_read( 5) * 10; + unsigned day = memory_cartrtc_read( 6) + memory_cartrtc_read( 7) * 10; + unsigned month = memory_cartrtc_read( 8); + unsigned year = memory_cartrtc_read( 9) + memory_cartrtc_read(10) * 10 + memory_cartrtc_read(11) * 100; + unsigned weekday = memory_cartrtc_read(12); + + day--; + month--; + year += 1000; + + second += diff; + while(second >= 60) { + second -= 60; + + minute++; + if(minute < 60) continue; + minute = 0; + + hour++; + if(hour < 24) continue; + hour = 0; + + day++; + weekday = (weekday + 1) % 7; + unsigned days = months[month % 12]; + if(days == 28) { + bool leapyear = false; + if((year % 4) == 0) { + leapyear = true; + if((year % 100) == 0 && (year % 400) != 0) leapyear = false; + } + if(leapyear) days++; + } + if(day < days) continue; + day = 0; + + month++; + if(month < 12) continue; + month = 0; + + year++; + } + + day++; + month++; + year -= 1000; + + memory_cartrtc_write( 0, second % 10); + memory_cartrtc_write( 1, second / 10); + memory_cartrtc_write( 2, minute % 10); + memory_cartrtc_write( 3, minute / 10); + memory_cartrtc_write( 4, hour % 10); + memory_cartrtc_write( 5, hour / 10); + memory_cartrtc_write( 6, day % 10); + memory_cartrtc_write( 7, day / 10); + memory_cartrtc_write( 8, month); + memory_cartrtc_write( 9, year % 10); + memory_cartrtc_write(10, (year / 10) % 10); + memory_cartrtc_write(11, year / 100); + memory_cartrtc_write(12, weekday % 7); + } + + memory_cartrtc_write(16, current_time >> 0); + memory_cartrtc_write(17, current_time >> 8); + memory_cartrtc_write(18, current_time >> 16); + memory_cartrtc_write(19, current_time >> 24); +} + +//returns day of week for specified date +//eg 0 = Sunday, 1 = Monday, ... 6 = Saturday +//usage: weekday(2008, 1, 1) returns weekday of January 1st, 2008 +unsigned SRTC::weekday(unsigned year, unsigned month, unsigned day) { + unsigned y = 1900, m = 1; //epoch is 1900-01-01 + unsigned sum = 0; //number of days passed since epoch + + year = max(1900, year); + month = max(1, min(12, month)); + day = max(1, min(31, day)); + + while(y < year) { + bool leapyear = false; + if((y % 4) == 0) { + leapyear = true; + if((y % 100) == 0 && (y % 400) != 0) leapyear = false; + } + sum += leapyear ? 366 : 365; + y++; + } + + while(m < month) { + unsigned days = months[m - 1]; + if(days == 28) { + bool leapyear = false; + if((y % 4) == 0) { + leapyear = true; + if((y % 100) == 0 && (y % 400) != 0) leapyear = false; + } + if(leapyear) days++; + } + sum += days; + m++; + } + + sum += day - 1; + return (sum + 1) % 7; //1900-01-01 was a Monday +} + +uint8 SRTC::mmio_read(unsigned addr) { + addr &= 0xffff; + + if(addr == 0x2800) { + if(rtc_mode != RTCM_Read) return 0x00; + + if(rtc_index < 0) { + update_time(); + rtc_index++; + return 0x0f; + } else if(rtc_index > 12) { + rtc_index = -1; + return 0x0f; + } else { + return memory_cartrtc_read(rtc_index++); + } + } + + return cpu_regs_mdr; +} + +void SRTC::mmio_write(unsigned addr, uint8 data) { + addr &= 0xffff; + + if(addr == 0x2801) { + data &= 0x0f; //only the low four bits are used + + if(data == 0x0d) { + rtc_mode = RTCM_Read; + rtc_index = -1; + return; + } + + if(data == 0x0e) { + rtc_mode = RTCM_Command; + return; + } + + if(data == 0x0f) return; //unknown behavior + + if(rtc_mode == RTCM_Write) { + if(rtc_index >= 0 && rtc_index < 12) { + memory_cartrtc_write(rtc_index++, data); + + if(rtc_index == 12) { + //day of week is automatically calculated and written + unsigned day = memory_cartrtc_read( 6) + memory_cartrtc_read( 7) * 10; + unsigned month = memory_cartrtc_read( 8); + unsigned year = memory_cartrtc_read( 9) + memory_cartrtc_read(10) * 10 + memory_cartrtc_read(11) * 100; + year += 1000; + + memory_cartrtc_write(rtc_index++, weekday(year, month, day)); + } + } + } else if(rtc_mode == RTCM_Command) { + if(data == 0) { + rtc_mode = RTCM_Write; + rtc_index = 0; + } else if(data == 4) { + rtc_mode = RTCM_Ready; + rtc_index = -1; + for(unsigned i = 0; i < 13; i++) memory_cartrtc_write(i, 0); + } else { + //unknown behavior + rtc_mode = RTCM_Ready; + } + } + } +} + +SRTC::SRTC() { +} + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/srtcemu.h b/plugins/snes9x_gx/source/snes9x/srtcemu.h new file mode 100644 index 00000000..fc1af24f --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/srtcemu.h @@ -0,0 +1,30 @@ +/***** + * S-RTC emulation code + * Copyright (c) byuu + *****/ + + +#ifndef _SRTCEMU_H_ +#define _SRTCEMU_H_ + +class SRTC { +public: + void update_time(); + unsigned weekday(unsigned year, unsigned month, unsigned day); + + void init(); + void enable(); + void power(); + void reset(); + + uint8 mmio_read (unsigned addr); + void mmio_write(unsigned addr, uint8 data); + + SRTC(); + + static const unsigned months[12]; + enum RTC_Mode { RTCM_Ready, RTCM_Command, RTCM_Read, RTCM_Write } rtc_mode; + signed rtc_index; +}; + +#endif diff --git a/plugins/snes9x_gx/source/snes9x/tile.cpp b/plugins/snes9x_gx/source/snes9x/tile.cpp new file mode 100644 index 00000000..f8d20827 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/tile.cpp @@ -0,0 +1,1514 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +// This file includes itself multiple times. +// The other option would be to have 4 files, where A includes B, and B includes C 3 times, and C includes D 5 times. +// Look for the following marker to find where the divisions are. + +// Top-level compilation. + +#ifndef _NEWTILE_CPP +#define _NEWTILE_CPP + +#include "snes9x.h" +#include "ppu.h" +#include "tile.h" + +static uint32 pixbit[8][16]; +static uint8 hrbit_odd[256]; +static uint8 hrbit_even[256]; + + +void S9xInitTileRenderer (void) +{ + register int i; + + for (i = 0; i < 16; i++) + { + register uint32 b = 0; + + #ifdef LSB_FIRST + if (i & 8) + b |= 1; + if (i & 4) + b |= 1 << 8; + if (i & 2) + b |= 1 << 16; + if (i & 1) + b |= 1 << 24; + #else + if (i & 8) + b |= 1 << 24; + if (i & 4) + b |= 1 << 16; + if (i & 2) + b |= 1 << 8; + if (i & 1) + b |= 1; + #endif + + for (uint8 bitshift = 0; bitshift < 8; bitshift++) + pixbit[bitshift][i] = b << bitshift; + } + + for (i = 0; i < 256; i++) + { + register uint8 m = 0; + register uint8 s = 0; + + if (i & 0x80) + s |= 8; + if (i & 0x40) + m |= 8; + if (i & 0x20) + s |= 4; + if (i & 0x10) + m |= 4; + if (i & 0x08) + s |= 2; + if (i & 0x04) + m |= 2; + if (i & 0x02) + s |= 1; + if (i & 0x01) + m |= 1; + + hrbit_odd[i] = m; + hrbit_even[i] = s; + } +} + +// Here are the tile converters, selected by S9xSelectTileConverter(). +// Really, except for the definition of DOBIT and the number of times it is called, they're all the same. + +#define DOBIT(n, i) \ + if ((pix = *(tp + (n)))) \ + { \ + p1 |= pixbit[(i)][pix >> 4]; \ + p2 |= pixbit[(i)][pix & 0xf]; \ + } + +static uint8 ConvertTile2 (uint8 *pCache, uint32 TileAddr, uint32) +{ + register uint8 *tp = &Memory.VRAM[TileAddr]; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + for (line = 8; line != 0; line--, tp += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + DOBIT( 0, 0); + DOBIT( 1, 1); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + + return (non_zero ? TRUE : BLANK_TILE); +} + +static uint8 ConvertTile4 (uint8 *pCache, uint32 TileAddr, uint32) +{ + register uint8 *tp = &Memory.VRAM[TileAddr]; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + for (line = 8; line != 0; line--, tp += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + DOBIT( 0, 0); + DOBIT( 1, 1); + DOBIT(16, 2); + DOBIT(17, 3); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + + return (non_zero ? TRUE : BLANK_TILE); +} + +static uint8 ConvertTile8 (uint8 *pCache, uint32 TileAddr, uint32) +{ + register uint8 *tp = &Memory.VRAM[TileAddr]; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + for (line = 8; line != 0; line--, tp += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + DOBIT( 0, 0); + DOBIT( 1, 1); + DOBIT(16, 2); + DOBIT(17, 3); + DOBIT(32, 4); + DOBIT(33, 5); + DOBIT(48, 6); + DOBIT(49, 7); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + + return (non_zero ? TRUE : BLANK_TILE); +} + +#undef DOBIT + +#define DOBIT(n, i) \ + if ((pix = hrbit_odd[*(tp1 + (n))])) \ + p1 |= pixbit[(i)][pix]; \ + if ((pix = hrbit_odd[*(tp2 + (n))])) \ + p2 |= pixbit[(i)][pix]; + +static uint8 ConvertTile2h_odd (uint8 *pCache, uint32 TileAddr, uint32 Tile) +{ + register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + if (Tile == 0x3ff) + tp2 = tp1 - (0x3ff << 4); + else + tp2 = tp1 + (1 << 4); + + for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + DOBIT( 0, 0); + DOBIT( 1, 1); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + + return (non_zero ? TRUE : BLANK_TILE); +} + +static uint8 ConvertTile4h_odd (uint8 *pCache, uint32 TileAddr, uint32 Tile) +{ + register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + if (Tile == 0x3ff) + tp2 = tp1 - (0x3ff << 5); + else + tp2 = tp1 + (1 << 5); + + for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + DOBIT( 0, 0); + DOBIT( 1, 1); + DOBIT(16, 2); + DOBIT(17, 3); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + + return (non_zero ? TRUE : BLANK_TILE); +} + +#undef DOBIT + +#define DOBIT(n, i) \ + if ((pix = hrbit_even[*(tp1 + (n))])) \ + p1 |= pixbit[(i)][pix]; \ + if ((pix = hrbit_even[*(tp2 + (n))])) \ + p2 |= pixbit[(i)][pix]; + +static uint8 ConvertTile2h_even (uint8 *pCache, uint32 TileAddr, uint32 Tile) +{ + register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + if (Tile == 0x3ff) + tp2 = tp1 - (0x3ff << 4); + else + tp2 = tp1 + (1 << 4); + + for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + DOBIT( 0, 0); + DOBIT( 1, 1); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + + return (non_zero ? TRUE : BLANK_TILE); +} + +static uint8 ConvertTile4h_even (uint8 *pCache, uint32 TileAddr, uint32 Tile) +{ + register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + if (Tile == 0x3ff) + tp2 = tp1 - (0x3ff << 5); + else + tp2 = tp1 + (1 << 5); + + for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + DOBIT( 0, 0); + DOBIT( 1, 1); + DOBIT(16, 2); + DOBIT(17, 3); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + + return (non_zero ? TRUE : BLANK_TILE); +} + +#undef DOBIT + +// First-level include: Get all the renderers. + +#include "tile.cpp" + +// Functions to select which converter and renderer to use. + +void S9xSelectTileRenderers (int BGMode, bool8 sub, bool8 obj) +{ + void (**DT) (uint32, uint32, uint32, uint32); + void (**DCT) (uint32, uint32, uint32, uint32, uint32, uint32); + void (**DMP) (uint32, uint32, uint32, uint32, uint32, uint32); + void (**DB) (uint32, uint32, uint32); + void (**DM7BG1) (uint32, uint32, int); + void (**DM7BG2) (uint32, uint32, int); + bool8 M7M1, M7M2; + + M7M1 = PPU.BGMosaic[0] && PPU.Mosaic > 1; + M7M2 = PPU.BGMosaic[1] && PPU.Mosaic > 1; + + bool8 interlace = obj ? FALSE : IPPU.Interlace; + bool8 hires = !sub && (BGMode == 5 || BGMode == 6 || IPPU.PseudoHires); + + if (!IPPU.DoubleWidthPixels) // normal width + { + DT = Renderers_DrawTile16Normal1x1; + DCT = Renderers_DrawClippedTile16Normal1x1; + DMP = Renderers_DrawMosaicPixel16Normal1x1; + DB = Renderers_DrawBackdrop16Normal1x1; + DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Normal1x1 : Renderers_DrawMode7BG1Normal1x1; + DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Normal1x1 : Renderers_DrawMode7BG2Normal1x1; + GFX.LinesPerTile = 8; + } + else if(hires) // hires double width + { + if (interlace) + { + DT = Renderers_DrawTile16HiresInterlace; + DCT = Renderers_DrawClippedTile16HiresInterlace; + DMP = Renderers_DrawMosaicPixel16HiresInterlace; + DB = Renderers_DrawBackdrop16Hires; + DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Hires : Renderers_DrawMode7BG1Hires; + DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Hires : Renderers_DrawMode7BG2Hires; + GFX.LinesPerTile = 4; + } + else + { + DT = Renderers_DrawTile16Hires; + DCT = Renderers_DrawClippedTile16Hires; + DMP = Renderers_DrawMosaicPixel16Hires; + DB = Renderers_DrawBackdrop16Hires; + DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Hires : Renderers_DrawMode7BG1Hires; + DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Hires : Renderers_DrawMode7BG2Hires; + GFX.LinesPerTile = 8; + } + } + else // normal double width + { + if (interlace) + { + DT = Renderers_DrawTile16Interlace; + DCT = Renderers_DrawClippedTile16Interlace; + DMP = Renderers_DrawMosaicPixel16Interlace; + DB = Renderers_DrawBackdrop16Normal2x1; + DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Normal2x1 : Renderers_DrawMode7BG1Normal2x1; + DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Normal2x1 : Renderers_DrawMode7BG2Normal2x1; + GFX.LinesPerTile = 4; + } + else + { + DT = Renderers_DrawTile16Normal2x1; + DCT = Renderers_DrawClippedTile16Normal2x1; + DMP = Renderers_DrawMosaicPixel16Normal2x1; + DB = Renderers_DrawBackdrop16Normal2x1; + DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Normal2x1 : Renderers_DrawMode7BG1Normal2x1; + DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Normal2x1 : Renderers_DrawMode7BG2Normal2x1; + GFX.LinesPerTile = 8; + } + } + + GFX.DrawTileNomath = DT[0]; + GFX.DrawClippedTileNomath = DCT[0]; + GFX.DrawMosaicPixelNomath = DMP[0]; + GFX.DrawBackdropNomath = DB[0]; + GFX.DrawMode7BG1Nomath = DM7BG1[0]; + GFX.DrawMode7BG2Nomath = DM7BG2[0]; + + int i; + + if (!Settings.Transparency) + i = 0; + else + { + i = (Memory.FillRAM[0x2131] & 0x80) ? 4 : 1; + if (Memory.FillRAM[0x2131] & 0x40) + { + i++; + if (Memory.FillRAM[0x2130] & 2) + i++; + } + } + + GFX.DrawTileMath = DT[i]; + GFX.DrawClippedTileMath = DCT[i]; + GFX.DrawMosaicPixelMath = DMP[i]; + GFX.DrawBackdropMath = DB[i]; + GFX.DrawMode7BG1Math = DM7BG1[i]; + GFX.DrawMode7BG2Math = DM7BG2[i]; +} + +void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic) +{ + switch (depth) + { + case 8: + BG.ConvertTile = BG.ConvertTileFlip = ConvertTile8; + BG.Buffer = BG.BufferFlip = IPPU.TileCache[TILE_8BIT]; + BG.Buffered = BG.BufferedFlip = IPPU.TileCached[TILE_8BIT]; + BG.TileShift = 6; + BG.PaletteShift = 0; + BG.PaletteMask = 0; + BG.DirectColourMode = Memory.FillRAM[0x2130] & 1; + + break; + + case 4: + if (hires) + { + if (sub || mosaic) + { + BG.ConvertTile = ConvertTile4h_even; + BG.Buffer = IPPU.TileCache[TILE_4BIT_EVEN]; + BG.Buffered = IPPU.TileCached[TILE_4BIT_EVEN]; + BG.ConvertTileFlip = ConvertTile4h_odd; + BG.BufferFlip = IPPU.TileCache[TILE_4BIT_ODD]; + BG.BufferedFlip = IPPU.TileCached[TILE_4BIT_ODD]; + } + else + { + BG.ConvertTile = ConvertTile4h_odd; + BG.Buffer = IPPU.TileCache[TILE_4BIT_ODD]; + BG.Buffered = IPPU.TileCached[TILE_4BIT_ODD]; + BG.ConvertTileFlip = ConvertTile4h_even; + BG.BufferFlip = IPPU.TileCache[TILE_4BIT_EVEN]; + BG.BufferedFlip = IPPU.TileCached[TILE_4BIT_EVEN]; + } + } + else + { + BG.ConvertTile = BG.ConvertTileFlip = ConvertTile4; + BG.Buffer = BG.BufferFlip = IPPU.TileCache[TILE_4BIT]; + BG.Buffered = BG.BufferedFlip = IPPU.TileCached[TILE_4BIT]; + } + + BG.TileShift = 5; + BG.PaletteShift = 10 - 4; + BG.PaletteMask = 7 << 4; + BG.DirectColourMode = FALSE; + + break; + + case 2: + if (hires) + { + if (sub || mosaic) + { + BG.ConvertTile = ConvertTile2h_even; + BG.Buffer = IPPU.TileCache[TILE_2BIT_EVEN]; + BG.Buffered = IPPU.TileCached[TILE_2BIT_EVEN]; + BG.ConvertTileFlip = ConvertTile2h_odd; + BG.BufferFlip = IPPU.TileCache[TILE_2BIT_ODD]; + BG.BufferedFlip = IPPU.TileCached[TILE_2BIT_ODD]; + } + else + { + BG.ConvertTile = ConvertTile2h_odd; + BG.Buffer = IPPU.TileCache[TILE_2BIT_ODD]; + BG.Buffered = IPPU.TileCached[TILE_2BIT_ODD]; + BG.ConvertTileFlip = ConvertTile2h_even; + BG.BufferFlip = IPPU.TileCache[TILE_2BIT_EVEN]; + BG.BufferedFlip = IPPU.TileCached[TILE_2BIT_EVEN]; + } + } + else + { + BG.ConvertTile = BG.ConvertTileFlip = ConvertTile2; + BG.Buffer = BG.BufferFlip = IPPU.TileCache[TILE_2BIT]; + BG.Buffered = BG.BufferedFlip = IPPU.TileCached[TILE_2BIT]; + } + + BG.TileShift = 4; + BG.PaletteShift = 10 - 2; + BG.PaletteMask = 7 << 2; + BG.DirectColourMode = FALSE; + + break; + } +} + +/*****************************************************************************/ +#else +#ifndef NAME1 // First-level: Get all the renderers. +/*****************************************************************************/ + +#define GET_CACHED_TILE() \ + uint32 TileNumber; \ + uint32 TileAddr = BG.TileAddress + ((Tile & 0x3ff) << BG.TileShift); \ + if (Tile & 0x100) \ + TileAddr += BG.NameSelect; \ + TileAddr &= 0xffff; \ + TileNumber = TileAddr >> BG.TileShift; \ + if (Tile & H_FLIP) \ + { \ + pCache = &BG.BufferFlip[TileNumber << 6]; \ + if (!BG.BufferedFlip[TileNumber]) \ + BG.BufferedFlip[TileNumber] = BG.ConvertTileFlip(pCache, TileAddr, Tile & 0x3ff); \ + } \ + else \ + { \ + pCache = &BG.Buffer[TileNumber << 6]; \ + if (!BG.Buffered[TileNumber]) \ + BG.Buffered[TileNumber] = BG.ConvertTile(pCache, TileAddr, Tile & 0x3ff); \ + } + +#define IS_BLANK_TILE() \ + (BG.Buffered[TileNumber] == BLANK_TILE) + +#define SELECT_PALETTE() \ + if (BG.DirectColourMode) \ + { \ + if (IPPU.DirectColourMapsNeedRebuild) \ + S9xBuildDirectColourMaps(); \ + GFX.RealScreenColors = DirectColourMaps[(Tile >> 10) & 7]; \ + } \ + else \ + GFX.RealScreenColors = &IPPU.ScreenColors[((Tile >> BG.PaletteShift) & BG.PaletteMask) + BG.StartPalette]; \ + GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors + +#define NOMATH(Op, Main, Sub, SD) \ + (Main) + +#define REGMATH(Op, Main, Sub, SD) \ + (COLOR_##Op((Main), ((SD) & 0x20) ? (Sub) : GFX.FixedColour)) + +#define MATHF1_2(Op, Main, Sub, SD) \ + (GFX.ClipColors ? (COLOR_##Op((Main), GFX.FixedColour)) : (COLOR_##Op##1_2((Main), GFX.FixedColour))) + +#define MATHS1_2(Op, Main, Sub, SD) \ + (GFX.ClipColors ? REGMATH(Op, Main, Sub, SD) : (((SD) & 0x20) ? COLOR_##Op##1_2((Main), (Sub)) : COLOR_##Op((Main), GFX.FixedColour))) + +// Basic routine to render an unclipped tile. +// Input parameters: +// BPSTART = either StartLine or (StartLine * 2 + BG.InterlaceLine), +// so interlace modes can render every other line from the tile. +// PITCH = 1 or 2, again so interlace can count lines properly. +// DRAW_PIXEL(N, M) is a routine to actually draw the pixel. N is the pixel in the row to draw, +// and M is a test which if false means the pixel should be skipped. +// Z1 is the "draw if Z1 > cur_depth". +// Z2 is the "cur_depth = new_depth". OBJ need the two separate. +// Pix is the pixel to draw. + +#define Z1 GFX.Z1 +#define Z2 GFX.Z2 + +#define DRAW_TILE() \ + uint8 *pCache; \ + register int32 l; \ + register uint8 *bp, Pix; \ + \ + GET_CACHED_TILE(); \ + if (IS_BLANK_TILE()) \ + return; \ + SELECT_PALETTE(); \ + \ + if (!(Tile & (V_FLIP | H_FLIP))) \ + { \ + bp = pCache + BPSTART; \ + for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \ + { \ + DRAW_PIXEL(0, Pix = bp[0]); \ + DRAW_PIXEL(1, Pix = bp[1]); \ + DRAW_PIXEL(2, Pix = bp[2]); \ + DRAW_PIXEL(3, Pix = bp[3]); \ + DRAW_PIXEL(4, Pix = bp[4]); \ + DRAW_PIXEL(5, Pix = bp[5]); \ + DRAW_PIXEL(6, Pix = bp[6]); \ + DRAW_PIXEL(7, Pix = bp[7]); \ + } \ + } \ + else \ + if (!(Tile & V_FLIP)) \ + { \ + bp = pCache + BPSTART; \ + for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \ + { \ + DRAW_PIXEL(0, Pix = bp[7]); \ + DRAW_PIXEL(1, Pix = bp[6]); \ + DRAW_PIXEL(2, Pix = bp[5]); \ + DRAW_PIXEL(3, Pix = bp[4]); \ + DRAW_PIXEL(4, Pix = bp[3]); \ + DRAW_PIXEL(5, Pix = bp[2]); \ + DRAW_PIXEL(6, Pix = bp[1]); \ + DRAW_PIXEL(7, Pix = bp[0]); \ + } \ + } \ + else \ + if (!(Tile & H_FLIP)) \ + { \ + bp = pCache + 56 - BPSTART; \ + for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \ + { \ + DRAW_PIXEL(0, Pix = bp[0]); \ + DRAW_PIXEL(1, Pix = bp[1]); \ + DRAW_PIXEL(2, Pix = bp[2]); \ + DRAW_PIXEL(3, Pix = bp[3]); \ + DRAW_PIXEL(4, Pix = bp[4]); \ + DRAW_PIXEL(5, Pix = bp[5]); \ + DRAW_PIXEL(6, Pix = bp[6]); \ + DRAW_PIXEL(7, Pix = bp[7]); \ + } \ + } \ + else \ + { \ + bp = pCache + 56 - BPSTART; \ + for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \ + { \ + DRAW_PIXEL(0, Pix = bp[7]); \ + DRAW_PIXEL(1, Pix = bp[6]); \ + DRAW_PIXEL(2, Pix = bp[5]); \ + DRAW_PIXEL(3, Pix = bp[4]); \ + DRAW_PIXEL(4, Pix = bp[3]); \ + DRAW_PIXEL(5, Pix = bp[2]); \ + DRAW_PIXEL(6, Pix = bp[1]); \ + DRAW_PIXEL(7, Pix = bp[0]); \ + } \ + } + +#define NAME1 DrawTile16 +#define ARGS uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount + +// Second-level include: Get the DrawTile16 renderers. + +#include "tile.cpp" + +#undef NAME1 +#undef ARGS +#undef DRAW_TILE +#undef Z1 +#undef Z2 + +// Basic routine to render a clipped tile. Inputs same as above. + +#define Z1 GFX.Z1 +#define Z2 GFX.Z2 + +#define DRAW_TILE() \ + uint8 *pCache; \ + register int32 l; \ + register uint8 *bp, Pix, w; \ + \ + GET_CACHED_TILE(); \ + if (IS_BLANK_TILE()) \ + return; \ + SELECT_PALETTE(); \ + \ + if (!(Tile & (V_FLIP | H_FLIP))) \ + { \ + bp = pCache + BPSTART; \ + for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \ + { \ + w = Width; \ + switch (StartPixel) \ + { \ + case 0: DRAW_PIXEL(0, Pix = bp[0]); if (!--w) break; \ + case 1: DRAW_PIXEL(1, Pix = bp[1]); if (!--w) break; \ + case 2: DRAW_PIXEL(2, Pix = bp[2]); if (!--w) break; \ + case 3: DRAW_PIXEL(3, Pix = bp[3]); if (!--w) break; \ + case 4: DRAW_PIXEL(4, Pix = bp[4]); if (!--w) break; \ + case 5: DRAW_PIXEL(5, Pix = bp[5]); if (!--w) break; \ + case 6: DRAW_PIXEL(6, Pix = bp[6]); if (!--w) break; \ + case 7: DRAW_PIXEL(7, Pix = bp[7]); break; \ + } \ + } \ + } \ + else \ + if (!(Tile & V_FLIP)) \ + { \ + bp = pCache + BPSTART; \ + for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \ + { \ + w = Width; \ + switch (StartPixel) \ + { \ + case 0: DRAW_PIXEL(0, Pix = bp[7]); if (!--w) break; \ + case 1: DRAW_PIXEL(1, Pix = bp[6]); if (!--w) break; \ + case 2: DRAW_PIXEL(2, Pix = bp[5]); if (!--w) break; \ + case 3: DRAW_PIXEL(3, Pix = bp[4]); if (!--w) break; \ + case 4: DRAW_PIXEL(4, Pix = bp[3]); if (!--w) break; \ + case 5: DRAW_PIXEL(5, Pix = bp[2]); if (!--w) break; \ + case 6: DRAW_PIXEL(6, Pix = bp[1]); if (!--w) break; \ + case 7: DRAW_PIXEL(7, Pix = bp[0]); break; \ + } \ + } \ + } \ + else \ + if (!(Tile & H_FLIP)) \ + { \ + bp = pCache + 56 - BPSTART; \ + for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \ + { \ + w = Width; \ + switch (StartPixel) \ + { \ + case 0: DRAW_PIXEL(0, Pix = bp[0]); if (!--w) break; \ + case 1: DRAW_PIXEL(1, Pix = bp[1]); if (!--w) break; \ + case 2: DRAW_PIXEL(2, Pix = bp[2]); if (!--w) break; \ + case 3: DRAW_PIXEL(3, Pix = bp[3]); if (!--w) break; \ + case 4: DRAW_PIXEL(4, Pix = bp[4]); if (!--w) break; \ + case 5: DRAW_PIXEL(5, Pix = bp[5]); if (!--w) break; \ + case 6: DRAW_PIXEL(6, Pix = bp[6]); if (!--w) break; \ + case 7: DRAW_PIXEL(7, Pix = bp[7]); break; \ + } \ + } \ + } \ + else \ + { \ + bp = pCache + 56 - BPSTART; \ + for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \ + { \ + w = Width; \ + switch (StartPixel) \ + { \ + case 0: DRAW_PIXEL(0, Pix = bp[7]); if (!--w) break; \ + case 1: DRAW_PIXEL(1, Pix = bp[6]); if (!--w) break; \ + case 2: DRAW_PIXEL(2, Pix = bp[5]); if (!--w) break; \ + case 3: DRAW_PIXEL(3, Pix = bp[4]); if (!--w) break; \ + case 4: DRAW_PIXEL(4, Pix = bp[3]); if (!--w) break; \ + case 5: DRAW_PIXEL(5, Pix = bp[2]); if (!--w) break; \ + case 6: DRAW_PIXEL(6, Pix = bp[1]); if (!--w) break; \ + case 7: DRAW_PIXEL(7, Pix = bp[0]); break; \ + } \ + } \ + } + +#define NAME1 DrawClippedTile16 +#define ARGS uint32 Tile, uint32 Offset, uint32 StartPixel, uint32 Width, uint32 StartLine, uint32 LineCount + +// Second-level include: Get the DrawClippedTile16 renderers. + +#include "tile.cpp" + +#undef NAME1 +#undef ARGS +#undef DRAW_TILE +#undef Z1 +#undef Z2 + +// Basic routine to render a single mosaic pixel. +// DRAW_PIXEL, BPSTART, Z1, Z2 and Pix are the same as above, but PITCH is not used. + +#define Z1 GFX.Z1 +#define Z2 GFX.Z2 + +#define DRAW_TILE() \ + uint8 *pCache; \ + register int32 l, w; \ + register uint8 Pix; \ + \ + GET_CACHED_TILE(); \ + if (IS_BLANK_TILE()) \ + return; \ + SELECT_PALETTE(); \ + \ + if (Tile & H_FLIP) \ + StartPixel = 7 - StartPixel; \ + \ + if (Tile & V_FLIP) \ + Pix = pCache[56 - BPSTART + StartPixel]; \ + else \ + Pix = pCache[BPSTART + StartPixel]; \ + \ + if (Pix) \ + { \ + for (l = LineCount; l > 0; l--, Offset += GFX.PPL) \ + { \ + for (w = Width - 1; w >= 0; w--) \ + DRAW_PIXEL(w, 1); \ + } \ + } + +#define NAME1 DrawMosaicPixel16 +#define ARGS uint32 Tile, uint32 Offset, uint32 StartLine, uint32 StartPixel, uint32 Width, uint32 LineCount + +// Second-level include: Get the DrawMosaicPixel16 renderers. + +#include "tile.cpp" + +#undef NAME1 +#undef ARGS +#undef DRAW_TILE +#undef Z1 +#undef Z2 + +// Basic routine to render the backdrop. +// DRAW_PIXEL is the same as above, but since we're just replicating a single pixel there's no need for PITCH or BPSTART +// (or interlace at all, really). +// The backdrop is always depth = 1, so Z1 = Z2 = 1. And backdrop is always color 0. + +#define NO_INTERLACE 1 +#define Z1 1 +#define Z2 1 +#define Pix 0 + +#define DRAW_TILE() \ + register uint32 l, x; \ + \ + GFX.RealScreenColors = IPPU.ScreenColors; \ + GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; \ + \ + for (l = GFX.StartY; l <= GFX.EndY; l++, Offset += GFX.PPL) \ + { \ + for (x = Left; x < Right; x++) \ + DRAW_PIXEL(x, 1); \ + } + +#define NAME1 DrawBackdrop16 +#define ARGS uint32 Offset, uint32 Left, uint32 Right + +// Second-level include: Get the DrawBackdrop16 renderers. + +#include "tile.cpp" + +#undef NAME1 +#undef ARGS +#undef DRAW_TILE +#undef Pix +#undef Z1 +#undef Z2 +#undef NO_INTERLACE + +// Basic routine to render a chunk of a Mode 7 BG. +// Mode 7 has no interlace, so BPSTART and PITCH are unused. +// We get some new parameters, so we can use the same DRAW_TILE to do BG1 or BG2: +// DCMODE tests if Direct Color should apply. +// BG is the BG, so we use the right clip window. +// MASK is 0xff or 0x7f, the 'color' portion of the pixel. +// We define Z1/Z2 to either be constant 5 or to vary depending on the 'priority' portion of the pixel. + +#define CLIP_10_BIT_SIGNED(a) (((a) & 0x2000) ? ((a) | ~0x3ff) : ((a) & 0x3ff)) + +extern struct SLineMatrixData LineMatrixData[240]; + +#define NO_INTERLACE 1 +#define Z1 (D + 7) +#define Z2 (D + 7) +#define MASK 0xff +#define DCMODE (Memory.FillRAM[0x2130] & 1) +#define BG 0 + +#define DRAW_TILE_NORMAL() \ + uint8 *VRAM1 = Memory.VRAM + 1; \ + \ + if (DCMODE) \ + { \ + if (IPPU.DirectColourMapsNeedRebuild) \ + S9xBuildDirectColourMaps(); \ + GFX.RealScreenColors = DirectColourMaps[0]; \ + } \ + else \ + GFX.RealScreenColors = IPPU.ScreenColors; \ + \ + GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; \ + \ + int aa, cc; \ + int startx; \ + \ + uint32 Offset = GFX.StartY * GFX.PPL; \ + struct SLineMatrixData *l = &LineMatrixData[GFX.StartY]; \ + \ + for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Offset += GFX.PPL, l++) \ + { \ + int yy, starty; \ + \ + int32 HOffset = ((int32) l->M7HOFS << 19) >> 19; \ + int32 VOffset = ((int32) l->M7VOFS << 19) >> 19; \ + \ + int32 CentreX = ((int32) l->CentreX << 19) >> 19; \ + int32 CentreY = ((int32) l->CentreY << 19) >> 19; \ + \ + if (PPU.Mode7VFlip) \ + starty = 255 - (int) (Line + 1); \ + else \ + starty = Line + 1; \ + \ + yy = CLIP_10_BIT_SIGNED(VOffset - CentreY); \ + \ + int BB = ((l->MatrixB * starty) & ~63) + ((l->MatrixB * yy) & ~63) + (CentreX << 8); \ + int DD = ((l->MatrixD * starty) & ~63) + ((l->MatrixD * yy) & ~63) + (CentreY << 8); \ + \ + if (PPU.Mode7HFlip) \ + { \ + startx = Right - 1; \ + aa = -l->MatrixA; \ + cc = -l->MatrixC; \ + } \ + else \ + { \ + startx = Left; \ + aa = l->MatrixA; \ + cc = l->MatrixC; \ + } \ + \ + int xx = CLIP_10_BIT_SIGNED(HOffset - CentreX); \ + int AA = l->MatrixA * startx + ((l->MatrixA * xx) & ~63); \ + int CC = l->MatrixC * startx + ((l->MatrixC * xx) & ~63); \ + \ + uint8 Pix; \ + \ + if (!PPU.Mode7Repeat) \ + { \ + for (uint32 x = Left; x < Right; x++, AA += aa, CC += cc) \ + { \ + int X = ((AA + BB) >> 8) & 0x3ff; \ + int Y = ((CC + DD) >> 8) & 0x3ff; \ + \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint8 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + \ + DRAW_PIXEL(x, Pix = (b & MASK)); \ + } \ + } \ + else \ + { \ + for (uint32 x = Left; x < Right; x++, AA += aa, CC += cc) \ + { \ + int X = ((AA + BB) >> 8); \ + int Y = ((CC + DD) >> 8); \ + \ + uint8 b; \ + \ + if (((X | Y) & ~0x3ff) == 0) \ + { \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + } \ + else \ + if (PPU.Mode7Repeat == 3) \ + b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ + else \ + continue; \ + \ + DRAW_PIXEL(x, Pix = (b & MASK)); \ + } \ + } \ + } + +#define DRAW_TILE_MOSAIC() \ + uint8 *VRAM1 = Memory.VRAM + 1; \ + \ + if (DCMODE) \ + { \ + if (IPPU.DirectColourMapsNeedRebuild) \ + S9xBuildDirectColourMaps(); \ + GFX.RealScreenColors = DirectColourMaps[0]; \ + } \ + else \ + GFX.RealScreenColors = IPPU.ScreenColors; \ + \ + GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; \ + \ + int aa, cc; \ + int startx, StartY = GFX.StartY; \ + \ + int HMosaic = 1, VMosaic = 1, MosaicStart = 0; \ + int32 MLeft = Left, MRight = Right; \ + \ + if (PPU.BGMosaic[0]) \ + { \ + VMosaic = PPU.Mosaic; \ + MosaicStart = ((uint32) GFX.StartY - PPU.MosaicStart) % VMosaic; \ + StartY -= MosaicStart; \ + } \ + \ + if (PPU.BGMosaic[BG]) \ + { \ + HMosaic = PPU.Mosaic; \ + MLeft -= MLeft % HMosaic; \ + MRight += HMosaic - 1; \ + MRight -= MRight % HMosaic; \ + } \ + \ + uint32 Offset = StartY * GFX.PPL; \ + struct SLineMatrixData *l = &LineMatrixData[StartY]; \ + \ + for (uint32 Line = StartY; Line <= GFX.EndY; Line += VMosaic, Offset += VMosaic * GFX.PPL, l += VMosaic) \ + { \ + if (Line + VMosaic > GFX.EndY) \ + VMosaic = GFX.EndY - Line + 1; \ + \ + int yy, starty; \ + \ + int32 HOffset = ((int32) l->M7HOFS << 19) >> 19; \ + int32 VOffset = ((int32) l->M7VOFS << 19) >> 19; \ + \ + int32 CentreX = ((int32) l->CentreX << 19) >> 19; \ + int32 CentreY = ((int32) l->CentreY << 19) >> 19; \ + \ + if (PPU.Mode7VFlip) \ + starty = 255 - (int) (Line + 1); \ + else \ + starty = Line + 1; \ + \ + yy = CLIP_10_BIT_SIGNED(VOffset - CentreY); \ + \ + int BB = ((l->MatrixB * starty) & ~63) + ((l->MatrixB * yy) & ~63) + (CentreX << 8); \ + int DD = ((l->MatrixD * starty) & ~63) + ((l->MatrixD * yy) & ~63) + (CentreY << 8); \ + \ + if (PPU.Mode7HFlip) \ + { \ + startx = MRight - 1; \ + aa = -l->MatrixA; \ + cc = -l->MatrixC; \ + } \ + else \ + { \ + startx = MLeft; \ + aa = l->MatrixA; \ + cc = l->MatrixC; \ + } \ + \ + int xx = CLIP_10_BIT_SIGNED(HOffset - CentreX); \ + int AA = l->MatrixA * startx + ((l->MatrixA * xx) & ~63); \ + int CC = l->MatrixC * startx + ((l->MatrixC * xx) & ~63); \ + \ + uint8 Pix; \ + uint8 ctr = 1; \ + \ + if (!PPU.Mode7Repeat) \ + { \ + for (int32 x = MLeft; x < MRight; x++, AA += aa, CC += cc) \ + { \ + if (--ctr) \ + continue; \ + ctr = HMosaic; \ + \ + int X = ((AA + BB) >> 8) & 0x3ff; \ + int Y = ((CC + DD) >> 8) & 0x3ff; \ + \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint8 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + \ + if ((Pix = (b & MASK))) \ + { \ + for (int32 h = MosaicStart; h < VMosaic; h++) \ + { \ + for (int32 w = x + HMosaic - 1; w >= x; w--) \ + DRAW_PIXEL(w + h * GFX.PPL, (w >= (int32) Left && w < (int32) Right)); \ + } \ + } \ + } \ + } \ + else \ + { \ + for (int32 x = MLeft; x < MRight; x++, AA += aa, CC += cc) \ + { \ + if (--ctr) \ + continue; \ + ctr = HMosaic; \ + \ + int X = ((AA + BB) >> 8); \ + int Y = ((CC + DD) >> 8); \ + \ + uint8 b; \ + \ + if (((X | Y) & ~0x3ff) == 0) \ + { \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + } \ + else \ + if (PPU.Mode7Repeat == 3) \ + b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ + else \ + continue; \ + \ + if ((Pix = (b & MASK))) \ + { \ + for (int32 h = MosaicStart; h < VMosaic; h++) \ + { \ + for (int32 w = x + HMosaic - 1; w >= x; w--) \ + DRAW_PIXEL(w + h * GFX.PPL, (w >= (int32) Left && w < (int32) Right)); \ + } \ + } \ + } \ + } \ + \ + MosaicStart = 0; \ + } + +#define DRAW_TILE() DRAW_TILE_NORMAL() +#define NAME1 DrawMode7BG1 +#define ARGS uint32 Left, uint32 Right, int D + +// Second-level include: Get the DrawMode7BG1 renderers. + +#include "tile.cpp" + +#undef NAME1 +#undef DRAW_TILE + +#define DRAW_TILE() DRAW_TILE_MOSAIC() +#define NAME1 DrawMode7MosaicBG1 + +// Second-level include: Get the DrawMode7MosaicBG1 renderers. + +#include "tile.cpp" + +#undef DRAW_TILE +#undef NAME1 +#undef Z1 +#undef Z2 +#undef MASK +#undef DCMODE +#undef BG + +#define NAME1 DrawMode7BG2 +#define DRAW_TILE() DRAW_TILE_NORMAL() +#define Z1 (D + ((b & 0x80) ? 11 : 3)) +#define Z2 (D + ((b & 0x80) ? 11 : 3)) +#define MASK 0x7f +#define DCMODE 0 +#define BG 1 + +// Second-level include: Get the DrawMode7BG2 renderers. + +#include "tile.cpp" + +#undef NAME1 +#undef DRAW_TILE + +#define DRAW_TILE() DRAW_TILE_MOSAIC() +#define NAME1 DrawMode7MosaicBG2 + +// Second-level include: Get the DrawMode7MosaicBG2 renderers. + +#include "tile.cpp" + +#undef MASK +#undef DCMODE +#undef BG +#undef NAME1 +#undef ARGS +#undef DRAW_TILE +#undef DRAW_TILE_NORMAL +#undef DRAW_TILE_MOSAIC +#undef Z1 +#undef Z2 +#undef NO_INTERLACE + +/*****************************************************************************/ +#else +#ifndef NAME2 // Second-level: Get all the NAME1 renderers. +/*****************************************************************************/ + +#define BPSTART StartLine +#define PITCH 1 + +// The 1x1 pixel plotter, for speedhacking modes. + +#define DRAW_PIXEL(N, M) \ + if (Z1 > GFX.DB[Offset + N] && (M)) \ + { \ + GFX.S[Offset + N] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + N], GFX.SubZBuffer[Offset + N]); \ + GFX.DB[Offset + N] = Z2; \ + } + +#define NAME2 Normal1x1 + +// Third-level include: Get the Normal1x1 renderers. + +#include "tile.cpp" + +#undef NAME2 +#undef DRAW_PIXEL + +// The 2x1 pixel plotter, for normal rendering when we've used hires/interlace already this frame. + +#define DRAW_PIXEL_N2x1(N, M) \ + if (Z1 > GFX.DB[Offset + 2 * N] && (M)) \ + { \ + GFX.S[Offset + 2 * N] = GFX.S[Offset + 2 * N + 1] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + 2 * N], GFX.SubZBuffer[Offset + 2 * N]); \ + GFX.DB[Offset + 2 * N] = GFX.DB[Offset + 2 * N + 1] = Z2; \ + } + +#define DRAW_PIXEL(N, M) DRAW_PIXEL_N2x1(N, M) +#define NAME2 Normal2x1 + +// Third-level include: Get the Normal2x1 renderers. + +#include "tile.cpp" + +#undef NAME2 +#undef DRAW_PIXEL + +// Hires pixel plotter, this combines the main and subscreen pixels as appropriate to render hires or pseudo-hires images. +// Use it only on the main screen, subscreen should use Normal2x1 instead. +// Hires math: +// Main pixel is mathed as normal: Main(x, y) * Sub(x, y). +// Sub pixel is mathed somewhat weird: Basically, for Sub(x + 1, y) we apply the same operation we applied to Main(x, y) +// (e.g. no math, add fixed, add1/2 subscreen) using Main(x, y) as the "corresponding subscreen pixel". +// Also, color window clipping clips Sub(x + 1, y) if Main(x, y) is clipped, not Main(x + 1, y). +// We don't know how Sub(0, y) is handled. + +#define DRAW_PIXEL_H2x1(N, M) \ + if (Z1 > GFX.DB[Offset + 2 * N] && (M)) \ + { \ + GFX.S[Offset + 2 * N] = MATH((GFX.ClipColors ? 0 : GFX.SubScreen[Offset + 2 * N]), GFX.RealScreenColors[Pix], GFX.SubZBuffer[Offset + 2 * N]); \ + GFX.S[Offset + 2 * N + 1] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + 2 * N], GFX.SubZBuffer[Offset + 2 * N]); \ + GFX.DB[Offset + 2 * N] = GFX.DB[Offset + 2 * N + 1] = Z2; \ + } + +#define DRAW_PIXEL(N, M) DRAW_PIXEL_H2x1(N, M) +#define NAME2 Hires + +// Third-level include: Get the Hires renderers. + +#include "tile.cpp" + +#undef NAME2 +#undef DRAW_PIXEL + +// Interlace: Only draw every other line, so we'll redefine BPSTART and PITCH to do so. +// Otherwise, it's the same as Normal2x1/Hires2x1. + +#undef BPSTART +#undef PITCH + +#define BPSTART (StartLine * 2 + BG.InterlaceLine) +#define PITCH 2 + +#ifndef NO_INTERLACE + +#define DRAW_PIXEL(N, M) DRAW_PIXEL_N2x1(N, M) +#define NAME2 Interlace + +// Third-level include: Get the double width Interlace renderers. + +#include "tile.cpp" + +#undef NAME2 +#undef DRAW_PIXEL + +#define DRAW_PIXEL(N, M) DRAW_PIXEL_H2x1(N, M) +#define NAME2 HiresInterlace + +// Third-level include: Get the HiresInterlace renderers. + +#include "tile.cpp" + +#undef NAME2 +#undef DRAW_PIXEL + +#endif + +#undef BPSTART +#undef PITCH + +/*****************************************************************************/ +#else // Third-level: Renderers for each math mode for NAME1 + NAME2. +/*****************************************************************************/ + +#define CONCAT3(A, B, C) A##B##C +#define MAKENAME(A, B, C) CONCAT3(A, B, C) + +static void MAKENAME(NAME1, _, NAME2) (ARGS) +{ +#define MATH(A, B, C) NOMATH(x, A, B, C) + DRAW_TILE(); +#undef MATH +} + +static void MAKENAME(NAME1, Add_, NAME2) (ARGS) +{ +#define MATH(A, B, C) REGMATH(ADD, A, B, C) + DRAW_TILE(); +#undef MATH +} + +static void MAKENAME(NAME1, AddF1_2_, NAME2) (ARGS) +{ +#define MATH(A, B, C) MATHF1_2(ADD, A, B, C) + DRAW_TILE(); +#undef MATH +} + +static void MAKENAME(NAME1, AddS1_2_, NAME2) (ARGS) +{ +#define MATH(A, B, C) MATHS1_2(ADD, A, B, C) + DRAW_TILE(); +#undef MATH +} + +static void MAKENAME(NAME1, Sub_, NAME2) (ARGS) +{ +#define MATH(A, B, C) REGMATH(SUB, A, B, C) + DRAW_TILE(); +#undef MATH +} + +static void MAKENAME(NAME1, SubF1_2_, NAME2) (ARGS) +{ +#define MATH(A, B, C) MATHF1_2(SUB, A, B, C) + DRAW_TILE(); +#undef MATH +} + +static void MAKENAME(NAME1, SubS1_2_, NAME2) (ARGS) +{ +#define MATH(A, B, C) MATHS1_2(SUB, A, B, C) + DRAW_TILE(); +#undef MATH +} + +static void (*MAKENAME(Renderers_, NAME1, NAME2)[7]) (ARGS) = +{ + MAKENAME(NAME1, _, NAME2), + MAKENAME(NAME1, Add_, NAME2), + MAKENAME(NAME1, AddF1_2_, NAME2), + MAKENAME(NAME1, AddS1_2_, NAME2), + MAKENAME(NAME1, Sub_, NAME2), + MAKENAME(NAME1, SubF1_2_, NAME2), + MAKENAME(NAME1, SubS1_2_, NAME2) +}; + +#undef MAKENAME +#undef CONCAT3 + +#endif +#endif +#endif diff --git a/plugins/snes9x_gx/source/snes9x/tile.h b/plugins/snes9x_gx/source/snes9x/tile.h new file mode 100644 index 00000000..d4bd94f9 --- /dev/null +++ b/plugins/snes9x_gx/source/snes9x/tile.h @@ -0,0 +1,185 @@ +/*********************************************************************************** + 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. + ***********************************************************************************/ + + +#ifndef _TILE_H_ +#define _TILE_H_ + +void S9xInitTileRenderer (void); +void S9xSelectTileRenderers (int, bool8, bool8); +void S9xSelectTileConverter (int, bool8, bool8, bool8); + +#endif diff --git a/plugins/snes9x_gx/source/snes9xgx.cpp b/plugins/snes9x_gx/source/snes9xgx.cpp new file mode 100644 index 00000000..b49ec1dc --- /dev/null +++ b/plugins/snes9x_gx/source/snes9xgx.cpp @@ -0,0 +1,574 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * crunchy2 May 2007-July 2007 + * Michniewski 2008 + * Tantric 2008-2010 + * + * snes9xgx.cpp + * + * This file controls overall program flow. Most things start and end here! + ***************************************************************************/ + +#include <gccore.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <string> +#include <ogcsys.h> +#include <unistd.h> +#include <wiiuse/wpad.h> +#include <wupc/wupc.h> +#include <fat.h> +#include <debug.h> +#include <sys/iosupport.h> + +#ifdef HW_RVL +#include <di/di.h> +#endif + +#include "snes9xgx.h" +#include "networkop.h" +#include "video.h" +#include "audio.h" +#include "menu.h" +#include "sram.h" +#include "freeze.h" +#include "preferences.h" +#include "button_mapping.h" +#include "fileop.h" +#include "filebrowser.h" +#include "input.h" +#include "mem2.h" +#include "utils/FreeTypeGX.h" + +#include "snes9x/snes9x.h" +#include "snes9x/memmap.h" +#include "snes9x/apu/apu.h" +#include "snes9x/controls.h" + +int ScreenshotRequested = 0; +int ConfigRequested = 0; +int ShutdownRequested = 0; +int ResetRequested = 0; +int ExitRequested = 0; +char appPath[1024] = { 0 }; +char loadedFile[1024] = { 0 }; +static int currentMode; + +extern "C" { +extern void __exception_setreload(int t); +} + +extern void S9xInitSync(); +extern uint32 prevRenderedFrameCount; + +/**************************************************************************** + * Shutdown / Reboot / Exit + ***************************************************************************/ + +void ExitCleanup() +{ + ShutdownAudio(); + StopGX(); + + HaltDeviceThread(); + UnmountAllFAT(); + +#ifdef HW_RVL + DI_Close(); +#endif +} + +#ifdef HW_DOL + #define PSOSDLOADID 0x7c6000a6 + int *psoid = (int *) 0x80001800; + void (*PSOReload) () = (void (*)()) 0x80001800; +#endif + +void ExitToWiiflow() +{ + ShutoffRumble(); + SavePrefs(SILENT); + if (SNESROMSize > 0 && !ConfigRequested && GCSettings.AutoSave == 1) + SaveSRAMAuto(SILENT); + ExitCleanup(); + + if( !!*(u32*)0x80001800 ) + { + // Were we launched via HBC? (or via wiiflows stub replacement? :P) + exit(1); + } + else + { + // Wii channel support + SYS_ResetSystem( SYS_RETURNTOMENU, 0, 0 ); + } +} + +void ExitApp() +{ +#ifdef HW_RVL + ShutoffRumble(); +#endif + + SavePrefs(SILENT); + + if (SNESROMSize > 0 && !ConfigRequested && GCSettings.AutoSave == 1) + SaveSRAMAuto(SILENT); + + ExitCleanup(); + + if(ShutdownRequested) + SYS_ResetSystem(SYS_POWEROFF, 0, 0); + + #ifdef HW_RVL + if(GCSettings.ExitAction == 0) // Auto + { + char * sig = (char *)0x80001804; + if( + sig[0] == 'S' && + sig[1] == 'T' && + sig[2] == 'U' && + sig[3] == 'B' && + sig[4] == 'H' && + sig[5] == 'A' && + sig[6] == 'X' && + sig[7] == 'X') + GCSettings.ExitAction = 3; // Exit to HBC + else + GCSettings.ExitAction = 1; // HBC not found + } + #endif + + if(GCSettings.ExitAction == 1) // Exit to Menu + { + #ifdef HW_RVL + SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); + #else + #define SOFTRESET_ADR ((volatile u32*)0xCC003024) + *SOFTRESET_ADR = 0x00000000; + #endif + } + else if(GCSettings.ExitAction == 2) // Shutdown Wii + { + SYS_ResetSystem(SYS_POWEROFF, 0, 0); + } + else // Exit to Loader + { + #ifdef HW_RVL + exit(0); + #else + if (psoid[0] == PSOSDLOADID) + PSOReload(); + #endif + } +} + +#ifdef HW_RVL +void ShutdownCB() +{ + ShutdownRequested = 1; +} +void ResetCB() +{ + ResetRequested = 1; +} +#endif + +#ifdef HW_DOL +/**************************************************************************** + * ipl_set_config + * lowlevel Qoob Modchip disable + ***************************************************************************/ + +void ipl_set_config(unsigned char c) +{ + volatile unsigned long* exi = (volatile unsigned long*)0xCC006800; + unsigned long val,addr; + addr=0xc0000000; + val = c << 24; + exi[0] = ((((exi[0]) & 0x405) | 256) | 48); //select IPL + //write addr of IPL + exi[0 * 5 + 4] = addr; + exi[0 * 5 + 3] = ((4 - 1) << 4) | (1 << 2) | 1; + while (exi[0 * 5 + 3] & 1); + //write the ipl we want to send + exi[0 * 5 + 4] = val; + exi[0 * 5 + 3] = ((4 - 1) << 4) | (1 << 2) | 1; + while (exi[0 * 5 + 3] & 1); + + exi[0] &= 0x405; //deselect IPL +} +#endif + +/**************************************************************************** + * setFrameTimerMethod() + * change frametimer method depending on whether ROM is NTSC or PAL + ***************************************************************************/ + +void setFrameTimerMethod() +{ + /* + Set frametimer method + (timerstyle: 0=NTSC vblank, 1=PAL int timer) + */ + if ( Settings.PAL ) { + if(vmode_60hz) + timerstyle = 1; + else + timerstyle = 0; + } else { + if(vmode_60hz) + timerstyle = 0; + else + timerstyle = 1; + } + return; +} + +/**************************************************************************** + * IOS Check + ***************************************************************************/ +#ifdef HW_RVL +bool SupportedIOS(u32 ios) +{ + if(ios == 58 || ios == 61) + return true; + + return false; +} + +bool SaneIOS(u32 ios) +{ + bool res = false; + u32 num_titles=0; + u32 tmd_size; + + if(ios > 200) + return false; + + if (ES_GetNumTitles(&num_titles) < 0) + return false; + + if(num_titles < 1) + return false; + + u64 *titles = (u64 *)memalign(32, num_titles * sizeof(u64) + 32); + + if(!titles) + return false; + + if (ES_GetTitles(titles, num_titles) < 0) + { + free(titles); + return false; + } + + u32 *tmdbuffer = (u32 *)memalign(32, MAX_SIGNED_TMD_SIZE); + + if(!tmdbuffer) + { + free(titles); + return false; + } + + for(u32 n=0; n < num_titles; n++) + { + if((titles[n] & 0xFFFFFFFF) != ios) + continue; + + if (ES_GetStoredTMDSize(titles[n], &tmd_size) < 0) + break; + + if (tmd_size > 4096) + break; + + if (ES_GetStoredTMD(titles[n], (signed_blob *)tmdbuffer, tmd_size) < 0) + break; + + if (tmdbuffer[1] || tmdbuffer[2]) + { + res = true; + break; + } + } + free(tmdbuffer); + free(titles); + return res; +} +#endif +/**************************************************************************** + * USB Gecko Debugging + ***************************************************************************/ + +static bool gecko = false; +static mutex_t gecko_mutex = 0; + +static ssize_t __out_write(struct _reent *r, int fd, const char *ptr, size_t len) +{ + if (!gecko || len == 0) + return len; + + if(!ptr || len < 0) + return -1; + + u32 level; + LWP_MutexLock(gecko_mutex); + level = IRQ_Disable(); + usb_sendbuffer(1, ptr, len); + IRQ_Restore(level); + LWP_MutexUnlock(gecko_mutex); + return len; +} + +const devoptab_t gecko_out = { + "stdout", // device name + 0, // size of file structure + NULL, // device open + NULL, // device close + __out_write,// device write + NULL, // device read + NULL, // device seek + NULL, // device fstat + NULL, // device stat + NULL, // device link + NULL, // device unlink + NULL, // device chdir + NULL, // device rename + NULL, // device mkdir + 0, // dirStateSize + NULL, // device diropen_r + NULL, // device dirreset_r + NULL, // device dirnext_r + NULL, // device dirclose_r + NULL // device statvfs_r +}; + +static void USBGeckoOutput() +{ + gecko = usb_isgeckoalive(1); + LWP_MutexInit(&gecko_mutex, false); + + devoptab_list[STD_OUT] = &gecko_out; + devoptab_list[STD_ERR] = &gecko_out; +} + +extern "C" { + s32 __STM_Close(); + s32 __STM_Init(); +} + +int main(int argc, char *argv[]) +{ + #ifdef HW_RVL + L2Enhance(); + + u32 ios = IOS_GetVersion(); + + if(!SupportedIOS(ios)) + { + s32 preferred = IOS_GetPreferredVersion(); + + if(SupportedIOS(preferred)) + IOS_ReloadIOS(preferred); + } + #else + ipl_set_config(6); // disable Qoob modchip + #endif + + USBGeckoOutput(); + __exception_setreload(8); + + InitGCVideo(); // Initialise video + ResetVideo_Menu (); // change to menu video mode + + #ifdef HW_RVL + // Wii Power/Reset buttons + __STM_Close(); + __STM_Init(); + __STM_Close(); + __STM_Init(); + SYS_SetPowerCallback(ShutdownCB); + SYS_SetResetCallback(ResetCB); + + WUPC_Init(); + WPAD_Init(); + WPAD_SetPowerButtonCallback((WPADShutdownCallback)ShutdownCB); + DI_Init(); + USBStorage_Initialize(); + StartNetworkThread(); + #else + DVD_Init (); // Initialize DVD subsystem (GameCube only) + #endif + + SetupPads(); + InitDeviceThread(); + MountAllFAT(); // Initialize libFAT for SD and USB + + #ifdef HW_RVL + // store path app was loaded from + if(argc > 0 && argv[0] != NULL) + CreateAppPath(argv[0]); + + InitMem2Manager(); + #endif + + DefaultSettings (); // Set defaults + S9xUnmapAllControls (); + SetDefaultButtonMap (); + + // Allocate SNES Memory + if (!Memory.Init ()) + ExitApp(); + + // Allocate APU + if (!S9xInitAPU ()) + ExitApp(); + + S9xSetRenderPixelFormat (RGB565); // Set Pixel Renderer to match 565 + S9xInitSound (64, 0); // Initialise Sound System + + // Initialise Graphics + setGFX (); + if (!S9xGraphicsInit ()) + ExitApp(); + + AllocGfxMem(); + S9xInitSync(); // initialize frame sync + InitFreeType((u8*)font_ttf, font_ttf_size); // Initialize font system +#ifdef HW_RVL + savebuffer = (unsigned char *)mem2_malloc(SAVEBUFFERSIZE); + browserList = (BROWSERENTRY *)mem2_malloc(sizeof(BROWSERENTRY)*MAX_BROWSER_SIZE); +#else + savebuffer = (unsigned char *)malloc(SAVEBUFFERSIZE); + browserList = (BROWSERENTRY *)malloc(sizeof(BROWSERENTRY)*MAX_BROWSER_SIZE); +#endif + InitGUIThreads(); + + bool autoboot = false; + if(argc > 3 && argv[1] != NULL && argv[2] != NULL && argv[3] != NULL) + { + autoboot = true; + ResetBrowser(); + LoadPrefs(); + if(strcasestr(argv[1], "sd:/") != NULL) + { + GCSettings.SaveMethod = DEVICE_SD; + GCSettings.LoadMethod = DEVICE_SD; + } + else + { + GCSettings.SaveMethod = DEVICE_USB; + GCSettings.LoadMethod = DEVICE_USB; + } + SavePrefs(SILENT); + selectLoadedFile = 1; + std::string dir(argv[1]); + dir.assign(&dir[dir.find_last_of(":") + 2]); + char arg_filename[1024]; + strncpy(arg_filename, argv[2], sizeof(arg_filename)); + strncpy(GCSettings.LoadFolder, dir.c_str(), sizeof(GCSettings.LoadFolder)); + OpenGameList(); + strncpy(GCSettings.Exit_Dol_File, argv[3], sizeof(GCSettings.Exit_Dol_File)); + if(argc > 5 && argv[4] != NULL && argv[5] != NULL) + { + sscanf(argv[4], "%08x", &GCSettings.Exit_Channel[0]); + sscanf(argv[5], "%08x", &GCSettings.Exit_Channel[1]); + } + else + { + GCSettings.Exit_Channel[0] = 0x00010008; + GCSettings.Exit_Channel[1] = 0x57494948; + } + if(argc > 6 && argv[6] != NULL) + strncpy(GCSettings.LoaderName, argv[6], sizeof(GCSettings.LoaderName)); + else + snprintf(GCSettings.LoaderName, sizeof(GCSettings.LoaderName), "WiiFlow"); + for(int i = 0; i < browser.numEntries; i++) + { + // Skip it + if (strcmp(browserList[i].filename, ".") == 0 || strcmp(browserList[i].filename, "..") == 0) + continue; + if(strcasestr(browserList[i].filename, arg_filename) != NULL) + { + browser.selIndex = i; + if(IsSz()) + { + BrowserLoadSz(); + browser.selIndex = 1; + } + break; + } + } + BrowserLoadFile(); + } + + while (1) // main loop + { + // go back to checking if devices were inserted/removed + // since we're entering the menu + ResumeDeviceThread(); + + SwitchAudioMode(1); + + if(!autoboot) + { + MainMenu(MENU_GAME); + ConfigRequested = 0; + ScreenshotRequested = 0; + } + else if(SNESROMSize != 0 && autoboot) + autoboot = false; + else + ExitApp(); +#ifdef HW_RVL + SelectFilterMethod(); +#endif + ConfigRequested = 0; + ScreenshotRequested = 0; + SwitchAudioMode(0); + + Settings.MultiPlayer5Master = (GCSettings.Controller == CTRL_PAD4 ? true : false); + Settings.SuperScopeMaster = (GCSettings.Controller == CTRL_SCOPE ? true : false); + Settings.MouseMaster = (GCSettings.Controller == CTRL_MOUSE ? true : false); + Settings.JustifierMaster = (GCSettings.Controller == CTRL_JUST ? true : false); + SetControllers (); + + // stop checking if devices were removed/inserted + // since we're starting emulation again + HaltDeviceThread(); + + AudioStart (); + + FrameTimer = 0; + setFrameTimerMethod (); // set frametimer method every time a ROM is loaded + + CheckVideo = 2; // force video update + prevRenderedFrameCount = IPPU.RenderedFramesCount; + currentMode = GCSettings.render; + + while(1) // emulation loop + { + S9xMainLoop (); + ReportButtons (); + + if(ResetRequested) + { + S9xSoftReset (); // reset game + ResetRequested = 0; + } + if (ConfigRequested) + { + ConfigRequested = 0; + ResetVideo_Menu(); + break; + } + #ifdef HW_RVL + if(ShutdownRequested) + ExitApp(); + #endif + } // emulation loop + } // main loop +} diff --git a/plugins/snes9x_gx/source/snes9xgx.h b/plugins/snes9x_gx/source/snes9xgx.h new file mode 100644 index 00000000..eca8db9f --- /dev/null +++ b/plugins/snes9x_gx/source/snes9xgx.h @@ -0,0 +1,134 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * crunchy2 May 2007-July 2007 + * Michniewski 2008 + * Tantric 2008-2010 + * + * snes9xgx.h + * + * This file controls overall program flow. Most things start and end here! + ***************************************************************************/ + +#ifndef _SNES9XGX_H_ +#define _SNES9XGX_H_ + +#include "utils/FreeTypeGX.h" +#include "snes9x.h" +#include "filter.h" +#include "filelist.h" + +#define APPNAME "Snes9x GX" +#define APPVERSION "4.3.4" +#define APPFOLDER "snes9xgx" +#define PREF_FILE_NAME "settings.xml" + +#define NOTSILENT 0 +#define SILENT 1 + +const char pathPrefix[9][8] = +{ "", "sd:/", "usb:/", "dvd:/", "smb:/", "carda:/", "cardb:/" }; + +enum { + DEVICE_AUTO, + DEVICE_SD, + DEVICE_USB, + DEVICE_DVD, + DEVICE_SMB, + DEVICE_SD_SLOTA, + DEVICE_SD_SLOTB +}; + +enum { + FILE_SRAM, + FILE_SNAPSHOT, + FILE_ROM, + FILE_CHEAT +}; + +enum +{ + CTRL_PAD, + CTRL_MOUSE, + CTRL_SCOPE, + CTRL_JUST, + CTRL_PAD2, + CTRL_PAD4, + CTRL_LENGTH +}; + +const char ctrlName[6][24] = +{ "SNES Controller", "SNES Mouse", "Superscope", "Justifier", "SNES Controllers (2)", "SNES Controllers (4)" }; + +enum { + LANG_JAPANESE = 0, + LANG_ENGLISH, + LANG_GERMAN, + LANG_FRENCH, + LANG_SPANISH, + LANG_ITALIAN, + LANG_DUTCH, + LANG_SIMP_CHINESE, + LANG_TRAD_CHINESE, + LANG_KOREAN, + LANG_PORTUGUESE, + LANG_BRAZILIAN_PORTUGUESE, + LANG_CATALAN, + LANG_TURKISH, + LANG_LENGTH +}; + +struct SGCSettings{ + int AutoLoad; + int AutoSave; + int LoadMethod; // For ROMS: Auto, SD, DVD, USB, Network (SMB) + int SaveMethod; // For SRAM, Freeze, Prefs: Auto, SD, USB, SMB + char LoadFolder[MAXPATHLEN]; // Path to game files + char LastFileLoaded[MAXPATHLEN]; //Last file loaded filename + char SaveFolder[MAXPATHLEN]; // Path to save files + char CheatFolder[MAXPATHLEN]; // Path to cheat files + char ScreenshotsFolder[MAXPATHLEN]; //Path to screenshots files + + char Exit_Dol_File[MAXPATHLEN]; // Exit Path + char LoaderName[20]; // Menu Loader Name + u32 Exit_Channel[2]; // Exit Channel + + char smbip[80]; + char smbuser[20]; + char smbpwd[20]; + char smbshare[20]; + + float zoomHor; // horizontal zoom amount + float zoomVert; // vertical zoom amount + int videomode; // 0 - automatic, 1 - NTSC (480i), 2 - Progressive (480p), 3 - PAL (50Hz), 4 - PAL (60Hz) + int render; // 0 - original, 1 - filtered, 2 - unfiltered + int FilterMethod; // convert to RenderFilter + int Controller; + int crosshair; + int widescreen; // 0 - 4:3 aspect, 1 - 16:9 aspect + int xshift; // video output shift + int yshift; + int WiimoteOrientation; + int ExitAction; + int MusicVolume; + int SFXVolume; + int Rumble; + int language; +}; + +void ExitApp(); +void ExitToWiiflow(); +void ShutdownWii(); +bool SupportedIOS(u32 ios); +bool SaneIOS(u32 ios); +extern struct SGCSettings GCSettings; +extern int ScreenshotRequested; +extern int ConfigRequested; +extern int ShutdownRequested; +extern int ExitRequested; +extern char appPath[]; +extern char loadedFile[]; +extern FreeTypeGX *fontSystem[]; + +#endif diff --git a/plugins/snes9x_gx/source/sounds/bg_music.ogg b/plugins/snes9x_gx/source/sounds/bg_music.ogg new file mode 100644 index 00000000..0431a02d Binary files /dev/null and b/plugins/snes9x_gx/source/sounds/bg_music.ogg differ diff --git a/plugins/snes9x_gx/source/sounds/button_click.pcm b/plugins/snes9x_gx/source/sounds/button_click.pcm new file mode 100644 index 00000000..de3d55e3 Binary files /dev/null and b/plugins/snes9x_gx/source/sounds/button_click.pcm differ diff --git a/plugins/snes9x_gx/source/sounds/button_over.pcm b/plugins/snes9x_gx/source/sounds/button_over.pcm new file mode 100644 index 00000000..777fbc56 Binary files /dev/null and b/plugins/snes9x_gx/source/sounds/button_over.pcm differ diff --git a/plugins/snes9x_gx/source/sounds/enter.ogg b/plugins/snes9x_gx/source/sounds/enter.ogg new file mode 100644 index 00000000..3f74df8e Binary files /dev/null and b/plugins/snes9x_gx/source/sounds/enter.ogg differ diff --git a/plugins/snes9x_gx/source/sounds/exit.ogg b/plugins/snes9x_gx/source/sounds/exit.ogg new file mode 100644 index 00000000..f792cb56 Binary files /dev/null and b/plugins/snes9x_gx/source/sounds/exit.ogg differ diff --git a/plugins/snes9x_gx/source/sram.cpp b/plugins/snes9x_gx/source/sram.cpp new file mode 100644 index 00000000..5ae9c96d --- /dev/null +++ b/plugins/snes9x_gx/source/sram.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * crunchy2 April 2007-July 2007 + * Michniewski 2008 + * Tantric 2008-2010 + * + * sram.cpp + * + * SRAM save/load/import/export handling + ***************************************************************************/ + +#include <gccore.h> +#include <stdio.h> +#include <string.h> +#include <ogcsys.h> + +#include "snes9xgx.h" +#include "menu.h" +#include "fileop.h" +#include "filebrowser.h" +#include "input.h" +#include "snes9x/snes9x.h" +#include "snes9x/memmap.h" +#include "snes9x/srtc.h" + +/**************************************************************************** + * Load SRAM + ***************************************************************************/ +bool +LoadSRAM (char * filepath, bool silent) +{ + int len = 0; + int device; + bool result = false; + + if(!FindDevice(filepath, &device)) + return 0; + + Memory.ClearSRAM(); + + int size = Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0; + + if (size > 0x20000) + size = 0x20000; + + if (size) + { + len = LoadFile((char *)Memory.SRAM, filepath, size, silent); + + if (len > 0) + { + if (len - size == 512) + memmove(Memory.SRAM, Memory.SRAM + 512, size); + + if (Settings.SRTC || Settings.SPC7110RTC) + { + int pathlen = strlen(filepath); + filepath[pathlen-3] = 'r'; + filepath[pathlen-2] = 't'; + filepath[pathlen-1] = 'c'; + LoadFile((char *)RTCData.reg, filepath, 20, silent); + } + result = true; + } + else if(!silent) + { + // if we reached here, nothing was done! + ErrorPrompt("SRAM file not found"); + } + S9xSoftReset(); + } + return result; +} + +bool +LoadSRAMAuto (bool silent) +{ + char filepath[MAXPATHLEN]; + + // look for Auto save file + if(!MakeFilePath(filepath, FILE_SRAM, Memory.ROMFilename, 0)) + return false; + + if (LoadSRAM(filepath, silent)) + return true; + + // look for file with no number or Auto appended + if(!MakeFilePath(filepath, FILE_SRAM, Memory.ROMFilename, -1)) + return false; + + if(LoadSRAM(filepath, silent)) + return true; + + return false; +} + +/**************************************************************************** + * Save SRAM + ***************************************************************************/ +bool +SaveSRAM (char * filepath, bool silent) +{ + bool retval = false; + int offset = 0; + int device; + + if(!FindDevice(filepath, &device)) + return 0; + + if (Settings.SuperFX && Memory.ROMType < 0x15) // doesn't have SRAM + return true; + + if (Settings.SA1 && Memory.ROMType == 0x34) // doesn't have SRAM + return true; + + // determine SRAM size + int size = Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0; + + if (size > 0x20000) + size = 0x20000; + + if (size > 0) + { + offset = SaveFile((char *)Memory.SRAM, filepath, size, silent); + + if (Settings.SRTC || Settings.SPC7110RTC) + { + int pathlen = strlen(filepath); + filepath[pathlen-3] = 'r'; + filepath[pathlen-2] = 't'; + filepath[pathlen-1] = 'c'; + SaveFile((char *)RTCData.reg, filepath, 20, silent); + } + + if (offset > 0) + { + if (!silent) + InfoPrompt("Save successful"); + retval = true; + } + } + else + { + if(!silent) + ErrorPrompt("No SRAM data to save!"); + } + return retval; +} + +bool +SaveSRAMAuto (bool silent) +{ + char filepath[1024]; + + // look for file with no number or Auto appended + if(!MakeFilePath(filepath, FILE_SRAM, Memory.ROMFilename, -1)) + return false; + + FILE * fp = fopen (filepath, "rb"); + + if(fp) // file found + { + fclose (fp); + } + else + { + if(!MakeFilePath(filepath, FILE_SRAM, Memory.ROMFilename, 0)) + return false; + } + + return SaveSRAM(filepath, silent); +} diff --git a/plugins/snes9x_gx/source/sram.h b/plugins/snes9x_gx/source/sram.h new file mode 100644 index 00000000..dc345e90 --- /dev/null +++ b/plugins/snes9x_gx/source/sram.h @@ -0,0 +1,16 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * crunchy2 April 2007-July 2007 + * Michniewski 2008 + * Tantric 2008-2010 + * + * sram.cpp + * + * SRAM save/load/import/export handling + ***************************************************************************/ + +bool SaveSRAM (char * filepath, bool silent); +bool SaveSRAMAuto (bool silent); +bool LoadSRAM (char * filepath, bool silent); +bool LoadSRAMAuto (bool silent); diff --git a/plugins/snes9x_gx/source/utils/FreeTypeGX.cpp b/plugins/snes9x_gx/source/utils/FreeTypeGX.cpp new file mode 100644 index 00000000..8c2f9365 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/FreeTypeGX.cpp @@ -0,0 +1,667 @@ +/* + * FreeTypeGX is a wrapper class for libFreeType which renders a compiled + * FreeType parsable font into a GX texture for Wii homebrew development. + * Copyright (C) 2008 Armin Tamzarian + * Modified by Tantric, 2009 + * + * This file is part of FreeTypeGX. + * + * FreeTypeGX 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 3 of the License, or + * (at your option) any later version. + * + * FreeTypeGX 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 FreeTypeGX. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "FreeTypeGX.h" + +static FT_Library ftLibrary; /**< FreeType FT_Library instance. */ +static FT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */ +static FT_GlyphSlot ftSlot; /**< FreeType reusable FT_GlyphSlot glyph container object. */ + +FreeTypeGX *fontSystem[MAX_FONT_SIZE+1]; + +void InitFreeType(uint8_t* fontBuffer, FT_Long bufferSize) +{ + FT_Init_FreeType(&ftLibrary); + FT_New_Memory_Face(ftLibrary, (FT_Byte *)fontBuffer, bufferSize, 0, &ftFace); + ftSlot = ftFace->glyph; + + for(int i=0; i<50; i++) + fontSystem[i] = NULL; +} + +void DeinitFreeType() +{ + ClearFontData(); + FT_Done_FreeType(ftLibrary); + ftLibrary = NULL; +} + +void ChangeFontSize(FT_UInt pixelSize) +{ + FT_Set_Pixel_Sizes(ftFace, 0, pixelSize); +} + +void ClearFontData() +{ + for(int i=0; i<50; i++) + { + if(fontSystem[i]) + delete fontSystem[i]; + fontSystem[i] = NULL; + } +} + +/** + * Convert a short char string to a wide char string. + * + * This routine converts a supplied shot character string into a wide character string. + * Note that it is the user's responsibility to clear the returned buffer once it is no longer needed. + * + * @param strChar Character string to be converted. + * @return Wide character representation of supplied character string. + */ + +wchar_t* charToWideChar(const char* strChar) +{ + wchar_t *strWChar = new wchar_t[strlen(strChar) + 1]; + if(!strWChar) + return NULL; + + int bt = mbstowcs(strWChar, strChar, strlen(strChar)); + if (bt > 0) + { + strWChar[bt] = (wchar_t)'\0'; + return strWChar; + } + + wchar_t *tempDest = strWChar; + while((*tempDest++ = *strChar++)); + + return strWChar; +} + +/** + * Default constructor for the FreeTypeGX class. + * + * @param vertexIndex Optional vertex format index (GX_VTXFMT*) of the glyph textures as defined by the libogc gx.h header file. If not specified default value is GX_VTXFMT1. + */ +FreeTypeGX::FreeTypeGX(FT_UInt pixelSize, uint8_t vertexIndex) +{ + this->setVertexFormat(vertexIndex); + this->setCompatibilityMode(FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR | FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE); + this->ftPointSize = pixelSize; + this->ftKerningEnabled = FT_HAS_KERNING(ftFace); +} + +/** + * Default destructor for the FreeTypeGX class. + */ +FreeTypeGX::~FreeTypeGX() +{ + this->unloadFont(); +} + +/** + * Setup the vertex attribute formats for the glyph textures. + * + * This function sets up the vertex format for the glyph texture on the specified vertex format index. + * Note that this function should not need to be called except if the vertex formats are cleared or the specified + * vertex format index is modified. + * + * @param vertexIndex Vertex format index (GX_VTXFMT*) of the glyph textures as defined by the libogc gx.h header file. +*/ +void FreeTypeGX::setVertexFormat(uint8_t vertexIndex) +{ + this->vertexIndex = vertexIndex; + GX_SetVtxAttrFmt(this->vertexIndex, GX_VA_POS, GX_POS_XY, GX_S16, 0); + GX_SetVtxAttrFmt(this->vertexIndex, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GX_SetVtxAttrFmt(this->vertexIndex, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); +} + +/** + * Sets the TEV and VTX rendering compatibility requirements for the class. + * + * This sets up the default TEV opertion and VTX descriptions rendering values for the class. This ensures that FreeTypeGX + * can remain compatible with external liraries or project code. Certain external libraries or code by design or lack of + * foresight assume that the TEV opertion and VTX descriptions values will remain constant or are always returned to a + * certain value. This will enable compatibility with those libraries and any other code which cannot or will not be changed. + * + * @param compatibilityMode Compatibility descritor (FTGX_COMPATIBILITY_*) as defined in FreeTypeGX.h +*/ +void FreeTypeGX::setCompatibilityMode(uint32_t compatibilityMode) +{ + this->compatibilityMode = compatibilityMode; +} + +/** + * Sets the TEV operation and VTX descriptor values after texture rendering it complete. + * + * This function calls the GX_SetTevOp and GX_SetVtxDesc functions with the compatibility parameters specified + * in setCompatibilityMode. + */ +void FreeTypeGX::setDefaultMode() +{ + if(this->compatibilityMode) + { + switch(this->compatibilityMode & 0x00FF) + { + case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_MODULATE: + GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + break; + case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_DECAL: + GX_SetTevOp(GX_TEVSTAGE0, GX_DECAL); + break; + case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_BLEND: + GX_SetTevOp(GX_TEVSTAGE0, GX_BLEND); + break; + case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_REPLACE: + GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); + break; + case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR: + GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR); + break; + default: + break; + } + + switch(this->compatibilityMode & 0xFF00) + { + case FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE: + GX_SetVtxDesc(GX_VA_TEX0, GX_NONE); + break; + case FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_DIRECT: + GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); + break; + case FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_INDEX8: + GX_SetVtxDesc(GX_VA_TEX0, GX_INDEX8); + break; + case FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_INDEX16: + GX_SetVtxDesc(GX_VA_TEX0, GX_INDEX16); + break; + default: + break; + } + } +} + +/** + * Clears all loaded font glyph data. + * + * This routine clears all members of the font map structure and frees all allocated memory back to the system. + */ +void FreeTypeGX::unloadFont() +{ + if(this->fontData.size() == 0) + return; + for(std::map<wchar_t, ftgxCharData>::iterator i = this->fontData.begin(), iEnd = this->fontData.end(); i != iEnd; ++i) + free(i->second.glyphDataTexture); + this->fontData.clear(); +} + +uint16_t FreeTypeGX::adjustTextureWidth(uint16_t textureWidth) +{ + uint16_t alignment = 4; + return textureWidth % alignment == 0 ? textureWidth : alignment + textureWidth - (textureWidth % alignment); +} + +uint16_t FreeTypeGX::adjustTextureHeight(uint16_t textureHeight) +{ + uint16_t alignment = 4; + return textureHeight % alignment == 0 ? textureHeight : alignment + textureHeight - (textureHeight % alignment); +} + +/** + * Caches the given font glyph in the instance font texture buffer. + * + * This routine renders and stores the requested glyph's bitmap and relevant information into its own quickly addressible + * structure within an instance-specific map. + * + * @param charCode The requested glyph's character code. + * @return A pointer to the allocated font structure. + */ +ftgxCharData *FreeTypeGX::cacheGlyphData(wchar_t charCode) +{ + FT_UInt gIndex; + uint16_t textureWidth = 0, textureHeight = 0; + + gIndex = FT_Get_Char_Index( ftFace, charCode ); + if (!FT_Load_Glyph(ftFace, gIndex, FT_LOAD_DEFAULT | FT_LOAD_RENDER )) + { + if(ftSlot->format == FT_GLYPH_FORMAT_BITMAP) + { + FT_Bitmap *glyphBitmap = &ftSlot->bitmap; + + textureWidth = adjustTextureWidth(glyphBitmap->width); + textureHeight = adjustTextureHeight(glyphBitmap->rows); + + this->fontData[charCode] = (ftgxCharData){ + ftSlot->bitmap_left, + ftSlot->advance.x >> 6, + gIndex, + textureWidth, + textureHeight, + ftSlot->bitmap_top, + ftSlot->bitmap_top, + glyphBitmap->rows - ftSlot->bitmap_top, + NULL + }; + this->loadGlyphData(glyphBitmap, &this->fontData[charCode]); + + return &this->fontData[charCode]; + } + } + return NULL; +} + +/** + * Locates each character in this wrapper's configured font face and proccess them. + * + * This routine locates each character in the configured font face and renders the glyph's bitmap. + * Each bitmap and relevant information is loaded into its own quickly addressible structure within an instance-specific map. + */ +uint16_t FreeTypeGX::cacheGlyphDataComplete() +{ + uint32_t i = 0; + FT_UInt gIndex; + FT_ULong charCode = FT_Get_First_Char( ftFace, &gIndex ); + while ( gIndex != 0 ) + { + if(this->cacheGlyphData(charCode) != NULL) + ++i; + charCode = FT_Get_Next_Char( ftFace, charCode, &gIndex ); + } + return (uint16_t)(i); +} + +/** + * Loads the rendered bitmap into the relevant structure's data buffer. + * + * This routine does a simple byte-wise copy of the glyph's rendered 8-bit grayscale bitmap into the structure's buffer. + * Each byte is converted from the bitmap's intensity value into the a uint32_t RGBA value. + * + * @param bmp A pointer to the most recently rendered glyph's bitmap. + * @param charData A pointer to an allocated ftgxCharData structure whose data represent that of the last rendered glyph. + * + * Optimized for RGBA8 use by Dimok. + */ +void FreeTypeGX::loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData) +{ + int length = charData->textureWidth * charData->textureHeight * 4; + + uint8_t * glyphData = (uint8_t *) memalign(32, length); + if(!glyphData) + return; + + memset(glyphData, 0x00, length); + + uint8_t *src = (uint8_t *)bmp->buffer; + uint32_t offset; + + for (int imagePosY = 0; imagePosY < bmp->rows; ++imagePosY) + { + for (int imagePosX = 0; imagePosX < bmp->width; ++imagePosX) + { + offset = ((((imagePosY >> 2) * (charData->textureWidth >> 2) + (imagePosX >> 2)) << 5) + ((imagePosY & 3) << 2) + (imagePosX & 3)) << 1; + glyphData[offset] = *src; + glyphData[offset+1] = *src; + glyphData[offset+32] = *src; + glyphData[offset+33] = *src; + ++src; + } + } + DCFlushRange(glyphData, length); + charData->glyphDataTexture = (uint32_t *) glyphData; +} + +/** + * Determines the x offset of the rendered string. + * + * This routine calculates the x offset of the rendered string based off of a supplied positional format parameter. + * + * @param width Current pixel width of the string. + * @param format Positional format of the string. + */ +int16_t FreeTypeGX::getStyleOffsetWidth(uint16_t width, uint16_t format) +{ + if (format & FTGX_JUSTIFY_LEFT) + return 0; + else if (format & FTGX_JUSTIFY_CENTER) + return -(width >> 1); + else if (format & FTGX_JUSTIFY_RIGHT) + return -width; + return 0; +} + +/** + * Determines the y offset of the rendered string. + * + * This routine calculates the y offset of the rendered string based off of a supplied positional format parameter. + * + * @param offset Current pixel offset data of the string. + * @param format Positional format of the string. + */ +int16_t FreeTypeGX::getStyleOffsetHeight(ftgxDataOffset *offset, uint16_t format) +{ + switch(format & FTGX_ALIGN_MASK) + { + case FTGX_ALIGN_TOP: + return offset->ascender; + + default: + case FTGX_ALIGN_MIDDLE: + return (offset->ascender + offset->descender + 1) >> 1; + + case FTGX_ALIGN_BOTTOM: + return offset->descender; + + case FTGX_ALIGN_BASELINE: + return 0; + + case FTGX_ALIGN_GLYPH_TOP: + return offset->max; + + case FTGX_ALIGN_GLYPH_MIDDLE: + return (offset->max + offset->min + 1) >> 1; + + case FTGX_ALIGN_GLYPH_BOTTOM: + return offset->min; + } + return 0; +} + +/** + * Processes the supplied text string and prints the results at the specified coordinates. + * + * This routine processes each character of the supplied text string, loads the relevant preprocessed bitmap buffer, + * a texture from said buffer, and loads the resultant texture into the EFB. + * + * @param x Screen X coordinate at which to output the text. + * @param y Screen Y coordinate at which to output the text. Note that this value corresponds to the text string origin and not the top or bottom of the glyphs. + * @param text NULL terminated string to output. + * @param color Optional color to apply to the text characters. If not specified default value is ftgxWhite: (GXColor){0xff, 0xff, 0xff, 0xff} + * @param textStyle Flags which specify any styling which should be applied to the rendered string. + * @return The number of characters printed. + */ +uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t *text, GXColor color, uint16_t textStyle) +{ + uint16_t x_pos = x, printed = 0; + uint16_t x_offset = 0, y_offset = 0; + GXTexObj glyphTexture; + FT_Vector pairDelta; + ftgxDataOffset offset; + + if(textStyle & FTGX_JUSTIFY_MASK) + { + x_offset = this->getStyleOffsetWidth(this->getWidth(text), textStyle); + } + if(textStyle & FTGX_ALIGN_MASK) + { + this->getOffset(text, &offset); + y_offset = this->getStyleOffsetHeight(&offset, textStyle); + } + + int i = 0; + while (text[i]) + { + ftgxCharData* glyphData = NULL; + if (this->fontData.find(text[i]) != this->fontData.end()) + { + glyphData = &this->fontData[text[i]]; + } + else + { + glyphData = this->cacheGlyphData(text[i]); + } + + if (glyphData != NULL) + { + if (this->ftKerningEnabled && i) + { + FT_Get_Kerning(ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta); + x_pos += pairDelta.x >> 6; + } + + GX_InitTexObj(&glyphTexture, glyphData->glyphDataTexture, glyphData->textureWidth, glyphData->textureHeight, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE); + this->copyTextureToFramebuffer(&glyphTexture, glyphData->textureWidth, glyphData->textureHeight, x_pos + glyphData->renderOffsetX + x_offset, y - glyphData->renderOffsetY + y_offset, color); + + x_pos += glyphData->glyphAdvanceX; + ++printed; + } + ++i; + } + + if(textStyle & FTGX_STYLE_MASK) + { + this->getOffset(text, &offset); + this->drawTextFeature(x + x_offset, y + y_offset, this->getWidth(text), &offset, textStyle, color); + } + + return printed; +} + +/** + * \overload + */ +uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t const *text, GXColor color, uint16_t textStyle) +{ + return this->drawText(x, y, (wchar_t *)text, color, textStyle); +} + +void FreeTypeGX::drawTextFeature(int16_t x, int16_t y, uint16_t width, ftgxDataOffset *offsetData, uint16_t format, GXColor color) +{ + uint16_t featureHeight = this->ftPointSize >> 4 > 0 ? this->ftPointSize >> 4 : 1; + + if (format & FTGX_STYLE_UNDERLINE) + this->copyFeatureToFramebuffer(width, featureHeight, x, y + 1, color); + + if (format & FTGX_STYLE_STRIKE) + this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData->max) >> 1), color); +} + +/** + * Processes the supplied string and return the width of the string in pixels. + * + * This routine processes each character of the supplied text string and calculates the width of the entire string. + * Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function. + * + * @param text NULL terminated string to calculate. + * @return The width of the text string in pixels. + */ +uint16_t FreeTypeGX::getWidth(wchar_t *text) +{ + uint16_t strWidth = 0; + FT_Vector pairDelta; + + int i = 0; + while (text[i]) + { + ftgxCharData* glyphData = NULL; + if (this->fontData.find(text[i]) != this->fontData.end()) + { + glyphData = &this->fontData[text[i]]; + } + else + { + glyphData = this->cacheGlyphData(text[i]); + } + + if (glyphData != NULL) + { + if (this->ftKerningEnabled && (i > 0)) + { + FT_Get_Kerning(ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta); + strWidth += pairDelta.x >> 6; + } + + strWidth += glyphData->glyphAdvanceX; + } + ++i; + } + return strWidth; +} + +/** + * + * \overload + */ +uint16_t FreeTypeGX::getWidth(wchar_t const *text) +{ + return this->getWidth((wchar_t *)text); +} + +/** + * Processes the supplied string and return the height of the string in pixels. + * + * This routine processes each character of the supplied text string and calculates the height of the entire string. + * Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function. + * + * @param text NULL terminated string to calculate. + * @return The height of the text string in pixels. + */ +uint16_t FreeTypeGX::getHeight(wchar_t *text) +{ + ftgxDataOffset offset; + this->getOffset(text, &offset); + return offset.max - offset.min; +} + +/** + * + * \overload + */ +uint16_t FreeTypeGX::getHeight(wchar_t const *text) +{ + return this->getHeight((wchar_t *)text); +} + +/** + * Get the maximum offset above and minimum offset below the font origin line. + * + * This function calculates the maximum pixel height above the font origin line and the minimum + * pixel height below the font origin line and returns the values in an addressible structure. + * + * @param text NULL terminated string to calculate. + * @param offset returns the max and min values above and below the font origin line + * + */ +void FreeTypeGX::getOffset(wchar_t *text, ftgxDataOffset* offset) +{ + int16_t strMax = 0, strMin = 9999; + + int i = 0; + while (text[i]) + { + ftgxCharData* glyphData = NULL; + if (this->fontData.find(text[i]) != this->fontData.end()) + { + glyphData = &this->fontData[text[i]]; + } + else + { + glyphData = this->cacheGlyphData(text[i]); + } + + if(glyphData != NULL) + { + strMax = glyphData->renderOffsetMax > strMax ? glyphData->renderOffsetMax : strMax; + strMin = glyphData->renderOffsetMin < strMin ? glyphData->renderOffsetMin : strMin; + } + ++i; + } + offset->ascender = ftFace->size->metrics.ascender>>6; + offset->descender = ftFace->size->metrics.descender>>6; + offset->max = strMax; + offset->min = strMin; +} + +/** + * + * \overload + */ +void FreeTypeGX::getOffset(wchar_t const *text, ftgxDataOffset* offset) +{ + this->getOffset(text, offset); +} + +/** + * Copies the supplied texture quad to the EFB. + * + * This routine uses the in-built GX quad builder functions to define the texture bounds and location on the EFB target. + * + * @param texObj A pointer to the glyph's initialized texture object. + * @param texWidth The pixel width of the texture object. + * @param texHeight The pixel height of the texture object. + * @param screenX The screen X coordinate at which to output the rendered texture. + * @param screenY The screen Y coordinate at which to output the rendered texture. + * @param color Color to apply to the texture. + */ +void FreeTypeGX::copyTextureToFramebuffer(GXTexObj *texObj, f32 texWidth, f32 texHeight, int16_t screenX, int16_t screenY, GXColor color) +{ + GX_LoadTexObj(texObj, GX_TEXMAP0); + GX_InvalidateTexAll(); + + GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE); + GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT); + + GX_Begin(GX_QUADS, this->vertexIndex, 4); + GX_Position2s16(screenX, screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + GX_TexCoord2f32(0.0f, 0.0f); + + GX_Position2s16(texWidth + screenX, screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + GX_TexCoord2f32(1.0f, 0.0f); + + GX_Position2s16(texWidth + screenX, texHeight + screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + GX_TexCoord2f32(1.0f, 1.0f); + + GX_Position2s16(screenX, texHeight + screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + GX_TexCoord2f32(0.0f, 1.0f); + GX_End(); + + this->setDefaultMode(); +} + +/** + * Creates a feature quad to the EFB. + * + * This function creates a simple quad for displaying underline or strikeout text styling. + * + * @param featureWidth The pixel width of the quad. + * @param featureHeight The pixel height of the quad. + * @param screenX The screen X coordinate at which to output the quad. + * @param screenY The screen Y coordinate at which to output the quad. + * @param color Color to apply to the texture. + */ +void FreeTypeGX::copyFeatureToFramebuffer(f32 featureWidth, f32 featureHeight, int16_t screenX, int16_t screenY, GXColor color) +{ + GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR); + GX_SetVtxDesc (GX_VA_TEX0, GX_NONE); + + GX_Begin(GX_QUADS, this->vertexIndex, 4); + GX_Position2s16(screenX, screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + + GX_Position2s16(featureWidth + screenX, screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + + GX_Position2s16(featureWidth + screenX, featureHeight + screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + + GX_Position2s16(screenX, featureHeight + screenY); + GX_Color4u8(color.r, color.g, color.b, color.a); + GX_End(); + + this->setDefaultMode(); +} diff --git a/plugins/snes9x_gx/source/utils/FreeTypeGX.h b/plugins/snes9x_gx/source/utils/FreeTypeGX.h new file mode 100644 index 00000000..b5910f19 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/FreeTypeGX.h @@ -0,0 +1,168 @@ +/* + * FreeTypeGX is a wrapper class for libFreeType which renders a compiled + * FreeType parsable font into a GX texture for Wii homebrew development. + * Copyright (C) 2008 Armin Tamzarian + * Modified by Tantric, 2009-2010 + * + * This file is part of FreeTypeGX. + * + * FreeTypeGX 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 3 of the License, or + * (at your option) any later version. + * + * FreeTypeGX 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 FreeTypeGX. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FREETYPEGX_H_ +#define FREETYPEGX_H_ + +#include <gccore.h> +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_BITMAP_H + +#include <malloc.h> +#include <string.h> +#include <wchar.h> +#include <map> + +#define MAX_FONT_SIZE 100 + +/*! \struct ftgxCharData_ + * + * Font face character glyph relevant data structure. + */ +typedef struct ftgxCharData_ { + int16_t renderOffsetX; /**< Texture X axis bearing offset. */ + uint16_t glyphAdvanceX; /**< Character glyph X coordinate advance in pixels. */ + uint16_t glyphIndex; /**< Charachter glyph index in the font face. */ + + uint16_t textureWidth; /**< Texture width in pixels/bytes. */ + uint16_t textureHeight; /**< Texture glyph height in pixels/bytes. */ + + int16_t renderOffsetY; /**< Texture Y axis bearing offset. */ + int16_t renderOffsetMax; /**< Texture Y axis bearing maximum value. */ + int16_t renderOffsetMin; /**< Texture Y axis bearing minimum value. */ + + uint32_t* glyphDataTexture; /**< Glyph texture bitmap data buffer. */ +} ftgxCharData; + +/*! \struct ftgxDataOffset_ + * + * Offset structure which hold both a maximum and minimum value. + */ +typedef struct ftgxDataOffset_ { + int16_t ascender; /**< Maximum data offset. */ + int16_t descender; /**< Minimum data offset. */ + int16_t max; /**< Maximum data offset. */ + int16_t min; /**< Minimum data offset. */ +} ftgxDataOffset; + +typedef struct ftgxCharData_ ftgxCharData; +typedef struct ftgxDataOffset_ ftgxDataOffset; + +#define _TEXT(t) L ## t /**< Unicode helper macro. */ + +#define FTGX_NULL 0x0000 +#define FTGX_JUSTIFY_LEFT 0x0001 +#define FTGX_JUSTIFY_CENTER 0x0002 +#define FTGX_JUSTIFY_RIGHT 0x0004 +#define FTGX_JUSTIFY_MASK 0x000f + +#define FTGX_ALIGN_TOP 0x0010 +#define FTGX_ALIGN_MIDDLE 0x0020 +#define FTGX_ALIGN_BOTTOM 0x0040 +#define FTGX_ALIGN_BASELINE 0x0080 +#define FTGX_ALIGN_GLYPH_TOP 0x0100 +#define FTGX_ALIGN_GLYPH_MIDDLE 0x0200 +#define FTGX_ALIGN_GLYPH_BOTTOM 0x0400 +#define FTGX_ALIGN_MASK 0x0ff0 + +#define FTGX_STYLE_UNDERLINE 0x1000 +#define FTGX_STYLE_STRIKE 0x2000 +#define FTGX_STYLE_MASK 0xf000 + +#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_MODULATE 0X0001 +#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_DECAL 0X0002 +#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_BLEND 0X0004 +#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_REPLACE 0X0008 +#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR 0X0010 + +#define FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE 0X0100 +#define FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_DIRECT 0X0200 +#define FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_INDEX8 0X0400 +#define FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_INDEX16 0X0800 + +#define FTGX_COMPATIBILITY_NONE 0x0000 +#define FTGX_COMPATIBILITY_GRRLIB FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR | FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE +#define FTGX_COMPATIBILITY_LIBWIISPRITE FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_MODULATE | FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_DIRECT + +const GXColor ftgxWhite = (GXColor){0xff, 0xff, 0xff, 0xff}; /**< Constant color value used only to sanitize Doxygen documentation. */ + +void InitFreeType(uint8_t* fontBuffer, FT_Long bufferSize); +void DeinitFreeType(); +void ChangeFontSize(FT_UInt pixelSize); +wchar_t* charToWideChar(const char* p); +void ClearFontData(); + +/*! \class FreeTypeGX + * \brief Wrapper class for the libFreeType library with GX rendering. + * \author Armin Tamzarian + * \version 0.2.4 + * + * FreeTypeGX acts as a wrapper class for the libFreeType library. It supports precaching of transformed glyph data into + * a specified texture format. Rendering of the data to the EFB is accomplished through the application of high performance + * GX texture functions resulting in high throughput of string rendering. + */ +class FreeTypeGX { + + private: + FT_UInt ftPointSize; /**< Requested size of the rendered font. */ + bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */ + uint8_t vertexIndex; /**< Vertex format descriptor index. */ + uint32_t compatibilityMode; /**< Compatibility mode for default tev operations and vertex descriptors. */ + std::map<wchar_t, ftgxCharData> fontData; /**< Map which holds the glyph data structures for the corresponding characters. */ + + static uint16_t adjustTextureWidth(uint16_t textureWidth); + static uint16_t adjustTextureHeight(uint16_t textureHeight); + + static int16_t getStyleOffsetWidth(uint16_t width, uint16_t format); + static int16_t getStyleOffsetHeight(ftgxDataOffset *offset, uint16_t format); + + void unloadFont(); + ftgxCharData *cacheGlyphData(wchar_t charCode); + uint16_t cacheGlyphDataComplete(); + void loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData); + + void setDefaultMode(); + + void drawTextFeature(int16_t x, int16_t y, uint16_t width, ftgxDataOffset *offsetData, uint16_t format, GXColor color); + void copyTextureToFramebuffer(GXTexObj *texObj, f32 texWidth, f32 texHeight, int16_t screenX, int16_t screenY, GXColor color); + void copyFeatureToFramebuffer(f32 featureWidth, f32 featureHeight, int16_t screenX, int16_t screenY, GXColor color); + + public: + FreeTypeGX(FT_UInt pixelSize, uint8_t vertexIndex = GX_VTXFMT1); + ~FreeTypeGX(); + + void setVertexFormat(uint8_t vertexIndex); + void setCompatibilityMode(uint32_t compatibilityMode); + + uint16_t drawText(int16_t x, int16_t y, wchar_t *text, GXColor color = ftgxWhite, uint16_t textStyling = FTGX_NULL); + uint16_t drawText(int16_t x, int16_t y, wchar_t const *text, GXColor color = ftgxWhite, uint16_t textStyling = FTGX_NULL); + + uint16_t getWidth(wchar_t *text); + uint16_t getWidth(wchar_t const *text); + uint16_t getHeight(wchar_t *text); + uint16_t getHeight(wchar_t const *text); + void getOffset(wchar_t *text, ftgxDataOffset* offset); + void getOffset(wchar_t const *text, ftgxDataOffset* offset); +}; + +#endif /* FREETYPEGX_H_ */ diff --git a/plugins/snes9x_gx/source/utils/gettext.cpp b/plugins/snes9x_gx/source/utils/gettext.cpp new file mode 100644 index 00000000..628b58cc --- /dev/null +++ b/plugins/snes9x_gx/source/utils/gettext.cpp @@ -0,0 +1,290 @@ +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <gctypes.h> +#include <unistd.h> + +#include "gettext.h" +#include "filelist.h" +#include "snes9xgx.h" + +typedef struct _MSG +{ + u32 id; + char* msgstr; + struct _MSG *next; +} MSG; +static MSG *baseMSG = 0; + +#define HASHWORDBITS 32 + +/* Defines the so called `hashpjw' function by P.J. Weinberger + [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, + 1986, 1987 Bell Telephone Laboratories, Inc.] */ +static inline u32 hash_string(const char *str_param) +{ + u32 hval, g; + const char *str = str_param; + + /* Compute the hash value for the given string. */ + hval = 0; + while (*str != '\0') + { + hval <<= 4; + hval += (u8) * str++; + g = hval & ((u32) 0xf << (HASHWORDBITS - 4)); + if (g != 0) + { + hval ^= g >> (HASHWORDBITS - 8); + hval ^= g; + } + } + return hval; +} + +/* Expand some escape sequences found in the argument string. */ +static char * +expand_escape(const char *str) +{ + char *retval, *rp; + const char *cp = str; + + retval = (char *) malloc(strlen(str) + 1); + if (retval == NULL) + return NULL; + rp = retval; + + while (cp[0] != '\0' && cp[0] != '\\') + *rp++ = *cp++; + if (cp[0] == '\0') + goto terminate; + do + { + + /* Here cp[0] == '\\'. */ + switch (*++cp) + { + case '\"': /* " */ + *rp++ = '\"'; + ++cp; + break; + case 'a': /* alert */ + *rp++ = '\a'; + ++cp; + break; + case 'b': /* backspace */ + *rp++ = '\b'; + ++cp; + break; + case 'f': /* form feed */ + *rp++ = '\f'; + ++cp; + break; + case 'n': /* new line */ + *rp++ = '\n'; + ++cp; + break; + case 'r': /* carriage return */ + *rp++ = '\r'; + ++cp; + break; + case 't': /* horizontal tab */ + *rp++ = '\t'; + ++cp; + break; + case 'v': /* vertical tab */ + *rp++ = '\v'; + ++cp; + break; + case '\\': + *rp = '\\'; + ++cp; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + { + int ch = *cp++ - '0'; + + if (*cp >= '0' && *cp <= '7') + { + ch *= 8; + ch += *cp++ - '0'; + + if (*cp >= '0' && *cp <= '7') + { + ch *= 8; + ch += *cp++ - '0'; + } + } + *rp = ch; + } + break; + default: + *rp = '\\'; + break; + } + + while (cp[0] != '\0' && cp[0] != '\\') + *rp++ = *cp++; + } while (cp[0] != '\0'); + + /* Terminate string. */ + terminate: *rp = '\0'; + return retval; +} + +static MSG *findMSG(u32 id) +{ + MSG *msg; + for (msg = baseMSG; msg; msg = msg->next) + { + if (msg->id == id) + return msg; + } + return NULL; +} + +static MSG *setMSG(const char *msgid, const char *msgstr) +{ + u32 id = hash_string(msgid); + MSG *msg = findMSG(id); + if (!msg) + { + msg = (MSG *) malloc(sizeof(MSG)); + msg->id = id; + msg->msgstr = NULL; + msg->next = baseMSG; + baseMSG = msg; + } + if (msg) + { + if (msgstr) + { + if (msg->msgstr) + free(msg->msgstr); + + msg->msgstr = expand_escape(msgstr); + } + return msg; + } + return NULL; +} + +static void gettextCleanUp(void) +{ + while (baseMSG) + { + MSG *nextMsg = baseMSG->next; + free(baseMSG->msgstr); + free(baseMSG); + baseMSG = nextMsg; + } +} + +static char * memfgets(char * dst, int maxlen, char * src) +{ + if(!src || !dst || maxlen <= 0) + return NULL; + + char * newline = strchr(src, '\n'); + + if(newline == NULL) + return NULL; + + memcpy(dst, src, (newline-src)); + dst[(newline-src)] = 0; + return ++newline; +} + +bool LoadLanguage() +{ + char line[200]; + char *lastID = NULL; + + char *file, *eof; + + switch(GCSettings.language) + { + case LANG_JAPANESE: file = (char *)jp_lang; eof = file + jp_lang_size; break; + case LANG_ENGLISH: file = (char *)en_lang; eof = file + en_lang_size; break; + case LANG_GERMAN: file = (char *)de_lang; eof = file + de_lang_size; break; + case LANG_FRENCH: file = (char *)fr_lang; eof = file + fr_lang_size; break; + case LANG_SPANISH: file = (char *)es_lang; eof = file + es_lang_size; break; + case LANG_ITALIAN: file = (char *)it_lang; eof = file + it_lang_size; break; + case LANG_DUTCH: file = (char *)nl_lang; eof = file + nl_lang_size; break; + case LANG_SIMP_CHINESE: + case LANG_TRAD_CHINESE: file = (char *)zh_lang; eof = file + zh_lang_size; break; + case LANG_KOREAN: file = (char *)ko_lang; eof = file + ko_lang_size; break; + case LANG_PORTUGUESE: file = (char *)pt_lang; eof = file + pt_lang_size; break; + case LANG_BRAZILIAN_PORTUGUESE: file = (char *)pt_br_lang; eof = file + pt_br_lang_size; break; + case LANG_CATALAN: file = (char *)ca_lang; eof = file + ca_lang_size; break; + case LANG_TURKISH: file = (char *)tr_lang; eof = file + tr_lang_size; break; + default: return false; + } + + gettextCleanUp(); + + while (file && file < eof) + { + file = memfgets(line, sizeof(line), file); + + if(!file) + break; + + // lines starting with # are comments + if (line[0] == '#') + continue; + + if (strncmp(line, "msgid \"", 7) == 0) + { + char *msgid, *end; + if (lastID) + { + free(lastID); + lastID = NULL; + } + msgid = &line[7]; + end = strrchr(msgid, '"'); + if (end && end - msgid > 1) + { + *end = 0; + lastID = strdup(msgid); + } + } + else if (strncmp(line, "msgstr \"", 8) == 0) + { + char *msgstr, *end; + + if (lastID == NULL) + continue; + + msgstr = &line[8]; + end = strrchr(msgstr, '"'); + if (end && end - msgstr > 1) + { + *end = 0; + setMSG(lastID, msgstr); + } + free(lastID); + lastID = NULL; + } + } + return true; +} + +const char *gettext(const char *msgid) +{ + MSG *msg = findMSG(hash_string(msgid)); + + if (msg && msg->msgstr) + { + return msg->msgstr; + } + return msgid; +} diff --git a/plugins/snes9x_gx/source/utils/gettext.h b/plugins/snes9x_gx/source/utils/gettext.h new file mode 100644 index 00000000..1309e934 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/gettext.h @@ -0,0 +1,12 @@ +#ifndef _GETTEXT_H_ +#define _GETTEXT_H_ + +bool LoadLanguage(); + +/* + * input msg = a text in ASCII + * output = the translated msg in utf-8 + */ +const char *gettext(const char *msg); + +#endif /* _GETTEXT_H_ */ diff --git a/plugins/snes9x_gx/source/utils/http.cpp b/plugins/snes9x_gx/source/utils/http.cpp new file mode 100644 index 00000000..ae52301c --- /dev/null +++ b/plugins/snes9x_gx/source/utils/http.cpp @@ -0,0 +1,411 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * Tantric December 2008 + * + * http.cpp + * + * HTTP operations + * Written by dhewg/bushing, modified by Tantric + ***************************************************************************/ + +#ifdef HW_RVL + +#include <malloc.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <ogcsys.h> +#include <network.h> +#include <ogc/lwp_watchdog.h> +#include <sys/types.h> +#include <sys/errno.h> +#include <fcntl.h> + +#include "menu.h" +#include "http.h" + +#define TCP_CONNECT_TIMEOUT 4000 // 4 secs to make a connection +#define TCP_SEND_SIZE (32 * 1024) +#define TCP_RECV_SIZE (32 * 1024) +#define TCP_BLOCK_RECV_TIMEOUT 4000 // 4 secs to receive +#define TCP_BLOCK_SEND_TIMEOUT 4000 // 4 secs to send +#define TCP_BLOCK_SIZE 1024 +#define HTTP_TIMEOUT 10000 // 10 secs to get an http response +#define IOS_O_NONBLOCK 0x04 + +static s32 tcp_socket(void) +{ + s32 s, res; + + s = net_socket(PF_INET, SOCK_STREAM, IPPROTO_IP); + if (s < 0) + return s; + + // Switch off Nagle with TCP_NODELAY + u32 nodelay = 1; + net_setsockopt(s,IPPROTO_TCP,TCP_NODELAY,&nodelay,sizeof(nodelay)); + + res = net_fcntl(s, F_GETFL, 0); + if (res < 0) + { + net_close(s); + return res; + } + + res = net_fcntl(s, F_SETFL, res | IOS_O_NONBLOCK); + if (res < 0) + { + net_close(s); + return res; + } + + return s; +} + +static s32 tcp_connect(char *host, const u16 port) +{ + struct hostent *hp; + struct sockaddr_in sa; + struct in_addr val; + s32 s, res; + u64 t1; + + s = tcp_socket(); + if (s < 0) + return s; + + memset(&sa, 0, sizeof(struct sockaddr_in)); + sa.sin_family= PF_INET; + sa.sin_len = sizeof(struct sockaddr_in); + sa.sin_port= htons(port); + + if(strlen(host) < 16 && inet_aton(host, &val)) + { + sa.sin_addr.s_addr = val.s_addr; + } + else + { + hp = net_gethostbyname (host); + if (!hp || !(hp->h_addrtype == PF_INET)) + return errno; + + memcpy((char *) &sa.sin_addr, hp->h_addr_list[0], hp->h_length); + } + + t1=ticks_to_secs(gettime()); + do + { + res = net_connect(s,(struct sockaddr*) &sa, sizeof (sa)); + if(ticks_to_secs(gettime())-t1 > TCP_CONNECT_TIMEOUT*1000) break; + usleep(500); + }while(res != -EISCONN); + if(res != -EISCONN) + { + net_close(s); + return -1; + } + + + return s; +} + +static int tcp_readln(const s32 s, char *buf, const u16 max_length) +{ + s32 res = -1; + s32 ret; + u64 start_time = gettime(); + u16 c = 0; + + while (c < max_length) + { + if (ticks_to_millisecs(diff_ticks(start_time, gettime())) > HTTP_TIMEOUT) + break; + + ret = net_read(s, &buf[c], 1); + + if (ret == -EAGAIN) + { + usleep(20 * 1000); + continue; + } + + if (ret <= 0) + break; + + if (c > 0 && buf[c - 1] == '\r' && buf[c] == '\n') + { + res = 0; + buf[c-1] = 0; + break; + } + c++; + start_time = gettime(); + usleep(100); + } + return res; +} + +static u32 tcp_read(const s32 s, u8 *buffer, const u32 length) +{ + char *p; + u32 left, block, received, step=0; + u64 t; + s32 res; + + p = (char *)buffer; + left = length; + received = 0; + + t = gettime(); + while (left) + { + if (ticks_to_millisecs(diff_ticks(t, gettime())) + > TCP_BLOCK_RECV_TIMEOUT) + { + break; + } + + block = left; + if (block > TCP_RECV_SIZE) + block = TCP_RECV_SIZE; + + res = net_read(s, p, block); + + if (res == -EAGAIN) + { + usleep(20 * 1000); + continue; + } + + if(res<=0) break; + + received += res; + left -= res; + p += res; + usleep(1000); + + if ((received / TCP_BLOCK_SIZE) > step) + { + t = gettime (); + step++; + } + } + return received; +} + +static u32 tcp_write(const s32 s, const u8 *buffer, const u32 length) +{ + const u8 *p; + u32 left, block, sent, step=0; + s64 t; + s32 res; + + p = buffer; + left = length; + sent = 0; + + t = gettime(); + while (left) + { + if (ticks_to_millisecs(diff_ticks(t, gettime())) + > TCP_BLOCK_SEND_TIMEOUT) + { + break; + } + + block = left; + if (block > TCP_SEND_SIZE) + block = TCP_SEND_SIZE; + + res = net_write(s, p, block); + + if ((res == 0) || (res == -56)) + { + usleep(20 * 1000); + continue; + } + + if (res < 0) + break; + + sent += res; + left -= res; + p += res; + usleep(100); + + if ((sent / TCP_BLOCK_SIZE) > step) + { + t = gettime (); + step++; + } + } + + return left == 0; +} + +static bool http_split_url(char *host, char *path, const char *url) +{ + const char *p; + char *c; + + if (strncasecmp(url, "http://", 7)) + return false; + + p = url + 7; + c = strchr(p, '/'); + + if (c == NULL || c[0] == 0) + return false; + + snprintf(host, c-p+1, "%s", p); + strcpy(path, c); + return true; +} + +#define MAX_SIZE (1024*1024*15) + +/**************************************************************************** + * http_request + * Retrieves the specified URL, and stores it in the specified file or buffer + ***************************************************************************/ +int http_request(const char *url, FILE *hfile, u8 *buffer, u32 maxsize, bool silent) +{ + int res = 0; + char http_host[1024]; + char http_path[1024]; + u16 http_port; + + http_res result; + u32 http_status; + u32 sizeread = 0, content_length = 0; + + int linecount; + + if(maxsize > MAX_SIZE) + return 0; + + if (url == NULL || (hfile == NULL && buffer == NULL)) + return 0; + + if (!http_split_url(http_host, http_path, url)) + return 0; + + http_port = 80; + http_status = 404; + + int s = tcp_connect(http_host, http_port); + + if (s < 0) + { + result = HTTPR_ERR_CONNECT; + return 0; + } + + char request[1024]; + char *r = request; + + r += sprintf(r, "GET %s HTTP/1.1\r\n", http_path); + r += sprintf(r, "Host: %s\r\n", http_host); + r += sprintf(r, "Cache-Control: no-cache\r\n\r\n"); + + res = tcp_write(s, (u8 *) request, strlen(request)); + + char line[256]; + + for (linecount = 0; linecount < 32; linecount++) + { + if (tcp_readln(s, line, 255) != 0) + { + http_status = 404; + result = HTTPR_ERR_REQUEST; + break; + } + + if (strlen(line) < 1) + break; + + sscanf(line, "HTTP/1.%*u %u", &http_status); + sscanf(line, "Content-Length: %u", &content_length); + } + + if (http_status != 200) + { + result = HTTPR_ERR_STATUS; + net_close(s); + return 0; + } + + // length unknown - just read as much as we can + if(content_length == 0) + { + content_length = maxsize; + } + else if (content_length > maxsize) + { + result = HTTPR_ERR_TOOBIG; + net_close(s); + return 0; + } + + if (buffer != NULL) + { + if(!silent) + ShowAction("Downloading..."); + + sizeread = tcp_read(s, buffer, content_length); + + if(!silent) + CancelAction(); + } + else + { + // read into file + u32 bufSize = (1024 * 32); + u32 bytesLeft = content_length; + u32 readSize; + + if(!silent) + ShowProgress("Downloading...", 0, content_length); + u8 * fbuffer = (u8 *) malloc(bufSize); + if(fbuffer) + { + while (bytesLeft > 0) + { + if (bytesLeft < bufSize) + readSize = bytesLeft; + else + readSize = bufSize; + + res = tcp_read(s, fbuffer, readSize); + if (!res) + break; + + sizeread += res; + bytesLeft -= res; + + res = fwrite(fbuffer, 1, res, hfile); + if (!res) + break; + + if(!silent) + ShowProgress("Downloading...", (content_length - bytesLeft), content_length); + } + free(fbuffer); + } + if(!silent) + CancelAction(); + } + + net_close(s); + + if (content_length < maxsize && sizeread != content_length) + { + result = HTTPR_ERR_RECEIVE; + return 0; + } + + result = HTTPR_OK; + return sizeread; +} +#endif diff --git a/plugins/snes9x_gx/source/utils/http.h b/plugins/snes9x_gx/source/utils/http.h new file mode 100644 index 00000000..41501afc --- /dev/null +++ b/plugins/snes9x_gx/source/utils/http.h @@ -0,0 +1,25 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * Tantric 2008-2010 + * + * http.h + * + * HTTP operations + ***************************************************************************/ + +#ifndef _HTTP_H_ +#define _HTTP_H_ + +typedef enum { + HTTPR_OK, + HTTPR_ERR_CONNECT, + HTTPR_ERR_REQUEST, + HTTPR_ERR_STATUS, + HTTPR_ERR_TOOBIG, + HTTPR_ERR_RECEIVE +} http_res; + +int http_request (const char *url, FILE * hfile, u8 * buffer, const u32 max_size, bool silent); + +#endif diff --git a/plugins/snes9x_gx/source/utils/oggplayer.c b/plugins/snes9x_gx/source/utils/oggplayer.c new file mode 100644 index 00000000..3f7de9a9 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/oggplayer.c @@ -0,0 +1,546 @@ +/* + Copyright (c) 2008 Francisco Muñoz 'Hermes' <www.elotrolado.net> + All rights reserved. + + Proper (standard) vorbis usage by Tantric, 2009 + Threading modifications/corrections by Tantric, 2009 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - The names of the contributors may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NO_SOUND + +#include <asndlib.h> +#include <tremor/ivorbiscodec.h> +#include <tremor/ivorbisfile.h> +#include <gccore.h> +#include <unistd.h> +#include <string.h> + +#include "oggplayer.h" + +/* functions to read the Ogg file from memory */ + +static struct +{ + char *mem; + int size; + int pos; +} file[4]; + +static int f_read(void * punt, int bytes, int blocks, int *f) +{ + int b; + int c = 0; + int d; + + if (bytes * blocks <= 0) + return 0; + + blocks *= bytes; + + while (blocks > 0) + { + b = blocks; + if (b > 4096) + b = 4096; + + d = (*f) - 0x666; + if((unsigned)(d) <= (0x669 - 0x666)) + { + if (file[d].size == 0) + return -1; + if ((file[d].pos + b) > file[d].size) + b = file[d].size - file[d].pos; + if (b > 0) + { + memcpy(punt, file[d].mem + file[d].pos, b); + file[d].pos += b; + } + } + else + b = read(*f, ((char *) punt) + c, b); + + if (b <= 0) + { + return c / bytes; + } + c += b; + blocks -= b; + } + return c / bytes; +} + +static int f_seek(int *f, ogg_int64_t offset, int mode) +{ + if(f==NULL) return(-1); + + int k; + mode &= 3; + + int d = (*f) - 0x666; + if((unsigned)(d) <= (0x669 - 0x666)) + { + k = 0; + + if (file[d].size == 0) + return -1; + + if (mode == 0) + { + if ((offset) >= file[d].size) + { + file[d].pos = file[d].size; + k = -1; + } + else if ((offset) < 0) + { + file[d].pos = 0; + k = -1; + } + else + file[d].pos = offset; + } + else if (mode == 1) + { + if ((file[d].pos + offset) >= file[d].size) + { + file[d].pos = file[d].size; + k = -1; + } + else if ((file[d].pos + offset) < 0) + { + file[d].pos = 0; + k = -1; + } + else + file[d].pos += offset; + } + else if (mode == 2) + { + + if ((file[d].size + offset) >= file[d].size) + { + file[d].pos = file[d].size; + k = -1; + } + else if ((file[d].size + offset) < 0) + { + file[d].pos = 0; + k = -1; + } + else + file[d].pos = file[d].size + offset; + } + + } + else + k = lseek(*f, (int) offset, mode); + + if (k < 0) + k = -1; + else + k = 0; + return k; +} + +static int f_close(int *f) +{ + int d = (*f) - 0x666; + if((unsigned)(d) <= (0x669 - 0x666)) + { + file[d].size = 0; + file[d].pos = 0; + if (file[d].mem) + { + file[d].mem = (void *) 0; + } + return 0; + } + else + return close(*f); + return 0; +} + +static long f_tell(int *f) +{ + int k; + + int d = (*f) - 0x666; + if((unsigned)(d) <= (0x669 - 0x666)) + { + k = file[d].pos; + } + else + k = lseek(*f, 0, 1); + + return (long) k; +} + +static int mem_open(char * ogg, int size) +{ + static int one = 1; + int n; + if (one) + { + one = 0; + + file[0].size = 0; + file[1].size = 0; + file[2].size = 0; + file[3].size = 0; + file[0].mem = ogg; + file[0].size = size; + file[0].pos = 0; + return (0x666); + } + + for (n = 0; n < 4; n++) + { + if (file[n].size == 0) + { + file[n].mem = ogg; + file[n].size = size; + file[n].pos = 0; + return (0x666 + n); + } + } + return -1; +} + +static int mem_close(int fd) +{ + if((unsigned)((fd) - 0x666) <= (0x669 - 0x666)) // it is a memory file descriptor? + { + fd -= 0x666; + file[fd].size = 0; + return 0; + } + else + return f_close(&fd); +} + +static ov_callbacks callbacks = { + (size_t (*)(void *, size_t, size_t, void *)) f_read, + (int (*)(void *, ogg_int64_t, int)) f_seek, + (int (*)(void *)) f_close, + (long (*)(void *)) f_tell +}; + +/* OGG control */ + +#define READ_SAMPLES 4096 // samples that it must read before to send +#define MAX_PCMOUT 4096 // minimum size to read ogg samples +typedef struct +{ + OggVorbis_File vf; + vorbis_info *vi; + int current_section; + + // OGG file operation + int fd; + int mode; + int eof; + int flag; + int volume; + int seek_time; + + /* OGG buffer control */ + short pcmout[2][READ_SAMPLES + MAX_PCMOUT * 2]; /* take 4k out of the data segment, not the stack */ + int pcmout_pos; + int pcm_indx; + +} private_data_ogg; + +static private_data_ogg private_ogg; + +// OGG thread control + +#define STACKSIZE 8192 + +static u8 oggplayer_stack[STACKSIZE]; +static lwpq_t oggplayer_queue = LWP_TQUEUE_NULL; +static lwp_t h_oggplayer = LWP_THREAD_NULL; +static int ogg_thread_running = 0; + +static void ogg_add_callback(int voice) +{ + if (!ogg_thread_running) + { + ASND_StopVoice(0); + return; + } + + if (private_ogg.flag & 128) + return; // Ogg is paused + + if (private_ogg.pcm_indx >= READ_SAMPLES) + { + if (ASND_AddVoice(0, + (void *) private_ogg.pcmout[private_ogg.pcmout_pos], + private_ogg.pcm_indx << 1) == 0) + { + private_ogg.pcmout_pos ^= 1; + private_ogg.pcm_indx = 0; + private_ogg.flag = 0; + LWP_ThreadSignal(oggplayer_queue); + } + } + else + { + if (private_ogg.flag & 64) + { + private_ogg.flag &= ~64; + LWP_ThreadSignal(oggplayer_queue); + } + } +} + +static void * ogg_player_thread(private_data_ogg * priv) +{ + int first_time = 1; + long ret; + + //init + LWP_InitQueue(&oggplayer_queue); + + priv[0].vi = ov_info(&priv[0].vf, -1); + + ASND_Pause(0); + + priv[0].pcm_indx = 0; + priv[0].pcmout_pos = 0; + priv[0].eof = 0; + priv[0].flag = 0; + priv[0].current_section = 0; + + ogg_thread_running = 1; + + while (!priv[0].eof && ogg_thread_running) + { + if (priv[0].flag) + LWP_ThreadSleep(oggplayer_queue); // wait only when i have samples to send + + if (priv[0].flag == 0) // wait to all samples are sent + { + if (ASND_TestPointer(0, priv[0].pcmout[priv[0].pcmout_pos]) + && ASND_StatusVoice(0) != SND_UNUSED) + { + priv[0].flag |= 64; + continue; + } + if (priv[0].pcm_indx < READ_SAMPLES) + { + priv[0].flag = 3; + + if (priv[0].seek_time >= 0) + { + ov_time_seek(&priv[0].vf, priv[0].seek_time); + priv[0].seek_time = -1; + } + + ret = ov_read( + &priv[0].vf, + (void *) &priv[0].pcmout[priv[0].pcmout_pos][priv[0].pcm_indx], + MAX_PCMOUT,/*0,2,1,*/&priv[0].current_section); + priv[0].flag &= 192; + if (ret == 0) + { + /* EOF */ + if (priv[0].mode & 1) + ov_time_seek(&priv[0].vf, 0); // repeat + else + priv[0].eof = 1; // stops + } + else if (ret < 0) + { + /* error in the stream. Not a problem, just reporting it in + case we (the app) cares. In this case, we don't. */ + if (ret != OV_HOLE) + { + if (priv[0].mode & 1) + ov_time_seek(&priv[0].vf, 0); // repeat + else + priv[0].eof = 1; // stops + } + } + else + { + /* we don't bother dealing with sample rate changes, etc, but + you'll have to*/ + priv[0].pcm_indx += ret >> 1; //get 16 bits samples + } + } + else + priv[0].flag = 1; + } + + if (priv[0].flag == 1) + { + if (ASND_StatusVoice(0) == SND_UNUSED || first_time) + { + first_time = 0; + if (priv[0].vi->channels == 2) + { + ASND_SetVoice(0, VOICE_STEREO_16BIT, priv[0].vi->rate, 0, + (void *) priv[0].pcmout[priv[0].pcmout_pos], + priv[0].pcm_indx << 1, priv[0].volume, + priv[0].volume, ogg_add_callback); + priv[0].pcmout_pos ^= 1; + priv[0].pcm_indx = 0; + priv[0].flag = 0; + } + else + { + ASND_SetVoice(0, VOICE_MONO_16BIT, priv[0].vi->rate, 0, + (void *) priv[0].pcmout[priv[0].pcmout_pos], + priv[0].pcm_indx << 1, priv[0].volume, + priv[0].volume, ogg_add_callback); + priv[0].pcmout_pos ^= 1; + priv[0].pcm_indx = 0; + priv[0].flag = 0; + } + } + } + usleep(100); + } + ov_clear(&priv[0].vf); + priv[0].fd = -1; + priv[0].pcm_indx = 0; + + return 0; +} + +void StopOgg() +{ + ASND_StopVoice(0); + ogg_thread_running = 0; + + if(h_oggplayer != LWP_THREAD_NULL) + { + if(oggplayer_queue != LWP_TQUEUE_NULL) + LWP_ThreadSignal(oggplayer_queue); + LWP_JoinThread(h_oggplayer, NULL); + h_oggplayer = LWP_THREAD_NULL; + } + if(oggplayer_queue != LWP_TQUEUE_NULL) + { + LWP_CloseQueue(oggplayer_queue); + oggplayer_queue = LWP_TQUEUE_NULL; + } +} + +int PlayOgg(const void *buffer, s32 len, int time_pos, int mode) +{ + StopOgg(); + + private_ogg.fd = mem_open((char *)buffer, len); + + if (private_ogg.fd < 0) + { + private_ogg.fd = -1; + return -1; + } + + private_ogg.mode = mode; + private_ogg.eof = 0; + private_ogg.volume = 127; + private_ogg.flag = 0; + private_ogg.seek_time = -1; + + if (time_pos > 0) + private_ogg.seek_time = time_pos; + + if (ov_open_callbacks((void *) &private_ogg.fd, &private_ogg.vf, NULL, 0, callbacks) < 0) + { + mem_close(private_ogg.fd); // mem_close() can too close files from devices + private_ogg.fd = -1; + ogg_thread_running = 0; + return -1; + } + + if (LWP_CreateThread(&h_oggplayer, (void *) ogg_player_thread, + &private_ogg, oggplayer_stack, STACKSIZE, 80) == -1) + { + ogg_thread_running = 0; + ov_clear(&private_ogg.vf); + private_ogg.fd = -1; + return -1; + } + return 0; +} + +void PauseOgg(int pause) +{ + if (pause) + { + private_ogg.flag |= 128; + } + else + { + if (private_ogg.flag & 128) + { + private_ogg.flag |= 64; + private_ogg.flag &= ~128; + if (ogg_thread_running > 0) + { + LWP_ThreadSignal(oggplayer_queue); + } + } + } +} + +int StatusOgg() +{ + if (ogg_thread_running == 0) + return -1; // Error + else if (private_ogg.eof) + return 255; // EOF + else if (private_ogg.flag & 128) + return 2; // paused + return 1; // running +} + +void SetVolumeOgg(int volume) +{ + private_ogg.volume = volume; + ASND_ChangeVolumeVoice(0, volume, volume); +} + +s32 GetTimeOgg() +{ + int ret; + if (ogg_thread_running == 0 || private_ogg.fd < 0) + return -1; + ret = ((s32) ov_time_tell(&private_ogg.vf)); + + return ret; +} + +void SetTimeOgg(s32 time_pos) +{ + if (time_pos >= 0) + private_ogg.seek_time = time_pos; +} + +#endif diff --git a/plugins/snes9x_gx/source/utils/oggplayer.h b/plugins/snes9x_gx/source/utils/oggplayer.h new file mode 100644 index 00000000..c5050403 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/oggplayer.h @@ -0,0 +1,112 @@ +/* + Copyright (c) 2008 Francisco Muñoz 'Hermes' <www.elotrolado.net> + All rights reserved. + + Proper (standard) vorbis usage by Tantric, 2009 + Threading modifications/corrections by Tantric, 2009 + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - The names of the contributors may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __OGGPLAYER_H__ +#define __OGGPLAYER_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define OGG_ONE_TIME 0 +#define OGG_INFINITE_TIME 1 + +#define OGG_STATUS_RUNNING 1 +#define OGG_STATUS_ERR -1 +#define OGG_STATUS_PAUSED 2 +#define OGG_STATUS_EOF 255 + +/**************************************************************************** + * PlayOgg + * + * Creates a thread that starts playing from the specific Ogg buffer + * buffer - pointer to the start of the Ogg data + * len - length of Ogg file + * time_pos - initial time position at which to start playback + * mode - playback mode (OGG_ONE_TIME or OGG_INFINITE_TIME) + * returns: -1 on error, 0 on success + ***************************************************************************/ +int PlayOgg(const void *buffer, s32 len, int time_pos, int mode); + +/**************************************************************************** + * StopOgg + * + * Stops playback. The player thread is shut down. + ***************************************************************************/ +void StopOgg(); + +/**************************************************************************** + * PauseOgg + * + * Pauses playback. 0 -> continue, 1-> pause + ***************************************************************************/ +void PauseOgg(int pause); + +/**************************************************************************** + * StatusOgg + * + * Returns the Ogg player's status + * returns: + * OGG_STATUS_RUNNING + * OGG_STATUS_ERR -> not initialized + * OGG_STATUS_PAUSED + * OGG_STATUS_EOF -> player stopped by End Of File + ***************************************************************************/ +int StatusOgg(); + +/**************************************************************************** + * SetVolumeOgg + * + * Sets the Ogg playback volume (0 to 255 (max)) + ***************************************************************************/ +void SetVolumeOgg(int volume); + +/**************************************************************************** + * GetTimeOgg + * + * Gets current Ogg position + * returns -1 on error, or the time in milliseconds from the start + ***************************************************************************/ +s32 GetTimeOgg(); + +/**************************************************************************** + * SetTimeOgg + * + * Sets the time position + * time_pos: time position (in milliseconds) to advance + ***************************************************************************/ +void SetTimeOgg(s32 time_pos); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/snes9x_gx/source/utils/pngu.c b/plugins/snes9x_gx/source/utils/pngu.c new file mode 100644 index 00000000..52ff7d9b --- /dev/null +++ b/plugins/snes9x_gx/source/utils/pngu.c @@ -0,0 +1,755 @@ +/**************************************************************************** + * + * PNGU + * + * Original author: frontier (http://frontier-dev.net) + * Modified by Tantric, 2009-2010 + * + ***************************************************************************/ + +#include <stdio.h> +#include <malloc.h> +#include "pngu.h" +#include <png.h> + +// Constants +#define PNGU_SOURCE_BUFFER 1 +#define PNGU_SOURCE_DEVICE 2 + +// Return codes +#define PNGU_OK 0 +#define PNGU_ODD_WIDTH 1 +#define PNGU_ODD_STRIDE 2 +#define PNGU_INVALID_WIDTH_OR_HEIGHT 3 +#define PNGU_FILE_IS_NOT_PNG 4 +#define PNGU_UNSUPPORTED_COLOR_TYPE 5 +#define PNGU_NO_FILE_SELECTED 6 +#define PNGU_CANT_OPEN_FILE 7 +#define PNGU_CANT_READ_FILE 8 +#define PNGU_LIB_ERROR 9 + +// Color types +#define PNGU_COLOR_TYPE_GRAY 1 +#define PNGU_COLOR_TYPE_GRAY_ALPHA 2 +#define PNGU_COLOR_TYPE_PALETTE 3 +#define PNGU_COLOR_TYPE_RGB 4 +#define PNGU_COLOR_TYPE_RGB_ALPHA 5 +#define PNGU_COLOR_TYPE_UNKNOWN 6 + +// PNGU Image context struct +struct _IMGCTX +{ + int source; + void *buffer; + char *filename; + u32 cursor; + + u32 propRead; + PNGUPROP prop; + + u32 infoRead; + png_structp png_ptr; + png_infop info_ptr; + FILE *fd; + + png_bytep *row_pointers; + png_bytep img_data; +}; + +// PNGU Implementation + +static void pngu_free_info (IMGCTX ctx) +{ + if (ctx->infoRead) + { + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + + png_destroy_read_struct (&(ctx->png_ptr), &(ctx->info_ptr), (png_infopp)NULL); + + ctx->infoRead = 0; + } +} + +// Custom data provider function used for reading from memory buffers. +static void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length) +{ + IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr); + memcpy (data, ctx->buffer + ctx->cursor, length); + ctx->cursor += length; +} + +// Custom data writer function used for writing to memory buffers. +static void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length) +{ + IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr); + memcpy (ctx->buffer + ctx->cursor, data, length); + ctx->cursor += length; +} + +// Custom data flusher function used for writing to memory buffers. +static void pngu_flush_data_to_buffer (png_structp png_ptr) +{ + // Nothing to do here +} + +static int pngu_info (IMGCTX ctx) +{ + png_byte magic[8]; + png_uint_32 width; + png_uint_32 height; + png_color_16p background; + png_bytep trans; + png_color_16p trans_values; + int scale, i; + + // Check if there is a file selected and if it is a valid .png + if (ctx->source == PNGU_SOURCE_BUFFER) + memcpy (magic, ctx->buffer, 8); + + else if (ctx->source == PNGU_SOURCE_DEVICE) + { + // Open file + if (!(ctx->fd = fopen (ctx->filename, "rb"))) + return PNGU_CANT_OPEN_FILE; + + // Load first 8 bytes into magic buffer + if (fread (magic, 1, 8, ctx->fd) != 8) + { + fclose (ctx->fd); + return PNGU_CANT_READ_FILE; + } + } + + else + return PNGU_NO_FILE_SELECTED;; + + if (png_sig_cmp(magic, 0, 8) != 0) + { + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + return PNGU_FILE_IS_NOT_PNG; + } + + // Allocation of libpng structs + ctx->png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!(ctx->png_ptr)) + { + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + return PNGU_LIB_ERROR; + } + + ctx->info_ptr = png_create_info_struct (ctx->png_ptr); + if (!(ctx->info_ptr)) + { + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + png_destroy_read_struct (&(ctx->png_ptr), (png_infopp)NULL, (png_infopp)NULL); + return PNGU_LIB_ERROR; + } + + if (ctx->source == PNGU_SOURCE_BUFFER) + { + // Installation of our custom data provider function + ctx->cursor = 0; + png_set_read_fn (ctx->png_ptr, ctx, pngu_read_data_from_buffer); + } + else if (ctx->source == PNGU_SOURCE_DEVICE) + { + // Default data provider uses function fread, so it needs to use our FILE* + png_init_io (ctx->png_ptr, ctx->fd); + png_set_sig_bytes (ctx->png_ptr, 8); // We have read 8 bytes already to check PNG authenticity + } + + // Read png header + png_read_info (ctx->png_ptr, ctx->info_ptr); + + // Query image properties if they have not been queried before + if (!ctx->propRead) + { + int ctxNumTrans; + + png_get_IHDR(ctx->png_ptr, ctx->info_ptr, &width, &height, + (int *) &(ctx->prop.imgBitDepth), + (int *) &(ctx->prop.imgColorType), + NULL, NULL, NULL); + + ctx->prop.imgWidth = width; + ctx->prop.imgHeight = height; + switch (ctx->prop.imgColorType) + { + case PNG_COLOR_TYPE_GRAY: + ctx->prop.imgColorType = PNGU_COLOR_TYPE_GRAY; + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + ctx->prop.imgColorType = PNGU_COLOR_TYPE_GRAY_ALPHA; + break; + case PNG_COLOR_TYPE_PALETTE: + ctx->prop.imgColorType = PNGU_COLOR_TYPE_PALETTE; + break; + case PNG_COLOR_TYPE_RGB: + ctx->prop.imgColorType = PNGU_COLOR_TYPE_RGB; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + ctx->prop.imgColorType = PNGU_COLOR_TYPE_RGB_ALPHA; + break; + default: + ctx->prop.imgColorType = PNGU_COLOR_TYPE_UNKNOWN; + break; + } + + // Constant used to scale 16 bit values to 8 bit values + scale = 0; + if (ctx->prop.imgBitDepth == 16) + scale = 8; + + // Query background color, if any. + ctx->prop.validBckgrnd = 0; + + switch(ctx->prop.imgColorType) + { + case PNGU_COLOR_TYPE_RGB: + case PNGU_COLOR_TYPE_RGB_ALPHA: + { + if(png_get_bKGD (ctx->png_ptr, ctx->info_ptr, &background)){ + ctx->prop.validBckgrnd = 1; + ctx->prop.bckgrnd.r = background->red >> scale; + ctx->prop.bckgrnd.g = background->green >> scale; + ctx->prop.bckgrnd.b = background->blue >> scale; + } + + // Query list of transparent colors, if any. + ctx->prop.numTrans = 0; + ctx->prop.trans = NULL; + + if(png_get_tRNS (ctx->png_ptr, ctx->info_ptr, &trans, (int *) &(ctx->prop.numTrans), &trans_values)){ + ctxNumTrans = ctx->prop.numTrans; + if(ctxNumTrans){ + ctx->prop.trans = malloc (sizeof (PNGUCOLOR) * ctxNumTrans); + if (ctx->prop.trans) + for (i = 0; i < ctxNumTrans; i++) + { + ctx->prop.trans[i].r = trans_values[i].red >> scale; + ctx->prop.trans[i].g = trans_values[i].green >> scale; + ctx->prop.trans[i].b = trans_values[i].blue >> scale; + } + else + ctx->prop.numTrans = 0; + } + } + + } + break; + + case PNGU_COLOR_TYPE_GRAY: + case PNGU_COLOR_TYPE_GRAY_ALPHA: + { + if(png_get_bKGD (ctx->png_ptr, ctx->info_ptr, &background)){ + ctx->prop.validBckgrnd = 1; + ctx->prop.bckgrnd.r = + ctx->prop.bckgrnd.g = + ctx->prop.bckgrnd.b = background->gray >> scale; + } + + // Query list of transparent colors, if any. + ctx->prop.numTrans = 0; + ctx->prop.trans = NULL; + + if(png_get_tRNS (ctx->png_ptr, ctx->info_ptr, &trans, (int *) &(ctx->prop.numTrans), &trans_values)){ + ctxNumTrans = ctx->prop.numTrans; + if(ctxNumTrans){ + ctx->prop.trans = malloc (sizeof (PNGUCOLOR) * ctxNumTrans); + if (ctx->prop.trans) + for (i = 0; i < ctxNumTrans; i++) + ctx->prop.trans[i].r = + ctx->prop.trans[i].g = + ctx->prop.trans[i].b = trans_values[i].gray >> scale; + else + ctx->prop.numTrans = 0; + } + } + + } + break; + + default: + + // It was none of those things, + { + // Query list of transparent colors, if any. + ctx->prop.numTrans = 0; + ctx->prop.trans = NULL; + } + break; + } + + ctx->propRead = 1; + } + + // Success + ctx->infoRead = 1; + + return PNGU_OK; +} + +static int pngu_decode (IMGCTX ctx, u32 width, u32 height, u32 stripAlpha) +{ + png_uint_32 rowbytes; + png_uint_32 i, propImgHeight; + + // Read info if it hasn't been read before + if (!ctx->infoRead) + { + int c = pngu_info (ctx); + if (c != PNGU_OK) + return c; + } + + // Check if the user has specified the real width and height of the image + if ( (ctx->prop.imgWidth != width) || (ctx->prop.imgHeight != height) ) + return PNGU_INVALID_WIDTH_OR_HEIGHT; + + // Check if color type is supported by PNGU + if (ctx->prop.imgColorType == PNGU_COLOR_TYPE_UNKNOWN) + return PNGU_UNSUPPORTED_COLOR_TYPE; + + // Scale 16 bit samples to 8 bit + if (ctx->prop.imgBitDepth == 16) + png_set_strip_16 (ctx->png_ptr); + + // Remove alpha channel if we don't need it + if (stripAlpha && ((ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA))) + png_set_strip_alpha (ctx->png_ptr); + + // Expand 1, 2 and 4 bit samples to 8 bit + if (ctx->prop.imgBitDepth < 8) + png_set_packing (ctx->png_ptr); + + // Transform grayscale images to RGB + if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) ) + png_set_gray_to_rgb (ctx->png_ptr); + + // Transform palette images to RGB + if (ctx->prop.imgColorType == PNGU_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(ctx->png_ptr); + + // Flush transformations + png_read_update_info (ctx->png_ptr, ctx->info_ptr); + + // Allocate memory to store the image + rowbytes = png_get_rowbytes (ctx->png_ptr, ctx->info_ptr); + + if (rowbytes & 3) + rowbytes = ((rowbytes >> 2) + 1) << 2; // Add extra padding so each row starts in a 4 byte boundary + + ctx->img_data = malloc (rowbytes * ctx->prop.imgHeight); + if (!ctx->img_data) + { + pngu_free_info (ctx); + return PNGU_LIB_ERROR; + } + + ctx->row_pointers = malloc (sizeof (png_bytep) * ctx->prop.imgHeight); + if (!ctx->row_pointers) + { + free (ctx->img_data); + pngu_free_info (ctx); + return PNGU_LIB_ERROR; + } + + propImgHeight = ctx->prop.imgHeight; + for (i = 0; i < propImgHeight; ++i) + ctx->row_pointers[i] = ctx->img_data + (i * rowbytes); + + // Transform the image and copy it to our allocated memory + png_read_image (ctx->png_ptr, ctx->row_pointers); + + // Free resources + pngu_free_info (ctx); + + // Success + return PNGU_OK; +} + +static inline u32 coordsRGBA8(u32 x, u32 y, u32 w) +{ + return ((((y >> 2) * (w >> 2) + (x >> 2)) << 5) + ((y & 3) << 2) + (x & 3)) << 1; +} + +static u8 * PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, u32 width, u32 height, int * dstWidth, int * dstHeight, u8 *dstPtr, int maxWidth, int maxHeight) +{ + u8 default_alpha = 255; + u8 *dst; + int x, y, x2, y2, offset; + int xRatio = 0, yRatio = 0; + png_byte *pixel; + + if (pngu_decode (ctx, width, height, 0) != PNGU_OK) + return NULL; + + int newWidth = width; + int newHeight = height; + + if((maxWidth > 0 && width > maxWidth) || (maxHeight > 0 && height > maxHeight)) + { + float ratio = (float)width/(float)height; + + newWidth = maxWidth; + newHeight = maxWidth/ratio; + + if(newHeight > maxHeight) + { + newWidth = maxHeight*ratio; + newHeight = maxHeight; + } + xRatio = (int)((width<<16)/newWidth)+1; + yRatio = (int)((height<<16)/newHeight)+1; + } + + int padWidth = newWidth; + int padHeight = newHeight; + if(padWidth%4) padWidth += (4-padWidth%4); + if(padHeight%4) padHeight += (4-padHeight%4); + + int len = (padWidth * padHeight) << 2; + if(len%32) len += (32-len%32); + + if(dstPtr) + dst = dstPtr; // use existing allocation + else + dst = memalign (32, len); + + if(!dst) + return NULL; + + for (y = 0; y < padHeight; y++) + { + for (x = 0; x < padWidth; x++) + { + offset = coordsRGBA8(x, y, padWidth); + + if(y >= newHeight || x >= newWidth) + { + dst[offset] = 0; + dst[offset+1] = 255; + dst[offset+32] = 255; + dst[offset+33] = 255; + } + else + { + if(xRatio > 0) + { + x2 = ((x*xRatio)>>16); + y2 = ((y*yRatio)>>16); + } + + if (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA || + ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) + { + if(xRatio > 0) + pixel = &(ctx->row_pointers[y2][x2*4]); + else + pixel = &(ctx->row_pointers[y][x*4]); + + dst[offset] = pixel[3]; // Alpha + dst[offset+1] = pixel[0]; // Red + dst[offset+32] = pixel[1]; // Green + dst[offset+33] = pixel[2]; // Blue + } + else + { + if(xRatio > 0) + pixel = &(ctx->row_pointers[y2][x2*3]); + else + pixel = &(ctx->row_pointers[y][x*3]); + + dst[offset] = default_alpha; // Alpha + dst[offset+1] = pixel[0]; // Red + dst[offset+32] = pixel[1]; // Green + dst[offset+33] = pixel[2]; // Blue + } + } + } + } + + // Free resources + free (ctx->img_data); + free (ctx->row_pointers); + + *dstWidth = padWidth; + *dstHeight = padHeight; + DCFlushRange(dst, len); + return dst; +} + +IMGCTX PNGU_SelectImageFromBuffer (const void *buffer) +{ + IMGCTX ctx = NULL; + + if (!buffer) + return NULL; + + ctx = malloc (sizeof (struct _IMGCTX)); + if (!ctx) + return NULL; + + ctx->buffer = (void *) buffer; + ctx->source = PNGU_SOURCE_BUFFER; + ctx->cursor = 0; + ctx->filename = NULL; + ctx->propRead = 0; + ctx->infoRead = 0; + + return ctx; +} + +IMGCTX PNGU_SelectImageFromDevice (const char *filename) +{ + IMGCTX ctx = NULL; + + if (!filename) + return NULL; + + ctx = malloc (sizeof (struct _IMGCTX)); + if (!ctx) + return NULL; + + ctx->buffer = NULL; + ctx->source = PNGU_SOURCE_DEVICE; + ctx->cursor = 0; + + ctx->filename = malloc (strlen (filename) + 1); + if (!ctx->filename) + { + free (ctx); + return NULL; + } + strcpy(ctx->filename, filename); + + ctx->propRead = 0; + ctx->infoRead = 0; + + return ctx; +} + +void PNGU_ReleaseImageContext (IMGCTX ctx) +{ + if (!ctx) + return; + + if (ctx->filename) + free (ctx->filename); + + if ((ctx->propRead) && (ctx->prop.trans)) + free (ctx->prop.trans); + + pngu_free_info (ctx); + free (ctx); +} + +int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *imgprop) +{ + int res; + + if (!ctx->propRead) + { + res = pngu_info (ctx); + if (res != PNGU_OK) + return res; + } + + *imgprop = ctx->prop; + return PNGU_OK; +} + +u8 * DecodePNG(const u8 *src, int * width, int * height, u8 *dstPtr, int maxwidth, int maxheight) +{ + PNGUPROP imgProp; + IMGCTX ctx = PNGU_SelectImageFromBuffer(src); + u8 *dst = NULL; + + if(!ctx) + return NULL; + + if(PNGU_GetImageProperties(ctx, &imgProp) == PNGU_OK) + dst = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, width, height, dstPtr, maxwidth, maxheight); + + PNGU_ReleaseImageContext (ctx); + return dst; +} + +int PNGU_EncodeFromRGB (IMGCTX ctx, u32 width, u32 height, void *buffer, u32 stride) +{ + png_uint_32 rowbytes; + u32 y; + + // Erase from the context any readed info + pngu_free_info (ctx); + ctx->propRead = 0; + + // Check if the user has selected a file to write the image + if (ctx->source == PNGU_SOURCE_BUFFER); + + else if (ctx->source == PNGU_SOURCE_DEVICE) + { + // Open file + if (!(ctx->fd = fopen (ctx->filename, "wb"))) + return PNGU_CANT_OPEN_FILE; + } + + else + return PNGU_NO_FILE_SELECTED; + + // Allocation of libpng structs + ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!(ctx->png_ptr)) + { + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + return PNGU_LIB_ERROR; + } + + ctx->info_ptr = png_create_info_struct (ctx->png_ptr); + if (!(ctx->info_ptr)) + { + png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + return PNGU_LIB_ERROR; + } + + if (ctx->source == PNGU_SOURCE_BUFFER) + { + // Installation of our custom data writer function + ctx->cursor = 0; + png_set_write_fn (ctx->png_ptr, ctx, pngu_write_data_to_buffer, pngu_flush_data_to_buffer); + } + else if (ctx->source == PNGU_SOURCE_DEVICE) + { + // Default data writer uses function fwrite, so it needs to use our FILE* + png_init_io (ctx->png_ptr, ctx->fd); + } + + // Setup output file properties + png_set_IHDR (ctx->png_ptr, ctx->info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + // Allocate memory to store the image in RGB format + rowbytes = width * 3; + if (rowbytes % 4) + rowbytes = ((rowbytes >>2) + 1) <<2; // Add extra padding so each row starts in a 4 byte boundary + + ctx->img_data = malloc(rowbytes * height); + + if (!ctx->img_data) + { + png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + return PNGU_LIB_ERROR; + } + + memset(ctx->img_data, 0, rowbytes * height); + ctx->row_pointers = malloc (sizeof (png_bytep) * height); + + if (!ctx->row_pointers) + { + png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + return PNGU_LIB_ERROR; + } + + memset(ctx->row_pointers, 0, sizeof (png_bytep) * height); + + for (y = 0; y < height; ++y) + { + ctx->row_pointers[y] = buffer + (y * rowbytes); + } + + // Tell libpng where is our image data + png_set_rows (ctx->png_ptr, ctx->info_ptr, ctx->row_pointers); + + // Write file header and image data + png_write_png (ctx->png_ptr, ctx->info_ptr, PNG_TRANSFORM_IDENTITY, NULL); + + // Tell libpng we have no more data to write + png_write_end (ctx->png_ptr, (png_infop) NULL); + + // Free resources + free (ctx->img_data); + free (ctx->row_pointers); + png_destroy_write_struct (&(ctx->png_ptr), &(ctx->info_ptr)); + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + + // Success + return ctx->cursor; +} + +int PNGU_EncodeFromGXTexture (IMGCTX ctx, u32 width, u32 height, void *buffer, u32 stride) +{ + int res; + u32 x, y, tmpy1, tmpy2, tmpyWid, tmpxy; + + unsigned char * ptr = (unsigned char*)buffer; + unsigned char * tmpbuffer = malloc(width*height*3); + + if(!tmpbuffer) + return PNGU_LIB_ERROR; + + memset(tmpbuffer, 0, width*height*3); + png_uint_32 offset; + + for(y=0; y < height; y++) + { + tmpy1 = y * 640*3; + tmpy2 = y%4 << 2; + tmpyWid = (((y >> 2)<<4)*width); + + for(x=0; x < width; x++) + { + offset = tmpyWid + ((x >> 2)<<6) + ((tmpy2+ x%4 ) << 1); + tmpxy = x * 3 + tmpy1; + + tmpbuffer[tmpxy ] = ptr[offset+1]; // R + tmpbuffer[tmpxy+1] = ptr[offset+32]; // G + tmpbuffer[tmpxy+2] = ptr[offset+33]; // B + } + } + + res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, stride); + free(tmpbuffer); + return res; +} + +int PNGU_EncodeFromEFB (IMGCTX ctx, u32 width, u32 height) +{ + int res; + u32 x, y, tmpy1, tmpxy; + GXColor color; + + unsigned char * tmpbuffer = malloc(width*height*3); + + if(!tmpbuffer) + return PNGU_LIB_ERROR; + + for(y=0; y < height; y++) + { + tmpy1 = y * width * 3; + + for(x=0; x < width; x++) + { + tmpxy = x * 3 + tmpy1; + GX_PeekARGB(x, y, &color); + tmpbuffer[tmpxy ] = color.r; // R + tmpbuffer[tmpxy+1] = color.g; // G + tmpbuffer[tmpxy+2] = color.b; // B + } + } + + res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, 0); + free(tmpbuffer); + return res; +} diff --git a/plugins/snes9x_gx/source/utils/pngu.h b/plugins/snes9x_gx/source/utils/pngu.h new file mode 100644 index 00000000..fa896501 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/pngu.h @@ -0,0 +1,75 @@ +/******************************************************************************************** +* +* PNGU +* +* Original author: frontier (http://frontier-dev.net) +* Modified by Tantric, 2009-2010 +* +********************************************************************************************/ + +#ifndef __PNGU__ +#define __PNGU__ + +#include <gccore.h> + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct +{ + u8 r; + u8 g; + u8 b; +} PNGUCOLOR; + +typedef struct +{ + u32 imgWidth; // In pixels + u32 imgHeight; // In pixels + u32 imgBitDepth; // In bitx + u32 imgColorType; // PNGU_COLOR_TYPE_* + u32 validBckgrnd; // Non zero if there is a background color + PNGUCOLOR bckgrnd; // Background color + u32 numTrans; // Number of transparent colors + PNGUCOLOR *trans; // Transparent colors +} PNGUPROP; + +// Image context, always initialize with SelectImageFrom* and free with ReleaseImageContext +struct _IMGCTX; +typedef struct _IMGCTX *IMGCTX; + +/**************************************************************************** +* Image context handling * +****************************************************************************/ + +// Selects a PNG file, previously loaded into a buffer, and creates an image context for subsequent processing. +IMGCTX PNGU_SelectImageFromBuffer (const void *buffer); + +// Selects a PNG file, from any devoptab device, and creates an image context for subsequent processing. +IMGCTX PNGU_SelectImageFromDevice (const char *filename); + +// Frees resources associated with an image context. Always call this function when you no longer need the IMGCTX. +void PNGU_ReleaseImageContext (IMGCTX ctx); + +/**************************************************************************** +* Miscellaneous * +****************************************************************************/ + +// Retrieves info from selected PNG file, including image dimensions, color format, background and transparency colors. +int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *fileproperties); + +/**************************************************************************** +* Image conversion * +****************************************************************************/ + +u8 * DecodePNG(const u8 *src, int *width, int *height, u8 *dst, int maxwidth, int maxheight); +int PNGU_EncodeFromRGB (IMGCTX ctx, u32 width, u32 height, void *buffer, u32 stride); +int PNGU_EncodeFromGXTexture (IMGCTX ctx, u32 width, u32 height, void *buffer, u32 stride); +int PNGU_EncodeFromEFB (IMGCTX ctx, u32 width, u32 height); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/plugins/snes9x_gx/source/utils/sz/7zAlloc.c b/plugins/snes9x_gx/source/utils/sz/7zAlloc.c new file mode 100644 index 00000000..d5da81b1 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zAlloc.c @@ -0,0 +1,70 @@ +/* 7zAlloc.c */ + +#include <stdlib.h> +#include "7zAlloc.h" + +/* #define _SZ_ALLOC_DEBUG */ +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ + +#ifdef _SZ_ALLOC_DEBUG + +#ifdef _WIN32 +#include <windows.h> +#endif +#include <stdio.h> +int g_allocCount = 0; +int g_allocCountTemp = 0; +#endif + +void *SzAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); + g_allocCount++; + #endif + return malloc(size); +} + +void SzFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + { + g_allocCount--; + fprintf(stderr, "\nFree; count = %10d", g_allocCount); + } + #endif + free(address); +} + +void *SzAllocTemp(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); + g_allocCountTemp++; + #ifdef _WIN32 + return HeapAlloc(GetProcessHeap(), 0, size); + #endif + #endif + return malloc(size); +} + +void SzFreeTemp(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + { + g_allocCountTemp--; + fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); + } + #ifdef _WIN32 + HeapFree(GetProcessHeap(), 0, address); + return; + #endif + #endif + free(address); +} diff --git a/plugins/snes9x_gx/source/utils/sz/7zAlloc.h b/plugins/snes9x_gx/source/utils/sz/7zAlloc.h new file mode 100644 index 00000000..b02c1dea --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zAlloc.h @@ -0,0 +1,20 @@ +/* 7zAlloc.h */ + +#ifndef __7Z_ALLOC_H +#define __7Z_ALLOC_H + +#include <stddef.h> + +typedef struct _ISzAlloc +{ + void *(*Alloc)(size_t size); + void (*Free)(void *address); /* address can be 0 */ +} ISzAlloc; + +void *SzAlloc(size_t size); +void SzFree(void *address); + +void *SzAllocTemp(size_t size); +void SzFreeTemp(void *address); + +#endif diff --git a/plugins/snes9x_gx/source/utils/sz/7zBuffer.c b/plugins/snes9x_gx/source/utils/sz/7zBuffer.c new file mode 100644 index 00000000..8bc8e067 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zBuffer.c @@ -0,0 +1,29 @@ +/* 7zBuffer.c */ + +#include "7zBuffer.h" +#include "7zAlloc.h" + +void SzByteBufferInit(CSzByteBuffer *buffer) +{ + buffer->Capacity = 0; + buffer->Items = 0; +} + +int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)) +{ + buffer->Capacity = newCapacity; + if (newCapacity == 0) + { + buffer->Items = 0; + return 1; + } + buffer->Items = (Byte *)allocFunc(newCapacity); + return (buffer->Items != 0); +} + +void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)) +{ + freeFunc(buffer->Items); + buffer->Items = 0; + buffer->Capacity = 0; +} diff --git a/plugins/snes9x_gx/source/utils/sz/7zBuffer.h b/plugins/snes9x_gx/source/utils/sz/7zBuffer.h new file mode 100644 index 00000000..afea3ca8 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zBuffer.h @@ -0,0 +1,19 @@ +/* 7zBuffer.h */ + +#ifndef __7Z_BUFFER_H +#define __7Z_BUFFER_H + +#include <stddef.h> +#include "7zTypes.h" + +typedef struct _CSzByteBuffer +{ + size_t Capacity; + Byte *Items; +}CSzByteBuffer; + +void SzByteBufferInit(CSzByteBuffer *buffer); +int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)); +void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)); + +#endif diff --git a/plugins/snes9x_gx/source/utils/sz/7zCrc.c b/plugins/snes9x_gx/source/utils/sz/7zCrc.c new file mode 100644 index 00000000..6dc7dd32 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zCrc.c @@ -0,0 +1,76 @@ +/* 7zCrc.c */ + +#include "7zCrc.h" + +#define kCrcPoly 0xEDB88320 + +UInt32 g_CrcTable[256]; + +void InitCrcTable() +{ + UInt32 i; + for (i = 0; i < 256; i++) + { + UInt32 r = i; + int j; + for (j = 0; j < 8; j++) + if (r & 1) + r = (r >> 1) ^ kCrcPoly; + else + r >>= 1; + g_CrcTable[i] = r; + } +} + +void CrcInit(UInt32 *crc) { *crc = 0xFFFFFFFF; } +UInt32 CrcGetDigest(UInt32 *crc) { return *crc ^ 0xFFFFFFFF; } + +void CrcUpdateByte(UInt32 *crc, Byte b) +{ + *crc = g_CrcTable[((Byte)(*crc)) ^ b] ^ (*crc >> 8); +} + +void CrcUpdateUInt16(UInt32 *crc, UInt16 v) +{ + CrcUpdateByte(crc, (Byte)v); + CrcUpdateByte(crc, (Byte)(v >> 8)); +} + +void CrcUpdateUInt32(UInt32 *crc, UInt32 v) +{ + int i; + for (i = 0; i < 4; i++) + CrcUpdateByte(crc, (Byte)(v >> (8 * i))); +} + +void CrcUpdateUInt64(UInt32 *crc, UInt64 v) +{ + int i; + for (i = 0; i < 8; i++) + { + CrcUpdateByte(crc, (Byte)(v)); + v >>= 8; + } +} + +void CrcUpdate(UInt32 *crc, const void *data, size_t size) +{ + UInt32 v = *crc; + const Byte *p = (const Byte *)data; + for (; size > 0 ; size--, p++) + v = g_CrcTable[((Byte)(v)) ^ *p] ^ (v >> 8); + *crc = v; +} + +UInt32 CrcCalculateDigest(const void *data, size_t size) +{ + UInt32 crc; + CrcInit(&crc); + CrcUpdate(&crc, data, size); + return CrcGetDigest(&crc); +} + +int CrcVerifyDigest(UInt32 digest, const void *data, size_t size) +{ + return (CrcCalculateDigest(data, size) == digest); +} diff --git a/plugins/snes9x_gx/source/utils/sz/7zCrc.h b/plugins/snes9x_gx/source/utils/sz/7zCrc.h new file mode 100644 index 00000000..bac26b14 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zCrc.h @@ -0,0 +1,24 @@ +/* 7zCrc.h */ + +#ifndef __7Z_CRC_H +#define __7Z_CRC_H + +#include <stddef.h> + +#include "7zTypes.h" + +extern UInt32 g_CrcTable[256]; +void InitCrcTable(); + +void CrcInit(UInt32 *crc); +UInt32 CrcGetDigest(UInt32 *crc); +void CrcUpdateByte(UInt32 *crc, Byte v); +void CrcUpdateUInt16(UInt32 *crc, UInt16 v); +void CrcUpdateUInt32(UInt32 *crc, UInt32 v); +void CrcUpdateUInt64(UInt32 *crc, UInt64 v); +void CrcUpdate(UInt32 *crc, const void *data, size_t size); + +UInt32 CrcCalculateDigest(const void *data, size_t size); +int CrcVerifyDigest(UInt32 digest, const void *data, size_t size); + +#endif diff --git a/plugins/snes9x_gx/source/utils/sz/7zDecode.c b/plugins/snes9x_gx/source/utils/sz/7zDecode.c new file mode 100644 index 00000000..a1207249 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zDecode.c @@ -0,0 +1,361 @@ +/* 7zDecode.c */ + +#include "7zDecode.h" +#ifdef _SZ_ONE_DIRECTORY +#include "LzmaDecode.h" +#else +#include "../../Compress/LZMA_C/LzmaDecode.h" +#endif + +#ifdef _LZMA_OUT_READ +#include <string.h> // for memcpy +#endif + +CMethodID k_Copy = { { 0x0 }, 1 }; +CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 }; + +#ifdef _LZMA_IN_CB + +typedef struct _CLzmaInCallbackImp +{ + ILzmaInCallback InCallback; + ISzInStream *InStream; + size_t Size; +} CLzmaInCallbackImp; + +int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size) +{ + CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object; + size_t processedSize; + SZ_RESULT res; + *size = 0; + res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, cb->Size, &processedSize); + *size = (SizeT)processedSize; + if (processedSize > cb->Size) + return (int)SZE_FAIL; + cb->Size -= processedSize; + if (res == SZ_OK) + return 0; + return (int)res; +} + +#endif + +SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, + #ifdef _LZMA_IN_CB + ISzInStream *inStream, + #else + const Byte *inBuffer, + #endif + Byte *outBuffer, size_t outSize, + size_t *outSizeProcessed, ISzAlloc *allocMain) +{ + UInt32 si; + size_t inSize = 0; + CCoderInfo *coder; + if (folder->NumPackStreams != 1) + return SZE_NOTIMPL; + if (folder->NumCoders != 1) + return SZE_NOTIMPL; + coder = folder->Coders; + *outSizeProcessed = 0; + + for (si = 0; si < folder->NumPackStreams; si++) + inSize += (size_t)packSizes[si]; + + if (AreMethodsEqual(&coder->MethodID, &k_Copy)) + { + size_t i; + if (inSize != outSize) + return SZE_DATA_ERROR; + #ifdef _LZMA_IN_CB + for (i = 0; i < inSize;) + { + size_t j; + Byte *inBuffer; + size_t bufferSize; + RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, inSize - i, &bufferSize)); + if (bufferSize == 0) + return SZE_DATA_ERROR; + if (bufferSize > inSize - i) + return SZE_FAIL; + *outSizeProcessed += bufferSize; + for (j = 0; j < bufferSize && i < inSize; j++, i++) + outBuffer[i] = inBuffer[j]; + } + #else + for (i = 0; i < inSize; i++) + outBuffer[i] = inBuffer[i]; + *outSizeProcessed = inSize; + #endif + return SZ_OK; + } + + if (AreMethodsEqual(&coder->MethodID, &k_LZMA)) + { + #ifdef _LZMA_IN_CB + CLzmaInCallbackImp lzmaCallback; + #else + SizeT inProcessed; + #endif + + CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ + int result; + SizeT outSizeProcessedLoc; + + #ifdef _LZMA_IN_CB + lzmaCallback.Size = inSize; + lzmaCallback.InStream = inStream; + lzmaCallback.InCallback.Read = LzmaReadImp; + #endif + + if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, + coder->Properties.Capacity) != LZMA_RESULT_OK) + return SZE_FAIL; + + state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); + if (state.Probs == 0) + return SZE_OUTOFMEMORY; + + #ifdef _LZMA_OUT_READ + if (state.Properties.DictionarySize == 0) + state.Dictionary = 0; + else + { + state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize); + if (state.Dictionary == 0) + { + allocMain->Free(state.Probs); + return SZE_OUTOFMEMORYDIC; + } + } + LzmaDecoderInit(&state); + #endif + + result = LzmaDecode(&state, + #ifdef _LZMA_IN_CB + &lzmaCallback.InCallback, + #else + inBuffer, (SizeT)inSize, &inProcessed, + #endif + outBuffer, (SizeT)outSize, &outSizeProcessedLoc); + *outSizeProcessed = (size_t)outSizeProcessedLoc; + allocMain->Free(state.Probs); + #ifdef _LZMA_OUT_READ + allocMain->Free(state.Dictionary); + #endif + if (result == LZMA_RESULT_DATA_ERROR) + return SZE_DATA_ERROR; + if (result != LZMA_RESULT_OK) + return SZE_FAIL; + return SZ_OK; + } + return SZE_NOTIMPL; +} + +#ifdef _LZMA_OUT_READ +// like SzDecode but uses less memory +SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder, + ISzInStream *inStream, + Byte *outBuffer, size_t outSize, + size_t *outSizeProcessed, ISzAlloc *allocMain, + size_t *fileOffset, size_t *fileSize) +{ + UInt32 si; + size_t inSize = 0; + CCoderInfo *coder; + if (folder->NumPackStreams != 1) + return SZE_NOTIMPL; + if (folder->NumCoders != 1) + return SZE_NOTIMPL; + coder = folder->Coders; + *outSizeProcessed = 0; + + for (si = 0; si < folder->NumPackStreams; si++) + inSize += (size_t)packSizes[si]; + + if (AreMethodsEqual(&coder->MethodID, &k_Copy)) + { + size_t i; + if (inSize != outSize) + return SZE_DATA_ERROR; + #ifdef _LZMA_IN_CB + for (i = 0; i < inSize;) + { + size_t j; + Byte *inBuffer; + size_t bufferSize; + RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, inSize - i, &bufferSize)); + if (bufferSize == 0) + return SZE_DATA_ERROR; + if (bufferSize > inSize - i) + return SZE_FAIL; + *outSizeProcessed += bufferSize; + for (j = 0; j < bufferSize && i < inSize; j++, i++) + outBuffer[i] = inBuffer[j]; + } + #else + for (i = 0; i < inSize; i++) + outBuffer[i] = inBuffer[i]; + *outSizeProcessed = inSize; + #endif + return SZ_OK; + } + + if (AreMethodsEqual(&coder->MethodID, &k_LZMA)) + { + #ifdef _LZMA_IN_CB + CLzmaInCallbackImp lzmaCallback; + #else + SizeT inProcessed; + #endif + + CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ + int result; + SizeT outSizeProcessedLoc; + + #ifdef _LZMA_IN_CB + lzmaCallback.Size = inSize; + lzmaCallback.InStream = inStream; + lzmaCallback.InCallback.Read = LzmaReadImp; + #endif + + if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, + coder->Properties.Capacity) != LZMA_RESULT_OK) + return SZE_FAIL; + + state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); + if (state.Probs == 0) + return SZE_OUTOFMEMORY; + + if (state.Properties.DictionarySize == 0) + state.Dictionary = 0; + else + { + state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize); + if (state.Dictionary == 0) + { + allocMain->Free(state.Probs); + return SZE_OUTOFMEMORYDIC; + } + } + LzmaDecoderInit(&state); + + // allocate memory for the temporary buffer + Byte *tmpBuffer = (Byte *)allocMain->Alloc(_LZMA_TEMP_BUFFER_SIZE); + + // variables containing the number of the first and the last bytes of the buffer + size_t bufferStart, bufferEnd; + bufferStart = bufferEnd = 0; + + // integers contains the offset, the size and the already copied data which will be + // copied from the tmpBuffer to outBuffer + size_t copyOffset, copySize, copyDone; + copyOffset = copySize = copyDone = 0; + + UInt32 i = 0; + int bytesToCopy = 0; + + // decompress data in _LZMA_TEMP_BUFFER_SIZE byte steps and copy the wanted file to outBuffer + do + { + if((*fileSize - copyDone) >= _LZMA_TEMP_BUFFER_SIZE) + bytesToCopy = _LZMA_TEMP_BUFFER_SIZE; + else + bytesToCopy = (*fileSize - copyDone); + + // decompress next bytes + result = LzmaDecode(&state, + #ifdef _LZMA_IN_CB + &lzmaCallback.InCallback, + #else + //inBuffer, (SizeT)inSize, &inProcessed, //TODO! + #endif + tmpBuffer, bytesToCopy, &outSizeProcessedLoc + ); + + // check result + if(result == LZMA_RESULT_DATA_ERROR) + { + return SZE_DATA_ERROR; + } + if(result != LZMA_RESULT_OK) + { + return SZE_FAIL; + } + + // normally this should never happen + if(outSizeProcessedLoc > _LZMA_TEMP_BUFFER_SIZE) + { + return SZE_FAIL; + } + + // update bufferStart and bufferEnd + bufferStart = _LZMA_TEMP_BUFFER_SIZE * i; + bufferEnd = bufferStart + outSizeProcessedLoc; + i++; + + // calculate copy offset and size + if(*fileOffset > bufferEnd) + { + // we haven't reached the start of the file yet + continue; + } + + // calculate offset + if(*fileOffset < bufferStart) + { + // the file has already started before this decompression step + copyOffset = 0; + } + else + { + // the file starts somewhere inside this buffer + copyDone = 0; + copyOffset = _LZMA_TEMP_BUFFER_SIZE - (bufferEnd - *fileOffset); + } + + // calculate size + if((*fileOffset + *fileSize) > bufferEnd) + { + // we'll need the whole buffer after copyOffset + copySize = _LZMA_TEMP_BUFFER_SIZE - copyOffset; + } + else + { + // we'll stop somewhere inside the buffer + copySize = (*fileOffset + *fileSize) - (bufferStart + copyOffset); + } + + // copy bytes to the real output buffer + if(copySize == 0) + { + continue; + } + // printf("memcpy(outBuffer + %d, tmpBuffer + %d, %d)\n", copyDone, copyOffset, copySize); + memcpy(outBuffer + copyDone, tmpBuffer + copyOffset, copySize); + copyDone += copySize; + } + while((*fileOffset + *fileSize) > bufferEnd); + + /* result = LzmaDecode(&state, + #ifdef _LZMA_IN_CB + &lzmaCallback.InCallback, + #else + inBuffer, (SizeT)inSize, &inProcessed, + #endif + outBuffer, (SizeT)outSize, &outSizeProcessedLoc);*/ + //*outSizeProcessed = (size_t)outSizeProcessedLoc; + *outSizeProcessed = copyDone; + allocMain->Free(tmpBuffer); // free the temporary buffer again + allocMain->Free(state.Probs); + allocMain->Free(state.Dictionary); + /* if (result == LZMA_RESULT_DATA_ERROR) + return SZE_DATA_ERROR; + if (result != LZMA_RESULT_OK) + return SZE_FAIL;*/ + return SZ_OK; + } + return SZE_NOTIMPL; + } + #endif diff --git a/plugins/snes9x_gx/source/utils/sz/7zDecode.h b/plugins/snes9x_gx/source/utils/sz/7zDecode.h new file mode 100644 index 00000000..9f15ba16 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zDecode.h @@ -0,0 +1,37 @@ +/* 7zDecode.h */ + +#if defined(_LZMA_OUT_READ) && !defined(_LZMA_IN_CB) +#error "Fixme: _LZMA_OUT_READ && _LZMA_IN_CB isn't currently possible!" +#endif + +#ifndef __7Z_DECODE_H +#define __7Z_DECODE_H + +#include "7zItem.h" +#include "7zAlloc.h" +#ifdef _LZMA_IN_CB +#include "7zIn.h" +#endif + +SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, + #ifdef _LZMA_IN_CB + ISzInStream *stream, + #else + const Byte *inBuffer, + #endif + Byte *outBuffer, size_t outSize, + size_t *outSizeProcessed, ISzAlloc *allocMain); + +#ifdef _LZMA_OUT_READ +#ifndef _LZMA_TEMP_BUFFER_SIZE +#define _LZMA_TEMP_BUFFER_SIZE (2048) // size of the temporary buffer in bytes +#endif + +SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder, + ISzInStream *stream, + Byte *outBuffer, size_t outSize, + size_t *outSizeProcessed, ISzAlloc *allocMain, + size_t *fileOffset, size_t *fileSize); +#endif // #ifdef _LZMA_OUT_READ + +#endif diff --git a/plugins/snes9x_gx/source/utils/sz/7zExtract.c b/plugins/snes9x_gx/source/utils/sz/7zExtract.c new file mode 100644 index 00000000..d7401460 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zExtract.c @@ -0,0 +1,254 @@ +/* 7zExtract.c */ + +#include "7zExtract.h" +#include "7zDecode.h" +#include "7zCrc.h" + +SZ_RESULT SzExtract( + ISzInStream *inStream, + CArchiveDatabaseEx *db, + UInt32 fileIndex, + UInt32 *blockIndex, + Byte **outBuffer, + size_t *outBufferSize, + size_t *offset, + size_t *outSizeProcessed, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex]; + SZ_RESULT res = SZ_OK; + *offset = 0; + *outSizeProcessed = 0; + if (folderIndex == (UInt32)-1) + { + allocMain->Free(*outBuffer); + *blockIndex = folderIndex; + *outBuffer = 0; + *outBufferSize = 0; + return SZ_OK; + } + + if (*outBuffer == 0 || *blockIndex != folderIndex) + { + CFolder *folder = db->Database.Folders + folderIndex; + CFileSize unPackSize = SzFolderGetUnPackSize(folder); + #ifndef _LZMA_IN_CB + CFileSize packSize = SzArDbGetFolderFullPackSize(db, folderIndex); + Byte *inBuffer = 0; + size_t processedSize; + #endif + *blockIndex = folderIndex; + allocMain->Free(*outBuffer); + *outBuffer = 0; + + RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0))); + + #ifndef _LZMA_IN_CB + if (packSize != 0) + { + inBuffer = (Byte *)allocTemp->Alloc((size_t)packSize); + if (inBuffer == 0) + return SZE_OUTOFMEMORY; + } + res = inStream->Read(inStream, inBuffer, (size_t)packSize, &processedSize); + if (res == SZ_OK && processedSize != (size_t)packSize) + res = SZE_FAIL; + #endif + if (res == SZ_OK) + { + *outBufferSize = (size_t)unPackSize; + if (unPackSize != 0) + { + *outBuffer = (Byte *)allocMain->Alloc((size_t)unPackSize); + if (*outBuffer == 0) + res = SZE_OUTOFMEMORY; + } + if (res == SZ_OK) + { + size_t outRealSize; + res = SzDecode(db->Database.PackSizes + + db->FolderStartPackStreamIndex[folderIndex], folder, + #ifdef _LZMA_IN_CB + inStream, + #else + inBuffer, + #endif + *outBuffer, (size_t)unPackSize, &outRealSize, allocTemp); + if (res == SZ_OK) + { + if (outRealSize == (size_t)unPackSize) + { + if (folder->UnPackCRCDefined) + { + if (!CrcVerifyDigest(folder->UnPackCRC, *outBuffer, (size_t)unPackSize)) + res = SZE_FAIL; + } + } + else + res = SZE_FAIL; + } + } + } + #ifndef _LZMA_IN_CB + allocTemp->Free(inBuffer); + #endif + } + if (res == SZ_OK) + { + UInt32 i; + CFileItem *fileItem = db->Database.Files + fileIndex; + *offset = 0; + for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) + *offset += (UInt32)db->Database.Files[i].Size; + *outSizeProcessed = (size_t)fileItem->Size; + if (*offset + *outSizeProcessed > *outBufferSize) + return SZE_FAIL; + { + if (fileItem->IsFileCRCDefined) + { + if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer + *offset, *outSizeProcessed)) + res = SZE_FAIL; + } + } + } + return res; +} + +#ifdef _LZMA_OUT_READ +// similar to SzExtract but needs less memory +SZ_RESULT SzExtract2( + ISzInStream *inStream, + CArchiveDatabaseEx *db, + UInt32 fileIndex, + UInt32 *blockIndex, + Byte **outBuffer, + size_t *outBufferSize, + size_t *offset, + size_t *outSizeProcessed, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex]; + SZ_RESULT res = SZ_OK; + *offset = 0; + *outSizeProcessed = 0; + if (folderIndex == (UInt32)-1) + { + *blockIndex = folderIndex; + #ifndef GEKKO + allocMain->Free(*outBuffer); + *outBuffer = 0; + #endif + *outBufferSize = 0; + return SZ_OK; + } + +// if (*outBuffer == 0 || *blockIndex != folderIndex) +// { + CFolder *folder = db->Database.Folders + folderIndex; + CFileSize unPackSize = SzFolderGetUnPackSize(folder); + #ifndef _LZMA_IN_CB + CFileSize packSize = SzArDbGetFolderFullPackSize(db, folderIndex); + Byte *inBuffer = 0; + size_t processedSize; + #endif + *blockIndex = folderIndex; + #ifndef GEKKO + allocMain->Free(*outBuffer); + *outBuffer = 0; + #endif + + RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0))); + + #ifndef _LZMA_IN_CB + if (packSize != 0) + { + inBuffer = (Byte *)allocTemp->Alloc((size_t)packSize); + if (inBuffer == 0) + return SZE_OUTOFMEMORY; + } + res = inStream->Read(inStream, inBuffer, (size_t)packSize, &processedSize); + if (res == SZ_OK && processedSize != (size_t)packSize) + res = SZE_FAIL; + #endif + if (res == SZ_OK) + { + // calculate file offset and filesize + CFileItem *fileItem = db->Database.Files + fileIndex; + UInt32 i; + *offset = 0; + for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) + *offset += (UInt32)db->Database.Files[i].Size; + *outSizeProcessed = (size_t)fileItem->Size; + *outBufferSize = (size_t)fileItem->Size; + if (unPackSize != 0) + { + #ifndef GEKKO + *outBuffer = (Byte *)allocMain->Alloc((size_t)fileItem->Size); + if (*outBuffer == 0) + res = SZE_OUTOFMEMORY; + #endif + } + if (res == SZ_OK) + { + + size_t outRealSize; + res = SzDecode2(db->Database.PackSizes + + db->FolderStartPackStreamIndex[folderIndex], folder, + #ifdef _LZMA_IN_CB + inStream, + #else + inBuffer, + #endif + *outBuffer, (size_t)unPackSize, &outRealSize, allocTemp, + offset, outSizeProcessed + ); + *outSizeProcessed = outRealSize; +/* if (res == SZ_OK) // we can't validate the CRC of the whole data stream because we only extracted the wanted file + { + if (outRealSize == (size_t)unPackSize) + { + if (folder->UnPackCRCDefined) + { + if (!CrcVerifyDigest(folder->UnPackCRC, *outBuffer, (size_t)unPackSize)) + res = SZE_FAIL; + } + } + else + res = SZE_FAIL; + }*/ + } +// } + #ifndef _LZMA_IN_CB + allocTemp->Free(inBuffer); + #endif + } + if (res == SZ_OK) + { +/* UInt32 i; + CFileItem *fileItem = db->Database.Files + fileIndex; + *offset = 0; + for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) + *offset += (UInt32)db->Database.Files[i].Size; + *outSizeProcessed = (size_t)fileItem->Size;*/ + //CFileItem *fileItem = db->Database.Files + fileIndex; + if (/**offset +*/ *outSizeProcessed > *outBufferSize) + return SZE_FAIL; + { + //if (fileItem->IsFileCRCDefined) + //{ + // if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer/* + *offset*/, *outSizeProcessed)) + // res = SZE_CRC_ERROR; // why does SzExtract return SZE_FAIL when we can return SZE_CRC_ERROR? + //} + } + } + + // change *offset to 0 because SzExtract normally decompresses the whole solid block + // and sets *offset to the offset of the wanted file. + // SzDecode2 does only copy the needed file to the output buffer and has to set *offset + // to 0 to ensure compatibility with SzExtract + *offset = 0; + return res; +} +#endif diff --git a/plugins/snes9x_gx/source/utils/sz/7zExtract.h b/plugins/snes9x_gx/source/utils/sz/7zExtract.h new file mode 100644 index 00000000..7f7e07ee --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zExtract.h @@ -0,0 +1,60 @@ +/* 7zExtract.h */ + +#if defined(_LZMA_OUT_READ) && !defined(_LZMA_IN_CB) +#error "Fixme: _LZMA_OUT_READ && _LZMA_IN_CB isn't currently possible!" +#endif + +#ifndef __7Z_EXTRACT_H +#define __7Z_EXTRACT_H + +#include "7zIn.h" + +/* + SzExtract extracts file from archive + + SzExtract2 does the same but needs less memory + + *outBuffer must be 0 before first call for each new archive. + + Extracting cache: + If you need to decompress more than one file, you can send + these values from previous call: + *blockIndex, + *outBuffer, + *outBufferSize + You can consider "*outBuffer" as cache of solid block. If your archive is solid, + it will increase decompression speed. + + If you use external function, you can declare these 3 cache variables + (blockIndex, outBuffer, outBufferSize) as static in that external function. + + Free *outBuffer and set *outBuffer to 0, if you want to flush cache. +*/ + +SZ_RESULT SzExtract( + ISzInStream *inStream, + CArchiveDatabaseEx *db, + UInt32 fileIndex, /* index of file */ + UInt32 *blockIndex, /* index of solid block */ + Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ + size_t *outBufferSize, /* buffer size for output buffer */ + size_t *offset, /* offset of stream for required file in *outBuffer */ + size_t *outSizeProcessed, /* size of file in *outBuffer */ + ISzAlloc *allocMain, + ISzAlloc *allocTemp); + +#ifdef _LZMA_OUT_READ +SZ_RESULT SzExtract2( + ISzInStream *inStream, + CArchiveDatabaseEx *db, + UInt32 fileIndex, /* index of file */ + UInt32 *blockIndex, /* index of solid block */ + Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ + size_t *outBufferSize, /* buffer size for output buffer */ + size_t *offset, /* offset of stream for required file in *outBuffer */ + size_t *outSizeProcessed, /* size of file in *outBuffer */ + ISzAlloc *allocMain, + ISzAlloc *allocTemp); +#endif + +#endif diff --git a/plugins/snes9x_gx/source/utils/sz/7zHeader.c b/plugins/snes9x_gx/source/utils/sz/7zHeader.c new file mode 100644 index 00000000..e26c0143 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zHeader.c @@ -0,0 +1,5 @@ +/* 7zHeader.c */ + +#include "7zHeader.h" + +Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; diff --git a/plugins/snes9x_gx/source/utils/sz/7zHeader.h b/plugins/snes9x_gx/source/utils/sz/7zHeader.h new file mode 100644 index 00000000..7edf640f --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zHeader.h @@ -0,0 +1,55 @@ +/* 7zHeader.h */ + +#ifndef __7Z_HEADER_H +#define __7Z_HEADER_H + +#include "7zTypes.h" + +#define k7zSignatureSize 6 +extern Byte k7zSignature[k7zSignatureSize]; + +#define k7zMajorVersion 0 + +#define k7zStartHeaderSize 0x20 + +enum EIdEnum +{ + k7zIdEnd, + + k7zIdHeader, + + k7zIdArchiveProperties, + + k7zIdAdditionalStreamsInfo, + k7zIdMainStreamsInfo, + k7zIdFilesInfo, + + k7zIdPackInfo, + k7zIdUnPackInfo, + k7zIdSubStreamsInfo, + + k7zIdSize, + k7zIdCRC, + + k7zIdFolder, + + k7zIdCodersUnPackSize, + k7zIdNumUnPackStream, + + k7zIdEmptyStream, + k7zIdEmptyFile, + k7zIdAnti, + + k7zIdName, + k7zIdCreationTime, + k7zIdLastAccessTime, + k7zIdLastWriteTime, + k7zIdWinAttributes, + k7zIdComment, + + k7zIdEncodedHeader, + + k7zIdStartPos +}; + +#endif diff --git a/plugins/snes9x_gx/source/utils/sz/7zIn.c b/plugins/snes9x_gx/source/utils/sz/7zIn.c new file mode 100644 index 00000000..b3e9ea27 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zIn.c @@ -0,0 +1,1281 @@ +/* 7zIn.c */ + +#include "7zIn.h" +#include "7zCrc.h" +#include "7zDecode.h" + +#define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; } + +void SzArDbExInit(CArchiveDatabaseEx *db) +{ + SzArchiveDatabaseInit(&db->Database); + db->FolderStartPackStreamIndex = 0; + db->PackStreamStartPositions = 0; + db->FolderStartFileIndex = 0; + db->FileIndexToFolderIndexMap = 0; +} + +void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)) +{ + freeFunc(db->FolderStartPackStreamIndex); + freeFunc(db->PackStreamStartPositions); + freeFunc(db->FolderStartFileIndex); + freeFunc(db->FileIndexToFolderIndexMap); + SzArchiveDatabaseFree(&db->Database, freeFunc); + SzArDbExInit(db); +} + +/* +CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const +{ + return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; +} + +CFileSize GetFilePackSize(int fileIndex) const +{ + int folderIndex = FileIndexToFolderIndexMap[fileIndex]; + if (folderIndex >= 0) + { + const CFolder &folderInfo = Folders[folderIndex]; + if (FolderStartFileIndex[folderIndex] == fileIndex) + return GetFolderFullPackSize(folderIndex); + } + return 0; +} +*/ + +#define MY_ALLOC(T, p, size, allocFunc) { if ((size) == 0) p = 0; else \ + if ((p = (T *)allocFunc((size) * sizeof(T))) == 0) return SZE_OUTOFMEMORY; } + +SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size)) +{ + UInt32 startPos = 0; + CFileSize startPosSize = 0; + UInt32 i; + UInt32 folderIndex = 0; + UInt32 indexInFolder = 0; + MY_ALLOC(UInt32, db->FolderStartPackStreamIndex, db->Database.NumFolders, allocFunc); + for(i = 0; i < db->Database.NumFolders; i++) + { + db->FolderStartPackStreamIndex[i] = startPos; + startPos += db->Database.Folders[i].NumPackStreams; + } + + MY_ALLOC(CFileSize, db->PackStreamStartPositions, db->Database.NumPackStreams, allocFunc); + + for(i = 0; i < db->Database.NumPackStreams; i++) + { + db->PackStreamStartPositions[i] = startPosSize; + startPosSize += db->Database.PackSizes[i]; + } + + MY_ALLOC(UInt32, db->FolderStartFileIndex, db->Database.NumFolders, allocFunc); + MY_ALLOC(UInt32, db->FileIndexToFolderIndexMap, db->Database.NumFiles, allocFunc); + + for (i = 0; i < db->Database.NumFiles; i++) + { + CFileItem *file = db->Database.Files + i; + int emptyStream = !file->HasStream; + if (emptyStream && indexInFolder == 0) + { + db->FileIndexToFolderIndexMap[i] = (UInt32)-1; + continue; + } + if (indexInFolder == 0) + { + /* + v3.13 incorrectly worked with empty folders + v4.07: Loop for skipping empty folders + */ + while(1) + { + if (folderIndex >= db->Database.NumFolders) + return SZE_ARCHIVE_ERROR; + db->FolderStartFileIndex[folderIndex] = i; + if (db->Database.Folders[folderIndex].NumUnPackStreams != 0) + break; + folderIndex++; + } + } + db->FileIndexToFolderIndexMap[i] = folderIndex; + if (emptyStream) + continue; + indexInFolder++; + if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams) + { + folderIndex++; + indexInFolder = 0; + } + } + return SZ_OK; +} + + +CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder) +{ + return db->ArchiveInfo.DataStartPosition + + db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; +} + +CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex) +{ + UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex]; + CFolder *folder = db->Database.Folders + folderIndex; + CFileSize size = 0; + UInt32 i; + for (i = 0; i < folder->NumPackStreams; i++) + size += db->Database.PackSizes[packStreamIndex + i]; + return size; +} + + +/* +SZ_RESULT SzReadTime(const CObjectVector<CSzByteBuffer> &dataVector, + CObjectVector<CFileItem> &files, UInt64 type) +{ + CBoolVector boolVector; + RINOK(ReadBoolVector2(files.Size(), boolVector)) + + CStreamSwitch streamSwitch; + RINOK(streamSwitch.Set(this, &dataVector)); + + for(int i = 0; i < files.Size(); i++) + { + CFileItem &file = files[i]; + CArchiveFileTime fileTime; + bool defined = boolVector[i]; + if (defined) + { + UInt32 low, high; + RINOK(SzReadUInt32(low)); + RINOK(SzReadUInt32(high)); + fileTime.dwLowDateTime = low; + fileTime.dwHighDateTime = high; + } + switch(type) + { + case k7zIdCreationTime: + file.IsCreationTimeDefined = defined; + if (defined) + file.CreationTime = fileTime; + break; + case k7zIdLastWriteTime: + file.IsLastWriteTimeDefined = defined; + if (defined) + file.LastWriteTime = fileTime; + break; + case k7zIdLastAccessTime: + file.IsLastAccessTimeDefined = defined; + if (defined) + file.LastAccessTime = fileTime; + break; + } + } + return SZ_OK; +} +*/ + +SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size) +{ + #ifdef _LZMA_IN_CB + while (size > 0) + { + Byte *inBuffer; + size_t processedSize; + RINOK(inStream->Read(inStream, (void **)&inBuffer, size, &processedSize)); + if (processedSize == 0 || processedSize > size) + return SZE_FAIL; + size -= processedSize; + do + { + *data++ = *inBuffer++; + } + while (--processedSize != 0); + } + #else + size_t processedSize; + RINOK(inStream->Read(inStream, data, size, &processedSize)); + if (processedSize != size) + return SZE_FAIL; + #endif + return SZ_OK; +} + +SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data) +{ + return SafeReadDirect(inStream, data, 1); +} + +SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value) +{ + int i; + *value = 0; + for (i = 0; i < 4; i++) + { + Byte b; + RINOK(SafeReadDirectByte(inStream, &b)); + *value |= ((UInt32)b << (8 * i)); + } + return SZ_OK; +} + +SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value) +{ + int i; + *value = 0; + for (i = 0; i < 8; i++) + { + Byte b; + RINOK(SafeReadDirectByte(inStream, &b)); + *value |= ((UInt32)b << (8 * i)); + } + return SZ_OK; +} + +int TestSignatureCandidate(Byte *testBytes) +{ + size_t i; + for (i = 0; i < k7zSignatureSize; i++) + if (testBytes[i] != k7zSignature[i]) + return 0; + return 1; +} + +typedef struct _CSzState +{ + Byte *Data; + size_t Size; +}CSzData; + +SZ_RESULT SzReadByte(CSzData *sd, Byte *b) +{ + if (sd->Size == 0) + return SZE_ARCHIVE_ERROR; + sd->Size--; + *b = *sd->Data++; + return SZ_OK; +} + +SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size) +{ + size_t i; + for (i = 0; i < size; i++) + { + RINOK(SzReadByte(sd, data + i)); + } + return SZ_OK; +} + +SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value) +{ + int i; + *value = 0; + for (i = 0; i < 4; i++) + { + Byte b; + RINOK(SzReadByte(sd, &b)); + *value |= ((UInt32)(b) << (8 * i)); + } + return SZ_OK; +} + +SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value) +{ + Byte firstByte; + Byte mask = 0x80; + int i; + RINOK(SzReadByte(sd, &firstByte)); + *value = 0; + for (i = 0; i < 8; i++) + { + Byte b; + if ((firstByte & mask) == 0) + { + UInt64 highPart = firstByte & (mask - 1); + *value += (highPart << (8 * i)); + return SZ_OK; + } + RINOK(SzReadByte(sd, &b)); + *value |= ((UInt64)b << (8 * i)); + mask >>= 1; + } + return SZ_OK; +} + +SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value) +{ + UInt64 value64; + RINOK(SzReadNumber(sd, &value64)); + *value = (CFileSize)value64; + return SZ_OK; +} + +SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value) +{ + UInt64 value64; + RINOK(SzReadNumber(sd, &value64)); + if (value64 >= 0x80000000) + return SZE_NOTIMPL; + if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) + return SZE_NOTIMPL; + *value = (UInt32)value64; + return SZ_OK; +} + +SZ_RESULT SzReadID(CSzData *sd, UInt64 *value) +{ + return SzReadNumber(sd, value); +} + +SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size) +{ + if (size > sd->Size) + return SZE_ARCHIVE_ERROR; + sd->Size -= (size_t)size; + sd->Data += (size_t)size; + return SZ_OK; +} + +SZ_RESULT SzSkeepData(CSzData *sd) +{ + UInt64 size; + RINOK(SzReadNumber(sd, &size)); + return SzSkeepDataSize(sd, size); +} + +SZ_RESULT SzReadArchiveProperties(CSzData *sd) +{ + while(1) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + break; + SzSkeepData(sd); + } + return SZ_OK; +} + +SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute) +{ + while(1) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == attribute) + return SZ_OK; + if (type == k7zIdEnd) + return SZE_ARCHIVE_ERROR; + RINOK(SzSkeepData(sd)); + } +} + +SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) +{ + Byte b = 0; + Byte mask = 0; + size_t i; + MY_ALLOC(Byte, *v, numItems, allocFunc); + for(i = 0; i < numItems; i++) + { + if (mask == 0) + { + RINOK(SzReadByte(sd, &b)); + mask = 0x80; + } + (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); + mask >>= 1; + } + return SZ_OK; +} + +SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) +{ + Byte allAreDefined; + size_t i; + RINOK(SzReadByte(sd, &allAreDefined)); + if (allAreDefined == 0) + return SzReadBoolVector(sd, numItems, v, allocFunc); + MY_ALLOC(Byte, *v, numItems, allocFunc); + for(i = 0; i < numItems; i++) + (*v)[i] = 1; + return SZ_OK; +} + +SZ_RESULT SzReadHashDigests( + CSzData *sd, + size_t numItems, + Byte **digestsDefined, + UInt32 **digests, + void * (*allocFunc)(size_t size)) +{ + size_t i; + RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc)); + MY_ALLOC(UInt32, *digests, numItems, allocFunc); + for(i = 0; i < numItems; i++) + if ((*digestsDefined)[i]) + { + RINOK(SzReadUInt32(sd, (*digests) + i)); + } + return SZ_OK; +} + +SZ_RESULT SzReadPackInfo( + CSzData *sd, + CFileSize *dataOffset, + UInt32 *numPackStreams, + CFileSize **packSizes, + Byte **packCRCsDefined, + UInt32 **packCRCs, + void * (*allocFunc)(size_t size)) +{ + UInt32 i; + RINOK(SzReadSize(sd, dataOffset)); + RINOK(SzReadNumber32(sd, numPackStreams)); + + RINOK(SzWaitAttribute(sd, k7zIdSize)); + + MY_ALLOC(CFileSize, *packSizes, (size_t)*numPackStreams, allocFunc); + + for(i = 0; i < *numPackStreams; i++) + { + RINOK(SzReadSize(sd, (*packSizes) + i)); + } + + while(1) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + break; + if (type == k7zIdCRC) + { + RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc)); + continue; + } + RINOK(SzSkeepData(sd)); + } + if (*packCRCsDefined == 0) + { + MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, allocFunc); + MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, allocFunc); + for(i = 0; i < *numPackStreams; i++) + { + (*packCRCsDefined)[i] = 0; + (*packCRCs)[i] = 0; + } + } + return SZ_OK; +} + +SZ_RESULT SzReadSwitch(CSzData *sd) +{ + Byte external; + RINOK(SzReadByte(sd, &external)); + return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR; +} + +SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size)) +{ + UInt32 numCoders; + UInt32 numBindPairs; + UInt32 numPackedStreams; + UInt32 i; + UInt32 numInStreams = 0; + UInt32 numOutStreams = 0; + RINOK(SzReadNumber32(sd, &numCoders)); + folder->NumCoders = numCoders; + + MY_ALLOC(CCoderInfo, folder->Coders, (size_t)numCoders, allocFunc); + + for (i = 0; i < numCoders; i++) + SzCoderInfoInit(folder->Coders + i); + + for (i = 0; i < numCoders; i++) + { + Byte mainByte; + CCoderInfo *coder = folder->Coders + i; + { + RINOK(SzReadByte(sd, &mainByte)); + coder->MethodID.IDSize = (Byte)(mainByte & 0xF); + RINOK(SzReadBytes(sd, coder->MethodID.ID, coder->MethodID.IDSize)); + if ((mainByte & 0x10) != 0) + { + RINOK(SzReadNumber32(sd, &coder->NumInStreams)); + RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); + } + else + { + coder->NumInStreams = 1; + coder->NumOutStreams = 1; + } + if ((mainByte & 0x20) != 0) + { + UInt64 propertiesSize = 0; + RINOK(SzReadNumber(sd, &propertiesSize)); + if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc)) + return SZE_OUTOFMEMORY; + RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize)); + } + } + while ((mainByte & 0x80) != 0) + { + RINOK(SzReadByte(sd, &mainByte)); + RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); + if ((mainByte & 0x10) != 0) + { + UInt32 n; + RINOK(SzReadNumber32(sd, &n)); + RINOK(SzReadNumber32(sd, &n)); + } + if ((mainByte & 0x20) != 0) + { + UInt64 propertiesSize = 0; + RINOK(SzReadNumber(sd, &propertiesSize)); + RINOK(SzSkeepDataSize(sd, propertiesSize)); + } + } + numInStreams += (UInt32)coder->NumInStreams; + numOutStreams += (UInt32)coder->NumOutStreams; + } + + numBindPairs = numOutStreams - 1; + folder->NumBindPairs = numBindPairs; + + + MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, allocFunc); + + for (i = 0; i < numBindPairs; i++) + { + CBindPair *bindPair = folder->BindPairs + i;; + RINOK(SzReadNumber32(sd, &bindPair->InIndex)); + RINOK(SzReadNumber32(sd, &bindPair->OutIndex)); + } + + numPackedStreams = numInStreams - (UInt32)numBindPairs; + + folder->NumPackStreams = numPackedStreams; + MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackedStreams, allocFunc); + + if (numPackedStreams == 1) + { + UInt32 j; + UInt32 pi = 0; + for (j = 0; j < numInStreams; j++) + if (SzFolderFindBindPairForInStream(folder, j) < 0) + { + folder->PackStreams[pi++] = j; + break; + } + } + else + for(i = 0; i < numPackedStreams; i++) + { + RINOK(SzReadNumber32(sd, folder->PackStreams + i)); + } + return SZ_OK; +} + +SZ_RESULT SzReadUnPackInfo( + CSzData *sd, + UInt32 *numFolders, + CFolder **folders, /* for allocFunc */ + void * (*allocFunc)(size_t size), + ISzAlloc *allocTemp) +{ + UInt32 i; + RINOK(SzWaitAttribute(sd, k7zIdFolder)); + RINOK(SzReadNumber32(sd, numFolders)); + { + RINOK(SzReadSwitch(sd)); + + MY_ALLOC(CFolder, *folders, (size_t)*numFolders, allocFunc); + + for(i = 0; i < *numFolders; i++) + SzFolderInit((*folders) + i); + + for(i = 0; i < *numFolders; i++) + { + RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc)); + } + } + + RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize)); + + for(i = 0; i < *numFolders; i++) + { + UInt32 j; + CFolder *folder = (*folders) + i; + UInt32 numOutStreams = SzFolderGetNumOutStreams(folder); + + MY_ALLOC(CFileSize, folder->UnPackSizes, (size_t)numOutStreams, allocFunc); + + for(j = 0; j < numOutStreams; j++) + { + RINOK(SzReadSize(sd, folder->UnPackSizes + j)); + } + } + + while(1) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + return SZ_OK; + if (type == k7zIdCRC) + { + SZ_RESULT res; + Byte *crcsDefined = 0; + UInt32 *crcs = 0; + res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc); + if (res == SZ_OK) + { + for(i = 0; i < *numFolders; i++) + { + CFolder *folder = (*folders) + i; + folder->UnPackCRCDefined = crcsDefined[i]; + folder->UnPackCRC = crcs[i]; + } + } + allocTemp->Free(crcs); + allocTemp->Free(crcsDefined); + RINOK(res); + continue; + } + RINOK(SzSkeepData(sd)); + } +} + +SZ_RESULT SzReadSubStreamsInfo( + CSzData *sd, + UInt32 numFolders, + CFolder *folders, + UInt32 *numUnPackStreams, + CFileSize **unPackSizes, + Byte **digestsDefined, + UInt32 **digests, + ISzAlloc *allocTemp) +{ + UInt64 type = 0; + UInt32 i; + UInt32 si = 0; + UInt32 numDigests = 0; + + for(i = 0; i < numFolders; i++) + folders[i].NumUnPackStreams = 1; + *numUnPackStreams = numFolders; + + while(1) + { + RINOK(SzReadID(sd, &type)); + if (type == k7zIdNumUnPackStream) + { + *numUnPackStreams = 0; + for(i = 0; i < numFolders; i++) + { + UInt32 numStreams; + RINOK(SzReadNumber32(sd, &numStreams)); + folders[i].NumUnPackStreams = numStreams; + *numUnPackStreams += numStreams; + } + continue; + } + if (type == k7zIdCRC || type == k7zIdSize) + break; + if (type == k7zIdEnd) + break; + RINOK(SzSkeepData(sd)); + } + + if (*numUnPackStreams == 0) + { + *unPackSizes = 0; + *digestsDefined = 0; + *digests = 0; + } + else + { + *unPackSizes = (CFileSize *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(CFileSize)); + RINOM(*unPackSizes); + *digestsDefined = (Byte *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(Byte)); + RINOM(*digestsDefined); + *digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32)); + RINOM(*digests); + } + + for(i = 0; i < numFolders; i++) + { + /* + v3.13 incorrectly worked with empty folders + v4.07: we check that folder is empty + */ + CFileSize sum = 0; + UInt32 j; + UInt32 numSubstreams = folders[i].NumUnPackStreams; + if (numSubstreams == 0) + continue; + if (type == k7zIdSize) + for (j = 1; j < numSubstreams; j++) + { + CFileSize size; + RINOK(SzReadSize(sd, &size)); + (*unPackSizes)[si++] = size; + sum += size; + } + (*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum; + } + if (type == k7zIdSize) + { + RINOK(SzReadID(sd, &type)); + } + + for(i = 0; i < *numUnPackStreams; i++) + { + (*digestsDefined)[i] = 0; + (*digests)[i] = 0; + } + + + for(i = 0; i < numFolders; i++) + { + UInt32 numSubstreams = folders[i].NumUnPackStreams; + if (numSubstreams != 1 || !folders[i].UnPackCRCDefined) + numDigests += numSubstreams; + } + + + si = 0; + while(1) + { + if (type == k7zIdCRC) + { + int digestIndex = 0; + Byte *digestsDefined2 = 0; + UInt32 *digests2 = 0; + SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc); + if (res == SZ_OK) + { + for (i = 0; i < numFolders; i++) + { + CFolder *folder = folders + i; + UInt32 numSubstreams = folder->NumUnPackStreams; + if (numSubstreams == 1 && folder->UnPackCRCDefined) + { + (*digestsDefined)[si] = 1; + (*digests)[si] = folder->UnPackCRC; + si++; + } + else + { + UInt32 j; + for (j = 0; j < numSubstreams; j++, digestIndex++) + { + (*digestsDefined)[si] = digestsDefined2[digestIndex]; + (*digests)[si] = digests2[digestIndex]; + si++; + } + } + } + } + allocTemp->Free(digestsDefined2); + allocTemp->Free(digests2); + RINOK(res); + } + else if (type == k7zIdEnd) + return SZ_OK; + else + { + RINOK(SzSkeepData(sd)); + } + RINOK(SzReadID(sd, &type)); + } +} + + +SZ_RESULT SzReadStreamsInfo( + CSzData *sd, + CFileSize *dataOffset, + CArchiveDatabase *db, + UInt32 *numUnPackStreams, + CFileSize **unPackSizes, /* allocTemp */ + Byte **digestsDefined, /* allocTemp */ + UInt32 **digests, /* allocTemp */ + void * (*allocFunc)(size_t size), + ISzAlloc *allocTemp) +{ + while(1) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if ((UInt64)(int)type != type) + return SZE_FAIL; + switch((int)type) + { + case k7zIdEnd: + return SZ_OK; + case k7zIdPackInfo: + { + RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams, + &db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc)); + break; + } + case k7zIdUnPackInfo: + { + RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp)); + break; + } + case k7zIdSubStreamsInfo: + { + RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders, + numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp)); + break; + } + default: + return SZE_FAIL; + } + } +} + +Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files, + void * (*allocFunc)(size_t size)) +{ + UInt32 i; + for(i = 0; i < numFiles; i++) + { + UInt32 len = 0; + UInt32 pos = 0; + CFileItem *file = files + i; + while(pos + 2 <= sd->Size) + { + int numAdds; + UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); + pos += 2; + len++; + if (value == 0) + break; + if (value < 0x80) + continue; + if (value >= 0xD800 && value < 0xE000) + { + UInt32 c2; + if (value >= 0xDC00) + return SZE_ARCHIVE_ERROR; + if (pos + 2 > sd->Size) + return SZE_ARCHIVE_ERROR; + c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); + pos += 2; + if (c2 < 0xDC00 || c2 >= 0xE000) + return SZE_ARCHIVE_ERROR; + value = ((value - 0xD800) << 10) | (c2 - 0xDC00); + } + for (numAdds = 1; numAdds < 5; numAdds++) + if (value < (((UInt32)1) << (numAdds * 5 + 6))) + break; + len += numAdds; + } + + MY_ALLOC(char, file->Name, (size_t)len, allocFunc); + + len = 0; + while(2 <= sd->Size) + { + int numAdds; + UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); + SzSkeepDataSize(sd, 2); + if (value < 0x80) + { + file->Name[len++] = (char)value; + if (value == 0) + break; + continue; + } + if (value >= 0xD800 && value < 0xE000) + { + UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); + SzSkeepDataSize(sd, 2); + value = ((value - 0xD800) << 10) | (c2 - 0xDC00); + } + for (numAdds = 1; numAdds < 5; numAdds++) + if (value < (((UInt32)1) << (numAdds * 5 + 6))) + break; + file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); + do + { + numAdds--; + file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); + } + while(numAdds > 0); + + len += numAdds; + } + } + return SZ_OK; +} + +SZ_RESULT SzReadHeader2( + CSzData *sd, + CArchiveDatabaseEx *db, /* allocMain */ + CFileSize **unPackSizes, /* allocTemp */ + Byte **digestsDefined, /* allocTemp */ + UInt32 **digests, /* allocTemp */ + Byte **emptyStreamVector, /* allocTemp */ + Byte **emptyFileVector, /* allocTemp */ + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + UInt64 type; + UInt32 numUnPackStreams = 0; + UInt32 numFiles = 0; + CFileItem *files = 0; + UInt32 numEmptyStreams = 0; + UInt32 i; + + RINOK(SzReadID(sd, &type)); + + if (type == k7zIdArchiveProperties) + { + RINOK(SzReadArchiveProperties(sd)); + RINOK(SzReadID(sd, &type)); + } + + + if (type == k7zIdMainStreamsInfo) + { + RINOK(SzReadStreamsInfo(sd, + &db->ArchiveInfo.DataStartPosition, + &db->Database, + &numUnPackStreams, + unPackSizes, + digestsDefined, + digests, allocMain->Alloc, allocTemp)); + db->ArchiveInfo.DataStartPosition += db->ArchiveInfo.StartPositionAfterHeader; + RINOK(SzReadID(sd, &type)); + } + + if (type == k7zIdEnd) + return SZ_OK; + if (type != k7zIdFilesInfo) + return SZE_ARCHIVE_ERROR; + + RINOK(SzReadNumber32(sd, &numFiles)); + db->Database.NumFiles = numFiles; + + MY_ALLOC(CFileItem, files, (size_t)numFiles, allocMain->Alloc); + + db->Database.Files = files; + for(i = 0; i < numFiles; i++) + SzFileInit(files + i); + + while(1) + { + UInt64 type; + UInt64 size; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + break; + RINOK(SzReadNumber(sd, &size)); + + if ((UInt64)(int)type != type) + { + RINOK(SzSkeepDataSize(sd, size)); + } + else + switch((int)type) + { + case k7zIdName: + { + RINOK(SzReadSwitch(sd)); + RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc)) + break; + } + case k7zIdEmptyStream: + { + RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp->Alloc)); + numEmptyStreams = 0; + for (i = 0; i < numFiles; i++) + if ((*emptyStreamVector)[i]) + numEmptyStreams++; + break; + } + case k7zIdEmptyFile: + { + RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp->Alloc)); + break; + } + default: + { + RINOK(SzSkeepDataSize(sd, size)); + } + } + } + + { + UInt32 emptyFileIndex = 0; + UInt32 sizeIndex = 0; + for(i = 0; i < numFiles; i++) + { + CFileItem *file = files + i; + file->IsAnti = 0; + if (*emptyStreamVector == 0) + file->HasStream = 1; + else + file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); + if(file->HasStream) + { + file->IsDirectory = 0; + file->Size = (*unPackSizes)[sizeIndex]; + file->FileCRC = (*digests)[sizeIndex]; + file->IsFileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; + sizeIndex++; + } + else + { + if (*emptyFileVector == 0) + file->IsDirectory = 1; + else + file->IsDirectory = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); + emptyFileIndex++; + file->Size = 0; + file->IsFileCRCDefined = 0; + } + } + } + return SzArDbExFill(db, allocMain->Alloc); +} + +SZ_RESULT SzReadHeader( + CSzData *sd, + CArchiveDatabaseEx *db, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + CFileSize *unPackSizes = 0; + Byte *digestsDefined = 0; + UInt32 *digests = 0; + Byte *emptyStreamVector = 0; + Byte *emptyFileVector = 0; + SZ_RESULT res = SzReadHeader2(sd, db, + &unPackSizes, &digestsDefined, &digests, + &emptyStreamVector, &emptyFileVector, + allocMain, allocTemp); + allocTemp->Free(unPackSizes); + allocTemp->Free(digestsDefined); + allocTemp->Free(digests); + allocTemp->Free(emptyStreamVector); + allocTemp->Free(emptyFileVector); + return res; +} + +SZ_RESULT SzReadAndDecodePackedStreams2( + ISzInStream *inStream, + CSzData *sd, + CSzByteBuffer *outBuffer, + CFileSize baseOffset, + CArchiveDatabase *db, + CFileSize **unPackSizes, + Byte **digestsDefined, + UInt32 **digests, + #ifndef _LZMA_IN_CB + Byte **inBuffer, + #endif + ISzAlloc *allocTemp) +{ + + UInt32 numUnPackStreams = 0; + CFileSize dataStartPos; + CFolder *folder; + #ifndef _LZMA_IN_CB + CFileSize packSize = 0; + UInt32 i = 0; + #endif + CFileSize unPackSize; + size_t outRealSize; + SZ_RESULT res; + + RINOK(SzReadStreamsInfo(sd, &dataStartPos, db, + &numUnPackStreams, unPackSizes, digestsDefined, digests, + allocTemp->Alloc, allocTemp)); + + dataStartPos += baseOffset; + if (db->NumFolders != 1) + return SZE_ARCHIVE_ERROR; + + folder = db->Folders; + unPackSize = SzFolderGetUnPackSize(folder); + + RINOK(inStream->Seek(inStream, dataStartPos)); + + #ifndef _LZMA_IN_CB + for (i = 0; i < db->NumPackStreams; i++) + packSize += db->PackSizes[i]; + + MY_ALLOC(Byte, *inBuffer, (size_t)packSize, allocTemp->Alloc); + + RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize)); + #endif + + if (!SzByteBufferCreate(outBuffer, (size_t)unPackSize, allocTemp->Alloc)) + return SZE_OUTOFMEMORY; + + res = SzDecode(db->PackSizes, folder, + #ifdef _LZMA_IN_CB + inStream, + #else + *inBuffer, + #endif + outBuffer->Items, (size_t)unPackSize, + &outRealSize, allocTemp); + RINOK(res) + if (outRealSize != (UInt32)unPackSize) + return SZE_FAIL; + if (folder->UnPackCRCDefined) + if (!CrcVerifyDigest(folder->UnPackCRC, outBuffer->Items, (size_t)unPackSize)) + return SZE_FAIL; + return SZ_OK; +} + +SZ_RESULT SzReadAndDecodePackedStreams( + ISzInStream *inStream, + CSzData *sd, + CSzByteBuffer *outBuffer, + CFileSize baseOffset, + ISzAlloc *allocTemp) +{ + CArchiveDatabase db; + CFileSize *unPackSizes = 0; + Byte *digestsDefined = 0; + UInt32 *digests = 0; + #ifndef _LZMA_IN_CB + Byte *inBuffer = 0; + #endif + SZ_RESULT res; + SzArchiveDatabaseInit(&db); + res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, + &db, &unPackSizes, &digestsDefined, &digests, + #ifndef _LZMA_IN_CB + &inBuffer, + #endif + allocTemp); + SzArchiveDatabaseFree(&db, allocTemp->Free); + allocTemp->Free(unPackSizes); + allocTemp->Free(digestsDefined); + allocTemp->Free(digests); + #ifndef _LZMA_IN_CB + allocTemp->Free(inBuffer); + #endif + return res; +} + +SZ_RESULT SzArchiveOpen2( + ISzInStream *inStream, + CArchiveDatabaseEx *db, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + Byte signature[k7zSignatureSize]; + Byte version; + UInt32 crcFromArchive; + UInt64 nextHeaderOffset; + UInt64 nextHeaderSize; + UInt32 nextHeaderCRC; + UInt32 crc; + CFileSize pos = 0; + CSzByteBuffer buffer; + CSzData sd; + SZ_RESULT res; + + RINOK(SafeReadDirect(inStream, signature, k7zSignatureSize)); + + if (!TestSignatureCandidate(signature)) + return SZE_ARCHIVE_ERROR; + + /* + db.Clear(); + db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; + */ + RINOK(SafeReadDirectByte(inStream, &version)); + if (version != k7zMajorVersion) + return SZE_ARCHIVE_ERROR; + RINOK(SafeReadDirectByte(inStream, &version)); + + RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive)); + + CrcInit(&crc); + RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset)); + CrcUpdateUInt64(&crc, nextHeaderOffset); + RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize)); + CrcUpdateUInt64(&crc, nextHeaderSize); + RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC)); + CrcUpdateUInt32(&crc, nextHeaderCRC); + + pos = k7zStartHeaderSize; + db->ArchiveInfo.StartPositionAfterHeader = pos; + + if (CrcGetDigest(&crc) != crcFromArchive) + return SZE_ARCHIVE_ERROR; + + if (nextHeaderSize == 0) + return SZ_OK; + + RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset))); + + if (!SzByteBufferCreate(&buffer, (size_t)nextHeaderSize, allocTemp->Alloc)) + return SZE_OUTOFMEMORY; + + res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize); + if (res == SZ_OK) + { + if (CrcVerifyDigest(nextHeaderCRC, buffer.Items, (UInt32)nextHeaderSize)) + { + while (1) + { + UInt64 type; + sd.Data = buffer.Items; + sd.Size = buffer.Capacity; + res = SzReadID(&sd, &type); + if (res != SZ_OK) + break; + if (type == k7zIdHeader) + { + res = SzReadHeader(&sd, db, allocMain, allocTemp); + break; + } + if (type != k7zIdEncodedHeader) + { + res = SZE_ARCHIVE_ERROR; + break; + } + { + CSzByteBuffer outBuffer; + res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, + db->ArchiveInfo.StartPositionAfterHeader, + allocTemp); + if (res != SZ_OK) + { + SzByteBufferFree(&outBuffer, allocTemp->Free); + break; + } + SzByteBufferFree(&buffer, allocTemp->Free); + buffer.Items = outBuffer.Items; + buffer.Capacity = outBuffer.Capacity; + } + } + } + } + SzByteBufferFree(&buffer, allocTemp->Free); + return res; +} + +SZ_RESULT SzArchiveOpen( + ISzInStream *inStream, + CArchiveDatabaseEx *db, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + SZ_RESULT res = SzArchiveOpen2(inStream, db, allocMain, allocTemp); + if (res != SZ_OK) + SzArDbExFree(db, allocMain->Free); + return res; +} diff --git a/plugins/snes9x_gx/source/utils/sz/7zIn.h b/plugins/snes9x_gx/source/utils/sz/7zIn.h new file mode 100644 index 00000000..8ded0ecc --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zIn.h @@ -0,0 +1,55 @@ +/* 7zIn.h */ + +#ifndef __7Z_IN_H +#define __7Z_IN_H + +#include "7zHeader.h" +#include "7zItem.h" +#include "7zAlloc.h" + +typedef struct _CInArchiveInfo +{ + CFileSize StartPositionAfterHeader; + CFileSize DataStartPosition; +}CInArchiveInfo; + +typedef struct _CArchiveDatabaseEx +{ + CArchiveDatabase Database; + CInArchiveInfo ArchiveInfo; + UInt32 *FolderStartPackStreamIndex; + CFileSize *PackStreamStartPositions; + UInt32 *FolderStartFileIndex; + UInt32 *FileIndexToFolderIndexMap; +}CArchiveDatabaseEx; + +void SzArDbExInit(CArchiveDatabaseEx *db); +void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)); +CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder); +CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex); + +typedef struct _ISzInStream +{ + #ifdef _LZMA_IN_CB + SZ_RESULT (*Read)( + void *object, /* pointer to ISzInStream itself */ + void **buffer, /* out: pointer to buffer with data */ + size_t maxRequiredSize, /* max required size to read */ + size_t *processedSize); /* real processed size. + processedSize can be less than maxRequiredSize. + If processedSize == 0, then there are no more + bytes in stream. */ + #else + SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize); + #endif + SZ_RESULT (*Seek)(void *object, CFileSize pos); +} ISzInStream; + + +int SzArchiveOpen( + ISzInStream *inStream, + CArchiveDatabaseEx *db, + ISzAlloc *allocMain, + ISzAlloc *allocTemp); + +#endif diff --git a/plugins/snes9x_gx/source/utils/sz/7zItem.c b/plugins/snes9x_gx/source/utils/sz/7zItem.c new file mode 100644 index 00000000..5f9a37f6 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zItem.c @@ -0,0 +1,133 @@ +/* 7zItem.c */ + +#include "7zItem.h" +#include "7zAlloc.h" + +void SzCoderInfoInit(CCoderInfo *coder) +{ + SzByteBufferInit(&coder->Properties); +} + +void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)) +{ + SzByteBufferFree(&coder->Properties, freeFunc); + SzCoderInfoInit(coder); +} + +void SzFolderInit(CFolder *folder) +{ + folder->NumCoders = 0; + folder->Coders = 0; + folder->NumBindPairs = 0; + folder->BindPairs = 0; + folder->NumPackStreams = 0; + folder->PackStreams = 0; + folder->UnPackSizes = 0; + folder->UnPackCRCDefined = 0; + folder->UnPackCRC = 0; + folder->NumUnPackStreams = 0; +} + +void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p)) +{ + UInt32 i; + for (i = 0; i < folder->NumCoders; i++) + SzCoderInfoFree(&folder->Coders[i], freeFunc); + freeFunc(folder->Coders); + freeFunc(folder->BindPairs); + freeFunc(folder->PackStreams); + freeFunc(folder->UnPackSizes); + SzFolderInit(folder); +} + +UInt32 SzFolderGetNumOutStreams(CFolder *folder) +{ + UInt32 result = 0; + UInt32 i; + for (i = 0; i < folder->NumCoders; i++) + result += folder->Coders[i].NumOutStreams; + return result; +} + +int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex) +{ + UInt32 i; + for(i = 0; i < folder->NumBindPairs; i++) + if (folder->BindPairs[i].InIndex == inStreamIndex) + return i; + return -1; +} + + +int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex) +{ + UInt32 i; + for(i = 0; i < folder->NumBindPairs; i++) + if (folder->BindPairs[i].OutIndex == outStreamIndex) + return i; + return -1; +} + +CFileSize SzFolderGetUnPackSize(CFolder *folder) +{ + int i = (int)SzFolderGetNumOutStreams(folder); + if (i == 0) + return 0; + for (i--; i >= 0; i--) + if (SzFolderFindBindPairForOutStream(folder, i) < 0) + return folder->UnPackSizes[i]; + /* throw 1; */ + return 0; +} + +/* +int FindPackStreamArrayIndex(int inStreamIndex) const +{ + for(int i = 0; i < PackStreams.Size(); i++) + if (PackStreams[i] == inStreamIndex) + return i; + return -1; +} +*/ + +void SzFileInit(CFileItem *fileItem) +{ + fileItem->IsFileCRCDefined = 0; + fileItem->HasStream = 1; + fileItem->IsDirectory = 0; + fileItem->IsAnti = 0; + fileItem->Name = 0; +} + +void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p)) +{ + freeFunc(fileItem->Name); + SzFileInit(fileItem); +} + +void SzArchiveDatabaseInit(CArchiveDatabase *db) +{ + db->NumPackStreams = 0; + db->PackSizes = 0; + db->PackCRCsDefined = 0; + db->PackCRCs = 0; + db->NumFolders = 0; + db->Folders = 0; + db->NumFiles = 0; + db->Files = 0; +} + +void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)) +{ + UInt32 i; + for (i = 0; i < db->NumFolders; i++) + SzFolderFree(&db->Folders[i], freeFunc); + for (i = 0; i < db->NumFiles; i++) + SzFileFree(&db->Files[i], freeFunc); + freeFunc(db->PackSizes); + freeFunc(db->PackCRCsDefined); + freeFunc(db->PackCRCs); + freeFunc(db->Folders); + freeFunc(db->Files); + SzArchiveDatabaseInit(db); +} diff --git a/plugins/snes9x_gx/source/utils/sz/7zItem.h b/plugins/snes9x_gx/source/utils/sz/7zItem.h new file mode 100644 index 00000000..e59b73f0 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zItem.h @@ -0,0 +1,90 @@ +/* 7zItem.h */ + +#ifndef __7Z_ITEM_H +#define __7Z_ITEM_H + +#include "7zMethodID.h" +#include "7zHeader.h" +#include "7zBuffer.h" + +typedef struct _CCoderInfo +{ + UInt32 NumInStreams; + UInt32 NumOutStreams; + CMethodID MethodID; + CSzByteBuffer Properties; +}CCoderInfo; + +void SzCoderInfoInit(CCoderInfo *coder); +void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)); + +typedef struct _CBindPair +{ + UInt32 InIndex; + UInt32 OutIndex; +}CBindPair; + +typedef struct _CFolder +{ + UInt32 NumCoders; + CCoderInfo *Coders; + UInt32 NumBindPairs; + CBindPair *BindPairs; + UInt32 NumPackStreams; + UInt32 *PackStreams; + CFileSize *UnPackSizes; + int UnPackCRCDefined; + UInt32 UnPackCRC; + + UInt32 NumUnPackStreams; +}CFolder; + +void SzFolderInit(CFolder *folder); +CFileSize SzFolderGetUnPackSize(CFolder *folder); +int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex); +UInt32 SzFolderGetNumOutStreams(CFolder *folder); +CFileSize SzFolderGetUnPackSize(CFolder *folder); + +/* #define CArchiveFileTime UInt64 */ + +typedef struct _CFileItem +{ + /* + CArchiveFileTime LastWriteTime; + CFileSize StartPos; + UInt32 Attributes; + */ + CFileSize Size; + UInt32 FileCRC; + char *Name; + + Byte IsFileCRCDefined; + Byte HasStream; + Byte IsDirectory; + Byte IsAnti; + /* + int AreAttributesDefined; + int IsLastWriteTimeDefined; + int IsStartPosDefined; + */ +}CFileItem; + +void SzFileInit(CFileItem *fileItem); + +typedef struct _CArchiveDatabase +{ + UInt32 NumPackStreams; + CFileSize *PackSizes; + Byte *PackCRCsDefined; + UInt32 *PackCRCs; + UInt32 NumFolders; + CFolder *Folders; + UInt32 NumFiles; + CFileItem *Files; +}CArchiveDatabase; + +void SzArchiveDatabaseInit(CArchiveDatabase *db); +void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)); + + +#endif diff --git a/plugins/snes9x_gx/source/utils/sz/7zMethodID.c b/plugins/snes9x_gx/source/utils/sz/7zMethodID.c new file mode 100644 index 00000000..9daf39c2 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zMethodID.c @@ -0,0 +1,14 @@ +/* 7zMethodID.c */ + +#include "7zMethodID.h" + +int AreMethodsEqual(CMethodID *a1, CMethodID *a2) +{ + int i; + if (a1->IDSize != a2->IDSize) + return 0; + for (i = 0; i < a1->IDSize; i++) + if (a1->ID[i] != a2->ID[i]) + return 0; + return 1; +} diff --git a/plugins/snes9x_gx/source/utils/sz/7zMethodID.h b/plugins/snes9x_gx/source/utils/sz/7zMethodID.h new file mode 100644 index 00000000..4d886899 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zMethodID.h @@ -0,0 +1,18 @@ +/* 7zMethodID.h */ + +#ifndef __7Z_METHOD_ID_H +#define __7Z_METHOD_ID_H + +#include "7zTypes.h" + +#define kMethodIDSize 15 + +typedef struct _CMethodID +{ + Byte ID[kMethodIDSize]; + Byte IDSize; +} CMethodID; + +int AreMethodsEqual(CMethodID *a1, CMethodID *a2); + +#endif diff --git a/plugins/snes9x_gx/source/utils/sz/7zTypes.h b/plugins/snes9x_gx/source/utils/sz/7zTypes.h new file mode 100644 index 00000000..e6f25767 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/7zTypes.h @@ -0,0 +1,72 @@ +/* 7zTypes.h */ + +#ifndef __COMMON_TYPES_H +#define __COMMON_TYPES_H + +#ifndef _7ZIP_BYTE_DEFINED +#define _7ZIP_BYTE_DEFINED +#ifndef ZCONF_H +typedef unsigned char Byte; +#endif +#endif + +#ifndef _7ZIP_UINT16_DEFINED +#define _7ZIP_UINT16_DEFINED +typedef unsigned short UInt16; +#endif + +#ifndef _7ZIP_UINT32_DEFINED +#define _7ZIP_UINT32_DEFINED +#ifdef _LZMA_UINT32_IS_ULONG +typedef unsigned long UInt32; +#else +typedef unsigned int UInt32; +#endif +#endif + +/* #define _SZ_NO_INT_64 */ +/* define it your compiler doesn't support long long int */ + +#ifndef _7ZIP_UINT64_DEFINED +#define _7ZIP_UINT64_DEFINED +#ifdef _SZ_NO_INT_64 +typedef unsigned long UInt64; +#else +#ifdef _MSC_VER +typedef unsigned __int64 UInt64; +#else +typedef unsigned long long int UInt64; +#endif +#endif +#endif + + +/* #define _SZ_FILE_SIZE_64 */ +/* Use _SZ_FILE_SIZE_64 if you need support for files larger than 4 GB*/ + +#ifndef CFileSize +#ifdef _SZ_FILE_SIZE_64 +typedef UInt64 CFileSize; +#else +typedef UInt32 CFileSize; +#endif +#endif + +#define SZ_RESULT int + +#define SZ_OK (0) +#define SZE_DATA_ERROR (1) +#define SZE_OUTOFMEMORY (2) +#define SZE_CRC_ERROR (3) + +#define SZE_NOTIMPL (4) +#define SZE_FAIL (5) +#define SZE_FAILREAD (6) + +#define SZE_ARCHIVE_ERROR (7) + +#define SZE_OUTOFMEMORYDIC (8) + +#define RINOK(x) { int __result_ = (x); if(__result_ != 0) return __result_; } + +#endif diff --git a/plugins/snes9x_gx/source/utils/sz/LzmaDecode.c b/plugins/snes9x_gx/source/utils/sz/LzmaDecode.c new file mode 100644 index 00000000..71c62c47 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/LzmaDecode.c @@ -0,0 +1,584 @@ +/* + LzmaDecode.c + LZMA Decoder (optimized for Speed version) + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this Code, expressly permits you to + statically or dynamically link your Code (or bind by name) to the + interfaces of this file without subjecting your linked Code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#include "LzmaDecode.h" + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_READ_BYTE (*Buffer++) + +#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \ + { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }} + +#ifdef _LZMA_IN_CB + +#define RC_TEST { if (Buffer == BufferLim) \ + { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \ + BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }} + +#define RC_INIT Buffer = BufferLim = 0; RC_INIT2 + +#else + +#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; } + +#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 + +#endif + +#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } + +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; + +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ + { UpdateBit0(p); mi <<= 1; A0; } else \ + { UpdateBit1(p); mi = (mi + mi) + 1; A1; } + +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) + +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \ + { int i = numLevels; res = 1; \ + do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \ + res -= (1 << numLevels); } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size) +{ + unsigned char prop0; + if (size < LZMA_PROPERTIES_SIZE) + return LZMA_RESULT_DATA_ERROR; + prop0 = propsData[0]; + if (prop0 >= (9 * 5 * 5)) + return LZMA_RESULT_DATA_ERROR; + { + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5)); + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9); + propsRes->lc = prop0; + /* + unsigned char remainder = (unsigned char)(prop0 / 9); + propsRes->lc = prop0 % 9; + propsRes->pb = remainder / 5; + propsRes->lp = remainder % 5; + */ + } + + #ifdef _LZMA_OUT_READ + { + int i; + propsRes->DictionarySize = 0; + for (i = 0; i < 4; i++) + propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8); + if (propsRes->DictionarySize == 0) + propsRes->DictionarySize = 1; + } + #endif + return LZMA_RESULT_OK; +} + +#define kLzmaStreamWasFinishedId (-1) + +int LzmaDecode(CLzmaDecoderState *vs, + #ifdef _LZMA_IN_CB + ILzmaInCallback *InCallback, + #else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + #endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed) +{ + CProb *p = vs->Probs; + SizeT nowPos = 0; + Byte previousByte = 0; + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; + int lc = vs->Properties.lc; + + #ifdef _LZMA_OUT_READ + + UInt32 Range = vs->Range; + UInt32 Code = vs->Code; + #ifdef _LZMA_IN_CB + const Byte *Buffer = vs->Buffer; + const Byte *BufferLim = vs->BufferLim; + #else + const Byte *Buffer = inStream; + const Byte *BufferLim = inStream + inSize; + #endif + int state = vs->State; + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; + int len = vs->RemainLen; + UInt32 globalPos = vs->GlobalPos; + UInt32 distanceLimit = vs->DistanceLimit; + + Byte *dictionary = vs->Dictionary; + UInt32 dictionarySize = vs->Properties.DictionarySize; + UInt32 dictionaryPos = vs->DictionaryPos; + + Byte tempDictionary[4]; + + #ifndef _LZMA_IN_CB + *inSizeProcessed = 0; + #endif + *outSizeProcessed = 0; + if (len == kLzmaStreamWasFinishedId) + return LZMA_RESULT_OK; + + if (dictionarySize == 0) + { + dictionary = tempDictionary; + dictionarySize = 1; + tempDictionary[0] = vs->TempDictionary[0]; + } + + if (len == kLzmaNeedInitId) + { + { + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + UInt32 i; + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + rep0 = rep1 = rep2 = rep3 = 1; + state = 0; + globalPos = 0; + distanceLimit = 0; + dictionaryPos = 0; + dictionary[dictionarySize - 1] = 0; + #ifdef _LZMA_IN_CB + RC_INIT; + #else + RC_INIT(inStream, inSize); + #endif + } + len = 0; + } + while(len != 0 && nowPos < outSize) + { + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + len--; + } + if (dictionaryPos == 0) + previousByte = dictionary[dictionarySize - 1]; + else + previousByte = dictionary[dictionaryPos - 1]; + + #else /* if !_LZMA_OUT_READ */ + + int state = 0; + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; + int len = 0; + const Byte *Buffer; + const Byte *BufferLim; + UInt32 Range; + UInt32 Code; + + #ifndef _LZMA_IN_CB + *inSizeProcessed = 0; + #endif + *outSizeProcessed = 0; + + { + UInt32 i; + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + } + + #ifdef _LZMA_IN_CB + RC_INIT; + #else + RC_INIT(inStream, inSize); + #endif + + #endif /* _LZMA_OUT_READ */ + + while(nowPos < outSize) + { + CProb *prob; + UInt32 bound; + int posState = (int)( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & posStateMask); + + prob = p + IsMatch + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + int symbol = 1; + UpdateBit0(prob) + prob = p + Literal + (LZMA_LIT_SIZE * + ((( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & literalPosMask) << lc) + (previousByte >> (8 - lc)))); + + if (state >= kNumLitStates) + { + int matchByte; + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + matchByte = dictionary[pos]; + #else + matchByte = outStream[nowPos - rep0]; + #endif + do + { + int bit; + CProb *probLit; + matchByte <<= 1; + bit = (matchByte & 0x100); + probLit = prob + 0x100 + bit + symbol; + RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) + } + while (symbol < 0x100); + } + while (symbol < 0x100) + { + CProb *probLit = prob + symbol; + RC_GET_BIT(probLit, symbol) + } + previousByte = (Byte)symbol; + + outStream[nowPos++] = previousByte; + #ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #endif + if (state < 4) state = 0; + else if (state < 10) state -= 3; + else state -= 6; + } + else + { + UpdateBit1(prob); + prob = p + IsRep + state; + IfBit0(prob) + { + UpdateBit0(prob); + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + state = state < kNumLitStates ? 0 : 3; + prob = p + LenCoder; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG0 + state; + IfBit0(prob) + { + UpdateBit0(prob); + prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + #ifdef _LZMA_OUT_READ + UInt32 pos; + #endif + UpdateBit0(prob); + + #ifdef _LZMA_OUT_READ + if (distanceLimit == 0) + #else + if (nowPos == 0) + #endif + return LZMA_RESULT_DATA_ERROR; + + state = state < kNumLitStates ? 9 : 11; + #ifdef _LZMA_OUT_READ + pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + outStream[nowPos++] = previousByte; + #ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + #endif + + continue; + } + else + { + UpdateBit1(prob); + } + } + else + { + UInt32 distance; + UpdateBit1(prob); + prob = p + IsRepG1 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep1; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG2 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep2; + } + else + { + UpdateBit1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = p + RepLenCoder; + } + { + int numBits, offset; + CProb *probLen = prob + LenChoice; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + numBits = kLenNumLowBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenChoice2; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + numBits = kLenNumMidBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + numBits = kLenNumHighBits; + } + } + RangeDecoderBitTreeDecode(probLen, numBits, len); + len += offset; + } + + if (state < 4) + { + int posSlot; + state += kNumLitStates; + prob = p + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + rep0 = (2 | ((UInt32)posSlot & 1)); + if (posSlot < kEndPosModelIndex) + { + rep0 <<= numDirectBits; + prob = p + SpecPos + rep0 - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + RC_NORMALIZE + Range >>= 1; + rep0 <<= 1; + if (Code >= Range) + { + Code -= Range; + rep0 |= 1; + } + } + while (--numDirectBits != 0); + prob = p + Align; + rep0 <<= kNumAlignBits; + numDirectBits = kNumAlignBits; + } + { + int i = 1; + int mi = 1; + do + { + CProb *prob3 = prob + mi; + RC_GET_BIT2(prob3, mi, ; , rep0 |= i); + i <<= 1; + } + while(--numDirectBits != 0); + } + } + else + rep0 = posSlot; + if (++rep0 == (UInt32)(0)) + { + /* it's for stream version */ + len = kLzmaStreamWasFinishedId; + break; + } + } + + len += kMatchMinLen; + #ifdef _LZMA_OUT_READ + if (rep0 > distanceLimit) + #else + if (rep0 > nowPos) + #endif + return LZMA_RESULT_DATA_ERROR; + + #ifdef _LZMA_OUT_READ + if (dictionarySize - distanceLimit > (UInt32)len) + distanceLimit += len; + else + distanceLimit = dictionarySize; + #endif + + do + { + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + len--; + outStream[nowPos++] = previousByte; + } + while(len != 0 && nowPos < outSize); + } + } + RC_NORMALIZE; + + #ifdef _LZMA_OUT_READ + vs->Range = Range; + vs->Code = Code; + vs->DictionaryPos = dictionaryPos; + vs->GlobalPos = globalPos + (UInt32)nowPos; + vs->DistanceLimit = distanceLimit; + vs->Reps[0] = rep0; + vs->Reps[1] = rep1; + vs->Reps[2] = rep2; + vs->Reps[3] = rep3; + vs->State = state; + vs->RemainLen = len; + vs->TempDictionary[0] = tempDictionary[0]; + #endif + + #ifdef _LZMA_IN_CB + vs->Buffer = Buffer; + vs->BufferLim = BufferLim; + #else + *inSizeProcessed = (SizeT)(Buffer - inStream); + #endif + *outSizeProcessed = nowPos; + return LZMA_RESULT_OK; +} diff --git a/plugins/snes9x_gx/source/utils/sz/LzmaDecode.h b/plugins/snes9x_gx/source/utils/sz/LzmaDecode.h new file mode 100644 index 00000000..8382fa85 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/LzmaDecode.h @@ -0,0 +1,113 @@ +/* + LzmaDecode.h + LZMA Decoder interface + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this code, expressly permits you to + statically or dynamically link your code (or bind by name) to the + interfaces of this file without subjecting your linked code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#ifndef __LZMADECODE_H +#define __LZMADECODE_H + +#include "LzmaTypes.h" + +/* #define _LZMA_IN_CB */ +/* Use callback for input data */ + +/* #define _LZMA_OUT_READ */ +/* Use read function for output data */ + +/* #define _LZMA_PROB32 */ +/* It can increase speed on some 32-bit CPUs, + but memory usage will be doubled in that case */ + +/* #define _LZMA_LOC_OPT */ +/* Enable local speed optimizations inside code */ + +#ifdef _LZMA_PROB32 +#define CProb UInt32 +#else +#define CProb UInt16 +#endif + +#define LZMA_RESULT_OK 0 +#define LZMA_RESULT_DATA_ERROR 1 + +#ifdef _LZMA_IN_CB +typedef struct _ILzmaInCallback +{ + int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize); +} ILzmaInCallback; +#endif + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LZMA_PROPERTIES_SIZE 5 + +typedef struct _CLzmaProperties +{ + int lc; + int lp; + int pb; + #ifdef _LZMA_OUT_READ + UInt32 DictionarySize; + #endif +}CLzmaProperties; + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); + +#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp))) + +#define kLzmaNeedInitId (-2) + +typedef struct _CLzmaDecoderState +{ + CLzmaProperties Properties; + CProb *Probs; + + #ifdef _LZMA_IN_CB + const unsigned char *Buffer; + const unsigned char *BufferLim; + #endif + + #ifdef _LZMA_OUT_READ + unsigned char *Dictionary; + UInt32 Range; + UInt32 Code; + UInt32 DictionaryPos; + UInt32 GlobalPos; + UInt32 DistanceLimit; + UInt32 Reps[4]; + int State; + int RemainLen; + unsigned char TempDictionary[4]; + #endif +} CLzmaDecoderState; + +#ifdef _LZMA_OUT_READ +#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; } +#endif + +int LzmaDecode(CLzmaDecoderState *vs, + #ifdef _LZMA_IN_CB + ILzmaInCallback *inCallback, + #else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + #endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed); + +#endif diff --git a/plugins/snes9x_gx/source/utils/sz/LzmaTypes.h b/plugins/snes9x_gx/source/utils/sz/LzmaTypes.h new file mode 100644 index 00000000..4a1f7db4 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/sz/LzmaTypes.h @@ -0,0 +1,45 @@ +/* +LzmaTypes.h + +Types for LZMA Decoder + +This file written and distributed to public domain by Igor Pavlov. +This file is part of LZMA SDK 4.40 (2006-05-01) +*/ + +#ifndef __LZMATYPES_H +#define __LZMATYPES_H + +#ifndef _7ZIP_BYTE_DEFINED +#define _7ZIP_BYTE_DEFINED +typedef unsigned char Byte; +#endif + +#ifndef _7ZIP_UINT16_DEFINED +#define _7ZIP_UINT16_DEFINED +typedef unsigned short UInt16; +#endif + +#ifndef _7ZIP_UINT32_DEFINED +#define _7ZIP_UINT32_DEFINED +#ifdef _LZMA_UINT32_IS_ULONG +typedef unsigned long UInt32; +#else +typedef unsigned int UInt32; +#endif +#endif + +/* #define _LZMA_SYSTEM_SIZE_T */ +/* Use system's size_t. You can use it to enable 64-bit sizes supporting */ + +#ifndef _7ZIP_SIZET_DEFINED +#define _7ZIP_SIZET_DEFINED +#ifdef _LZMA_SYSTEM_SIZE_T +#include <stddef.h> +typedef size_t SizeT; +#else +typedef UInt32 SizeT; +#endif +#endif + +#endif diff --git a/plugins/snes9x_gx/source/utils/unzip/crypt.h b/plugins/snes9x_gx/source/utils/unzip/crypt.h new file mode 100644 index 00000000..f14a628b --- /dev/null +++ b/plugins/snes9x_gx/source/utils/unzip/crypt.h @@ -0,0 +1,132 @@ +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page + http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) + const char *passwd; /* password string */ + unsigned char *buf; /* where to write header */ + int bufSize; + unsigned long* pkeys; + const unsigned long* pcrc_32_tab; + unsigned long crcForCrypting; +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize<RAND_HEAD_LEN) + return 0; + + /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the + * output of rand() to get less predictability, since rand() is + * often poorly implemented. + */ + if (++calls == 1) + { + srand((unsigned)(time(NULL) ^ ZCR_SEED2)); + } + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + c = (rand() >> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif diff --git a/plugins/snes9x_gx/source/utils/unzip/ioapi.c b/plugins/snes9x_gx/source/utils/unzip/ioapi.c new file mode 100644 index 00000000..7f20c182 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/unzip/ioapi.c @@ -0,0 +1,177 @@ +/* ioapi.c -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "zlib.h" +#include "ioapi.h" + + + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +voidpf ZCALLBACK fopen_file_func OF(( + voidpf opaque, + const char* filename, + int mode)); + +uLong ZCALLBACK fread_file_func OF(( + voidpf opaque, + voidpf stream, + void* buf, + uLong size)); + +uLong ZCALLBACK fwrite_file_func OF(( + voidpf opaque, + voidpf stream, + const void* buf, + uLong size)); + +long ZCALLBACK ftell_file_func OF(( + voidpf opaque, + voidpf stream)); + +long ZCALLBACK fseek_file_func OF(( + voidpf opaque, + voidpf stream, + uLong offset, + int origin)); + +int ZCALLBACK fclose_file_func OF(( + voidpf opaque, + voidpf stream)); + +int ZCALLBACK ferror_file_func OF(( + voidpf opaque, + voidpf stream)); + + +voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) + voidpf opaque; + const char* filename; + int mode; +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen(filename, mode_fopen); + return file; +} + + +uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + void* buf; + uLong size; +{ + uLong ret; + ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + + +uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + const void* buf; + uLong size; +{ + uLong ret; + ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +long ZCALLBACK ftell_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + long ret; + ret = ftell((FILE *)stream); + return ret; +} + +long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) + voidpf opaque; + voidpf stream; + uLong offset; + int origin; +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + fseek((FILE *)stream, offset, fseek_origin); + return ret; +} + +int ZCALLBACK fclose_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + int ret; + ret = fclose((FILE *)stream); + return ret; +} + +int ZCALLBACK ferror_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + int ret; + ret = ferror((FILE *)stream); + return ret; +} + +void fill_fopen_filefunc (pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def; +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/plugins/snes9x_gx/source/utils/unzip/ioapi.h b/plugins/snes9x_gx/source/utils/unzip/ioapi.h new file mode 100644 index 00000000..e73a3b2b --- /dev/null +++ b/plugins/snes9x_gx/source/utils/unzip/ioapi.h @@ -0,0 +1,75 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#ifndef _ZLIBIOAPI_H +#define _ZLIBIOAPI_H + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + +#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) +#define ZCALLBACK CALLBACK +#else +#define ZCALLBACK +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); + +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + + + +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) +#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) +#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) +#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) +#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/plugins/snes9x_gx/source/utils/unzip/miniunz.cpp b/plugins/snes9x_gx/source/utils/unzip/miniunz.cpp new file mode 100644 index 00000000..945c970c --- /dev/null +++ b/plugins/snes9x_gx/source/utils/unzip/miniunz.cpp @@ -0,0 +1,324 @@ +/* + miniunz.c + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <utime.h> + +#include "unzip.h" +#include "menu.h" + +#define CASESENSITIVITY (0) +#define WRITEBUFFERSIZE (1024*256) +#define MAXFILENAME (256) + +// used to display unzip progress +static uLong total_size; +static uLong total_unzipped; + +static int mymkdir(const char* dirname) +{ + int ret=0; + ret = mkdir (dirname,0775); + return ret; +} + +int makedir (char *newdir) +{ + char *buffer ; + char *p; + int len = (int)strlen(newdir); + + if (len <= 0) + return 0; + + buffer = (char*)malloc(len+1); + strcpy(buffer,newdir); + + if (buffer[len-1] == '/') { + buffer[len-1] = '\0'; + } + if (mymkdir(buffer) == 0) + { + free(buffer); + return 1; + } + + p = buffer+1; + while (1) + { + char hold; + + while(*p && *p != '\\' && *p != '/') + p++; + hold = *p; + *p = 0; + if ((mymkdir(buffer) == -1) && (errno == ENOENT)) + { + //printf("couldn't create directory %s\n",buffer); + free(buffer); + return 0; + } + if (hold == 0) + break; + *p++ = hold; + } + free(buffer); + return 1; +} + +static int do_extract_currentfile(unzFile uf,const int* popt_extract_without_path,int* popt_overwrite,const char* password) +{ + char filename_inzip[256]; + char* filename_withoutpath; + char* p; + int err=UNZ_OK; + FILE *fout=NULL; + void* buf; + uInt size_buf; + + unz_file_info file_info; + err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0); + + if (err!=UNZ_OK) + { + //printf("error %d with zipfile in unzGetCurrentFileInfo\n",err); + return err; + } + + size_buf = WRITEBUFFERSIZE; + buf = (void*)malloc(size_buf); + if (buf==NULL) + { + //printf("Error allocating memory\n"); + return UNZ_INTERNALERROR; + } + + p = filename_withoutpath = filename_inzip; + while ((*p) != '\0') + { + if (((*p)=='/') || ((*p)=='\\')) + filename_withoutpath = p+1; + p++; + } + + if ((*filename_withoutpath)=='\0') + { + if ((*popt_extract_without_path)==0) + { + //printf("creating directory: %s\n",filename_inzip); + mymkdir(filename_inzip); + } + } + else + { + char* write_filename; + int skip=0; + + if ((*popt_extract_without_path)==0) + write_filename = filename_inzip; + else + write_filename = filename_withoutpath; + + err = unzOpenCurrentFilePassword(uf,password); + if (err!=UNZ_OK) + { + //printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err); + } + + if (((*popt_overwrite)==0) && (err==UNZ_OK)) + { + char rep=0; + FILE* ftestexist; + ftestexist = fopen(write_filename,"rb"); + if (ftestexist!=NULL) + { + fclose(ftestexist); + do + { + char answer[128]; + int ret; + + printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ",write_filename); + ret = scanf("%1s",answer); + if (ret != 1) + { + exit(EXIT_FAILURE); + } + rep = answer[0] ; + if ((rep>='a') && (rep<='z')) + rep -= 0x20; + } + while ((rep!='Y') && (rep!='N') && (rep!='A')); + } + + if (rep == 'N') + skip = 1; + + if (rep == 'A') + *popt_overwrite=1; + } + + if ((skip==0) && (err==UNZ_OK)) + { + fout=fopen(write_filename,"wb"); + + /* some zipfile don't contain directory alone before file */ + if ((fout==NULL) && ((*popt_extract_without_path)==0) && + (filename_withoutpath!=(char*)filename_inzip)) + { + char c=*(filename_withoutpath-1); + *(filename_withoutpath-1)='\0'; + makedir(write_filename); + *(filename_withoutpath-1)=c; + fout=fopen(write_filename,"wb"); + } + + if (fout==NULL) + { + //printf("error opening %s\n",write_filename); + } + } + + if (fout!=NULL) + { + //printf(" extracting: %s\n",write_filename); + + do + { + err = unzReadCurrentFile(uf,buf,size_buf); + if (err<0) + { + //printf("error %d with zipfile in unzReadCurrentFile\n",err); + break; + } + if (err>0) + if (fwrite(buf,err,1,fout)!=1) + { + //printf("error in writing extracted file\n"); + err=UNZ_ERRNO; + break; + } + total_unzipped += size_buf; + // show progress + ShowProgress("Unzipping...", total_unzipped, total_size); + } + while (err>0); + if (fout) + fclose(fout); + + } + + if (err==UNZ_OK) + { + err = unzCloseCurrentFile (uf); + if (err!=UNZ_OK) + { + //printf("error %d with zipfile in unzCloseCurrentFile\n",err); + } + } + else + unzCloseCurrentFile(uf); /* don't lose the error */ + } + + free(buf); + return err; +} + +static uLong zipSize(unzFile uf) +{ + uLong i; + unz_global_info gi; + int err; + + uLong total = 0; + + unz_file_info file_info; + char filename_inzip[256]; + + err = unzGetGlobalInfo (uf,&gi); + + for (i=0;i<gi.number_entry;i++) + { + err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0); + + if (err!=UNZ_OK) + return err; + + total += file_info.uncompressed_size; + + if ((i+1)<gi.number_entry) + { + err = unzGoToNextFile(uf); + if (err!=UNZ_OK) + return err; + } + } + + err = unzGoToFirstFile(uf); + if (err!=UNZ_OK) + return err; + + return total; +} + +int extractZip(unzFile uf,int opt_extract_without_path,int opt_overwrite,const char* password) +{ + uLong i; + unz_global_info gi; + int err; + + total_size = zipSize(uf); + total_unzipped = 0; + ShowProgress("Unzipping...", total_unzipped, total_size); + + err = unzGetGlobalInfo (uf,&gi); + //if (err!=UNZ_OK) + // printf("error %d with zipfile in unzGetGlobalInfo \n",err); + + for (i=0;i<gi.number_entry;i++) + { + if (do_extract_currentfile(uf,&opt_extract_without_path, + &opt_overwrite, + password) != UNZ_OK) + break; + + if ((i+1)<gi.number_entry) + { + err = unzGoToNextFile(uf); + if (err!=UNZ_OK) + { + //printf("error %d with zipfile in unzGoToNextFile\n",err); + break; + } + } + } + CancelAction(); + return 0; +} + +int extractZipOnefile(unzFile uf,const char* filename,int opt_extract_without_path,int opt_overwrite,const char* password) +{ + if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK) + { + //printf("file %s not found in the zipfile\n",filename); + return 2; + } + + if (do_extract_currentfile(uf,&opt_extract_without_path, + &opt_overwrite, + password) == UNZ_OK) + return 0; + else + return 1; +} diff --git a/plugins/snes9x_gx/source/utils/unzip/miniunz.h b/plugins/snes9x_gx/source/utils/unzip/miniunz.h new file mode 100644 index 00000000..751fd842 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/unzip/miniunz.h @@ -0,0 +1,9 @@ + +#ifndef _miniunz_H +#define _miniunz_H + +int extractZip(unzFile uf,int opt_extract_without_path,int opt_overwrite,const char* password); +int extractZipOnefile(unzFile uf,const char* filename,int opt_extract_without_path,int opt_overwrite,const char* password); +int makedir(char *newdir); + +#endif diff --git a/plugins/snes9x_gx/source/utils/unzip/unzip.c b/plugins/snes9x_gx/source/utils/unzip/unzip.c new file mode 100644 index 00000000..eda77d51 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/unzip/unzip.c @@ -0,0 +1,1598 @@ +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + Read unzip.h for more info +*/ + +/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of +compatibility with older software. The following is from the original crypt.c. Code +woven in by Terry Thorsen 1/2003. +*/ +/* + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html +*/ +/* + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + */ + +/* + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include <stddef.h> +# include <string.h> +# include <stdlib.h> +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include <errno.h> +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO +# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# define CASESENSITIVITYDEFAULT_NO +# endif +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (1024*256) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info_internal_s +{ + uLong offset_curfile;/* relative offset of local header 4 bytes */ +} unz_file_info_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + + uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + uLong offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + uLong pos_local_extrafield; /* position in the local extra field in read*/ + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + uLong rest_read_compressed; /* number of byte to be decompressed */ + uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip_read_info_s; + + +/* unz_s contain internal information about the zipfile +*/ +typedef struct +{ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + unz_global_info gi; /* public global information */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + uLong num_file; /* number of the current file in the zipfile*/ + uLong pos_in_central_dir; /* pos of the current file in the central dir*/ + uLong current_file_ok; /* flag about the usability of the current file*/ + uLong central_pos; /* position of the beginning of the central dir*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info cur_file_info; /* public info about the current file in zip*/ + unz_file_info_internal cur_file_info_internal; /* private info about it*/ + file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ + int encrypted; +# ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; +# endif +} unz_s; + + +#ifndef NOUNCRYPT +#include "crypt.h" +#endif + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ + + +local int unzlocal_getByte OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + int *pi; +{ + unsigned char c; + int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unzlocal_getShort OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i = 0; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unzlocal_getLong OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i = 0; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (fileName1,fileName2) + const char* fileName1; + const char* fileName2; +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1<c2) + return -1; + if (c1>c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) + const char* fileName1; + const char* fileName2; + int iCaseSensitivity; +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong unzlocal_SearchCentralDir OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream)); + +local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackRead<uMaxBack) + { + uLong uReadSize,uReadPos ; + int i; + if (uBackRead+BUFREADCOMMENT>uMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer + "zlib/zlib114.zip". + If the zipfile cannot be opened (file doesn't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def) + const char *path; + zlib_filefunc_def* pzlib_filefunc_def; +{ + unz_s us; + unz_s *s; + uLong central_pos,uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (pzlib_filefunc_def==NULL) + fill_fopen_filefunc(&us.z_filefunc); + else + us.z_filefunc = *pzlib_filefunc_def; + + us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, + path, + ZLIB_FILEFUNC_MODE_READ | + ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) + return NULL; + + central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream); + if (central_pos==0) + err=UNZ_ERRNO; + + if (ZSEEK(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* zipfile comment length */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((central_pos<us.offset_central_dir+us.size_central_dir) && + (err==UNZ_OK)) + err=UNZ_BADZIPFILE; + + if (err!=UNZ_OK) + { + ZCLOSE(us.z_filefunc, us.filestream); + return NULL; + } + + us.byte_before_the_zipfile = central_pos - + (us.offset_central_dir+us.size_central_dir); + us.central_pos = central_pos; + us.pfile_in_zip_read = NULL; + us.encrypted = 0; + + + s=(unz_s*)ALLOC(sizeof(unz_s)); + *s=us; + unzGoToFirstFile((unzFile)s); + return (unzFile)s; +} + + +extern unzFile ZEXPORT unzOpen (path) + const char *path; +{ + return unzOpen2(path, NULL); +} + +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzipOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzClose (file) + unzFile file; +{ + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + if (s->pfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + ZCLOSE(s->z_filefunc, s->filestream); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) + unzFile file; + unz_global_info *pglobal_info; +{ + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + + +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) + uLong ulDosDate; + tm_unz* ptm; +{ + uLong uDate; + uDate = (uLong)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info *pfile_info, + unz_file_info_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unzlocal_GetCurrentFileInfoInternal (file, + pfile_info, + pfile_info_internal, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + unz_file_info_internal *pfile_info_internal; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + unz_s* s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (ZSEEK(s->z_filefunc, s->filestream, + s->pos_in_central_dir+s->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + { + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename<fileNameBufferSize) + { + *(szFileName+file_info.size_filename)='\0'; + uSizeRead = file_info.size_filename; + } + else + uSizeRead = fileNameBufferSize; + + if ((file_info.size_filename>0) && (fileNameBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + + if ((err==UNZ_OK) && (extraField!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_extra<extraFieldBufferSize) + uSizeRead = file_info.size_file_extra; + else + uSizeRead = extraFieldBufferSize; + + if (lSeek!=0) + { + if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek += file_info.size_file_extra - uSizeRead; + } + else + lSeek+=file_info.size_file_extra; + + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_comment<commentBufferSize) + { + *(szComment+file_info.size_file_comment)='\0'; + uSizeRead = file_info.size_file_comment; + } + else + uSizeRead = commentBufferSize; + + if (lSeek!=0) + { + if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo (file, + pfile_info, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (file) + unzFile file; +{ + int err=UNZ_OK; + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (file) + unzFile file; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) + unzFile file; + const char *szFileName; + int iCaseSensitivity; +{ + unz_s* s; + int err; + + /* We remember the 'current' position in the file so that we can jump + * back there if we fail. + */ + unz_file_info cur_file_infoSaved; + unz_file_info_internal cur_file_info_internalSaved; + uLong num_fileSaved; + uLong pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + cur_file_infoSaved = s->cur_file_info; + cur_file_info_internalSaved = s->cur_file_info_internal; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + err = unzGetCurrentFileInfo(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (err == UNZ_OK) + { + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + } + + /* We failed, so restore the state of the 'current file' to where we + * were. + */ + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + s->cur_file_info = cur_file_infoSaved; + s->cur_file_info_internal = cur_file_info_internalSaved; + return err; +} + + +/* +/////////////////////////////////////////// +// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) +// I need random access +// +// Further optimization could be realized by adding an ability +// to cache the directory in memory. The goal being a single +// comprehensive file read to put the file I need in a memory. +*/ + +/* +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; // offset in file + uLong num_of_file; // # of file +} unz_file_pos; +*/ + +extern int ZEXPORT unzGetFilePos(file, file_pos) + unzFile file; + unz_file_pos* file_pos; +{ + unz_s* s; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +extern int ZEXPORT unzGoToFilePos(file, file_pos) + unzFile file; + unz_file_pos* file_pos; +{ + unz_s* s; + int err; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// +*/ + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, + poffset_local_extrafield, + psize_local_extrafield) + unz_s* s; + uInt* piSizeVar; + uLong *poffset_local_extrafield; + uInt *psize_local_extrafield; +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + { + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) + unzFile file; + int* method; + int* level; + int raw; + const char* password; +{ + int err=UNZ_OK; + uInt iSizeVar; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uLong offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ +# ifndef NOUNCRYPT + char source[12]; +# else + if (password != NULL) + return UNZ_PARAMERROR; +# endif + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, + &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip_read_info_s*) + ALLOC(sizeof(file_in_zip_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + pfile_in_zip_read_info->raw=raw; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if (method!=NULL) + *method = (int)s->cur_file_info.compression_method; + + if (level!=NULL) + { + *level = 6; + switch (s->cur_file_info.flag & 0x06) + { + case 6 : *level = 1; break; + case 4 : *level = 2; break; + case 2 : *level = 9; break; + } + } + + if ((s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->compression_method = + s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream=s->filestream; + pfile_in_zip_read_info->z_filefunc=s->z_filefunc; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method==Z_DEFLATED) && + (!raw)) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=1; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + +# ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = get_crc_table(); + init_keys(password,s->keys,s->pcrc_32_tab); + if (ZSEEK(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + + s->pfile_in_zip_read->byte_before_the_zipfile, + SEEK_SET)!=0) + return UNZ_INTERNALERROR; + if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12) + return UNZ_INTERNALERROR; + + for (i = 0; i<12; i++) + zdecode(s->keys,s->pcrc_32_tab,source[i]); + + s->pfile_in_zip_read->pos_in_zipfile+=12; + s->encrypted=1; + } +# endif + + + return UNZ_OK; +} + +extern int ZEXPORT unzOpenCurrentFile (file) + unzFile file; +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +extern int ZEXPORT unzOpenCurrentFilePassword (file, password) + unzFile file; + const char* password; +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw) + unzFile file; + int* method; + int* level; + int raw; +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (file, buf, len) + unzFile file; + voidp buf; + unsigned len; +{ + int err=UNZ_OK; + uInt iRead = 0; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->read_buffer == NULL)) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && + (!(pfile_in_zip_read_info->raw))) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressed<uReadThis) + uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer, + uReadThis)!=uReadThis) + return UNZ_ERRNO; + + +# ifndef NOUNCRYPT + if(s->encrypted) + { + uInt i; + for(i=0;i<uReadThis;i++) + pfile_in_zip_read_info->read_buffer[i] = + zdecode(s->keys,s->pcrc_32_tab, + pfile_in_zip_read_info->read_buffer[i]); + } +# endif + + + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) + { + uInt uDoCopy,i ; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (iRead==0) ? UNZ_EOF : iRead; + + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;i<uDoCopy;i++) + *(pfile_in_zip_read_info->stream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else + { + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) + err = Z_DATA_ERROR; + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) + unzFile file; + voidp buf; + unsigned len; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + buf,read_now)!=read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) + unzFile file; + char *szComment; + uLong uSizeBuf; +{ + unz_s* s; + uLong uReadThis ; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + +/* Additions by RX '2004 */ +extern uLong ZEXPORT unzGetOffset (file) + unzFile file; +{ + unz_s* s; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file==s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +extern int ZEXPORT unzSetOffset (file, pos) + unzFile file; + uLong pos; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} diff --git a/plugins/snes9x_gx/source/utils/unzip/unzip.h b/plugins/snes9x_gx/source/utils/unzip/unzip.h new file mode 100644 index 00000000..c3206a05 --- /dev/null +++ b/plugins/snes9x_gx/source/utils/unzip/unzip.h @@ -0,0 +1,354 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + + Multi volume ZipFile (span) are not supported. + Encryption compatible with pkzip 2.04g only supported + Old compressions used by old PKZip 1.x are not supported + + + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip + http://www.info-zip.org/pub/infozip/doc/ + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern unzFile ZEXPORT unzOpen2 OF((const char *path, + zlib_filefunc_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +/* ****************************************** */ + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, + const char* password)); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, + int* method, + int* level, + int raw)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, + int* method, + int* level, + int raw, + const char* password)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +extern uLong ZEXPORT unzGetOffset (unzFile file); + +/* Set the current file offset */ +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/plugins/snes9x_gx/source/video.cpp b/plugins/snes9x_gx/source/video.cpp new file mode 100644 index 00000000..74c8e002 --- /dev/null +++ b/plugins/snes9x_gx/source/video.cpp @@ -0,0 +1,1068 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * crunchy2 May 2007 + * Michniewski 2008 + * Tantric 2008-2010 + * + * video.cpp + * + * Video routines + ***************************************************************************/ + +#include <gccore.h> +#include <ogcsys.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <ogc/texconv.h> + +#include "snes9xgx.h" +#include "menu.h" +#include "filter.h" +#include "filelist.h" +#include "audio.h" +#include "gui/gui.h" +#include "input.h" + +#include "snes9x/snes9x.h" +#include "snes9x/memmap.h" + +extern void UpdatePlaybackRate(void); + +/*** Snes9x GFX Buffer ***/ +#define SNES9XGFX_SIZE (EXT_PITCH*EXT_HEIGHT) +#define FILTERMEM_SIZE (512*MAX_SNES_HEIGHT*4) + +static unsigned char * snes9xgfx = NULL; +unsigned char * filtermem = NULL; // only want ((512*2) X (239*2)) + +/*** 2D Video ***/ +static unsigned int *xfb[2] = { NULL, NULL }; // Double buffered +static int whichfb = 0; // Switch +GXRModeObj *vmode = NULL; // Current video mode +int screenheight = 480; +int screenwidth = 640; +static int oldRenderMode = -1; // set to GCSettings.render when changing (temporarily) to another mode +int CheckVideo = 0; // for forcing video reset + +/*** GX ***/ +#define TEX_WIDTH 512 +#define TEX_HEIGHT 512 +#define TEXTUREMEM_SIZE TEX_WIDTH*(TEX_HEIGHT+8)*2 +static unsigned char texturemem[TEXTUREMEM_SIZE] ATTRIBUTE_ALIGN (32); + +#define DEFAULT_FIFO_SIZE 256 * 1024 +static unsigned int copynow = GX_FALSE; +static unsigned char gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN (32); +static GXTexObj texobj; +static Mtx view; +static Mtx GXmodelView2D; +static int vwidth, vheight, oldvwidth, oldvheight; + +u8 * gameScreenPng = NULL; +int gameScreenPngSize = 0; + +u32 FrameTimer = 0; + +bool vmode_60hz = true; +int timerstyle = 0; +bool progressive = 0; + +#define HASPECT 320 +#define VASPECT 240 + +/* New texture based scaler */ +typedef struct tagcamera +{ + guVector pos; + guVector up; + guVector view; +} +camera; + +/*** Square Matrix + This structure controls the size of the image on the screen. + Think of the output as a -80 x 80 by -60 x 60 graph. +***/ +s16 square[] ATTRIBUTE_ALIGN (32) = +{ + /* + * X, Y, Z + * Values set are for roughly 4:3 aspect + */ + -HASPECT, VASPECT, 0, // 0 + HASPECT, VASPECT, 0, // 1 + HASPECT, -VASPECT, 0, // 2 + -HASPECT, -VASPECT, 0 // 3 +}; + + +static camera cam = { + {0.0F, 0.0F, 0.0F}, + {0.0F, 0.5F, 0.0F}, + {0.0F, 0.0F, -0.5F} +}; + + +/*** +*** Custom Video modes (used to emulate original console video modes) +***/ + +/** Original SNES PAL Resolutions: **/ + +/* 239 lines progressive (PAL 50Hz) */ +static GXRModeObj TV_239p = +{ + VI_TVMODE_PAL_DS, // viDisplayMode + 512, // fbWidth + 239, // efbHeight + 239, // xfbHeight + (VI_MAX_WIDTH_PAL - 640)/2, // viXOrigin + (VI_MAX_HEIGHT_PAL/2 - 478/2)/2, // viYOrigin + 640, // viWidth + 478, // viHeight + VI_XFBMODE_SF, // xFBmode + GX_FALSE, // field_rendering + GX_FALSE, // aa + + // sample points arranged in increasing Y order + { + {6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each + {6,6},{6,6},{6,6}, // pix 1 + {6,6},{6,6},{6,6}, // pix 2 + {6,6},{6,6},{6,6} // pix 3 + }, + + // vertical filter[7], 1/64 units, 6 bits each + { + 0, // line n-1 + 0, // line n-1 + 21, // line n + 22, // line n + 21, // line n + 0, // line n+1 + 0 // line n+1 + } +}; + +/* 478 lines interlaced (PAL 50Hz, Deflicker) */ +static GXRModeObj TV_478i = +{ + VI_TVMODE_PAL_INT, // viDisplayMode + 512, // fbWidth + 478, // efbHeight + 478, // xfbHeight + (VI_MAX_WIDTH_PAL - 640)/2, // viXOrigin + (VI_MAX_HEIGHT_PAL - 478)/2, // viYOrigin + 640, // viWidth + 478, // viHeight + VI_XFBMODE_DF, // xFBmode + GX_FALSE, // field_rendering + GX_FALSE, // aa + + // sample points arranged in increasing Y order + { + {6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each + {6,6},{6,6},{6,6}, // pix 1 + {6,6},{6,6},{6,6}, // pix 2 + {6,6},{6,6},{6,6} // pix 3 + }, + + // vertical filter[7], 1/64 units, 6 bits each + { + 8, // line n-1 + 8, // line n-1 + 10, // line n + 12, // line n + 10, // line n + 8, // line n+1 + 8 // line n+1 + } +}; + +/** Original SNES NTSC Resolutions: **/ + +/* 224 lines progressive (NTSC or PAL 60Hz) */ +static GXRModeObj TV_224p = +{ + VI_TVMODE_EURGB60_DS, // viDisplayMode + 512, // fbWidth + 224, // efbHeight + 224, // xfbHeight + (VI_MAX_WIDTH_NTSC - 640)/2, // viXOrigin + (VI_MAX_HEIGHT_NTSC/2 - 448/2)/2, // viYOrigin + 640, // viWidth + 448, // viHeight + VI_XFBMODE_SF, // xFBmode + GX_FALSE, // field_rendering + GX_FALSE, // aa + + // sample points arranged in increasing Y order + { + {6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each + {6,6},{6,6},{6,6}, // pix 1 + {6,6},{6,6},{6,6}, // pix 2 + {6,6},{6,6},{6,6} // pix 3 + }, + + // vertical filter[7], 1/64 units, 6 bits each + { + 0, // line n-1 + 0, // line n-1 + 21, // line n + 22, // line n + 21, // line n + 0, // line n+1 + 0 // line n+1 + } +}; + +/* 448 lines interlaced (NTSC or PAL 60Hz, Deflicker) */ +static GXRModeObj TV_448i = +{ + VI_TVMODE_EURGB60_INT, // viDisplayMode + 512, // fbWidth + 448, // efbHeight + 448, // xfbHeight + (VI_MAX_WIDTH_NTSC - 640)/2, // viXOrigin + (VI_MAX_HEIGHT_NTSC - 448)/2, // viYOrigin + 640, // viWidth + 448, // viHeight + VI_XFBMODE_DF, // xFBmode + GX_FALSE, // field_rendering + GX_FALSE, // aa + + + // sample points arranged in increasing Y order + { + {6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each + {6,6},{6,6},{6,6}, // pix 1 + {6,6},{6,6},{6,6}, // pix 2 + {6,6},{6,6},{6,6} // pix 3 + }, + + // vertical filter[7], 1/64 units, 6 bits each + { + 8, // line n-1 + 8, // line n-1 + 10, // line n + 12, // line n + 10, // line n + 8, // line n+1 + 8 // line n+1 + } +}; + +static GXRModeObj TV_Custom; + +/* TV Modes table */ +static GXRModeObj *tvmodes[4] = { + &TV_239p, &TV_478i, /* Snes PAL video modes */ + &TV_224p, &TV_448i, /* Snes NTSC video modes */ +}; + +/**************************************************************************** + * VideoThreading + ***************************************************************************/ +#define TSTACK 16384 +static lwp_t vbthread = LWP_THREAD_NULL; +static unsigned char vbstack[TSTACK]; + +/**************************************************************************** + * vbgetback + * + * This callback enables the emulator to keep running while waiting for a + * vertical blank. + * + * Putting LWP to good use :) + ***************************************************************************/ +static void * +vbgetback (void *arg) +{ + while (1) + { + VIDEO_WaitVSync (); /**< Wait for video vertical blank */ + LWP_SuspendThread (vbthread); + } + return NULL; +} + +/**************************************************************************** + * copy_to_xfb + * + * Stock code to copy the GX buffer to the current display mode. + * Also increments the frameticker, as it's called for each vb. + ***************************************************************************/ +static inline void +copy_to_xfb (u32 arg) +{ + if (copynow == GX_TRUE) + { + GX_CopyDisp (xfb[whichfb], GX_TRUE); + GX_Flush (); + copynow = GX_FALSE; + } + ++FrameTimer; +} + +/**************************************************************************** + * Scaler Support Functions + ***************************************************************************/ +static inline void +draw_init () +{ + GX_ClearVtxDesc (); + GX_SetVtxDesc (GX_VA_POS, GX_INDEX8); + GX_SetVtxDesc (GX_VA_CLR0, GX_INDEX8); + GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT); + + GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0); + GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + + GX_SetArray (GX_VA_POS, square, 3 * sizeof (s16)); + + GX_SetNumTexGens (1); + GX_SetNumChans (0); + + GX_SetTexCoordGen (GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); + + GX_SetTevOp (GX_TEVSTAGE0, GX_REPLACE); + GX_SetTevOrder (GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLORNULL); + + memset (&view, 0, sizeof (Mtx)); + guLookAt(view, &cam.pos, &cam.up, &cam.view); + GX_LoadPosMtxImm (view, GX_PNMTX0); + + GX_InvVtxCache (); // update vertex cache +} + +static inline void +draw_vert (u8 pos, u8 c, f32 s, f32 t) +{ + GX_Position1x8 (pos); + GX_Color1x8 (c); + GX_TexCoord2f32 (s, t); +} + +static inline void +draw_square (Mtx v) +{ + Mtx m; // model matrix. + Mtx mv; // modelview matrix. + + guMtxIdentity (m); + guMtxTransApply (m, m, 0, 0, -100); + guMtxConcat (v, m, mv); + + GX_LoadPosMtxImm (mv, GX_PNMTX0); + GX_Begin (GX_QUADS, GX_VTXFMT0, 4); + draw_vert (0, 0, 0.0, 0.0); + draw_vert (1, 0, 1.0, 0.0); + draw_vert (2, 0, 1.0, 1.0); + draw_vert (3, 0, 0.0, 1.0); + GX_End (); +} + +/**************************************************************************** + * StopGX + * + * Stops GX (when exiting) + ***************************************************************************/ +void StopGX() +{ + GX_AbortFrame(); + GX_Flush(); + + VIDEO_SetBlack(TRUE); + VIDEO_Flush(); +} + +/**************************************************************************** + * FindVideoMode + * + * Finds the optimal video mode, or uses the user-specified one + * Also configures original video modes + ***************************************************************************/ +static GXRModeObj * FindVideoMode() +{ + GXRModeObj * mode; + + // choose the desired video mode + switch(GCSettings.videomode) + { + case 1: // NTSC (480i) + mode = &TVNtsc480IntDf; + break; + case 2: // Progressive (480p) + mode = &TVNtsc480Prog; + break; + case 3: // PAL (50Hz) + mode = &TVPal576IntDfScale; + break; + case 4: // PAL (60Hz) + mode = &TVEurgb60Hz480IntDf; + break; + default: + mode = VIDEO_GetPreferredMode(NULL); + + #ifdef HW_DOL + /* we have component cables, but the preferred mode is interlaced + * why don't we switch into progressive? + * on the Wii, the user can do this themselves on their Wii Settings */ + if(VIDEO_HaveComponentCable()) + mode = &TVNtsc480Prog; + #endif + + break; + } + + // configure original modes + switch (mode->viTVMode >> 2) + { + case VI_PAL: + // 576 lines (PAL 50Hz) + vmode_60hz = false; + + // Original Video modes (forced to PAL 50Hz) + // set video signal mode + TV_224p.viTVMode = VI_TVMODE_PAL_DS; + TV_448i.viTVMode = VI_TVMODE_PAL_INT; + // set VI position + TV_224p.viYOrigin = (VI_MAX_HEIGHT_PAL/2 - 448/2)/2; + TV_448i.viYOrigin = (VI_MAX_HEIGHT_PAL - 448)/2; + break; + + case VI_NTSC: + // 480 lines (NTSC 60Hz) + vmode_60hz = true; + + // Original Video modes (forced to NTSC 60hz) + // set video signal mode + TV_239p.viTVMode = VI_TVMODE_NTSC_DS; + TV_478i.viTVMode = VI_TVMODE_NTSC_INT; + TV_224p.viTVMode = VI_TVMODE_NTSC_DS; + TV_448i.viTVMode = VI_TVMODE_NTSC_INT; + // set VI position + TV_239p.viYOrigin = (VI_MAX_HEIGHT_NTSC/2 - 478/2)/2; + TV_478i.viYOrigin = (VI_MAX_HEIGHT_NTSC - 478)/2; + TV_224p.viYOrigin = (VI_MAX_HEIGHT_NTSC/2 - 448/2)/2; + TV_448i.viYOrigin = (VI_MAX_HEIGHT_NTSC - 448)/2; + break; + + default: + // 480 lines (PAL 60Hz) + vmode_60hz = true; + + // Original Video modes (forced to PAL 60hz) + // set video signal mode + TV_239p.viTVMode = VI_TVMODE(mode->viTVMode >> 2, VI_NON_INTERLACE); + TV_478i.viTVMode = VI_TVMODE(mode->viTVMode >> 2, VI_INTERLACE); + TV_224p.viTVMode = VI_TVMODE(mode->viTVMode >> 2, VI_NON_INTERLACE); + TV_448i.viTVMode = VI_TVMODE(mode->viTVMode >> 2, VI_INTERLACE); + // set VI position + TV_239p.viYOrigin = (VI_MAX_HEIGHT_NTSC/2 - 478/2)/2; + TV_478i.viYOrigin = (VI_MAX_HEIGHT_NTSC - 478)/2; + TV_224p.viYOrigin = (VI_MAX_HEIGHT_NTSC/2 - 448/2)/2; + TV_448i.viYOrigin = (VI_MAX_HEIGHT_NTSC - 448)/2; + break; + } + + // check for progressive scan + if (mode->viTVMode == VI_TVMODE_NTSC_PROG) + progressive = true; + else + progressive = false; + + #ifdef HW_RVL + if (CONF_GetAspectRatio() == CONF_ASPECT_16_9) + mode->viWidth = 678; + else + mode->viWidth = 672; + + if (vmode_60hz) + { + mode->viXOrigin = (VI_MAX_WIDTH_NTSC - mode->viWidth) / 2; + mode->viYOrigin = (VI_MAX_HEIGHT_NTSC - mode->viHeight) / 2; + } + else + { + mode->viXOrigin = (VI_MAX_WIDTH_PAL - mode->viWidth) / 2; + mode->viYOrigin = (VI_MAX_HEIGHT_PAL - mode->viHeight) / 2; + } + #endif + return mode; +} + +/**************************************************************************** + * SetupVideoMode + * + * Sets up the given video mode + ***************************************************************************/ +static void SetupVideoMode(GXRModeObj * mode) +{ + if(vmode == mode) + return; + + VIDEO_SetPostRetraceCallback (NULL); + copynow = GX_FALSE; + VIDEO_Configure (mode); + VIDEO_Flush(); + + // Clear framebuffers etc. + VIDEO_ClearFrameBuffer (mode, xfb[0], COLOR_BLACK); + VIDEO_ClearFrameBuffer (mode, xfb[1], COLOR_BLACK); + VIDEO_SetNextFramebuffer (xfb[0]); + + VIDEO_SetBlack (FALSE); + VIDEO_Flush (); + VIDEO_WaitVSync (); + + if (mode->viTVMode & VI_NON_INTERLACE) + VIDEO_WaitVSync(); + else + while (VIDEO_GetNextField()) + VIDEO_WaitVSync(); + + VIDEO_SetPostRetraceCallback ((VIRetraceCallback)copy_to_xfb); + vmode = mode; +} + +/**************************************************************************** + * InitGCVideo + * + * This function MUST be called at startup. + * - also sets up menu video mode + ***************************************************************************/ + +void +InitGCVideo () +{ + VIDEO_Init(); + + // Allocate the video buffers + xfb[0] = (u32 *) memalign(32, 640*576*2); + xfb[1] = (u32 *) memalign(32, 640*576*2); + DCInvalidateRange(xfb[0], 640*576*2); + DCInvalidateRange(xfb[1], 640*576*2); + xfb[0] = (u32 *) MEM_K0_TO_K1 (xfb[0]); + xfb[1] = (u32 *) MEM_K0_TO_K1 (xfb[1]); + + GXRModeObj *rmode = FindVideoMode(); + SetupVideoMode(rmode); +#ifdef HW_RVL + InitLUTs(); // init LUTs for hq2x +#endif + LWP_CreateThread (&vbthread, vbgetback, NULL, vbstack, TSTACK, 68); + + // Initialize GX + GXColor background = { 0, 0, 0, 0xff }; + memset (&gp_fifo, 0, DEFAULT_FIFO_SIZE); + GX_Init (&gp_fifo, DEFAULT_FIFO_SIZE); + GX_SetCopyClear (background, 0x00ffffff); + GX_SetDispCopyGamma (GX_GM_1_0); + GX_SetCullMode (GX_CULL_NONE); + + vwidth = 100; + vheight = 100; +} + +void ResetFbWidth(int width, GXRModeObj *rmode) +{ + if(rmode->fbWidth == width) + return; + + rmode->fbWidth = width; + + if(rmode != vmode) + return; + + GX_InvVtxCache(); + VIDEO_Configure(rmode); + VIDEO_Flush(); +} + +/**************************************************************************** + * ResetVideo_Emu + * + * Reset the video/rendering mode for the emulator rendering +****************************************************************************/ +void +ResetVideo_Emu () +{ + GXRModeObj *rmode; + Mtx44 p; + int i = -1; + + // original render mode or hq2x + if (GCSettings.render == 0) + { + for (int j=0; j<4; j++) + { + if (tvmodes[j]->efbHeight == vheight) + { + i = j; + break; + } + } + } + + if(i >= 0) // we found a matching original mode + { + rmode = tvmodes[i]; + + // hack to fix video output for hq2x (only when actually filtering; h<=239, w<=256) + if (GCSettings.FilterMethod != FILTER_NONE && vheight <= 239 && vwidth <= 256) + { + memcpy(&TV_Custom, tvmodes[i], sizeof(TV_Custom)); + rmode = &TV_Custom; + + rmode->fbWidth = 512; + rmode->efbHeight *= 2; + rmode->xfbHeight *= 2; + rmode->xfbMode = VI_XFBMODE_DF; + rmode->viTVMode |= VI_INTERLACE; + } + Settings.SoundInputRate = 31894; + UpdatePlaybackRate(); + } + else + { + rmode = FindVideoMode(); + + if (GCSettings.widescreen) + ResetFbWidth(640, rmode); + else + ResetFbWidth(512, rmode); + + Settings.SoundInputRate = 31953; + UpdatePlaybackRate(); + } + + SetupVideoMode(rmode); // reconfigure VI + + GXColor background = {0, 0, 0, 255}; + GX_SetCopyClear (background, 0x00ffffff); + + GX_SetViewport (0, 0, rmode->fbWidth, rmode->efbHeight, 0, 1); + GX_SetDispCopyYScale ((f32) rmode->xfbHeight / (f32) rmode->efbHeight); + GX_SetScissor (0, 0, rmode->fbWidth, rmode->efbHeight); + + GX_SetDispCopySrc (0, 0, rmode->fbWidth, rmode->efbHeight); + GX_SetDispCopyDst (rmode->fbWidth, rmode->xfbHeight); + GX_SetCopyFilter(rmode->aa, rmode->sample_pattern, (rmode->xfbMode == VI_XFBMODE_SF) ? GX_FALSE : GX_TRUE, rmode->vfilter); + + GX_SetFieldMode (rmode->field_rendering, ((rmode->viHeight == 2 * rmode->xfbHeight) ? GX_ENABLE : GX_DISABLE)); + + if (rmode->aa) + GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR); + else + GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + + GX_SetZMode (GX_TRUE, GX_LEQUAL, GX_TRUE); + GX_SetColorUpdate (GX_TRUE); + + guOrtho(p, rmode->efbHeight/2, -(rmode->efbHeight/2), -(rmode->fbWidth/2), rmode->fbWidth/2, 100, 1000); // matrix, t, b, l, r, n, f + GX_LoadProjectionMtx (p, GX_ORTHOGRAPHIC); + + draw_init (); +} + +/**************************************************************************** + * MakeTexture + * + * Modified for a buffer with an offset (border) + ***************************************************************************/ +void +MakeTexture (const void *src, void *dst, s32 width, s32 height) +{ + register u32 tmp0=0,tmp1=0,tmp2=0,tmp3=0; + + __asm__ __volatile__ ( + " srwi %6,%6,2\n" + " srwi %7,%7,2\n" + " subi %3,%4,4\n" + " mr %4,%3\n" + " subi %4,%4,4\n" + + "2: mtctr %6\n" + " mr %0,%5\n" + // + "1: lwz %1,0(%5)\n" //1 + " stwu %1,8(%4)\n" + " lwz %2,4(%5)\n" //1 + " stwu %2,8(%3)\n" + " lwz %1,1032(%5)\n" //2 + " stwu %1,8(%4)\n" + " lwz %2,1036(%5)\n" //2 + " stwu %2,8(%3)\n" + " lwz %1,2064(%5)\n" //3 + " stwu %1,8(%4)\n" + " lwz %2,2068(%5)\n" //3 + " stwu %2,8(%3)\n" + " lwz %1,3096(%5)\n" //4 + " stwu %1,8(%4)\n" + " lwz %2,3100(%5)\n" //4 + " stwu %2,8(%3)\n" + " addi %5,%5,8\n" + " bdnz 1b\n" + " addi %5,%0,4128\n" //5 + " subic. %7,%7,1\n" + " bne 2b" + // 0 1 2 3 4 5 6 7 + : "=&b"(tmp0), "=&b"(tmp1), "=&b"(tmp2), "=&b"(tmp3), "+b"(dst) : "b"(src), "b"(width), "b"(height) + ); +} + +/**************************************************************************** + * Update Video + ***************************************************************************/ +uint32 prevRenderedFrameCount = 0; +int fscale = 1; + +void +update_video (int width, int height) +{ + vwidth = width; + vheight = height; + + if(CheckVideo == 2 && IPPU.RenderedFramesCount == prevRenderedFrameCount) + return; // we haven't rendered any frames yet, so we can't draw anything! + + // Ensure previous vb has complete + while ((LWP_ThreadIsSuspended (vbthread) == 0) || (copynow == GX_TRUE)) + usleep (50); + + whichfb ^= 1; + + if (oldvheight != vheight || oldvwidth != vwidth) // if rendered width/height changes, update scaling + CheckVideo = 1; + + if (CheckVideo) // if we get back from the menu, and have rendered at least 1 frame + { + int xscale, yscale; +#ifdef HW_RVL + if(vwidth <= 256) + fscale = GetFilterScale((RenderFilter)GCSettings.FilterMethod); + else + fscale = 1; +#endif + ResetVideo_Emu (); // reset video to emulator rendering settings + + /** Update scaling **/ + if (GCSettings.render == 0) // original render mode + { + if (GCSettings.FilterMethod != FILTER_NONE && vheight <= 239 && vwidth <= 256) + { // filters; normal operation + xscale = vwidth; + yscale = vheight; + } + else + { // no filtering + fscale = 1; + xscale = 256; + yscale = vheight / 2; + } + } + else // unfiltered and filtered mode + { + xscale = 256; + + if(vheight == 224 || vheight == 448) + yscale = 224; + else + yscale = 239; + } + + if (GCSettings.widescreen) + { + if(GCSettings.render == 0) + xscale = (3*xscale)/4; + else + xscale = 256; // match the original console's width for "widescreen" to prevent flickering + } + + xscale *= GCSettings.zoomHor; + yscale *= GCSettings.zoomVert; + + square[6] = square[3] = xscale + GCSettings.xshift; + square[0] = square[9] = -xscale + GCSettings.xshift; + square[4] = square[1] = yscale - GCSettings.yshift; + square[7] = square[10] = -yscale - GCSettings.yshift; + DCFlushRange (square, 32); // update memory BEFORE the GPU accesses it! + draw_init (); + + // initialize the texture obj we are going to use + GX_InitTexObj (&texobj, texturemem, vwidth*fscale, vheight*fscale, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE); + + if (GCSettings.render == 0 || GCSettings.render == 2) + GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,2.5,9.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1); // original/unfiltered video mode: force texture filtering OFF + + GX_LoadTexObj (&texobj, GX_TEXMAP0); // load texture object so its ready to use + + oldvwidth = vwidth; + oldvheight = vheight; + CheckVideo = 0; + } +#ifdef HW_RVL + // convert image to texture + if (GCSettings.FilterMethod != FILTER_NONE && vheight <= 239 && vwidth <= 256) // don't do filtering on game textures > 256 x 239 + { + FilterMethod ((uint8*) GFX.Screen, EXT_PITCH, (uint8*) filtermem, vwidth*fscale*2, vwidth, vheight); + MakeTexture565((char *) filtermem, (char *) texturemem, vwidth*fscale, vheight*fscale); + } + else +#endif + { + MakeTexture((char *) GFX.Screen, (char *) texturemem, vwidth, vheight); + } + + DCFlushRange (texturemem, TEXTUREMEM_SIZE); // update the texture memory + GX_InvalidateTexAll (); + + draw_square (view); // draw the quad + + GX_DrawDone (); + + if(ScreenshotRequested) + { + if(GCSettings.render == 0) // we can't take a screenshot in Original mode + { + oldRenderMode = 0; + GCSettings.render = 2; // switch to unfiltered mode + CheckVideo = 1; // request the switch + } + else + { + ScreenshotRequested = 0; + TakeScreenshot(); + if(oldRenderMode != -1) + { + GCSettings.render = oldRenderMode; + oldRenderMode = -1; + } + ConfigRequested = 1; + } + } + + VIDEO_SetNextFramebuffer (xfb[whichfb]); + VIDEO_Flush (); + copynow = GX_TRUE; + + // Return to caller, don't waste time waiting for vb + LWP_ResumeThread (vbthread); +} + +void AllocGfxMem() +{ + snes9xgfx = (unsigned char *)memalign(32, SNES9XGFX_SIZE); + memset(snes9xgfx, 0, SNES9XGFX_SIZE); + +#ifdef HW_RVL + filtermem = (unsigned char *)memalign(32, FILTERMEM_SIZE); + memset(filtermem, 0, FILTERMEM_SIZE); +#endif + + GFX.Pitch = EXT_PITCH; + GFX.Screen = (uint16*)(snes9xgfx + EXT_OFFSET); +} + +/**************************************************************************** + * setGFX + * + * Setup the global GFX information for Snes9x + ***************************************************************************/ +void +setGFX () +{ + GFX.Pitch = EXT_PITCH; +} + +/**************************************************************************** + * TakeScreenshot + * + * Copies the current screen into a GX texture + ***************************************************************************/ +void TakeScreenshot() +{ + IMGCTX pngContext = PNGU_SelectImageFromBuffer(savebuffer); + + if (pngContext != NULL) + { + gameScreenPngSize = PNGU_EncodeFromEFB(pngContext, vmode->fbWidth, vmode->efbHeight); + PNGU_ReleaseImageContext(pngContext); + gameScreenPng = (u8 *)malloc(gameScreenPngSize); + memcpy(gameScreenPng, savebuffer, gameScreenPngSize); + } +} + +/**************************************************************************** + * ResetVideo_Menu + * + * Reset the video/rendering mode for the menu +****************************************************************************/ +void +ResetVideo_Menu () +{ + Mtx44 p; + f32 yscale; + u32 xfbHeight; + GXRModeObj * rmode = FindVideoMode(); + + SetupVideoMode(rmode); // reconfigure VI + + // clears the bg to color and clears the z buffer + GXColor background = {0, 0, 0, 255}; + GX_SetCopyClear (background, 0x00ffffff); + + yscale = GX_GetYScaleFactor(vmode->efbHeight,vmode->xfbHeight); + xfbHeight = GX_SetDispCopyYScale(yscale); + GX_SetScissor(0,0,vmode->fbWidth,vmode->efbHeight); + GX_SetDispCopySrc(0,0,vmode->fbWidth,vmode->efbHeight); + GX_SetDispCopyDst(vmode->fbWidth,xfbHeight); + GX_SetCopyFilter(vmode->aa,vmode->sample_pattern,GX_TRUE,vmode->vfilter); + GX_SetFieldMode(vmode->field_rendering,((vmode->viHeight==2*vmode->xfbHeight)?GX_ENABLE:GX_DISABLE)); + + if (vmode->aa) + GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR); + else + GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + + // setup the vertex descriptor + // tells the flipper to expect direct data + GX_ClearVtxDesc(); + GX_InvVtxCache (); + GX_InvalidateTexAll(); + + GX_SetVtxDesc(GX_VA_TEX0, GX_NONE); + GX_SetVtxDesc(GX_VA_POS, GX_DIRECT); + GX_SetVtxDesc (GX_VA_CLR0, GX_DIRECT); + + GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GX_SetZMode (GX_FALSE, GX_LEQUAL, GX_TRUE); + + GX_SetNumChans(1); + GX_SetNumTexGens(1); + GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR); + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); + + guMtxIdentity(GXmodelView2D); + guMtxTransApply (GXmodelView2D, GXmodelView2D, 0.0F, 0.0F, -50.0F); + GX_LoadPosMtxImm(GXmodelView2D,GX_PNMTX0); + + guOrtho(p,0,479,0,639,0,300); + GX_LoadProjectionMtx(p, GX_ORTHOGRAPHIC); + + GX_SetViewport(0,0,vmode->fbWidth,vmode->efbHeight,0,1); + GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); + GX_SetAlphaUpdate(GX_TRUE); +} + +/**************************************************************************** + * Menu_Render + * + * Renders everything current sent to GX, and flushes video + ***************************************************************************/ +void Menu_Render() +{ + whichfb ^= 1; // flip framebuffer + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GX_SetColorUpdate(GX_TRUE); + GX_CopyDisp(xfb[whichfb],GX_TRUE); + GX_DrawDone(); + VIDEO_SetNextFramebuffer(xfb[whichfb]); + VIDEO_Flush(); + VIDEO_WaitVSync(); +} + +/**************************************************************************** + * Menu_DrawImg + * + * Draws the specified image on screen using GX + ***************************************************************************/ +void Menu_DrawImg(f32 xpos, f32 ypos, u16 width, u16 height, u8 data[], + f32 degrees, f32 scaleX, f32 scaleY, u8 alpha) +{ + if(data == NULL) + return; + + GXTexObj texObj; + + GX_InitTexObj(&texObj, data, width,height, GX_TF_RGBA8,GX_CLAMP, GX_CLAMP,GX_FALSE); + GX_LoadTexObj(&texObj, GX_TEXMAP0); + GX_InvalidateTexAll(); + + GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE); + GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT); + + Mtx m,m1,m2, mv; + width >>= 1; + height >>= 1; + + guMtxIdentity (m1); + guMtxScaleApply(m1,m1,scaleX,scaleY,1.0); + guVector axis = (guVector) {0 , 0, 1 }; + guMtxRotAxisDeg (m2, &axis, degrees); + guMtxConcat(m2,m1,m); + + guMtxTransApply(m,m, xpos+width,ypos+height,0); + guMtxConcat (GXmodelView2D, m, mv); + GX_LoadPosMtxImm (mv, GX_PNMTX0); + + GX_Begin(GX_QUADS, GX_VTXFMT0,4); + GX_Position3f32(-width, -height, 0); + GX_Color4u8(0xFF,0xFF,0xFF,alpha); + GX_TexCoord2f32(0, 0); + + GX_Position3f32(width, -height, 0); + GX_Color4u8(0xFF,0xFF,0xFF,alpha); + GX_TexCoord2f32(1, 0); + + GX_Position3f32(width, height, 0); + GX_Color4u8(0xFF,0xFF,0xFF,alpha); + GX_TexCoord2f32(1, 1); + + GX_Position3f32(-width, height, 0); + GX_Color4u8(0xFF,0xFF,0xFF,alpha); + GX_TexCoord2f32(0, 1); + GX_End(); + GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0); + + GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR); + GX_SetVtxDesc (GX_VA_TEX0, GX_NONE); +} + +/**************************************************************************** + * Menu_DrawRectangle + * + * Draws a rectangle at the specified coordinates using GX + ***************************************************************************/ +void Menu_DrawRectangle(f32 x, f32 y, f32 width, f32 height, GXColor color, u8 filled) +{ + long n = 4; + f32 x2 = x+width; + f32 y2 = y+height; + guVector v[] = {{x,y,0.0f}, {x2,y,0.0f}, {x2,y2,0.0f}, {x,y2,0.0f}, {x,y,0.0f}}; + u8 fmt = GX_TRIANGLEFAN; + + if(!filled) + { + fmt = GX_LINESTRIP; + n = 5; + } + + GX_Begin(fmt, GX_VTXFMT0, n); + for(long i=0; i<n; ++i) + { + GX_Position3f32(v[i].x, v[i].y, v[i].z); + GX_Color4u8(color.r, color.g, color.b, color.a); + } + GX_End(); +} + diff --git a/plugins/snes9x_gx/source/video.h b/plugins/snes9x_gx/source/video.h new file mode 100644 index 00000000..83a46a13 --- /dev/null +++ b/plugins/snes9x_gx/source/video.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * Snes9x Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * Michniewski 2008 + * Tantric 2008-2010 + * + * video.h + * + * Video routines + ***************************************************************************/ + +#ifndef _GCVIDEOH_ +#define _GCVIDEOH_ + +#include <ogcsys.h> + +#include "snes9x/snes9x.h" + +void AllocGfxMem(); +void InitGCVideo (); +void StopGX(); +void ResetVideo_Emu(); +void setGFX(); +void update_video (int width, int height); +void ResetVideo_Menu(); +void TakeScreenshot(); +void Menu_Render(); +void Menu_DrawImg(f32 xpos, f32 ypos, u16 width, u16 height, u8 data[], f32 degrees, f32 scaleX, f32 scaleY, u8 alphaF ); +void Menu_DrawRectangle(f32 x, f32 y, f32 width, f32 height, GXColor color, u8 filled); + +extern GXRModeObj *vmode; +extern int screenheight; +extern int screenwidth; +extern bool progressive; +extern u8 * gameScreenPng; +extern int gameScreenPngSize; +extern u32 FrameTimer; +extern bool vmode_60hz; +extern int timerstyle; +extern int CheckVideo; + +#endif diff --git a/plugins/snes9x_gx/source/xenon/README b/plugins/snes9x_gx/source/xenon/README new file mode 100644 index 00000000..93e08e73 --- /dev/null +++ b/plugins/snes9x_gx/source/xenon/README @@ -0,0 +1,7 @@ +This is a very early port to the xbox 360 using the libxenon library, +available from http://www.free60.org/wiki/Libxenon + +It doesn't yet have sound, a graphical menu, but will load the file +"SNES9XGX.SMC" from the first available USB storage device, and run that. + +Controls are using the first wired controller. diff --git a/plugins/snes9x_gx/source/xenon/ffs_content.c b/plugins/snes9x_gx/source/xenon/ffs_content.c new file mode 100644 index 00000000..47b0f006 --- /dev/null +++ b/plugins/snes9x_gx/source/xenon/ffs_content.c @@ -0,0 +1,45 @@ +static unsigned char content_datapspsu[] = { +0x10, 0x2a, 0x11, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x4b, +0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x30, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00, 0xab, 0xab, 0x00, 0x04, 0x00, 0x0c, +0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, +0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0xab, 0xab, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x21, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0xf0, 0x50, 0x00, 0x01, 0x10, 0x02, 0x00, 0x00, 0x12, 0x00, 0xc4, 0x00, 0x00, 0x00, +0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, +0x1f, 0x1f, 0xf6, 0x88, 0x00, 0x00, 0x40, 0x00, 0xc8, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, +0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static unsigned char content_datavsvsu[] = { +0x10, 0x2a, 0x11, 0x01, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x23, +0xff, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, +0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, +0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x21, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x90, +0x00, 0x10, 0x00, 0x03, 0x00, 0x30, 0x50, 0x04, 0x00, 0x00, 0xf0, 0x50, 0x00, 0x00, 0x10, 0x06, +0x30, 0x05, 0x20, 0x03, 0x00, 0x00, 0x12, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x05, +0x00, 0x00, 0x12, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x06, 0x00, 0x00, 0x22, 0x00, +0x00, 0x00, 0x00, 0x00, 0x05, 0xf8, 0x10, 0x00, 0x00, 0x00, 0x06, 0x88, 0x00, 0x00, 0x00, 0x00, +0x05, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x06, 0x88, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x0f, 0x80, 0x3e, +0x00, 0x00, 0x00, 0x00, 0xe2, 0x01, 0x01, 0x00, 0xc8, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, +0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + + +struct ffs_s +{ + const char *filename; + int size; + void *content; +} ffs_files[] = { + {"ps.psu", 224, content_datapspsu}, + {"vs.vsu", 240, content_datavsvsu}, + {0, 0, 0}, +}; diff --git a/plugins/snes9x_gx/source/xenon/filebrowser.h b/plugins/snes9x_gx/source/xenon/filebrowser.h new file mode 100644 index 00000000..e69de29b diff --git a/plugins/snes9x_gx/source/xenon/fileop.h b/plugins/snes9x_gx/source/xenon/fileop.h new file mode 100644 index 00000000..e69de29b diff --git a/plugins/snes9x_gx/source/xenon/freeze.cpp b/plugins/snes9x_gx/source/xenon/freeze.cpp new file mode 100644 index 00000000..15d86006 --- /dev/null +++ b/plugins/snes9x_gx/source/xenon/freeze.cpp @@ -0,0 +1,70 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "snes9x.h" +#include "memmap.h" +#include "soundux.h" +#include "snapshot.h" +#include "srtc.h" + +int +GetMem (char *buffer, int len) +{ + printf("%s:%d\n", __FILE__, __LINE__); while (1); +} + +void +NGCFreezeBlock (char *name, uint8 * block, int size) +{ + printf("%s:%d\n", __FILE__, __LINE__); while (1); +} + +/**************************************************************************** + * NGCFreezeMembuffer + * + * Copies a snapshot of Snes9x state into memory + ***************************************************************************/ +static int +NGCFreezeMemBuffer () +{ + printf("%s:%d\n", __FILE__, __LINE__); while (1); + + return 0; +} + + +/**************************************************************************** + * NGCFreezeGame + * + * Do freeze game for Nintendo Gamecube + ***************************************************************************/ +int +NGCFreezeGame (char * filepath, int method, bool silent) +{ + printf("%s:%d\n", __FILE__, __LINE__); while (1); +} + +int +NGCFreezeGameAuto (int method, bool silent) +{ + printf("%s:%d\n", __FILE__, __LINE__); while (1); +} + +/**************************************************************************** + * NGCUnFreezeBlock + ***************************************************************************/ +int +NGCUnFreezeBlock (char *name, uint8 * block, int size) +{ + printf("%s:%d\n", __FILE__, __LINE__); while (1); +} + +/**************************************************************************** + * NGCUnfreezeGame + ***************************************************************************/ +int +NGCUnfreezeGame (char * filepath, int method, bool silent) +{ + printf("%s:%d\n", __FILE__, __LINE__); while (1); +} diff --git a/plugins/snes9x_gx/source/xenon/freeze.h b/plugins/snes9x_gx/source/xenon/freeze.h new file mode 100644 index 00000000..e69de29b diff --git a/plugins/snes9x_gx/source/xenon/gccore.h b/plugins/snes9x_gx/source/xenon/gccore.h new file mode 100644 index 00000000..e69de29b diff --git a/plugins/snes9x_gx/source/xenon/main.cpp b/plugins/snes9x_gx/source/xenon/main.cpp new file mode 100644 index 00000000..065d732e --- /dev/null +++ b/plugins/snes9x_gx/source/xenon/main.cpp @@ -0,0 +1,382 @@ +#include <stdio.h> +#include <malloc.h> + +#include "s9xconfig.h" + +#include "snes9x.h" +#include "memmap.h" +#include "s9xdebug.h" +#include "cpuexec.h" +#include "ppu.h" +#include "apu.h" +#include "display.h" +#include "gfx.h" +#include "soundux.h" +#include "spc700.h" +#include "spc7110.h" +#include "controls.h" + +#include <console/console.h> +#include <diskio/diskio.h> +#include <xenos/xenos.h> +#include <xenon_sound/sound.h> +#include <xenon_soc/xenon_power.h> + +//#include "smc.h" + +#include "video.h" + +extern unsigned long SNESROMSize; + +extern void S9xInitSync(); + +void ExitApp(void) +{ + printf(" *** ExitApp\n"); + while (1); +} + +int ResetRequested = 1, ConfigRequested; + +extern "C" { + void usb_do_poll(void); + void kmem_init(void); + void usb_init(void); + +#include <input/input.h> +}; + +#include <stdint.h> +#include <unistd.h> +#include <fcntl.h> + +static inline uint32_t bswap_32(uint32_t t) +{ + return ((t & 0xFF) << 24) | ((t & 0xFF00) << 8) | ((t & 0xFF0000) >> 8) | ((t & 0xFF000000) >> 24); +} + +void +emulate () +{ + while(1) // emulation loop + { + int ctrl; + for (ctrl = 0; ctrl < 4; ++ctrl) + { + struct controller_data_s c; + if (get_controller_data(&c, ctrl)) + { + // printf("got controller data!\n"); + int offset = 0x10 + ctrl * 0x10; + // printf("a=%d, b=%d, x=%d, y=%d, lb=%d, rb=%d, start=%d, select=%d, up=%d, down=%d, left=%d, right=%d\n", + // c.a, c.b, c.x, c.y, c.lb, c.rb, c.start, c.select, c.up, c.down, c.left, c.right); + + S9xReportButton (offset + 0, c.b); + S9xReportButton (offset + 1, c.a); + S9xReportButton (offset + 2, c.x); + S9xReportButton (offset + 3, c.y); + + S9xReportButton (offset + 4, c.lb); + S9xReportButton (offset + 5, c.rb); + + S9xReportButton (offset + 6, c.start); + S9xReportButton (offset + 7, c.select); + + S9xReportButton (offset + 8, c.up); + S9xReportButton (offset + 9, c.down); + S9xReportButton (offset + 10, c.left); + S9xReportButton (offset + 11, c.right); + } + } + S9xMainLoop (); + + usb_do_poll(); + + if(ResetRequested) + { + S9xSoftReset (); // reset game + ResetRequested = 0; + } + if (ConfigRequested) + { + ConfigRequested = 0; + break; + } + + + /* this all isn't that great... */ + int sample_rate = 48000 * 2; + int samples_per_frame = Settings.PAL ? sample_rate / 50 : sample_rate / 60; + + int samples_guard = 16384; + + if (xenon_sound_get_unplayed() < samples_guard) + { + so.samples_mixed_so_far = so.play_position = 0; + + unsigned char buffer[2048]; + +#if 0 + int req_samples = xenon_sound_get_unplayed(); + if ((req_samples + samples_per_frame) < samples_guard) + req_samples = samples_guard + samples_per_frame; + else + req_samples = samples_per_frame; +#endif + int req_samples = samples_per_frame; + + S9xMixSamples(buffer, req_samples); + + int i; + for (i = 0; i < req_samples * 2; i += 4) + *(int*)(buffer + i) = bswap_32(*(int*)(buffer + i)); + xenon_sound_submit(buffer, req_samples * 2); + + } + + + } // main loop +} + +#define ASSIGN_BUTTON_TRUE( keycode, snescmd ) \ + S9xMapButton( keycode, cmd = S9xGetCommandT(snescmd), true) + +#define ASSIGN_BUTTON_FALSE( keycode, snescmd ) \ + S9xMapButton( keycode, cmd = S9xGetCommandT(snescmd), false) + +void SetDefaultButtonMap () +{ + int maxcode = 0x10; + s9xcommand_t cmd; + + /*** Joypad 1 ***/ + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 A"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 B"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 X"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 Y"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 L"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 R"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 Start"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 Select"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 Up"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 Down"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 Left"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad1 Right"); + + maxcode = 0x20; + /*** Joypad 2 ***/ + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 A"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 B"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 X"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 Y"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 L"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 R"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 Start"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 Select"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 Up"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 Down"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 Left"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad2 Right"); + + maxcode = 0x30; + /*** Joypad 3 ***/ + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 A"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 B"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 X"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 Y"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 L"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 R"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 Start"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 Select"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 Up"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 Down"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 Left"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad3 Right"); + + maxcode = 0x40; + /*** Joypad 4 ***/ + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 A"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 B"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 X"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 Y"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 L"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 R"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 Start"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 Select"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 Up"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 Down"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 Left"); + ASSIGN_BUTTON_FALSE (maxcode++, "Joypad4 Right"); + + maxcode = 0x50; + /*** Superscope ***/ + ASSIGN_BUTTON_FALSE (maxcode++, "Superscope Fire"); + ASSIGN_BUTTON_FALSE (maxcode++, "Superscope AimOffscreen"); + ASSIGN_BUTTON_FALSE (maxcode++, "Superscope Cursor"); + ASSIGN_BUTTON_FALSE (maxcode++, "Superscope ToggleTurbo"); + ASSIGN_BUTTON_FALSE (maxcode++, "Superscope ToggleTurbo"); + ASSIGN_BUTTON_FALSE (maxcode++, "Superscope Pause"); + + maxcode = 0x60; + /*** Mouse ***/ + ASSIGN_BUTTON_FALSE (maxcode++, "Mouse1 L"); + ASSIGN_BUTTON_FALSE (maxcode++, "Mouse1 R"); + ASSIGN_BUTTON_FALSE (maxcode++, "Mouse2 L"); + ASSIGN_BUTTON_FALSE (maxcode++, "Mouse2 R"); + + maxcode = 0x70; + /*** Justifier ***/ + ASSIGN_BUTTON_FALSE (maxcode++, "Justifier1 Trigger"); + ASSIGN_BUTTON_FALSE (maxcode++, "Justifier1 AimOffscreen"); + ASSIGN_BUTTON_FALSE (maxcode++, "Justifier1 Start"); + ASSIGN_BUTTON_FALSE (maxcode++, "Justifier2 Trigger"); + ASSIGN_BUTTON_FALSE (maxcode++, "Justifier2 AimOffscreen"); + ASSIGN_BUTTON_FALSE (maxcode++, "Justifier2 Start"); + + maxcode = 0x80; + S9xMapPointer(maxcode++, S9xGetCommandT("Pointer Superscope"), false); + S9xMapPointer(maxcode++, S9xGetCommandT("Pointer Mouse1"), false); + S9xMapPointer(maxcode++, S9xGetCommandT("Pointer Mouse2"), false); + S9xMapPointer(maxcode++, S9xGetCommandT("Pointer Justifier1"), false); + S9xMapPointer(maxcode++, S9xGetCommandT("Pointer Justifier2"), false); + + maxcode = 0x90; + ASSIGN_BUTTON_FALSE (maxcode++, "Screenshot"); + + // Plugin 2 Joypads by default + S9xSetController (0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController (1, CTL_JOYPAD, 1, 0, 0, 0); + S9xVerifyControllers(); +} + + +int main(void) +{ + extern void xenos_init(); + xenos_init(); + console_init(); + + xenon_thread_startup(); + xenon_make_it_faster(XENON_SPEED_FULL); + xenon_sleep_thread(1); + xenon_sleep_thread(2); + xenon_sleep_thread(3); + xenon_sleep_thread(4); + xenon_sleep_thread(5); + + printf("SNES9x GX\n"); + + kmem_init(); + usb_init(); + // Set defaults + DefaultSettings (); + + S9xUnmapAllControls (); + SetDefaultButtonMap (); + + // Allocate SNES Memory + if (!Memory.Init ()) + ExitApp(); + + // Allocate APU + if (!S9xInitAPU ()) + ExitApp(); + + // Set Pixel Renderer to match 565 + S9xSetRenderPixelFormat (RGB565); + + // Initialise Snes Sound System + S9xInitSound (5, TRUE, 1024); + + // Initialise Graphics + +// setGFX (); + videoInit(); + + if (!S9xGraphicsInit ()) + ExitApp(); + + S9xSetSoundMute (TRUE); + S9xInitSync(); // initialize frame sync + + // Plugin 2 Joypads by default + S9xSetController (0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController (1, CTL_JOYPAD, 1, 0, 0, 0); + S9xVerifyControllers(); + + printf("Waiting for USB storage...\n"); + + extern void xenos_init(); + int fd; + + do { + usb_do_poll(); + + fd = open("uda:/SNES9X.SMC", O_RDONLY); + } while (fd < 0); + + struct stat stat; + fstat(fd, &stat); + + SNESROMSize = stat.st_size; + if (read(fd, Memory.ROM, SNESROMSize) != SNESROMSize) + { + printf("Failed to read rom\n"); + while (1); + } + +// memcpy(Memory.ROM, smc, SNESROMSize = sizeof(smc)); + + Memory.LoadROM ("BLANK.SMC"); + Memory.LoadSRAM ("BLANK"); + + console_close(); + + emulate(); // main loop + + while (1); + return 0; +} + +extern "C" { + +char* getcwd(char*, size_t) +{ + return 0; +} + +int chdir(const char *f) +{ + return -1; +} + + +uid_t getuid(void) +{ + return 0; +} + +gid_t getgid(void) +{ + return 0; +} + +int chown(const char*, uid_t, gid_t) +{ +} + +int stat(const char*, struct stat*) +{ + return -1; +} + +int unlink(const char*) +{ + return -1; +} + +void gettimeofday() +{ +} + +} diff --git a/plugins/snes9x_gx/source/xenon/png.h b/plugins/snes9x_gx/source/xenon/png.h new file mode 100644 index 00000000..e69de29b diff --git a/plugins/snes9x_gx/source/xenon/pngu/pngu.h b/plugins/snes9x_gx/source/xenon/pngu/pngu.h new file mode 100644 index 00000000..e69de29b diff --git a/plugins/snes9x_gx/source/xenon/s9xconfig.cpp b/plugins/snes9x_gx/source/xenon/s9xconfig.cpp new file mode 100644 index 00000000..61567eb4 --- /dev/null +++ b/plugins/snes9x_gx/source/xenon/s9xconfig.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** + * Snes9x 1.51 Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * crunchy2 May 2007 + * Michniewski 2008 + * Tantric 2008-2009 + * + * s9xconfig.cpp + * + * Configuration parameters are here for easy maintenance. + * Refer to Snes9x.h for all combinations. + * The defaults used here are taken directly from porting.html + ***************************************************************************/ + +#include "snes9x.h" + +// struct SGCSettings GCSettings; + +/**************************************************************************** + * FixInvalidSettings + * + * Attempts to correct at least some invalid settings - the ones that + * might cause crashes + ***************************************************************************/ +void FixInvalidSettings() +{ + +/* if(!(GCSettings.ZoomLevel > 0.5 && GCSettings.ZoomLevel < 1.5)) + GCSettings.ZoomLevel = 1.0; + if(!(GCSettings.xshift > -50 && GCSettings.xshift < 50)) + GCSettings.xshift = 0; + if(!(GCSettings.yshift > -50 && GCSettings.yshift < 50)) + GCSettings.yshift = 0; + if(!(GCSettings.MusicVolume >= 0 && GCSettings.MusicVolume <= 100)) + GCSettings.MusicVolume = 40; + if(!(GCSettings.SFXVolume >= 0 && GCSettings.SFXVolume <= 100)) + GCSettings.SFXVolume = 40; + if(GCSettings.Controller > CTRL_PAD4 || GCSettings.Controller < CTRL_MOUSE) + GCSettings.Controller = CTRL_PAD2; + if(!(GCSettings.render >= 0 && GCSettings.render < 3)) + GCSettings.render = 2; + if(!(GCSettings.videomode >= 0 && GCSettings.videomode < 5)) + GCSettings.videomode = 0; */ +} + +/**************************************************************************** + * DefaultSettings + * + * Sets all the defaults! + ***************************************************************************/ +void +DefaultSettings () +{ +#if 0 + /************** GameCube/Wii Settings *********************/ + ResetControls(); // controller button mappings + + GCSettings.LoadMethod = METHOD_AUTO; // Auto, SD, DVD, USB, Network (SMB) + GCSettings.SaveMethod = METHOD_AUTO; // Auto, SD, Memory Card Slot A, Memory Card Slot B, USB, Network (SMB) + sprintf (GCSettings.LoadFolder,"snes9x/roms"); // Path to game files + sprintf (GCSettings.SaveFolder,"snes9x/saves"); // Path to save files + sprintf (GCSettings.CheatFolder,"snes9x/cheats"); // Path to cheat files + GCSettings.AutoLoad = 1; + GCSettings.AutoSave = 1; + + GCSettings.VerifySaves = 0; + + // custom SMB settings + strncpy (GCSettings.smbip, "", 15); // IP Address of share server + strncpy (GCSettings.smbuser, "", 19); // Your share user + strncpy (GCSettings.smbpwd, "", 19); // Your share user password + strncpy (GCSettings.smbshare, "", 19); // Share name on server + + GCSettings.smbip[15] = 0; + GCSettings.smbuser[19] = 0; + GCSettings.smbpwd[19] = 0; + GCSettings.smbshare[19] = 0; + + GCSettings.Controller = CTRL_PAD2; + + GCSettings.videomode = 0; // automatic video mode detection + GCSettings.ZoomLevel = 1.0; // zoom level + GCSettings.render = 2; // Unfiltered + GCSettings.widescreen = 0; // no aspect ratio correction + GCSettings.FilterMethod = FILTER_NONE; // no hq2x + + GCSettings.xshift = 0; // horizontal video shift + GCSettings.yshift = 0; // vertical video shift + + GCSettings.WiimoteOrientation = 0; + GCSettings.ExitAction = 0; + GCSettings.MusicVolume = 40; + GCSettings.SFXVolume = 40; + GCSettings.Rumble = 1; +#endif + + /****************** SNES9x Settings ***********************/ + + // Default ALL to false + memset (&Settings, 0, sizeof (Settings)); + + // General + + Settings.MouseMaster = false; + Settings.SuperScopeMaster = false; + Settings.MultiPlayer5Master = false; + Settings.JustifierMaster = false; + Settings.ShutdownMaster = true; // needs to be on for ActRaiser 2 + Settings.ApplyCheats = true; + + Settings.BlockInvalidVRAMAccess = false; + Settings.HDMATimingHack = 100; + + // Sound defaults. On GC this is 32Khz/16bit/Stereo/InterpolatedSound + Settings.APUEnabled = true; + Settings.NextAPUEnabled = true; + Settings.SoundPlaybackRate = 32000; + Settings.Stereo = true; + Settings.SixteenBitSound = true; + Settings.SoundEnvelopeHeightReading = true; + Settings.SoundSync = true; + Settings.FixFrequency = false; + Settings.DisableSampleCaching = true; + Settings.InterpolatedSound = true; + Settings.ReverseStereo = true; + + // Graphics + Settings.Transparency = true; + Settings.SupportHiRes = true; + Settings.SkipFrames = AUTO_FRAMERATE; + Settings.TurboSkipFrames = 19; + Settings.DisplayFrameRate = false; + Settings.AutoDisplayMessages = 0; + Settings.InitialInfoStringTimeout = 200; // # frames to display messages for + + // Frame timings in 50hz and 60hz cpu mode + Settings.FrameTimePAL = 20000; + Settings.FrameTimeNTSC = 16667; + + // SDD1 - Star Ocean Returns + Settings.SDD1Pack = true; + + Settings.ForceNTSC = 0; + Settings.ForcePAL = 0; + Settings.ForceHiROM = 0; + Settings.ForceLoROM = 0; + Settings.ForceHeader = 0; + Settings.ForceNoHeader = 0; + Settings.ForceTransparency = 0; + Settings.ForceInterleaved = 0; + Settings.ForceInterleaved2 = 0; + Settings.ForceInterleaveGD24 = 0; + Settings.ForceNotInterleaved = 0; + Settings.ForceNoSuperFX = 0; + Settings.ForceSuperFX = 0; + Settings.ForceDSP1 = 0; + Settings.ForceNoDSP1 = 0; +} diff --git a/plugins/snes9x_gx/source/xenon/s9xconfig.h b/plugins/snes9x_gx/source/xenon/s9xconfig.h new file mode 100644 index 00000000..d2551086 --- /dev/null +++ b/plugins/snes9x_gx/source/xenon/s9xconfig.h @@ -0,0 +1,22 @@ +/**************************************************************************** + * Snes9x 1.51 Nintendo Wii/Gamecube Port + * + * softdev July 2006 + * crunchy2 May 2007 + * Michniewski 2008 + * Tantric 2008-2009 + * + * s9xconfig.h + * + * Configuration parameters are here for easy maintenance. + * Refer to Snes9x.h for all combinations. + * The defaults used here are taken directly from porting.html + ***************************************************************************/ + +#ifndef _S9XCONFIG_ +#define _S9XCONFIG_ + +void FixInvalidSettings(); +void DefaultSettings(); + +#endif diff --git a/plugins/snes9x_gx/source/xenon/s9xsupport.cpp b/plugins/snes9x_gx/source/xenon/s9xsupport.cpp new file mode 100644 index 00000000..0e5fe64c --- /dev/null +++ b/plugins/snes9x_gx/source/xenon/s9xsupport.cpp @@ -0,0 +1,288 @@ +#include "snes9x.h" +#include "memmap.h" +#include "s9xdebug.h" +#include "cpuexec.h" +#include "ppu.h" +#include "apu.h" +#include "display.h" +#include "gfx.h" +#include "soundux.h" +#include "spc700.h" +#include "spc7110.h" +#include "controls.h" + +#include "video.h" + + +#include <time/time.h> +#include <ppc/timebase.h> +#include <xenon_sound/sound.h> + +int FrameTimer, timerstyle = 1; +unsigned long long prev, now; + +unsigned long long gettime(void) +{ + return mftb(); +} + +int diff_usec(unsigned long long prev, unsigned long long now) +{ + return (now - prev) /(PPC_TIMEBASE_FREQ/1000000); +} + + +extern void S9xSetInfoString (const char *string); + +/*** Miscellaneous Functions ***/ +void S9xMessage(int /*type */, int /*number */, const char *message) +{ +#define MAX_MESSAGE_LEN (36 * 3) + + static char buffer[MAX_MESSAGE_LEN + 1]; + strncpy(buffer, message, MAX_MESSAGE_LEN); + buffer[MAX_MESSAGE_LEN] = 0; + S9xSetInfoString(buffer); +} + +void S9xExit() +{ + printf(" *** EXIT\n"); + while (1); +} + +/*** File based functions ***/ +const char * +S9xChooseFilename(bool8 read_only) +{ + return NULL; +} + +const char * +S9xChooseMovieFilename(bool8 read_only) +{ + return NULL; +} + +const char * +S9xGetDirectory(enum s9x_getdirtype dirtype) +{ + return NULL; +} + +const char * +S9xGetFilename(const char *ex, enum s9x_getdirtype dirtype) +{ + return NULL; +} + +const char * +S9xGetFilenameInc(const char *e, enum s9x_getdirtype dirtype) +{ + return NULL; +} + +/*** Memory based functions ***/ +void S9xAutoSaveSRAM() +{ + +} + +/*** Sound based functions ***/ +void S9xToggleSoundChannel(int c) +{ + if (c == 8) + so.sound_switch = 255; + else + so.sound_switch ^= 1 << c; + S9xSetSoundControl(so.sound_switch); +} + +/**************************************************************************** + * OpenSoundDevice + * + * Main initialisation for NGC sound system + ***************************************************************************/ +bool8 S9xOpenSoundDevice(int mode, bool8 stereo, int buffer_size) +{ + so.stereo = TRUE; + so.playback_rate = 48000; + so.sixteen_bit = TRUE; + so.encoded = 0; + so.buffer_size = 4096; + so.sound_switch = 255; + S9xSetPlaybackRate(so.playback_rate); + +// init audio + + xenon_sound_init(); + + return TRUE; +} + +/*** Deprecated function. NGC uses threaded sound ***/ +void S9xGenerateSound() +{ +} + +/* eke-eke */ +void S9xInitSync() +{ + FrameTimer = 0; + prev = gettime(); +} + +/*** Synchronisation ***/ + +void S9xSyncSpeed () +{ + uint32 skipFrms = Settings.SkipFrames; + + if (Settings.TurboMode) + skipFrms = Settings.TurboSkipFrames; + + if (timerstyle == 0) /* use NGC vertical sync (VSYNC) with NTSC roms */ + { + while (FrameTimer == 0) + { + udelay(50); + } + + if (FrameTimer > skipFrms) + FrameTimer = skipFrms; + + if ((FrameTimer > 1) && (IPPU.SkippedFrames < skipFrms)) + { + IPPU.SkippedFrames++; + IPPU.RenderThisFrame = FALSE; + } + else + { + IPPU.SkippedFrames = 0; + IPPU.RenderThisFrame = TRUE; + } + } + else /* use internal timer for PAL roms */ + { + unsigned int timediffallowed = Settings.TurboMode ? 0 : Settings.FrameTime; + now = gettime(); + + if (diff_usec(prev, now) > timediffallowed) + { + printf("L\n"); + /* Timer has already expired */ + if (IPPU.SkippedFrames < skipFrms) + { + IPPU.SkippedFrames++; + IPPU.RenderThisFrame = FALSE; + } + else + { + IPPU.SkippedFrames = 0; + IPPU.RenderThisFrame = TRUE; + } + } + else + { + /*** Ahead - so hold up ***/ + while (diff_usec(prev, now) < timediffallowed) + { + now = gettime(); + udelay(50); + } + IPPU.RenderThisFrame = TRUE; + IPPU.SkippedFrames = 0; + } + + prev = now; + } + + if (!Settings.TurboMode) + FrameTimer--; + return; +} + +/*** Video / Display related functions ***/ +bool8 S9xInitUpdate() +{ + return (TRUE); +} + +bool8 S9xDeinitUpdate(int Width, int Height) +{ +// update_video(Width, Height); + videoBlit(Width, Height); + return (TRUE); +} + +bool8 S9xContinueUpdate(int Width, int Height) +{ + return (TRUE); +} + +void S9xSetPalette() +{ + return; +} + +/*** Input functions ***/ +void S9xHandlePortCommand(s9xcommand_t cmd, int16 data1, int16 data2) +{ + return; +} + +bool S9xPollButton(uint32 id, bool * pressed) +{ + return 0; +} + +bool S9xPollAxis(uint32 id, int16 * value) +{ + return 0; +} + +bool S9xPollPointer(uint32 id, int16 * x, int16 * y) +{ + return 0; +} + +void S9xLoadSDD1Data() +{ + Memory.FreeSDD1Data(); + + Settings.SDD1Pack = FALSE; + + if (strncmp(Memory.ROMName, "Star Ocean", 10) == 0) + Settings.SDD1Pack = TRUE; + + if (strncmp(Memory.ROMName, "STREET FIGHTER ALPHA2", 21) == 0) + Settings.SDD1Pack = TRUE; + + return; +} + +/**************************************************************************** + * Note that these are DUMMY functions, and only allow Snes9x to + * compile. Where possible, they will return an error signal. + ***************************************************************************/ + +/*** splitpath function ***/ +void _splitpath(char const *buffer, char *drive, char *dir, char *fname, + char *ext) +{ + return; // Do nothing - NGC code should NEVER call a function which relies on it +} + +void _makepath(char *filename, const char *drive, const char *dir, + const char *fname, const char *ext) +{ + return; // Do nothing - NGC code should NEVER call a function which relies on it +} + +char * +S9xBasename(char *name) +{ + return name; +} + +unsigned long SNESROMSize = 0; diff --git a/plugins/snes9x_gx/source/xenon/snes9xGX.h b/plugins/snes9x_gx/source/xenon/snes9xGX.h new file mode 100644 index 00000000..e69de29b diff --git a/plugins/snes9x_gx/source/xenon/video.cpp b/plugins/snes9x_gx/source/xenon/video.cpp new file mode 100644 index 00000000..43a458ae --- /dev/null +++ b/plugins/snes9x_gx/source/xenon/video.cpp @@ -0,0 +1,160 @@ +#include <xenos/xe.h> +#include <stdio.h> + +#include "gfx.h" + +extern "C" void do_edram_foo(struct XenosDevice *xe, int complete); + +struct XenosSurface *gfxplane; +struct XenosDevice _xe, *xe; +struct XenosShader *sh_ps, *sh_vs; +struct XenosVertexBuffer *vb; +struct XenosIndexBuffer *ib; + +static unsigned char content_datapspsu[] = { +0x10, 0x2a, 0x11, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x4b, +0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x30, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00, 0xab, 0xab, 0x00, 0x04, 0x00, 0x0c, +0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, +0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0xab, 0xab, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x21, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0xf0, 0x50, 0x00, 0x01, 0x10, 0x02, 0x00, 0x00, 0x12, 0x00, 0xc4, 0x00, 0x00, 0x00, +0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, +0x1f, 0x1f, 0xf6, 0x88, 0x00, 0x00, 0x40, 0x00, 0xc8, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, +0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static unsigned char content_datavsvsu[] = { +0x10, 0x2a, 0x11, 0x01, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x23, +0xff, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, +0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, +0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x21, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x90, +0x00, 0x10, 0x00, 0x03, 0x00, 0x30, 0x50, 0x04, 0x00, 0x00, 0xf0, 0x50, 0x00, 0x00, 0x10, 0x06, +0x30, 0x05, 0x20, 0x03, 0x00, 0x00, 0x12, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x05, +0x00, 0x00, 0x12, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x06, 0x00, 0x00, 0x22, 0x00, +0x00, 0x00, 0x00, 0x00, 0x05, 0xf8, 0x10, 0x00, 0x00, 0x00, 0x06, 0x88, 0x00, 0x00, 0x00, 0x00, +0x05, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x06, 0x88, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x0f, 0x80, 0x3e, +0x00, 0x00, 0x00, 0x00, 0xe2, 0x01, 0x01, 0x00, 0xc8, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, +0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +void videoInit(void) +{ + xe = &_xe; + /* initialize the GPU */ + Xe_Init(xe); + + gfxplane = Xe_CreateTexture(xe, MAX_SNES_WIDTH, MAX_SNES_HEIGHT, 1, 4 | 0x40, 0); + + GFX.Screen = (uint16*)(((unsigned char*)gfxplane->base) + gfxplane->pitch * 2 + 2 * 2); + GFX.Pitch = gfxplane->pitch; + + /* create a render target (the framebuffer) */ + struct XenosSurface *fb = Xe_GetFramebufferSurface(xe); + Xe_SetRenderTarget(xe, fb); + + printf("framebuffer at: %p, pitch %d\n", fb->base, fb->pitch); + + /* let's define a vertex buffer format */ + static const struct XenosVBFFormat vbf = + { + 2, { + {XE_USAGE_POSITION, 0, XE_TYPE_FLOAT2}, + {XE_USAGE_TEXCOORD, 0, XE_TYPE_FLOAT2}, + } + }; + + float rect[] = { + -1, 1, 0, 0, + -1, -1, 0, 1, + 1, 1, 1, 0, + 1, -1, 1, 1 + }; + + unsigned short rect_indices[] = {0, 2, 1, 1, 2, 3}; + + printf("loading pixel shader...\n"); + /* load pixel shader */ + sh_ps = Xe_LoadShaderFromMemory(xe, content_datapspsu); + Xe_InstantiateShader(xe, sh_ps, 0); + + printf("loading vertex shader...\n"); + /* load vertex shader */ + sh_vs = Xe_LoadShaderFromMemory(xe, content_datavsvsu); + Xe_InstantiateShader(xe, sh_vs, 0); + Xe_ShaderApplyVFetchPatches(xe, sh_vs, 0, &vbf); + + printf("create vb...\n"); + /* create and fill vertex buffer */ + vb = Xe_CreateVertexBuffer(xe, sizeof(rect)); + void *v = Xe_VB_Lock(xe, vb, 0, sizeof(rect), XE_LOCK_WRITE); + memcpy(v, rect, sizeof(rect)); + Xe_VB_Unlock(xe, vb); + + printf("create ib...\n"); + /* create and fill index buffer */ + ib = Xe_CreateIndexBuffer(xe, sizeof(rect_indices), XE_FMT_INDEX16); + unsigned short *i = (unsigned short*)Xe_IB_Lock(xe, ib, 0, sizeof(rect_indices), XE_LOCK_WRITE); + memcpy(i, rect_indices, sizeof(rect_indices)); + Xe_IB_Unlock(xe, ib); + + do_edram_foo(xe, 1); +} + + +/* void waitVBlank(void) +{ + while (!Xe_IsVBlank(xe)); +} */ + +void videoBlit(int xres, int yres) +{ + /* flush cache */ + Xe_Surface_LockRect(xe, gfxplane, 0, 0, 0, 0, XE_LOCK_WRITE); + Xe_Surface_Unlock(xe, gfxplane); + + + /* we don't want the border. Note that because of interpolation, some fractional pixel values might get through. */ + float *v = (float*)Xe_VB_Lock(xe, vb, 0, 16*4, XE_LOCK_WRITE); + v[2] = v[6] = 2.0 / xres; + v[3] = v[11] = 2.0 / yres; + Xe_VB_Unlock(xe, vb); + + /* create new surface with right size */ + XenosSurface surface = *gfxplane; + surface.width = xres; + surface.height = yres; + /* begin a new frame, i.e. reset all renderstates to the default */ + Xe_InvalidateState(xe); + + int max_vertices = 4; + int nr_primitives = 2; + + /* draw cube */ + Xe_SetShader(xe, SHADER_TYPE_PIXEL, sh_ps, 0); + Xe_SetShader(xe, SHADER_TYPE_VERTEX, sh_vs, 0); + Xe_SetStreamSource(xe, 0, vb, 0, 4); /* using this vertex buffer */ + Xe_SetIndices(xe, ib); /* ... this index buffer... */ + Xe_SetTexture(xe, 0, &surface); /* ... and this texture */ + Xe_DrawIndexedPrimitive(xe, XE_PRIMTYPE_TRIANGLELIST, 0, 0, max_vertices, 0, nr_primitives); + + /* clear to white */ + Xe_SetClearColor(xe, ~0); + +// waitVBlank(); + + /* resolve (and clear) */ + Xe_Resolve(xe); + + /* wait for render finish */ + Xe_Sync(xe); +} + diff --git a/plugins/snes9x_gx/source/xenon/video.h b/plugins/snes9x_gx/source/xenon/video.h new file mode 100644 index 00000000..9f0111a7 --- /dev/null +++ b/plugins/snes9x_gx/source/xenon/video.h @@ -0,0 +1,4 @@ + +void videoInit(void); +void videoBlit(int xres, int yres); + diff --git a/plugins/snes9x_gx/update.xml b/plugins/snes9x_gx/update.xml new file mode 100644 index 00000000..258cb9d1 --- /dev/null +++ b/plugins/snes9x_gx/update.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<app version="4.3.4"> +<file url="http://snes9x-gx.googlecode.com/files/Snes9x%20GX%204.3.2.zip"></file> +</app> diff --git a/plugins/snes9x_gx/wfsnesplugin.pnproj b/plugins/snes9x_gx/wfsnesplugin.pnproj new file mode 100644 index 00000000..150aeb31 --- /dev/null +++ b/plugins/snes9x_gx/wfsnesplugin.pnproj @@ -0,0 +1 @@ +<Project name="wfsnesplugin"><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="snes" path=""><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="portlibs" path="portlibs\"><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="include" path="include\"><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="freetype2" path="freetype2\"><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="freetype" path="freetype\"><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="config" path="config\"><File path="ftconfig.h"></File><File path="ftheader.h"></File><File path="ftmodule.h"></File><File path="ftoption.h"></File><File path="ftstdlib.h"></File></MagicFolder><File path="freetype.h"></File><File path="ftadvanc.h"></File><File path="ftbbox.h"></File><File path="ftbdf.h"></File><File path="ftbitmap.h"></File><File path="ftcache.h"></File><File path="ftchapters.h"></File><File path="ftcid.h"></File><File path="fterrdef.h"></File><File path="fterrors.h"></File><File path="ftgasp.h"></File><File path="ftglyph.h"></File><File path="ftgxval.h"></File><File path="ftgzip.h"></File><File path="ftimage.h"></File><File path="ftincrem.h"></File><File path="ftlcdfil.h"></File><File path="ftlist.h"></File><File path="ftlzw.h"></File><File path="ftmac.h"></File><File path="ftmm.h"></File><File path="ftmodapi.h"></File><File path="ftmoderr.h"></File><File path="ftotval.h"></File><File path="ftoutln.h"></File><File path="ftpfr.h"></File><File path="ftrender.h"></File><File path="ftsizes.h"></File><File path="ftsnames.h"></File><File path="ftstroke.h"></File><File path="ftsynth.h"></File><File path="ftsystem.h"></File><File path="fttrigon.h"></File><File path="fttypes.h"></File><File path="ftwinfnt.h"></File><File path="ftxf86.h"></File><File path="t1tables.h"></File><File path="ttnameid.h"></File><File path="tttables.h"></File><File path="tttags.h"></File><File path="ttunpat.h"></File></MagicFolder></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="libunrar" path="libunrar\"><File path="archive.hpp"></File><File path="array.hpp"></File><File path="cmddata.hpp"></File><File path="coder.hpp"></File><File path="compress.hpp"></File><File path="consio.hpp"></File><File path="crc.hpp"></File><File path="crypt.hpp"></File><File path="dll.hpp"></File><File path="encname.hpp"></File><File path="errhnd.hpp"></File><File path="extinfo.hpp"></File><File path="extract.hpp"></File><File path="filcreat.hpp"></File><File path="file.hpp"></File><File path="filefn.hpp"></File><File path="filestr.hpp"></File><File path="find.hpp"></File><File path="getbits.hpp"></File><File path="global.hpp"></File><File path="headers.hpp"></File><File path="isnt.hpp"></File><File path="list.hpp"></File><File path="loclang.hpp"></File><File path="log.hpp"></File><File path="match.hpp"></File><File path="model.hpp"></File><File path="options.hpp"></File><File path="os.hpp"></File><File path="pathfn.hpp"></File><File path="rar.hpp"></File><File path="rardefs.hpp"></File><File path="rarlang.hpp"></File><File path="raros.hpp"></File><File path="rartypes.hpp"></File><File path="rarvm.hpp"></File><File path="rawread.hpp"></File><File path="rdwrfn.hpp"></File><File path="recvol.hpp"></File><File path="resource.hpp"></File><File path="rijndael.hpp"></File><File path="rs.hpp"></File><File path="savepos.hpp"></File><File path="scantree.hpp"></File><File path="sha1.hpp"></File><File path="smallfn.hpp"></File><File path="strfn.hpp"></File><File path="strlist.hpp"></File><File path="suballoc.hpp"></File><File path="system.hpp"></File><File path="timefn.hpp"></File><File path="ulinks.hpp"></File><File path="unicode.hpp"></File><File path="unpack.hpp"></File><File path="version.hpp"></File><File path="volume.hpp"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="mupdf" path="mupdf\"><File path="fitz.h"></File><File path="fitz_base.h"></File><File path="fitz_draw.h"></File><File path="fitz_res.h"></File><File path="fitz_stream.h"></File><File path="mupdf.h"></File><File path="pdftool.h"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="sevenzip" path="sevenzip\"><File path="7zAlloc.h"></File><File path="7zBuf.h"></File><File path="7zCrc.h"></File><File path="7zDecode.h"></File><File path="7zExtract.h"></File><File path="7zFile.h"></File><File path="7zHeader.h"></File><File path="7zIn.h"></File><File path="7zItem.h"></File><File path="7zVersion.h"></File><File path="Bcj2.h"></File><File path="Bra.h"></File><File path="CpuArch.h"></File><File path="LzmaDec.h"></File><File path="Types.h"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="tremor" path="tremor\"><File path="config_types.h"></File><File path="ivorbiscodec.h"></File><File path="ivorbisfile.h"></File><File path="ogg.h"></File><File path="os_types.h"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="wupc" path="wupc\"><File path="wupc.h"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="zip" path="zip\"><File path="ioapi.h"></File><File path="unzip.h"></File><File path="zip.h"></File></MagicFolder><File path="ext2.h"></File><File path="ft2build.h"></File><File path="gd.h"></File><File path="gdfx.h"></File><File path="gd_io.h"></File><File path="jconfig.h"></File><File path="jerror.h"></File><File path="jmorecfg.h"></File><File path="jpeglib.h"></File><File path="mxml.h"></File><File path="nfs.h"></File><File path="ntfs.h"></File><File path="png.h"></File><File path="pngconf.h"></File><File path="pnglibconf.h"></File><File path="tiff.h"></File><File path="tiffconf.h"></File><File path="tiffio.h"></File><File path="tiffvers.h"></File><File path="tif_config.h"></File><File path="zconf.h"></File><File path="zlib.h"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="lib" path="lib\"><File path="libext2fs.a"></File><File path="libfreetype.a"></File><File path="libgd.a"></File><File path="libjpeg.a"></File><File path="libmupdf.a"></File><File path="libmxml.a"></File><File path="libnfs.a"></File><File path="libntfs.a"></File><File path="libpng.a"></File><File path="libsevenzip.a"></File><File path="libtiff.a"></File><File path="libunrar.a"></File><File path="libvorbisidec.a"></File><File path="libwupc.a"></File><File path="libz.a"></File><File path="libzip.a"></File></MagicFolder></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="source" path="source\"><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="fonts" path="fonts\"><File path="font.ttf"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="gui" path="gui\"><File path="gui.h"></File><File path="gui_button.cpp"></File><File path="gui_element.cpp"></File><File path="gui_filebrowser.cpp"></File><File path="gui_image.cpp"></File><File path="gui_imagedata.cpp"></File><File path="gui_keyboard.cpp"></File><File path="gui_optionbrowser.cpp"></File><File path="gui_savebrowser.cpp"></File><File path="gui_sound.cpp"></File><File path="gui_text.cpp"></File><File path="gui_trigger.cpp"></File><File path="gui_window.cpp"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="images" path="images\"><File path="battery.png"></File><File path="battery_bar.png"></File><File path="battery_red.png"></File><File path="bg_bottom.png"></File><File path="bg_game_selection.png"></File><File path="bg_game_selection_entry.png"></File><File path="bg_options.png"></File><File path="bg_options_entry.png"></File><File path="bg_preview.png"></File><File path="bg_top.png"></File><File path="button.png"></File><File path="button_arrow_down.png"></File><File path="button_arrow_down_over.png"></File><File path="button_arrow_left.png"></File><File path="button_arrow_left_over.png"></File><File path="button_arrow_right.png"></File><File path="button_arrow_right_over.png"></File><File path="button_arrow_up.png"></File><File path="button_arrow_up_over.png"></File><File path="button_gamesave.png"></File><File path="button_gamesave_blank.png"></File><File path="button_gamesave_over.png"></File><File path="button_large.png"></File><File path="button_large_over.png"></File><File path="button_long.png"></File><File path="button_long_over.png"></File><File path="button_over.png"></File><File path="button_prompt.png"></File><File path="button_prompt_over.png"></File><File path="button_short.png"></File><File path="button_short_over.png"></File><File path="button_small.png"></File><File path="button_small_over.png"></File><File path="credits_box.png"></File><File path="dialogue_box.png"></File><File path="icon_dvd.png"></File><File path="icon_folder.png"></File><File path="icon_game_cheats.png"></File><File path="icon_game_controllers.png"></File><File path="icon_game_load.png"></File><File path="icon_game_reset.png"></File><File path="icon_game_save.png"></File><File path="icon_game_settings.png"></File><File path="icon_home.png"></File><File path="icon_sd.png"></File><File path="icon_settings.png"></File><File path="icon_settings_classic.png"></File><File path="icon_settings_file.png"></File><File path="icon_settings_gamecube.png"></File><File path="icon_settings_justifier.png"></File><File path="icon_settings_mappings.png"></File><File path="icon_settings_menu.png"></File><File path="icon_settings_mouse.png"></File><File path="icon_settings_network.png"></File><File path="icon_settings_nunchuk.png"></File><File path="icon_settings_screenshot.png"></File><File path="icon_settings_snescontroller.png"></File><File path="icon_settings_superscope.png"></File><File path="icon_settings_video.png"></File><File path="icon_settings_wiimote.png"></File><File path="icon_settings_wiiupro.png"></File><File path="icon_smb.png"></File><File path="icon_usb.png"></File><File path="keyboard_key.png"></File><File path="keyboard_key_over.png"></File><File path="keyboard_largekey.png"></File><File path="keyboard_largekey_over.png"></File><File path="keyboard_mediumkey.png"></File><File path="keyboard_mediumkey_over.png"></File><File path="keyboard_textbox.png"></File><File path="logo.png"></File><File path="logo_over.png"></File><File path="player1_grab.png"></File><File path="player1_point.png"></File><File path="player2_grab.png"></File><File path="player2_point.png"></File><File path="player3_grab.png"></File><File path="player3_point.png"></File><File path="player4_grab.png"></File><File path="player4_point.png"></File><File path="progressbar.png"></File><File path="progressbar_empty.png"></File><File path="progressbar_outline.png"></File><File path="screen_position.png"></File><File path="scrollbar.png"></File><File path="scrollbar_arrowdown.png"></File><File path="scrollbar_arrowdown_over.png"></File><File path="scrollbar_arrowup.png"></File><File path="scrollbar_arrowup_over.png"></File><File path="scrollbar_box.png"></File><File path="scrollbar_box_over.png"></File><File path="throbber.png"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="lang" path="lang\"><File path="ca.lang"></File><File path="de.lang"></File><File path="en.lang"></File><File path="es.lang"></File><File path="fr.lang"></File><File path="it.lang"></File><File path="jp.lang"></File><File path="ko.lang"></File><File path="nl.lang"></File><File path="pt.lang"></File><File path="pt_br.lang"></File><File path="tr.lang"></File><File path="zh.lang"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="snes9x" path="snes9x\"><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="apu" path="apu\"><File path="apu.cpp"></File><File path="apu.h"></File><File path="blargg_common.h"></File><File path="blargg_config.h"></File><File path="blargg_endian.h"></File><File path="blargg_source.h"></File><File path="hermite_resampler.h"></File><File path="license.txt"></File><File path="linear_resampler.h"></File><File path="resampler.h"></File><File path="ring_buffer.h"></File><File path="SNES_SPC.cpp"></File><File path="SNES_SPC.h"></File><File path="SNES_SPC_misc.cpp"></File><File path="SNES_SPC_state.cpp"></File><File path="SPC_CPU.h"></File><File path="SPC_DSP.cpp"></File><File path="SPC_DSP.h"></File><File path="SPC_Filter.cpp"></File><File path="SPC_Filter.h"></File></MagicFolder><File path="65c816.h"></File><File path="bsx.cpp"></File><File path="bsx.h"></File><File path="c4.cpp"></File><File path="c4.h"></File><File path="c4emu.cpp"></File><File path="cheats.cpp"></File><File path="cheats.h"></File><File path="cheats2.cpp"></File><File path="clip.cpp"></File><File path="controls.cpp"></File><File path="controls.h"></File><File path="cpu.cpp"></File><File path="cpuaddr.h"></File><File path="cpuexec.cpp"></File><File path="cpuexec.h"></File><File path="cpumacro.h"></File><File path="cpuops.cpp"></File><File path="cpuops.h"></File><File path="crosshairs.cpp"></File><File path="crosshairs.h"></File><File path="display.h"></File><File path="dma.cpp"></File><File path="dma.h"></File><File path="dsp.cpp"></File><File path="dsp.h"></File><File path="dsp1.cpp"></File><File path="dsp2.cpp"></File><File path="dsp3.cpp"></File><File path="dsp4.cpp"></File><File path="font.h"></File><File path="fxdbg.cpp"></File><File path="fxemu.cpp"></File><File path="fxemu.h"></File><File path="fxinst.cpp"></File><File path="fxinst.h"></File><File path="getset.h"></File><File path="gfx.cpp"></File><File path="gfx.h"></File><File path="globals.cpp"></File><File path="language.h"></File><File path="logger.cpp"></File><File path="logger.h"></File><File path="memmap.cpp"></File><File path="memmap.h"></File><File path="messages.h"></File><File path="missing.h"></File><File path="movie.cpp"></File><File path="movie.h"></File><File path="obc1.cpp"></File><File path="obc1.h"></File><File path="pixform.h"></File><File path="port.h"></File><File path="ppu.cpp"></File><File path="ppu.h"></File><File path="reader.cpp"></File><File path="reader.h"></File><File path="sa1.cpp"></File><File path="sa1.h"></File><File path="sa1cpu.cpp"></File><File path="sar.h"></File><File path="screenshot.cpp"></File><File path="screenshot.h"></File><File path="sdd1.cpp"></File><File path="sdd1.h"></File><File path="sdd1emu.cpp"></File><File path="sdd1emu.h"></File><File path="seta.cpp"></File><File path="seta.h"></File><File path="seta010.cpp"></File><File path="seta011.cpp"></File><File path="seta018.cpp"></File><File path="snapshot.cpp"></File><File path="snapshot.h"></File><File path="snes9x.h"></File><File path="spc7110.cpp"></File><File path="spc7110.h"></File><File path="spc7110dec.cpp"></File><File path="spc7110dec.h"></File><File path="spc7110emu.cpp"></File><File path="spc7110emu.h"></File><File path="srtc.cpp"></File><File path="srtc.h"></File><File path="srtcemu.cpp"></File><File path="srtcemu.h"></File><File path="tile.cpp"></File><File path="tile.h"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="sounds" path="sounds\"><File path="bg_music.ogg"></File><File path="button_click.pcm"></File><File path="button_over.pcm"></File><File path="enter.ogg"></File><File path="exit.ogg"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="utils" path="utils\"><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="sz" path="sz\"><File path="7zAlloc.c"></File><File path="7zAlloc.h"></File><File path="7zBuffer.c"></File><File path="7zBuffer.h"></File><File path="7zCrc.c"></File><File path="7zCrc.h"></File><File path="7zDecode.c"></File><File path="7zDecode.h"></File><File path="7zExtract.c"></File><File path="7zExtract.h"></File><File path="7zHeader.c"></File><File path="7zHeader.h"></File><File path="7zIn.c"></File><File path="7zIn.h"></File><File path="7zItem.c"></File><File path="7zItem.h"></File><File path="7zMethodID.c"></File><File path="7zMethodID.h"></File><File path="7zTypes.h"></File><File path="LzmaDecode.c"></File><File path="LzmaDecode.h"></File><File path="LzmaTypes.h"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="unzip" path="unzip\"><File path="crypt.h"></File><File path="ioapi.c"></File><File path="ioapi.h"></File><File path="miniunz.cpp"></File><File path="miniunz.h"></File><File path="unzip.c"></File><File path="unzip.h"></File></MagicFolder><File path="FreeTypeGX.cpp"></File><File path="FreeTypeGX.h"></File><File path="gettext.cpp"></File><File path="gettext.h"></File><File path="http.cpp"></File><File path="http.h"></File><File path="oggplayer.c"></File><File path="oggplayer.h"></File><File path="pngu.c"></File><File path="pngu.h"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="xenon" path="xenon\"><MagicFolder excludeFolders="CVS;.svn;build_wii;executables;hbc" filter="*" name="pngu" path="pngu\"><File path="pngu.h"></File></MagicFolder><File path="ffs_content.c"></File><File path="filebrowser.h"></File><File path="fileop.h"></File><File path="freeze.cpp"></File><File path="freeze.h"></File><File path="gccore.h"></File><File path="main.cpp"></File><File path="png.h"></File><File path="README"></File><File path="s9xconfig.cpp"></File><File path="s9xconfig.h"></File><File path="s9xsupport.cpp"></File><File path="snes9xGX.h"></File><File path="video.cpp"></File><File path="video.h"></File></MagicFolder><File path="audio.cpp"></File><File path="audio.h"></File><File path="button_mapping.c"></File><File path="button_mapping.h"></File><File path="cheatmgr.cpp"></File><File path="filebrowser.cpp"></File><File path="filebrowser.h"></File><File path="filelist.h"></File><File path="fileop.cpp"></File><File path="fileop.h"></File><File path="filter.cpp"></File><File path="filter.h"></File><File path="freeze.cpp"></File><File path="freeze.h"></File><File path="gcunzip.cpp"></File><File path="gcunzip.h"></File><File path="input.cpp"></File><File path="input.h"></File><File path="mem2.cpp"></File><File path="mem2.h"></File><File path="menu.cpp"></File><File path="menu.h"></File><File path="networkop.cpp"></File><File path="networkop.h"></File><File path="preferences.cpp"></File><File path="preferences.h"></File><File path="s9xsupport.cpp"></File><File path="snes9xgx.cpp"></File><File path="snes9xgx.h"></File><File path="sram.cpp"></File><File path="sram.h"></File><File path="video.cpp"></File><File path="video.h"></File></MagicFolder><File path="compile.cmd"></File><File path="Makefile"></File><File path="Makefile.gc"></File><File path="Makefile.xenon"></File><File path="Makefile1"></File><File path="readme.txt"></File><File path="update.xml"></File><File path="wfsnesplugin.pnproj"></File><File path="wfsnesplugin.pnps"></File></MagicFolder></Project> \ No newline at end of file diff --git a/plugins/snes9x_gx/wfsnesplugin.pnps b/plugins/snes9x_gx/wfsnesplugin.pnps new file mode 100644 index 00000000..53242a55 --- /dev/null +++ b/plugins/snes9x_gx/wfsnesplugin.pnps @@ -0,0 +1 @@ +<pd><ViewState><e p="wfsnesplugin\snes\portlibs" x="false"></e><e p="wfsnesplugin\snes\source\gui" x="false"></e><e p="wfsnesplugin\snes\source\images" x="false"></e><e p="wfsnesplugin\snes\source" x="true"></e><e p="wfsnesplugin\snes\source\snes9x" x="false"></e><e p="wfsnesplugin\snes\source\sounds" x="false"></e><e p="wfsnesplugin\snes\source\utils" x="false"></e><e p="wfsnesplugin" x="true"></e><e p="wfsnesplugin\snes" x="true"></e><e p="wfsnesplugin\snes\source\fonts" x="false"></e><e p="wfsnesplugin\snes\source\lang" x="false"></e><e p="wfsnesplugin\snes\source\xenon" x="false"></e></ViewState></pd> \ No newline at end of file