summaryrefslogtreecommitdiff
path: root/old
diff options
context:
space:
mode:
authoraliaspider2015-11-05 19:32:30 +0100
committeraliaspider2015-11-05 19:32:30 +0100
commit771178cf2078da10b9f07590329b3e7c7c7a9259 (patch)
tree8dc67765a4a8355487dc1ee796b6d3a51fcbfb20 /old
parent0731cea41cf04d205f98a7b3d516dfb7633265a7 (diff)
downloadsnes9x2002-771178cf2078da10b9f07590329b3e7c7c7a9259.tar.gz
snes9x2002-771178cf2078da10b9f07590329b3e7c7c7a9259.tar.bz2
snes9x2002-771178cf2078da10b9f07590329b3e7c7c7a9259.zip
move/delete some unused files.
Diffstat (limited to 'old')
-rw-r--r--old/Makefile241
-rw-r--r--old/Makefile.22062010105
-rw-r--r--old/Makefile.gp2x105
-rw-r--r--old/Makefile.last99
-rw-r--r--old/Makefile.old243
-rw-r--r--old/Makefile.wiz.OpenWiz82
-rw-r--r--old/Makefile.wiz.bck82
-rw-r--r--old/Makefile_giz88
-rw-r--r--old/clip.cpp.new405
-rw-r--r--old/gfx16.cpp.last3185
-rw-r--r--old/gfx16.cpp.old23201
11 files changed, 7836 insertions, 0 deletions
diff --git a/old/Makefile b/old/Makefile
new file mode 100644
index 0000000..c967051
--- /dev/null
+++ b/old/Makefile
@@ -0,0 +1,241 @@
+# Two stages Makefile
+
+## Common vars
+
+DEFAULT = wiz
+NFAST = fast
+NCOMP = compatible
+ALL_TARGETS = wiz caanoo gp2x
+ODIR_SUFFIX = objs
+PNAME = pocketsnes
+
+## First stage
+ifneq ($(STAGE),2)
+
+FILE_DATE = $(shell date +%Y-%m-%d)
+
+export MNAME
+export VNAME
+export COPT
+export OBJS
+export ARCH
+export SDK
+export STAGE
+export FILE_DATE
+
+all:
+ make wiz
+ make caanoo
+ make gp2x
+
+# default to fast version
+default: $(DEFAULT)f
+
+# clean
+clean: ALL_TARGETS_DIRS = $(addsuffix _$(NFAST)_$(ODIR_SUFFIX)/,$(ALL_TARGETS)) $(addsuffix _$(NCOMP)_$(ODIR_SUFFIX)/,$(ALL_TARGETS))
+clean:
+ rm -f $(addsuffix *.o,$(ALL_TARGETS_DIRS))
+ rm -f *.gpe
+
+# when release is targeted compile both fast and compatible versions
+release:
+ make $(DEFAULT)f
+ make $(DEFAULT)c
+ rm -f rel/*.gpe
+ cp $(PNAME)_$(DEFAULT)_*.gpe rel/.
+ zip $(PNAME)-$(FILE_DATE).zip rel/*
+
+# invoke stage 2
+do: STAGE = 2
+do:
+ make
+
+# ---------------------
+# Wiz
+# ---------------------
+
+# -- Wiz common
+wiz_common: MNAME = wiz
+wiz_common: COPT += -mcpu=arm926ej-s -mtune=arm926ej-s -g -D__WIZ__
+#wiz_common: COPT += -D__FAST_OBJS__
+#wiz_common: COPT += -O3
+wiz_common: COPT += -Os
+wiz_common: COPT += -ffast-math -msoft-float
+wiz_common: COPT += -finline -finline-functions -fexpensive-optimizations
+wiz_common: COPT += -falign-functions=32 -falign-loops -falign-labels -falign-jumps
+wiz_common: COPT += -fomit-frame-pointer
+wiz_common: COPT += -fno-common -fno-builtin -fstrict-aliasing -mstructure-size-boundary=32
+# -fweb -frename-registers
+# -fsplit-ivs-in-unroller
+#wiz_common: COPT += -Wall -Wno-sign-compare -Wunused -Wpointer-arith -Wcast-align -Waggregate-return
+wiz_common: OBJS = wiz_sdk.o warm.o squidgehack.o pollux_set.o
+wiz_common: OBJS += os9x_65c816_global.o os9x_65c816_spcasm.o os9x_65c816_spcc.o os9x_asm_cpu.o
+wiz_common: ARCH = arm-open2x-linux
+wiz_common: SDK = /opt/open2x/gcc-4.1.1-glibc-2.3.6
+#/$(ARCH)
+#wiz_common: ARCH = arm-openwiz-linux-gnu
+#wiz_common: SDK = /opt/openwiz/toolchain/$(ARCH)
+wiz_common: do
+
+# -- Fast version
+wizf: VNAME = $(NFAST)
+#wizf: COPT = -DASMCPU -D__DEBUG__
+wizf: COPT = -DASMCPU
+wizf: wiz_common
+
+# -- Normal version
+wizc: VNAME = $(NCOMP)
+wizc: COPT = -DUSE_SA1
+wizc: wiz_common
+
+wiz:
+ make $@f
+ make $@c
+
+# ---------------------
+# Caanoo
+# ---------------------
+
+# -- Caanoo common
+caanoo_common: MNAME = caanoo
+caanoo_common: COPT += -mcpu=arm926ej-s -mtune=arm926ej-s -g -D__WIZ__ -D__CAANOO__
+caanoo_common: COPT += -Os
+caanoo_common: COPT += -finline -finline-functions -fexpensive-optimizations
+caanoo_common: COPT += -falign-functions=32 -falign-loops -falign-labels -falign-jumps
+caanoo_common: COPT += -fomit-frame-pointer
+caanoo_common: COPT += -fno-common -fno-builtin -fstrict-aliasing -mstructure-size-boundary=32
+caanoo_common: OBJS = caanoo_sdk.o warm.o squidgehack.o pollux_set.o
+caanoo_common: OBJS += os9x_65c816_global.o os9x_65c816_spcasm.o os9x_65c816_spcc.o os9x_asm_cpu.o
+# EABI
+#caanoo_common: ARCH = arm-gph-linux-gnueabi
+#caanoo_common: SDK = /opt/caanoo_sdk/tools/gcc-4.2.4-glibc-2.7-eabi
+# OABI
+caanoo_common: COPT += -static -ffast-math -msoft-float
+caanoo_common: ARCH = arm-open2x-linux
+caanoo_common: SDK = /opt/open2x/gcc-4.1.1-glibc-2.3.6
+caanoo_common: do
+
+# -- Fast version
+caanoof: VNAME = $(NFAST)
+#caanoof: COPT = -DASMCPU -D__DEBUG__
+caanoof: COPT = -DASMCPU
+caanoof: caanoo_common
+
+# -- Normal version
+caanooc: VNAME = $(NCOMP)
+caanooc: COPT = -DUSE_SA1
+caanooc: caanoo_common
+
+caanoo:
+ make $@f
+ make $@c
+
+# ---------------------
+# GP2X
+# ---------------------
+
+# -- GP2X common
+gp2x_common: MNAME = gp2x
+gp2x_common: COPT += -mcpu=arm920t -mtune=arm920t -static -g -D__GP2X__
+gp2x_common: COPT += -Os
+gp2x_common: COPT += -ffast-math -msoft-float
+gp2x_common: COPT += -finline -finline-functions -fexpensive-optimizations
+gp2x_common: COPT += -falign-functions=32 -falign-loops -falign-labels -falign-jumps
+gp2x_common: COPT += -fomit-frame-pointer
+gp2x_common: COPT += -fno-common -fstrict-aliasing -mstructure-size-boundary=32
+gp2x_common: OBJS = gp2x_sdk.o warm.o squidgehack.o mmuhack.o
+gp2x_common: OBJS += os9x_65c816_global_armv4.o os9x_65c816_spcasm.o os9x_65c816_spcc.o os9x_asm_cpu.o
+gp2x_common: ARCH = arm-open2x-linux
+gp2x_common: SDK = /opt/open2x/gcc-4.1.1-glibc-2.3.6
+gp2x_common: do
+
+# -- Fast version
+gp2xf: VNAME = $(NFAST)
+gp2xf: COPT = -DASMCPU
+gp2xf: gp2x_common
+
+# -- Normal version
+gp2xc: VNAME = $(NCOMP)
+gp2xc: COPT = -DUSE_SA1
+gp2xc: gp2x_common
+
+gp2x:
+ make $@f
+ make $@c
+
+
+## Second stage
+else
+
+TOOLS = $(SDK)/bin
+GCC = $(TOOLS)/$(ARCH)-gcc
+STRIP = $(TOOLS)/$(ARCH)-strip
+ADSASM = $(TOOLS)/$(ARCH)-as
+LIBS = -I$(SDK)/include
+INCS = -L$(SDK)/lib
+ODIR = $(MNAME)_$(VNAME)_$(ODIR_SUFFIX)
+# Inopia's menu system, hacked for the GP2X under rlyeh's sdk
+PRELIBS = -lpthread -lz $(LIBS)
+
+#
+# SNES stuff (c-based)
+#
+#OBJS += touchscreen.o
+OBJS += apu.o apuaux.o c4.o c4emu.o cheats.o cheats2.o clip.o data.o screenshot.o
+OBJS += dsp1.o fxemu.o fxinst.o globals.o loadzip.o ppu.o
+OBJS += dma.o memmap.o
+OBJS += cpu.o cpuexec.o
+OBJS += cpuops.o
+OBJS += sa1.o sa1cpu.o
+OBJS += sdd1.o sdd1emu.o snapshot.o soundux.o spc700.o spc700a.o srtc.o
+#OBJS += spc_decode.o
+OBJS += tile16.o tile16add.o tile16add1_2.o tile16fadd1_2.o tile16sub.o tile16sub1_2.o tile16fsub1_2.o
+OBJS += mode7new.o mode7.o mode7add.o mode7add1_2.o mode7sub.o mode7sub1_2.o
+OBJS += mode7prio.o mode7addprio.o mode7add1_2prio.o mode7subprio.o mode7sub1_2prio.o
+OBJS += gfx16.o rops.o
+OBJS += usbjoy.o
+#
+# and some asm from LJP...
+#
+#OBJS += m3d_func.o
+#
+# Dave's minimal SDK
+#
+OBJS += menu.o config.o input.o gp2x_menutile.o gp2x_highlightbar.o \
+ gp2x_menu_header.o unzip.o ioapi.o zip.o asm_util.o png.o graphics.o lodepng.o theme.o minIni.o
+OBJS += disk_img.o
+OBJS += memset.o memcmp.o memcpy.o strlen.o strcmp.o strncmp.o
+
+#
+# and the glue code that sticks it all together :)
+#
+OBJS += main.o
+FOBJS = $(addprefix $(ODIR)/,$(OBJS))
+COPT += $(INCS) $(LIBS)
+
+executable: $(FOBJS)
+ $(GCC) $(COPT) $(FOBJS) $(PRELIBS) -o $(PNAME)d_$(MNAME)_$(VNAME).gpe -lstdc++ -lm
+ $(STRIP) $(PNAME)d_$(MNAME)_$(VNAME).gpe -o $(PNAME)_$(MNAME)_$(VNAME).gpe
+
+$(FOBJS): | $(ODIR)
+
+$(ODIR):
+ mkdir -p $(ODIR)
+
+tidy:
+ rm $(ODIR)/*.o
+
+# -- Compilation rules
+$(ODIR)/%.o: %.cpp
+ $(GCC) $(COPT) -c $< -o $@
+
+$(ODIR)/%.o: %.c
+ $(GCC) $(COPT) -c $< -o $@
+
+$(ODIR)/%.o: %.s
+ $(GCC) $(COPT) -c $< -o $@
+
+$(ODIR)/%.o: %.S
+ $(GCC) $(COPT) -c $< -o $@
+
+endif
diff --git a/old/Makefile.22062010 b/old/Makefile.22062010
new file mode 100644
index 0000000..2fa3364
--- /dev/null
+++ b/old/Makefile.22062010
@@ -0,0 +1,105 @@
+COPT = -mcpu=arm926ej-s -mtune=arm926ej-s -g -D__WIZ__
+COPT += -DASMCPU
+COPT += -DARM
+COPT += -DVAR_CYCLES
+#COPT += -D_C_GW_
+#COPT = -DUSE_SA1
+COPT += -O3
+# -DFAST_LSB_WORD_ACCESS
+COPT += -ffast-math -msoft-float
+COPT += -finline -finline-functions -fexpensive-optimizations
+COPT += -falign-functions=16 -falign-loops -falign-labels
+#COPT += -falign-jumps
+COPT += -fomit-frame-pointer
+COPT += -fstrict-aliasing -mstructure-size-boundary=32 -fweb -fsigned-char -frename-registers
+SDK = /opt/openwiz/toolchain/arm-openwiz-linux-gnu
+TOOLS = $(SDK)/bin
+ARCH = arm-openwiz-linux-gnu-
+GCC = $(TOOLS)/$(ARCH)gcc
+STRIP = $(TOOLS)/$(ARCH)strip
+ADSASM = $(TOOLS)/$(ARCH)as
+COPT += -I$(SDK)/include
+COPT += -L$(SDK)/lib
+#COPT += -fprofile-generate
+#COPT += -fprofile-use
+#
+# SNES stuff (c-based)
+#
+OBJS = memset.o memcpy.o
+OBJS += 2xsaiwin.o apu.o c4.o c4emu.o cheats.o cheats2.o clip.o data.o
+OBJS += dsp1.o fxemu.o fxinst.o globals.o loadzip.o ppu.o
+OBJS += dma.o memmap.o
+OBJS += cpu.o cpuexec.o
+OBJS += cpuops.o
+# OBJS += sa1.o sa1cpu.o
+OBJS += sdd1.o sdd1emu.o snapshot.o soundux.o spc_decode.o spc700.o spc700a.o srtc.o
+OBJS += tile16.o tile16add.cpp tile16sub.cpp gfx16.o
+OBJS += os9x_65c816.o os9x_asm_cpu.o
+OBJS += usbjoy.o
+#
+# and some asm from LJP...
+#
+OBJS += m3d_func.o
+#
+# Dave's minimal SDK
+#
+OBJS += wiz_sdk.o warm.o menu.o input.o gp2x_menutile.o gp2x_highlightbar.o \
+ gp2x_menu_header.o unzip.o ioapi.o squidgehack.o zip.o asm_util.o pollux_set.o
+
+#
+# and the glue code that sticks it all together :)
+#
+OBJS += main.o
+
+# Inopia's menu system, hacked for the GP2X under rlyeh's sdk
+PRELIBS = -lpthread -lz $(LIBS)
+
+all: pocketsnes.gpe
+clean: tidy pocketsnes.gpe
+
+.c.o:
+ $(GCC) $(COPT) -c $< -o $@
+
+.cpp.o:
+ $(GCC) $(COPT) -c $< -o $@
+
+# make seems to lowercase the extensions, so files with '.S' end up being passed to the compiler as '.s', which means thousands of errors.
+# this is a small workaround.
+
+spc700a.o: spc700a.s
+ $(GCC) $(COPT) -c $< -o $@
+
+os9x_65c816.o: os9x_65c816.s
+ $(GCC) $(COPT) -c $< -o $@
+
+osnes9xgp_asmfunc.o: osnes9xgp_asmfunc.s
+ $(GCC) $(COPT) -c $< -o $@
+
+m3d_func.o: m3d_func.S
+ $(GCC) $(COPT) -c $< -o $@
+
+spc_decode.o: spc_decode.S
+ $(GCC) $(COPT) -c $< -o $@
+
+memset.o: memset.s
+ $(GCC) $(COPT) -c $< -o $@
+
+#sa1_asm.o: sa1_asm.s
+# $(GCC) $(COPT) -c $< -o $@
+
+memcpy.o: memcpy.s
+ $(GCC) $(COPT) -c $< -o $@
+
+dspMixer.o: dspMixer.s
+ $(GCC) $(COPT) -c $< -o $@
+
+asm_util.o: asm_util.S
+ $(GCC) $(COPT) -c $< -o $@
+
+pocketsnesd.gpe: $(OBJS)
+ $(GCC) $(COPT) $(OBJS) $(PRELIBS) -o $@ -lstdc++ -lm
+
+pocketsnes.gpe: pocketsnesd.gpe
+ $(STRIP) pocketsnesd.gpe -o pocketsnes_wiz_fast.gpe
+tidy:
+ rm *.o
diff --git a/old/Makefile.gp2x b/old/Makefile.gp2x
new file mode 100644
index 0000000..ecc07fd
--- /dev/null
+++ b/old/Makefile.gp2x
@@ -0,0 +1,105 @@
+COPT = -mcpu=arm926ej-s -mtune=arm926ej-s -static -g -D__WIZ__
+COPT += -DASMCPU
+COPT += -DARM
+COPT += -DVAR_CYCLES
+#COPT += -D_C_GW_
+#COPT = -DUSE_SA1
+COPT += -O3
+# -DFAST_LSB_WORD_ACCESS
+COPT += -ffast-math -msoft-float
+COPT += -finline -finline-functions -fexpensive-optimizations
+COPT += -falign-functions=16 -falign-loops -falign-labels
+#COPT += -falign-jumps
+COPT += -fomit-frame-pointer
+COPT += -fstrict-aliasing -mstructure-size-boundary=32 -fweb -fsigned-char -frename-registers
+SDK = /opt/openwiz/toolchain/arm-openwiz-linux-gnu
+TOOLS = $(SDK)/bin
+ARCH = arm-openwiz-linux-gnu-
+GCC = $(TOOLS)/$(ARCH)gcc
+STRIP = $(TOOLS)/$(ARCH)strip
+ADSASM = $(TOOLS)/$(ARCH)as
+COPT += -I$(SDK)/include
+COPT += -L$(SDK)/lib
+#COPT += -fprofile-generate
+#COPT += -fprofile-use
+#
+# SNES stuff (c-based)
+#
+OBJS = memset.o memcpy.o
+OBJS += 2xsaiwin.o apu.o c4.o c4emu.o cheats.o cheats2.o clip.o data.o
+OBJS += dsp1.o fxemu.o fxinst.o globals.o loadzip.o ppu.o
+OBJS += dma.o memmap.o
+OBJS += cpu.o cpuexec.o
+OBJS += cpuops.o
+# OBJS += sa1.o sa1cpu.o
+OBJS += sdd1.o sdd1emu.o snapshot.o soundux.o spc_decode.o spc700.o spc700a.o srtc.o
+OBJS += tile16.o tile16add.cpp tile16sub.cpp gfx16.o
+OBJS += os9x_65c816.o os9x_asm_cpu.o
+OBJS += usbjoy.o
+#
+# and some asm from LJP...
+#
+OBJS += m3d_func.o
+#
+# Dave's minimal SDK
+#
+OBJS += wiz_sdk.o warm.o menu.o input.o gp2x_menutile.o gp2x_highlightbar.o \
+ gp2x_menu_header.o unzip.o ioapi.o squidgehack.o zip.o asm_util.o pollux_set.o
+
+#
+# and the glue code that sticks it all together :)
+#
+OBJS += main.o
+
+# Inopia's menu system, hacked for the GP2X under rlyeh's sdk
+PRELIBS = -lpthread -lz $(LIBS)
+
+all: pocketsnes.gpe
+clean: tidy pocketsnes.gpe
+
+.c.o:
+ $(GCC) $(COPT) -c $< -o $@
+
+.cpp.o:
+ $(GCC) $(COPT) -c $< -o $@
+
+# make seems to lowercase the extensions, so files with '.S' end up being passed to the compiler as '.s', which means thousands of errors.
+# this is a small workaround.
+
+spc700a.o: spc700a.s
+ $(GCC) $(COPT) -c $< -o $@
+
+os9x_65c816.o: os9x_65c816.s
+ $(GCC) $(COPT) -c $< -o $@
+
+osnes9xgp_asmfunc.o: osnes9xgp_asmfunc.s
+ $(GCC) $(COPT) -c $< -o $@
+
+m3d_func.o: m3d_func.S
+ $(GCC) $(COPT) -c $< -o $@
+
+spc_decode.o: spc_decode.S
+ $(GCC) $(COPT) -c $< -o $@
+
+memset.o: memset.s
+ $(GCC) $(COPT) -c $< -o $@
+
+#sa1_asm.o: sa1_asm.s
+# $(GCC) $(COPT) -c $< -o $@
+
+memcpy.o: memcpy.s
+ $(GCC) $(COPT) -c $< -o $@
+
+dspMixer.o: dspMixer.s
+ $(GCC) $(COPT) -c $< -o $@
+
+asm_util.o: asm_util.S
+ $(GCC) $(COPT) -c $< -o $@
+
+pocketsnesd.gpe: $(OBJS)
+ $(GCC) $(COPT) $(OBJS) $(PRELIBS) -o $@ -lstdc++ -lm
+
+pocketsnes.gpe: pocketsnesd.gpe
+ $(STRIP) pocketsnesd.gpe -o pocketsnes_wiz_fast.gpe
+tidy:
+ rm *.o
diff --git a/old/Makefile.last b/old/Makefile.last
new file mode 100644
index 0000000..9249d22
--- /dev/null
+++ b/old/Makefile.last
@@ -0,0 +1,99 @@
+MNAME = wiz
+COPT = -mcpu=arm926ej-s -mtune=arm926ej-s -g -D__WIZ__
+COPT += -O3
+COPT += -ffast-math -msoft-float
+COPT += -finline -finline-functions -fexpensive-optimizations
+COPT += -falign-functions=32 -falign-loops -falign-labels
+COPT += -falign-jumps
+COPT += -fomit-frame-pointer
+#COPT += -fprofile-generate
+#COPT += -fprofile-use
+#COPT += -pg
+ARCH = arm-open2x-linux
+SDK = /opt/open2x/gcc-4.1.1-glibc-2.3.6/$(ARCH)
+TOOLS = $(SDK)/bin
+GCC = $(TOOLS)/$(ARCH)-gcc
+STRIP = $(TOOLS)/$(ARCH)-strip
+ADSASM = $(TOOLS)/$(ARCH)-as
+COPT += -I$(SDK)/include
+COPT += -L$(SDK)/lib
+#
+# SNES stuff (c-based)
+#
+OBJS = memcpy.o
+#OBJS += touchscreen.o
+OBJS += apu.o apuaux.o c4.o c4emu.o cheats.o cheats2.o clip.o data.o
+OBJS += dsp1.o fxemu.o fxinst.o globals.o loadzip.o ppu.o
+OBJS += dma.o memmap.o
+OBJS += cpu.o cpuexec.o
+OBJS += cpuops.o
+OBJS += sa1.o sa1cpu.o
+OBJS += sdd1.o sdd1emu.o snapshot.o soundux.o spc700.o spc700a.o srtc.o
+OBJS += spc_decode.o
+OBJS += tile16.o tile16add.o tile16add1_2.o tile16fadd1_2.o tile16sub.o tile16sub1_2.o tile16fsub1_2.o
+OBJS += mode7new.o mode7.o mode7add.o mode7add1_2.o mode7sub.o mode7sub1_2.o
+OBJS += mode7prio.o mode7addprio.o mode7add1_2prio.o mode7subprio.o mode7sub1_2prio.o
+OBJS += gfx16.o
+OBJS += os9x_65c816_global.o os9x_65c816_spcasm.o os9x_65c816_spcc.o os9x_asm_cpu.o
+OBJS += usbjoy.o
+#
+# and some asm from LJP...
+#
+OBJS += m3d_func.o
+#
+# Dave's minimal SDK
+#
+OBJS += loadlast.o wiz_sdk.o warm.o menu.o input.o gp2x_menutile.o gp2x_highlightbar.o \
+ gp2x_menu_header.o unzip.o ioapi.o squidgehack.o zip.o asm_util.o pollux_set.o
+
+OBJS += disk_img.o
+#
+# and the glue code that sticks it all together :)
+#
+OBJS += main.o
+
+# Inopia's menu system, hacked for the GP2X under rlyeh's sdk
+PRELIBS = -lpthread -lz $(LIBS)
+
+all: vfast
+clean: tidy all
+
+first:
+ mkdir -p $(MNAME)_$(VNAME)_obj
+
+$(OBJS): first
+
+pocketsnesd.gpe: $(OBJS)
+ $(GCC) $(COPT) $(addprefix $(MNAME)_$(VNAME)_obj/,$(OBJS)) $(PRELIBS) -o pocketsnesd_$(MNAME)_$(VNAME).gpe -lstdc++ -lm
+
+pocketsnes.gpe: pocketsnesd.gpe
+ $(STRIP) pocketsnesd_$(MNAME)_$(VNAME).gpe -o pocketsnes_$(MNAME)_$(VNAME).gpe
+
+tidy:
+ rm $(OBJDIR)/*.o
+
+# -- Fast version
+vfast: VNAME = fast
+vfast: COPT += -DASMCPU
+vfast: OBJDIR = $(MNAME)_$(VNAME)_obj
+vfast: pocketsnes.gpe
+
+# -- Normal version
+vnormal: VNAME = normal
+vnormal: COPT += -DUSE_SA1
+vnormal: ODIR = $(MNAME)_$(VNAME)_obj
+vnormal: pocketsnes.gpe
+
+# -- Compilation rules
+%.o: %.cpp
+ $(GCC) $(COPT) -c $< -o $(MNAME)_$(VNAME)_obj/$@
+
+%.o: %.c
+ $(GCC) $(COPT) -c $< -o $(MNAME)_$(VNAME)_obj/$@
+
+%.o: %.s
+ $(GCC) $(COPT) -c $< -o $(MNAME)_$(VNAME)_obj/$@
+
+%.o: %.S
+ $(GCC) $(COPT) -c $< -o $(MNAME)_$(VNAME)_obj/$@
+
diff --git a/old/Makefile.old b/old/Makefile.old
new file mode 100644
index 0000000..1c713c0
--- /dev/null
+++ b/old/Makefile.old
@@ -0,0 +1,243 @@
+# Two stages Makefile
+
+## Common vars
+
+DEFAULT = wiz
+NFAST = fast
+NCOMP = compatible
+ALL_TARGETS = wiz caanoo gp2x
+ODIR_SUFFIX = objs
+PNAME = pocketsnes
+
+## First stage
+ifneq ($(STAGE),2)
+
+FILE_DATE = $(shell date +%Y-%m-%d)
+
+export MNAME
+export VNAME
+export COPT
+export OBJS
+export ARCH
+export SDK
+export STAGE
+export FILE_DATE
+
+all:
+ make wiz
+ make caanoo
+ make gp2x
+
+# default to fast version
+default: $(DEFAULT)f
+
+# clean
+clean: ALL_TARGETS_DIRS = $(addsuffix _$(NFAST)_$(ODIR_SUFFIX)/,$(ALL_TARGETS)) $(addsuffix _$(NCOMP)_$(ODIR_SUFFIX)/,$(ALL_TARGETS))
+clean:
+ rm -f $(addsuffix *.o,$(ALL_TARGETS_DIRS))
+ rm -f *.gpe
+
+# when release is targeted compile both fast and compatible versions
+release:
+ make $(DEFAULT)f
+ make $(DEFAULT)c
+ rm -f rel/*.gpe
+ cp $(PNAME)_$(DEFAULT)_*.gpe rel/.
+ zip $(PNAME)-$(FILE_DATE).zip rel/*
+
+# invoke stage 2
+do: STAGE = 2
+do:
+ make
+
+# ---------------------
+# Wiz
+# ---------------------
+
+# -- Wiz common
+wiz_common: MNAME = wiz
+wiz_common: COPT += -mcpu=arm926ej-s -mtune=arm926ej-s -g -D__WIZ__
+#wiz_common: COPT += -D__FAST_OBJS__
+#wiz_common: COPT += -O3
+wiz_common: COPT += -Os
+wiz_common: COPT += -ffast-math -msoft-float
+wiz_common: COPT += -finline -finline-functions -fexpensive-optimizations
+wiz_common: COPT += -falign-functions=32 -falign-loops -falign-labels -falign-jumps
+wiz_common: COPT += -fomit-frame-pointer
+wiz_common: COPT += -fno-common -fno-builtin -fstrict-aliasing -mstructure-size-boundary=32
+# -fweb -frename-registers
+# -fsplit-ivs-in-unroller
+#wiz_common: COPT += -Wall -Wno-sign-compare -Wunused -Wpointer-arith -Wcast-align -Waggregate-return
+wiz_common: OBJS = wiz_sdk.o warm.o squidgehack.o pollux_set.o
+wiz_common: OBJS += os9x_65c816_global.o os9x_65c816_spcasm.o os9x_65c816_spcc.o os9x_asm_cpu.o
+wiz_common: ARCH = arm-open2x-linux
+wiz_common: SDK = /opt/open2x/gcc-4.1.1-glibc-2.3.6
+#/$(ARCH)
+#wiz_common: ARCH = arm-openwiz-linux-gnu
+#wiz_common: SDK = /opt/openwiz/toolchain/$(ARCH)
+wiz_common: do
+
+# -- Fast version
+wizf: VNAME = $(NFAST)
+#wizf: COPT = -DASMCPU -D__DEBUG__
+wizf: COPT = -DASMCPU
+wizf: wiz_common
+
+# -- Normal version
+wizc: VNAME = $(NCOMP)
+wizc: COPT = -DUSE_SA1
+wizc: wiz_common
+
+wiz:
+ make $@f
+ make $@c
+
+# ---------------------
+# Caanoo
+# ---------------------
+
+# -- Caanoo common
+caanoo_common: MNAME = caanoo
+caanoo_common: COPT += -mcpu=arm926ej-s -mtune=arm926ej-s -g -D__WIZ__ -D__CAANOO__
+#caanoo_coomon: COPT += -D__FAST_OBJS__
+#caanoo_common: COPT += -O3
+caanoo_common: COPT += -Os
+caanoo_common: COPT += -finline -finline-functions -fexpensive-optimizations
+caanoo_common: COPT += -falign-functions=32 -falign-loops -falign-labels -falign-jumps
+caanoo_common: COPT += -fomit-frame-pointer
+caanoo_common: COPT += -fno-common -fno-builtin -fstrict-aliasing -mstructure-size-boundary=32
+caanoo_common: OBJS = caanoo_sdk.o warm.o squidgehack.o pollux_set.o
+caanoo_common: OBJS += os9x_65c816_global.o os9x_65c816_spcasm.o os9x_65c816_spcc.o os9x_asm_cpu.o
+# EABI
+#caanoo_common: ARCH = arm-gph-linux-gnueabi
+#caanoo_common: SDK = /opt/caanoo_sdk/tools/gcc-4.2.4-glibc-2.7-eabi
+# OABI
+caanoo_common: COPT += -static -ffast-math -msoft-float
+caanoo_common: ARCH = arm-open2x-linux
+caanoo_common: SDK = /opt/open2x/gcc-4.1.1-glibc-2.3.6
+caanoo_common: do
+
+# -- Fast version
+caanoof: VNAME = $(NFAST)
+#caanoof: COPT = -DASMCPU -D__DEBUG__
+caanoof: COPT = -DASMCPU
+caanoof: caanoo_common
+
+# -- Normal version
+caanooc: VNAME = $(NCOMP)
+caanooc: COPT = -DUSE_SA1
+caanooc: caanoo_common
+
+caanoo:
+ make $@f
+ make $@c
+
+# ---------------------
+# GP2X
+# ---------------------
+
+# -- GP2X common
+gp2x_common: MNAME = gp2x
+gp2x_common: COPT += -mcpu=arm920t -mtune=arm920t -static -g -D__GP2X__
+gp2x_common: COPT += -Os
+gp2x_common: COPT += -ffast-math -msoft-float
+gp2x_common: COPT += -finline -finline-functions -fexpensive-optimizations
+gp2x_common: COPT += -falign-functions=32 -falign-loops -falign-labels -falign-jumps
+gp2x_common: COPT += -fomit-frame-pointer
+gp2x_common: COPT += -fno-common -fstrict-aliasing -mstructure-size-boundary=32
+gp2x_common: OBJS = gp2x_sdk.o warm.o squidgehack.o mmuhack.o
+gp2x_common: OBJS += os9x_65c816_global_armv4.o os9x_65c816_spcasm.o os9x_65c816_spcc.o os9x_asm_cpu.o
+gp2x_common: ARCH = arm-open2x-linux
+gp2x_common: SDK = /opt/open2x/gcc-4.1.1-glibc-2.3.6
+gp2x_common: do
+
+# -- Fast version
+gp2xf: VNAME = $(NFAST)
+gp2xf: COPT = -DASMCPU
+gp2xf: gp2x_common
+
+# -- Normal version
+gp2xc: VNAME = $(NCOMP)
+gp2xc: COPT = -DUSE_SA1
+gp2xc: gp2x_common
+
+gp2x:
+ make $@f
+ make $@c
+
+
+## Second stage
+else
+
+TOOLS = $(SDK)/bin
+GCC = $(TOOLS)/$(ARCH)-gcc
+STRIP = $(TOOLS)/$(ARCH)-strip
+ADSASM = $(TOOLS)/$(ARCH)-as
+LIBS = -I$(SDK)/include
+INCS = -L$(SDK)/lib
+ODIR = $(MNAME)_$(VNAME)_$(ODIR_SUFFIX)
+# Inopia's menu system, hacked for the GP2X under rlyeh's sdk
+PRELIBS = -lpthread -lz $(LIBS)
+
+#
+# SNES stuff (c-based)
+#
+#OBJS += touchscreen.o
+OBJS += apu.o apuaux.o c4.o c4emu.o cheats.o cheats2.o clip.o data.o screenshot.o
+OBJS += dsp1.o fxemu.o fxinst.o globals.o loadzip.o ppu.o
+OBJS += dma.o memmap.o
+OBJS += cpu.o cpuexec.o
+OBJS += cpuops.o
+OBJS += sa1.o sa1cpu.o
+OBJS += sdd1.o sdd1emu.o snapshot.o soundux.o spc700.o spc700a.o srtc.o
+#OBJS += spc_decode.o
+OBJS += tile16.o tile16add.o tile16add1_2.o tile16fadd1_2.o tile16sub.o tile16sub1_2.o tile16fsub1_2.o
+OBJS += mode7new.o mode7.o mode7add.o mode7add1_2.o mode7sub.o mode7sub1_2.o
+OBJS += mode7prio.o mode7addprio.o mode7add1_2prio.o mode7subprio.o mode7sub1_2prio.o
+OBJS += gfx16.o rops.o
+OBJS += usbjoy.o
+#
+# and some asm from LJP...
+#
+#OBJS += m3d_func.o
+#
+# Dave's minimal SDK
+#
+OBJS += menu.o config.o input.o gp2x_menutile.o gp2x_highlightbar.o \
+ gp2x_menu_header.o unzip.o ioapi.o zip.o asm_util.o png.o graphics.o lodepng.o theme.o minIni.o
+OBJS += disk_img.o
+OBJS += memset.o memcmp.o memcpy.o strlen.o strcmp.o strncmp.o
+
+#
+# and the glue code that sticks it all together :)
+#
+OBJS += main.o
+FOBJS = $(addprefix $(ODIR)/,$(OBJS))
+COPT += $(INCS) $(LIBS)
+
+executable: $(FOBJS)
+ $(GCC) $(COPT) $(FOBJS) $(PRELIBS) -o $(PNAME)d_$(MNAME)_$(VNAME).gpe -lstdc++ -lm
+ $(STRIP) $(PNAME)d_$(MNAME)_$(VNAME).gpe -o $(PNAME)_$(MNAME)_$(VNAME).gpe
+
+$(FOBJS): | $(ODIR)
+
+$(ODIR):
+ mkdir -p $(ODIR)
+
+tidy:
+ rm $(ODIR)/*.o
+
+# -- Compilation rules
+$(ODIR)/%.o: %.cpp
+ $(GCC) $(COPT) -c $< -o $@
+
+$(ODIR)/%.o: %.c
+ $(GCC) $(COPT) -c $< -o $@
+
+$(ODIR)/%.o: %.s
+ $(GCC) $(COPT) -c $< -o $@
+
+$(ODIR)/%.o: %.S
+ $(GCC) $(COPT) -c $< -o $@
+
+endif
diff --git a/old/Makefile.wiz.OpenWiz b/old/Makefile.wiz.OpenWiz
new file mode 100644
index 0000000..4950675
--- /dev/null
+++ b/old/Makefile.wiz.OpenWiz
@@ -0,0 +1,82 @@
+COPT = -mcpu=arm926ej-s -mtune=arm926ej-s -g -O3 -static -D__WIZ__ -DUSE_SA1
+COPT += -ffast-math -fexpensive-optimizations -finline -finline-functions -msoft-float
+# -msoft-float
+COPT += -falign-functions=32 -falign-loops -falign-labels -falign-jumps -fomit-frame-pointer
+SDK = /opt/openwiz/toolchain/arm-openwiz-linux-gnu
+TOOLS = $(SDK)/bin
+ARCH = arm-openwiz-linux-gnu-
+GCC = $(TOOLS)/$(ARCH)gcc
+STRIP = $(TOOLS)/$(ARCH)strip
+ADSASM = $(TOOLS)/$(ARCH)as
+COPT += -I$(SDK)/include
+COPT += -L$(SDK)/lib
+#
+# SNES stuff (c-based)
+#
+OBJS = memset.o memcpy.o 2xsaiwin.o apu.o c4.o c4emu.o cheats.o cheats2.o clip.o cpu.o cpuexec.o data.o
+OBJS += dma.o dsp1.o fxemu.o fxinst.o gfx.o globals.o loadzip.o memmap.o ppu.o sa1.o sa1cpu.o
+OBJS += sdd1.o sdd1emu.o snapshot.o soundux.o spc700.o spc700a.o srtc.o tile.o usbjoy.o cpuops.o os9x_asm_cpu.o
+#
+# and some asm from LJP...
+#
+OBJS += m3d_func.o
+#
+# Dave's minimal SDK
+#
+OBJS += wiz_sdk.o warm.o menu.o input.o gp2x_menutile.o gp2x_highlightbar.o \
+ gp2x_menu_header.o unzip.o ioapi.o squidgehack.o zip.o asm_util.o pollux_set.o
+
+#
+# and the glue code that sticks it all together :)
+#
+OBJS += main.o
+
+# Inopia's menu system, hacked for the GP2X under rlyeh's sdk
+PRELIBS = -lpthread -lz $(LIBS)
+
+all: pocketsnes.gpe
+clean: tidy pocketsnes.gpe
+
+.c.o:
+ $(GCC) $(COPT) -c $< -o $@
+
+.cpp.o:
+ $(GCC) $(COPT) -c $< -o $@
+
+# make seems to lowercase the extensions, so files with '.S' end up being passed to the compiler as '.s', which means thousands of errors.
+# this is a small workaround.
+
+spc700a.o: spc700a.s
+ $(GCC) $(COPT) -c $< -o $@
+
+os9x_65c816.o: os9x_65c816.s
+ $(GCC) $(COPT) -c $< -o $@
+
+osnes9xgp_asmfunc.o: osnes9xgp_asmfunc.s
+ $(GCC) $(COPT) -c $< -o $@
+
+m3d_func.o: m3d_func.S
+ $(GCC) $(COPT) -c $< -o $@
+
+spc_decode.o: spc_decode.s
+ $(GCC) $(COPT) -c $< -o $@
+
+memset.o: memset.s
+ $(GCC) $(COPT) -c $< -o $@
+
+memcpy.o: memcpy.s
+ $(GCC) $(COPT) -c $< -o $@
+
+dspMixer.o: dspMixer.s
+ $(GCC) $(COPT) -c $< -o $@
+
+asm_util.o: asm_util.S
+ $(GCC) $(COPT) -c $< -o $@
+
+pocketsnesd.gpe: $(OBJS)
+ $(GCC) $(COPT) $(OBJS) $(PRELIBS) -o $@ -lstdc++ -lm
+
+pocketsnes.gpe: pocketsnesd.gpe
+ $(STRIP) pocketsnesd.gpe -o pocketsnes_wiz.gpe
+tidy:
+ rm *.o
diff --git a/old/Makefile.wiz.bck b/old/Makefile.wiz.bck
new file mode 100644
index 0000000..b682196
--- /dev/null
+++ b/old/Makefile.wiz.bck
@@ -0,0 +1,82 @@
+COPT = -mcpu=arm926ej-s -mtune=arm926ej-s -g -O3 -static -D__WIZ__ -DUSE_SA1
+COPT += -ffast-math -fexpensive-optimizations -finline -finline-functions -msoft-float
+# -msoft-float
+COPT += -falign-functions=32 -falign-loops -falign-labels -falign-jumps -fomit-frame-pointer
+SDK = $(HOME)/GPH_SDK
+TOOLS = $(SDK)/tools/gcc-4.0.2-glibc-2.3.6/arm-linux/bin
+ARCH = arm-linux-
+GCC = $(TOOLS)/$(ARCH)gcc
+STRIP = $(TOOLS)/$(ARCH)strip
+ADSASM = $(TOOLS)/$(ARCH)as
+COPT += -I$(SDK)/include
+COPT += -L$(SDK)/lib/target
+#
+# SNES stuff (c-based)
+#
+OBJS = memset.o memcpy.o 2xsaiwin.o apu.o c4.o c4emu.o cheats.o cheats2.o clip.o cpu.o cpuexec.o data.o
+OBJS += dma.o dsp1.o fxemu.o fxinst.o gfx.o globals.o loadzip.o memmap.o ppu.o sa1.o sa1cpu.o
+OBJS += sdd1.o sdd1emu.o snapshot.o soundux.o spc700.o spc700a.o srtc.o tile.o usbjoy.o cpuops.o os9x_asm_cpu.o
+#
+# and some asm from LJP...
+#
+OBJS += m3d_func.o
+#
+# Dave's minimal SDK
+#
+OBJS += wiz_sdk.o warm.o menu.o input.o gp2x_menutile.o gp2x_highlightbar.o \
+ gp2x_menu_header.o unzip.o ioapi.o squidgehack.o zip.o asm_util.o pollux_set.o
+
+#
+# and the glue code that sticks it all together :)
+#
+OBJS += main.o
+
+# Inopia's menu system, hacked for the GP2X under rlyeh's sdk
+PRELIBS = -lpthread -lz $(LIBS)
+
+all: pocketsnes.gpe
+clean: tidy pocketsnes.gpe
+
+.c.o:
+ $(GCC) $(COPT) -c $< -o $@
+
+.cpp.o:
+ $(GCC) $(COPT) -c $< -o $@
+
+# make seems to lowercase the extensions, so files with '.S' end up being passed to the compiler as '.s', which means thousands of errors.
+# this is a small workaround.
+
+spc700a.o: spc700a.s
+ $(GCC) $(COPT) -c $< -o $@
+
+os9x_65c816.o: os9x_65c816.s
+ $(GCC) $(COPT) -c $< -o $@
+
+osnes9xgp_asmfunc.o: osnes9xgp_asmfunc.s
+ $(GCC) $(COPT) -c $< -o $@
+
+m3d_func.o: m3d_func.S
+ $(GCC) $(COPT) -c $< -o $@
+
+spc_decode.o: spc_decode.s
+ $(GCC) $(COPT) -c $< -o $@
+
+memset.o: memset.s
+ $(GCC) $(COPT) -c $< -o $@
+
+memcpy.o: memcpy.s
+ $(GCC) $(COPT) -c $< -o $@
+
+dspMixer.o: dspMixer.s
+ $(GCC) $(COPT) -c $< -o $@
+
+asm_util.o: asm_util.S
+ $(GCC) $(COPT) -c $< -o $@
+
+pocketsnesd.gpe: $(OBJS)
+ $(GCC) $(COPT) $(OBJS) $(PRELIBS) -o $@ -lstdc++ -lm
+
+pocketsnes.gpe: pocketsnesd.gpe
+ $(STRIP) pocketsnesd.gpe -o pocketsnes_wiz.gpe
+tidy:
+ rm *.o
diff --git a/old/Makefile_giz b/old/Makefile_giz
new file mode 100644
index 0000000..f20d02c
--- /dev/null
+++ b/old/Makefile_giz
@@ -0,0 +1,88 @@
+#COPT = -static -g -I. -I C:/devkitGP2X/include -IC:/devkitGP2X/sysroot/usr/include -O3 -D__GP2X__
+
+SDK_BASE = C:/cygwin/usr/local/arm-wince-pe/lib/KGSDK
+ZLIB_BASE = C:/cygwin/usr/local/arm-wince-pe/lib/zlib
+
+#COPT = -IC:/cygwin/usr/local/arm-wince-pe/include -I$(SDK_BASE)/include -static -g -I. -O3 -mtune=arm920t -ftracer -fstrength-reduce -Wno-unused -funroll-loops -fomit-frame-pointer -fstrict-aliasing -ffast-math -D__GP2X__
+COPT = -IC:/cygwin/usr/local/arm-wince-pe/include -I$(SDK_BASE)/include -I$(ZLIB_BASE)/include -I . -mcpu=arm920 \
+ -mtune=arm920t -O2 -msoft-float -ffast-math -fstrict-aliasing -mstructure-size-boundary=8 \
+ -fexpensive-optimizations -fweb -frename-registers -fomit-frame-pointer -falign-functions -finline -finline-functions \
+ -fno-builtin -fno-common -D__GIZ__
+GCC = arm-wince-pe-gcc
+STRIP = arm-wince-pe-strip
+ADSASM = armasm
+
+#
+# SNES stuff (c-based)
+#
+OBJS = 2xsaiwin.o apu.o c4.o c4emu.o cheats.o cheats2.o clip.o cpu.o cpuexec.o data.o
+OBJS += dma.o dsp1.o fxemu.o fxinst.o gfx.o globals.o loadzip.o memmap.o ppu.o
+OBJS += sdd1.o snapshot.o soundux.o spc700.o srtc.o tile.o
+#
+# ASM CPU Core, ripped from Yoyo's OpenSnes9X
+#
+OBJS += os9x_asm_cpu.o os9x_65c816.o spc700a.o
+#osnes9xgp_asmfunc.o
+#RenderASM/render8.o
+#
+# and some asm from LJP...
+#
+OBJS += m3d_func.o spc_decode.o
+#
+#
+#
+OBJS += giz_kgsdk.o menu.o input.o gp2x_menutile.o gp2x_highlightbar.o \
+ gp2x_menu_header.o unzip.o ioapi.o giz_kgsdkasm.o
+
+#
+# and the glue code that sticks it all together :)
+#
+OBJS += main.o
+
+# Inopia's menu system, hacked for the GP2X under rlyeh's sdk
+PRELIBS = -LC:/cygwin/usr/local/arm-wince-pe/lib -L$(ZLIB_BASE) -lzip -L$(SDK_BASE) -lKGSDK $(LIBS)
+
+all: squidgesnes.gpe
+clean: tidy squidgesnes.gpe
+
+.c.o:
+ $(GCC) $(COPT) -c $< -o $@
+
+.cpp.o:
+ $(GCC) $(COPT) -c $< -o $@
+
+# make seems to lowercase the extensions, so files with '.S' end up being passed to the compiler as '.s', which means thousands of errors.
+# this is a small workaround.
+
+myuname.o: myuname.S
+ $(GCC) $(COPT) -c $< -o $@
+
+os9x_65c816.o: os9x_65c816.s
+ $(GCC) $(COPT) -c $< -o $@
+
+osnes9xgp_asmfunc.o: osnes9xgp_asmfunc.S
+ $(GCC) $(COPT) -c $< -o $@
+
+m3d_func.o: m3d_func.S
+ $(GCC) $(COPT) -c $< -o $@
+
+spc_decode.o: spc_decode.s
+ $(GCC) $(COPT) -c $< -o $@
+
+spc700a.o: spc700a.s
+ $(GCC) $(COPT) -c $< -o $@
+
+giz_kgsdkasm.o: giz_kgsdkasm.s
+ $(GCC) $(COPT) -c $< -o $@
+
+RenderASM/render8.o: RenderASM/render8.S
+ $(GCC) $(COPT) -c $< -o $@
+
+squidgesnesd.gpe: $(OBJS)
+ $(GCC) $(COPT) $(OBJS) -static $(PRELIBS) -o $@ -lstdc++ -lm
+
+squidgesnes.gpe: squidgesnesd.gpe
+ $(STRIP) squidgesnesd.gpe -o squidgesnes.gpe
+ cp squidgesnes.gpe autorun.exe
+tidy:
+ del *.o
diff --git a/old/clip.cpp.new b/old/clip.cpp.new
new file mode 100644
index 0000000..8e6baa3
--- /dev/null
+++ b/old/clip.cpp.new
@@ -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/old/gfx16.cpp.last b/old/gfx16.cpp.last
new file mode 100644
index 0000000..24e004b
--- /dev/null
+++ b/old/gfx16.cpp.last
@@ -0,0 +1,3185 @@
+/*
+ * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
+ *
+ * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
+ * Jerremy Koot (jkoot@snes9x.com)
+ *
+ * Super FX C emulator code
+ * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
+ * Gary Henderson.
+ * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
+ *
+ * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
+ * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
+ * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
+ *
+ * DOS port code contains the works of other authors. See headers in
+ * individual files.
+ *
+ * Snes9x homepage: http://www.snes9x.com
+ *
+ * Permission to use, copy, modify and 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.
+ *
+ * Snes9x is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Snes9x or software derived from Snes9x.
+ *
+ * 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 "ppu.h"
+#include "cpuexec.h"
+#include "display.h"
+#include "gfx.h"
+#include "apu.h"
+#include "cheats.h"
+#include <stdint.h>
+#include "asmmemfuncs.h"
+#include "mode7.h"
+#include "rops.h"
+#include "tile16.h"
+uint32 TileBlank;
+
+const int tx_table[16] = {
+// t1 = 16, t2 = 0
+ // FLIP = 0x00
+ 16 + 0, // 0x00
+ 16 + 1, // 0x01
+
+ // FLIP = 0x01
+ 16 + 1 - 0, // 0x02
+ 16 + 1 - 1, // 0x03
+
+ // FLIP = 0x02
+ 0 + 0, // 0x04
+ 0 + 1, // 0x05
+
+ // FLIP = 0x03
+ 0 + 1 - 0, // 0x06
+ 0 + 1 - 1, // 0x07
+
+// t1 = 0, t2 = 16
+ // FLIP = 0x00
+ 0 + 0, // 0x08
+ 0 + 1, // 0x09
+
+ // FLIP = 0x01
+ 0 + 1 - 0, // 0x0A
+ 0 + 1 - 1, // 0x0B
+
+ // FLIP = 0x02
+ 16 + 0, // 0x0C
+ 16 + 1, // 0x0D
+
+ // FLIP = 0x03
+ 16 + 1 - 0, // 0x0E
+ 16 + 1 - 1 // 0x0F
+};
+
+#define M7 19
+#define M8 19
+
+void ComputeClipWindows ();
+static void S9xDisplayFrameRate ();
+static void S9xDisplayString (const char *string);
+
+extern uint8 BitShifts[8][4];
+extern uint8 TileShifts[8][4];
+extern uint8 PaletteShifts[8][4];
+extern uint8 PaletteMasks[8][4];
+extern uint8 Depths[8][4];
+extern uint8 BGSizes [2];
+
+extern NormalTileRenderer DrawTilePtr;
+extern ClippedTileRenderer DrawClippedTilePtr;
+extern NormalTileRenderer DrawHiResTilePtr;
+extern ClippedTileRenderer DrawHiResClippedTilePtr;
+extern LargePixelRenderer DrawLargePixelPtr;
+
+extern struct SBG BG;
+
+extern struct SLineData LineData[240];
+extern struct SLineMatrixData LineMatrixData [240];
+
+extern uint8 Mode7Depths [2];
+
+#define ON_MAIN(N) (GFX.r212c & (1 << (N)))
+
+#define SUB_OR_ADD(N) \
+(GFX.r2131 & (1 << (N)))
+
+#define ON_SUB(N) \
+((GFX.r2130 & 0x30) != 0x30 && \
+ (GFX.r2130 & 2) && \
+ (GFX.r212d & (1 << N)))
+
+#define ANYTHING_ON_SUB \
+((GFX.r2130 & 0x30) != 0x30 && \
+ (GFX.r2130 & 2) && \
+ (GFX.r212d & 0x1f))
+
+#define ADD_OR_SUB_ON_ANYTHING \
+(GFX.r2131 & 0x3f)
+
+#define BLACK BUILD_PIXEL(0,0,0)
+
+void DrawNoZTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount);
+void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+void DrawClippedTile16 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+void DrawTile16x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+void DrawClippedTile16x2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+void DrawTile16x2x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+void DrawClippedTile16x2x2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+void DrawLargePixel16 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Pixels,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawNoZTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawClippedTile16Add (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawNoZTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawClippedTile16Add1_2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawClippedTile16FixedAdd1_2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawNoZTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+
+void DrawTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawClippedTile16Sub (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawNoZTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+
+void DrawTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawClippedTile16Sub1_2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawLargePixel16Add (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Pixels,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Pixels,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawLargePixel16Sub (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Pixels,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Pixels,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawHiResClippedTile16 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawHiResTile16 (uint32 Tile, uint32 Offset,
+ uint32 StartLine, uint32 LineCount);
+
+bool8_32 S9xGraphicsInit ()
+{
+ register uint32 PixelOdd = 1;
+ register uint32 PixelEven = 2;
+
+#ifdef GFX_MULTI_FORMAT
+ if (GFX.BuildPixel == NULL)
+ S9xSetRenderPixelFormat (RGB565);
+#endif
+
+ for (uint8 bitshift = 0; bitshift < 4; bitshift++)
+ {
+ for (register int i = 0; i < 16; i++)
+ {
+ register uint32 h = 0;
+ register uint32 l = 0;
+
+#if defined(LSB_FIRST)
+// Wiz usa LSB_FIRST
+ if (i & 8)
+ h |= PixelOdd;
+ if (i & 4)
+ h |= PixelOdd << 8;
+ if (i & 2)
+ h |= PixelOdd << 16;
+ if (i & 1)
+ h |= PixelOdd << 24;
+ if (i & 8)
+ l |= PixelOdd;
+ if (i & 4)
+ l |= PixelOdd << 8;
+ if (i & 2)
+ l |= PixelOdd << 16;
+ if (i & 1)
+ l |= PixelOdd << 24;
+#else
+ if (i & 8)
+ h |= (PixelOdd << 24);
+ if (i & 4)
+ h |= (PixelOdd << 16);
+ if (i & 2)
+ h |= (PixelOdd << 8);
+ if (i & 1)
+ h |= PixelOdd;
+ if (i & 8)
+ l |= (PixelOdd << 24);
+ if (i & 4)
+ l |= (PixelOdd << 16);
+ if (i & 2)
+ l |= (PixelOdd << 8);
+ if (i & 1)
+ l |= PixelOdd;
+#endif
+
+ odd_high[bitshift][i] = h;
+ odd_low[bitshift][i] = l;
+ h = l = 0;
+
+#if defined(LSB_FIRST)
+ if (i & 8)
+ h |= PixelEven;
+ if (i & 4)
+ h |= PixelEven << 8;
+ if (i & 2)
+ h |= PixelEven << 16;
+ if (i & 1)
+ h |= PixelEven << 24;
+ if (i & 8)
+ l |= PixelEven;
+ if (i & 4)
+ l |= PixelEven << 8;
+ if (i & 2)
+ l |= PixelEven << 16;
+ if (i & 1)
+ l |= PixelEven << 24;
+#else
+ if (i & 8)
+ h |= (PixelEven << 24);
+ if (i & 4)
+ h |= (PixelEven << 16);
+ if (i & 2)
+ h |= (PixelEven << 8);
+ if (i & 1)
+ h |= PixelEven;
+ if (i & 8)
+ l |= (PixelEven << 24);
+ if (i & 4)
+ l |= (PixelEven << 16);
+ if (i & 2)
+ l |= (PixelEven << 8);
+ if (i & 1)
+ l |= PixelEven;
+#endif
+
+ even_high[bitshift][i] = h;
+ even_low[bitshift][i] = l;
+ }
+ PixelEven <<= 2;
+ PixelOdd <<= 2;
+ }
+
+ GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
+ GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
+ //GFX.InfoStringTimeout = 0;
+ //GFX.InfoString = NULL;
+
+ PPU.BG_Forced = 0;
+ IPPU.OBJChanged = TRUE;
+
+ IPPU.DirectColourMapsNeedRebuild = TRUE;
+ DrawTilePtr = DrawTile16;
+ DrawClippedTilePtr = DrawClippedTile16;
+ DrawLargePixelPtr = DrawLargePixel16;
+ DrawHiResTilePtr= DrawHiResTile16;
+ DrawHiResClippedTilePtr = DrawHiResClippedTile16;
+ S9xFixColourBrightness ();
+
+ if (!(GFX.X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)))
+ return (FALSE);
+
+ if (!(GFX.ZERO_OR_X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)) ||
+ !(GFX.ZERO = (uint16 *) malloc (sizeof (uint16) * 0x10000)))
+ {
+ if (GFX.ZERO_OR_X2)
+ {
+ free ((char *) GFX.ZERO_OR_X2);
+ GFX.ZERO_OR_X2 = NULL;
+ }
+ if (GFX.X2)
+ {
+ free ((char *) GFX.X2);
+ GFX.X2 = NULL;
+ }
+ return (FALSE);
+ }
+ uint32 r, g, b;
+
+ // Build a lookup table that multiplies a packed RGB value by 2 with
+ // saturation.
+ for (r = 0; r <= MAX_RED; r++)
+ {
+ uint32 r2 = r << 1;
+ if (r2 > MAX_RED)
+ r2 = MAX_RED;
+ for (g = 0; g <= MAX_GREEN; g++)
+ {
+ uint32 g2 = g << 1;
+ if (g2 > MAX_GREEN)
+ g2 = MAX_GREEN;
+ for (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);
+ }
+ }
+ }
+ ZeroMemory (GFX.ZERO, 0x10000 * sizeof (uint16));
+ ZeroMemory (GFX.ZERO_OR_X2, 0x10000 * sizeof (uint16));
+ // Build a lookup table that if the top bit of the color value is zero
+ // then the value is zero, otherwise multiply the value by 2. Used by
+ // the color subtraction code.
+
+#if defined(OLD_COLOUR_BLENDING)
+ for (r = 0; r <= MAX_RED; r++)
+ {
+ uint32 r2 = r;
+ if ((r2 & 0x10) == 0)
+ r2 = 0;
+ else
+ r2 = (r2 << 1) & MAX_RED;
+
+ for (g = 0; g <= MAX_GREEN; g++)
+ {
+ uint32 g2 = g;
+ if ((g2 & GREEN_HI_BIT) == 0)
+ g2 = 0;
+ else
+ g2 = (g2 << 1) & MAX_GREEN;
+
+ for (b = 0; b <= MAX_BLUE; b++)
+ {
+ uint32 b2 = b;
+ if ((b2 & 0x10) == 0)
+ b2 = 0;
+ else
+ b2 = (b2 << 1) & MAX_BLUE;
+
+ GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
+ GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
+ }
+ }
+ }
+#else
+ for (r = 0; r <= MAX_RED; r++)
+ {
+ uint32 r2 = r;
+ if ((r2 & 0x10) == 0)
+ r2 = 0;
+ else
+ r2 = (r2 << 1) & MAX_RED;
+
+ if (r2 == 0)
+ r2 = 1;
+ for (g = 0; g <= MAX_GREEN; g++)
+ {
+ uint32 g2 = g;
+ if ((g2 & GREEN_HI_BIT) == 0)
+ g2 = 0;
+ else
+ g2 = (g2 << 1) & MAX_GREEN;
+
+ if (g2 == 0)
+ g2 = 1;
+ for (b = 0; b <= MAX_BLUE; b++)
+ {
+ uint32 b2 = b;
+ if ((b2 & 0x10) == 0)
+ b2 = 0;
+ else
+ b2 = (b2 << 1) & MAX_BLUE;
+
+ if (b2 == 0)
+ b2 = 1;
+ GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
+ GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
+ }
+ }
+ }
+#endif
+
+ // Build a lookup table that if the top bit of the color value is zero
+ // then the value is zero, otherwise its just the value.
+ for (r = 0; r <= MAX_RED; r++)
+ {
+ uint32 r2 = r;
+ if ((r2 & 0x10) == 0)
+ r2 = 0;
+ else
+ r2 &= ~0x10;
+
+ for (g = 0; g <= MAX_GREEN; g++)
+ {
+ uint32 g2 = g;
+ if ((g2 & GREEN_HI_BIT) == 0)
+ g2 = 0;
+ else
+ g2 &= ~GREEN_HI_BIT;
+ for (b = 0; b <= MAX_BLUE; b++)
+ {
+ uint32 b2 = b;
+ if ((b2 & 0x10) == 0)
+ b2 = 0;
+ else
+ b2 &= ~0x10;
+
+ 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)
+{
+ // Free any memory allocated in S9xGraphicsInit
+ if (GFX.X2)
+ {
+ free ((char *) GFX.X2);
+ GFX.X2 = NULL;
+ }
+ if (GFX.ZERO_OR_X2)
+ {
+ free ((char *) GFX.ZERO_OR_X2);
+ GFX.ZERO_OR_X2 = NULL;
+ }
+ if (GFX.ZERO)
+ {
+ free ((char *) GFX.ZERO);
+ GFX.ZERO = NULL;
+ }
+}
+
+void S9xBuildDirectColourMaps ()
+{
+ for (uint32 p = 0; p < 8; p++)
+ {
+ for (uint32 c = 0; c < 256; c++)
+ {
+// XXX: Brightness
+ DirectColourMaps [p][c] = BUILD_PIXEL (((c & 7) << 2) | ((p & 1) << 1),
+ ((c & 0x38) >> 1) | (p & 2),
+ ((c & 0xc0) >> 3) | (p & 4));
+ }
+ }
+ IPPU.DirectColourMapsNeedRebuild = FALSE;
+}
+
+void S9xStartScreenRefresh ()
+{
+ if (IPPU.RenderThisFrame)
+ {
+#ifndef _SNESPPC
+ if (!S9xInitUpdate ())
+ {
+ IPPU.RenderThisFrame = FALSE;
+ return;
+ }
+#endif
+ IPPU.RenderedFramesCount++;
+ IPPU.PreviousLine = IPPU.CurrentLine = 0;
+ IPPU.MaxBrightness = PPU.Brightness;
+ IPPU.LatchedBlanking = PPU.ForcedBlanking;
+ IPPU.LatchedInterlace = (Memory.FillRAM[0x2133] & 1);
+ IPPU.RenderedScreenWidth = 256;
+ IPPU.RenderedScreenHeight = PPU.ScreenHeight;
+ IPPU.DoubleWidthPixels = FALSE;
+
+ PPU.RecomputeClipWindows = TRUE;
+ GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
+ GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
+
+ }
+ if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0)
+ {
+ IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount;
+ IPPU.RenderedFramesCount = 0;
+ IPPU.FrameCount = 0;
+ }
+}
+
+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;
+ }
+ else
+ {
+ if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 &&
+ PPU.BG[2].HOffset == 0xe000)
+ {
+ LineData[C].BG[2].VOffset = 0xe1;
+ LineData[C].BG[2].HOffset = 0;
+ }
+ 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;
+ }
+}
+
+
+void S9xEndScreenRefresh()
+{
+ IPPU.HDMAStarted = FALSE;
+
+//RC
+ if (IPPU.RenderThisFrame)
+ {
+ FLUSH_REDRAW ();
+ //if (IPPU.ColorsChanged)
+ //{
+ IPPU.ColorsChanged = FALSE;
+ //}
+
+
+ S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight,
+ 1);
+ }
+#ifndef RC_OPTIMIZED
+ S9xApplyCheats ();
+#endif
+
+
+#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 S9xSetInfoString (const char *string)
+{
+ }
+
+
+
+int TileRenderer;
+TileRendererSet TileRenderers[] = {
+ {DrawTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 0 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 0
+ {DrawTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 1 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 1
+ {DrawTile16FixedAdd1_2, DrawClippedTile16FixedAdd1_2, DrawLargePixel16Add1_2}, // 2 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 0
+ {DrawTile16Add1_2, DrawClippedTile16Add1_2, DrawLargePixel16Add1_2}, // 3 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 1
+ {DrawTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 4 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 0
+ {DrawTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 5 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 1
+ {DrawTile16FixedSub1_2, DrawClippedTile16FixedSub1_2, DrawLargePixel16Sub1_2}, // 6 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 0
+ {DrawTile16Sub1_2, DrawClippedTile16Sub1_2, DrawLargePixel16Sub1_2}, // 7 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 1
+ {DrawTile16, DrawClippedTile16, DrawLargePixel16} // 8 -> normal
+ };
+TileRendererSet TileRenderersNoZ[] = {
+ {DrawNoZTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 0 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 0
+ {DrawNoZTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 1 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 1
+ {DrawTile16FixedAdd1_2, DrawClippedTile16FixedAdd1_2, DrawLargePixel16Add1_2}, // 2 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 0
+ {DrawNoZTile16Add1_2, DrawClippedTile16Add1_2, DrawLargePixel16Add1_2}, // 3 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 1
+ {DrawNoZTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 4 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 0
+ {DrawNoZTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 5 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 1
+ {DrawTile16FixedSub1_2, DrawClippedTile16FixedSub1_2, DrawLargePixel16Sub1_2}, // 6 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 0
+ {DrawNoZTile16Sub1_2, DrawClippedTile16Sub1_2, DrawLargePixel16Sub1_2}, // 7 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 1
+ {DrawNoZTile16, DrawClippedTile16, DrawLargePixel16} // 8 -> normal
+ };
+INLINE void SelectTileRenderer (bool8_32 normal, bool NoZ = false)
+{
+ if (normal) {
+ TileRenderer = 8;
+ }
+ else {
+ TileRenderer = (((GFX.r2131 >> 5) & 0x06) | ((GFX.r2130 >> 1) & 1));
+ }
+
+#ifdef __DEBUG__
+ char *TRName[] = {
+ "Add", "Add", "FixedAdd1_2", "Add1_2",
+ "Sub", "Sub", "FixedSub1_2", "Sub1_2",
+ "Normal"
+ };
+ printf("SelectTileRenderer: %s\n", TRName[TileRenderer]);
+#endif
+
+ if (NoZ) {
+ DrawTilePtr = TileRenderersNoZ[TileRenderer].Normal;
+ DrawClippedTilePtr = TileRenderersNoZ[TileRenderer].Clipped;
+ DrawLargePixelPtr = TileRenderersNoZ[TileRenderer].Large;
+ }
+ else {
+ DrawTilePtr = TileRenderers[TileRenderer].Normal;
+ DrawClippedTilePtr = TileRenderers[TileRenderer].Clipped;
+ DrawLargePixelPtr = TileRenderers[TileRenderer].Large;
+ }
+}
+
+void S9xSetupOBJ ()
+{
+ int SmallSize;
+ int LargeSize;
+
+ switch (PPU.OBJSizeSelect)
+ {
+ case 0:
+ SmallSize = 8;
+ LargeSize = 16;
+ break;
+ case 1:
+ SmallSize = 8;
+ LargeSize = 32;
+ break;
+ case 2:
+ SmallSize = 8;
+ LargeSize = 64;
+ break;
+ case 3:
+ SmallSize = 16;
+ LargeSize = 32;
+ break;
+ case 4:
+ SmallSize = 16;
+ LargeSize = 64;
+ break;
+ case 5:
+ default:
+ SmallSize = 32;
+ LargeSize = 64;
+ break;
+ }
+
+ int C = 0;
+
+ int FirstSprite = PPU.FirstSprite & 0x7f;
+ int S = FirstSprite;
+ do
+ {
+ int Size;
+ if (PPU.OBJ [S].Size)
+ Size = LargeSize;
+ else
+ Size = SmallSize;
+
+ long VPos = PPU.OBJ [S].VPos;
+
+ if (VPos >= PPU.ScreenHeight)
+ VPos -= 256;
+ if (PPU.OBJ [S].HPos < 256 && PPU.OBJ [S].HPos > -Size &&
+ VPos < PPU.ScreenHeight && VPos > -Size)
+ {
+ int x = 0;
+ int a, b;
+ //GFX.OBJList[C++] = S;
+ // -- Sort objects (from low to high priority)
+ while (x < C) {
+ a = GFX.OBJList[x];
+ if (PPU.OBJ[a].Priority >= PPU.OBJ[S].Priority) break;
+ x++;
+ }
+
+ GFX.OBJList[x] = S;
+ x++; C++;
+
+ while (x < C) {
+ b = GFX.OBJList[x];
+ GFX.OBJList[x] = a;
+ a = b;
+ x++;
+ }
+ // --
+ GFX.Sizes[S] = Size;
+ GFX.VPositions[S] = VPos;
+ }
+ S = (S + 1) & 0x7f;
+ } while (S != FirstSprite);
+
+ // Terminate the list
+ GFX.OBJList [C] = -1;
+ IPPU.OBJChanged = FALSE;
+}
+
+void DrawOBJS (bool8_32 OnMain = FALSE, uint8 D = 0)
+{
+ int bg_ta_ns;
+ int bg_ta;
+ uint32 O;
+ uint32 BaseTile, Tile;
+
+ CHECK_SOUND();
+
+ BG.BitShift = 4;
+ SelectConvertTile();
+ BG.TileShift = 5;
+ //BG.TileAddress = PPU.OBJNameBase;
+ BG.StartPalette = 128;
+ BG.PaletteShift = 4;
+ BG.PaletteMask = 7;
+ BG.Buffer = IPPU.TileCache [TILE_4BIT];
+ BG.Buffered = IPPU.TileCached [TILE_4BIT];
+ //BG.NameSelect = PPU.OBJNameSelect;
+ BG.DirectColourMode = FALSE;
+
+ SelectPalette();
+ bg_ta = PPU.OBJNameBase;
+ bg_ta_ns = bg_ta + PPU.OBJNameSelect;
+
+ GFX.Z1 = D + 2;
+
+ int I = 0;
+ for (int S = GFX.OBJList [I++]; S >= 0; S = GFX.OBJList [I++])
+ {
+ int VPos = GFX.VPositions [S];
+ int Size = GFX.Sizes[S];
+ int TileInc = 1;
+ int Offset;
+
+ if (VPos + Size <= (int) GFX.StartY || VPos > (int) GFX.EndY)
+ continue;
+
+ if (OnMain && SUB_OR_ADD(4))
+ {
+ SelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4, true);
+ }
+
+ BaseTile = PPU.OBJ[S].Name | (PPU.OBJ[S].Palette << 10);
+
+ if (PPU.OBJ[S].HFlip)
+ {
+ BaseTile += ((Size >> 3) - 1) | H_FLIP;
+ TileInc = -1;
+ }
+
+ if (PPU.OBJ[S].VFlip) BaseTile |= V_FLIP;
+ //BaseTile |= PPU.OBJ[S].VFlip << 15;
+
+ int clipcount = GFX.pCurrentClip->Count [4];
+ if (!clipcount) clipcount = 1;
+
+ GFX.Z2 = (PPU.OBJ[S].Priority + 1) * 4 + D;
+
+ for (int clip = 0; clip < clipcount; clip++)
+ {
+ int Left;
+ int Right;
+ if (!GFX.pCurrentClip->Count [4])
+ {
+ Left = 0;
+ Right = 256;
+ }
+ else
+ {
+ Left = GFX.pCurrentClip->Left [clip][4];
+ Right = GFX.pCurrentClip->Right [clip][4];
+ }
+
+ if (Right <= Left || PPU.OBJ[S].HPos + Size <= Left ||
+ PPU.OBJ[S].HPos >= Right)
+ continue;
+
+ for (int Y = 0; Y < Size; Y += 8)
+ {
+ if (VPos + Y + 7 >= (int) GFX.StartY && VPos + Y <= (int) GFX.EndY)
+ {
+ int StartLine;
+ int TileLine;
+ int LineCount;
+ int Last;
+
+ if ((StartLine = VPos + Y) < (int) GFX.StartY)
+ {
+ StartLine = GFX.StartY - StartLine;
+ LineCount = 8 - StartLine;
+ }
+ else
+ {
+ StartLine = 0;
+ LineCount = 8;
+ }
+ if ((Last = VPos + Y + 7 - GFX.EndY) > 0)
+ if ((LineCount -= Last) <= 0)
+ break;
+
+ TileLine = StartLine << 3;
+
+ O = (VPos + Y + StartLine) * GFX_PPL;
+ if (!PPU.OBJ[S].VFlip) Tile = BaseTile + (Y << 1);
+ else Tile = BaseTile + ((Size - Y - 8) << 1);
+
+ if (Tile & 0x100) BG.TileAddress = bg_ta_ns;
+ else BG.TileAddress = bg_ta;
+
+ int Middle = Size >> 3;
+ if (PPU.OBJ[S].HPos < Left)
+ {
+ Tile += ((Left - PPU.OBJ[S].HPos) >> 3) * TileInc;
+ Middle -= (Left - PPU.OBJ[S].HPos) >> 3;
+ O += Left * GFX_PIXSIZE;
+ if ((Offset = (Left - PPU.OBJ[S].HPos) & 7))
+ {
+ O -= Offset * GFX_PIXSIZE;
+ int W = 8 - Offset;
+ int Width = Right - Left;
+ if (W > Width) W = Width;
+ //if (Tile & 0x100) BG.TileAddress = bg_ta_ns;
+ //else BG.TileAddress = bg_ta;
+ (*DrawClippedTilePtr) (Tile, O, Offset, W, TileLine, LineCount);
+
+ if (W >= Width)
+ continue;
+ Tile += TileInc;
+ Middle--;
+ O += 8 * GFX_PIXSIZE;
+ }
+ }
+ else
+ O += PPU.OBJ[S].HPos * GFX_PIXSIZE;
+
+ if (PPU.OBJ[S].HPos + Size >= Right)
+ {
+ Middle -= ((PPU.OBJ[S].HPos + Size + 7) -
+ Right) >> 3;
+ Offset = (Right - (PPU.OBJ[S].HPos + Size)) & 7;
+ }
+ else
+ Offset = 0;
+
+ for (int X = 0; X < Middle; X++, O += 8 * GFX_PIXSIZE,
+ Tile += TileInc)
+ {
+ //if (Tile & 0x100) BG.TileAddress = bg_ta_ns;
+ //else BG.TileAddress = bg_ta;
+ (*DrawTilePtr) (Tile, O, TileLine, LineCount);
+ }
+ if (Offset)
+ {
+ //if (Tile & 0x100) BG.TileAddress = bg_ta_ns;
+ //else BG.TileAddress = bg_ta;
+ (*DrawClippedTilePtr) (Tile, O, 0, Offset, TileLine, LineCount);
+ }
+ }
+ }
+ }
+ }
+}
+void DrawBackgroundMosaic (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
+{
+#ifdef __DEBUG__
+ printf("DrawBackgroundMosaic(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2);
+#endif
+ CHECK_SOUND();
+
+ uint32 Tile;
+ uint16 *SC0;
+ uint16 *SC1;
+ uint16 *SC2;
+ uint16 *SC3;
+ uint8 depths [2] = {Z1, Z2};
+
+ if (BGMode == 0)
+ BG.StartPalette = bg << 5;
+ else
+ BG.StartPalette = 0;
+ SelectPalette();
+
+ SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
+
+ if (PPU.BG[bg].SCSize & 1)
+ SC1 = SC0 + 1024;
+ else
+ SC1 = SC0;
+
+ if(((uint8*)SC1-Memory.VRAM)>=0x10000)
+ SC1-=0x08000;
+
+
+ if (PPU.BG[bg].SCSize & 2)
+ SC2 = SC1 + 1024;
+ else
+ SC2 = SC0;
+
+ if(((uint8*)SC2-Memory.VRAM)>=0x10000)
+ SC2-=0x08000;
+
+
+ if (PPU.BG[bg].SCSize & 1)
+ SC3 = SC2 + 1024;
+ else
+ SC3 = SC2;
+
+ if(((uint8*)SC3-Memory.VRAM)>=0x10000)
+ SC3-=0x08000;
+
+ uint32 Lines;
+ uint32 OffsetMask;
+ uint32 OffsetShift;
+
+ if (BG.TileSize == 16)
+ {
+ OffsetMask = 0x3ff;
+ OffsetShift = 4;
+ }
+ else
+ {
+ OffsetMask = 0x1ff;
+ OffsetShift = 3;
+ }
+
+ for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
+ {
+ uint32 VOffset = LineData [Y].BG[bg].VOffset;
+ uint32 HOffset = LineData [Y].BG[bg].HOffset;
+ uint32 MosaicOffset = Y % PPU.Mosaic;
+
+ for (Lines = 1; Lines < PPU.Mosaic - MosaicOffset; Lines++)
+ if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
+ (HOffset != LineData [Y + Lines].BG[bg].HOffset))
+ break;
+
+ uint32 MosaicLine = VOffset + Y - MosaicOffset;
+
+ if (Y + Lines > GFX.EndY)
+ Lines = GFX.EndY + 1 - Y;
+ uint32 VirtAlign = (MosaicLine & 7) << 3;
+
+ uint16 *b1;
+ uint16 *b2;
+
+ uint32 ScreenLine = MosaicLine >> OffsetShift;
+ uint32 Rem16 = MosaicLine & 15;
+
+ if (ScreenLine & 0x20)
+ b1 = SC2, b2 = SC3;
+ else
+ b1 = SC0, b2 = SC1;
+
+ b1 += (ScreenLine & 0x1f) << 5;
+ b2 += (ScreenLine & 0x1f) << 5;
+ uint16 *t;
+ uint32 Left = 0;
+ uint32 Right = 256;
+
+ uint32 ClipCount = GFX.pCurrentClip->Count [bg];
+ uint32 HPos = HOffset;
+ uint32 PixWidth = PPU.Mosaic;
+
+ if (!ClipCount)
+ ClipCount = 1;
+
+ for (uint32 clip = 0; clip < ClipCount; clip++)
+ {
+ if (GFX.pCurrentClip->Count [bg])
+ {
+ Left = GFX.pCurrentClip->Left [clip][bg];
+ Right = GFX.pCurrentClip->Right [clip][bg];
+ uint32 r = Left % PPU.Mosaic;
+ HPos = HOffset + Left;
+ PixWidth = PPU.Mosaic - r;
+ }
+ uint32 s = Y * GFX_PPL + Left * GFX_PIXSIZE;
+ for (uint32 x = Left; x < Right; x += PixWidth,
+ s += PixWidth * GFX_PIXSIZE,
+ HPos += PixWidth, PixWidth = PPU.Mosaic)
+ {
+ uint32 Quot = (HPos & OffsetMask) >> 3;
+
+ if (x + PixWidth >= Right)
+ PixWidth = Right - x;
+
+ if (BG.TileSize == 8)
+ {
+ if (Quot > 31)
+ t = b2 + (Quot & 0x1f);
+ else
+ t = b1 + Quot;
+ }
+ else
+ {
+ if (Quot > 63)
+ t = b2 + ((Quot >> 1) & 0x1f);
+ else
+ t = b1 + (Quot >> 1);
+ }
+
+ Tile = READ_2BYTES (t);
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+
+ // Draw tile...
+ if (BG.TileSize != 8)
+ {
+ if (Tile & H_FLIP)
+ {
+ // Horizontal flip, but what about vertical flip ?
+ if (Tile & V_FLIP)
+ {
+ // Both horzontal & vertical flip
+ if (Rem16 < 8)
+ {
+ (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ else
+ {
+ (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ // Horizontal flip only
+ if (Rem16 > 7)
+ {
+ (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ else
+ {
+ (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ }
+ }
+ else
+ {
+ // No horizontal flip, but is there a vertical flip ?
+ if (Tile & V_FLIP)
+ {
+ // Vertical flip only
+ if (Rem16 < 8)
+ {
+ (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ else
+ {
+ (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ // Normal unflipped
+ if (Rem16 > 7)
+ {
+ (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ else
+ {
+ (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ }
+ }
+ }
+ else
+ (*DrawLargePixelPtr) (Tile, s, HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ }
+ }
+}
+
+void DrawBackgroundOffset (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
+{
+#ifdef __DEBUG__
+ printf("DrawBackgroundOffse(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2);
+#endif
+
+ CHECK_SOUND();
+
+ uint32 Tile;
+ uint16 *SC0;
+ uint16 *SC1;
+ uint16 *SC2;
+ uint16 *SC3;
+ uint16 *BPS0;
+ uint16 *BPS1;
+ uint16 *BPS2;
+ uint16 *BPS3;
+ uint32 Width;
+ int VOffsetOffset = BGMode == 4 ? 0 : 32;
+ uint8 depths [2] = {Z1, Z2};
+
+ BG.StartPalette = 0;
+ SelectPalette();
+
+ BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1];
+
+ if (PPU.BG[2].SCSize & 1)
+ BPS1 = BPS0 + 1024;
+ else
+ BPS1 = BPS0;
+
+ if (PPU.BG[2].SCSize & 2)
+ BPS2 = BPS1 + 1024;
+ else
+ BPS2 = BPS0;
+
+ if (PPU.BG[2].SCSize & 1)
+ BPS3 = BPS2 + 1024;
+ else
+ BPS3 = BPS2;
+
+ SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
+
+ if (PPU.BG[bg].SCSize & 1)
+ SC1 = SC0 + 1024;
+ else
+ SC1 = SC0;
+
+ if(((uint8*)SC1-Memory.VRAM)>=0x10000)
+ SC1-=0x08000;
+
+
+ if (PPU.BG[bg].SCSize & 2)
+ SC2 = SC1 + 1024;
+ else
+ SC2 = SC0;
+
+ if(((uint8*)SC2-Memory.VRAM)>=0x10000)
+ SC2-=0x08000;
+
+
+ if (PPU.BG[bg].SCSize & 1)
+ SC3 = SC2 + 1024;
+ else
+ SC3 = SC2;
+
+ if(((uint8*)SC3-Memory.VRAM)>=0x10000)
+ SC3-=0x08000;
+
+ static const int Lines = 1;
+ int OffsetMask;
+ int OffsetShift;
+ int OffsetEnableMask = 1 << (bg + 13);
+
+ if (BG.TileSize == 16)
+ {
+ OffsetMask = 0x3ff;
+ OffsetShift = 4;
+ }
+ else
+ {
+ OffsetMask = 0x1ff;
+ OffsetShift = 3;
+ }
+
+ TileBlank = 0xFFFFFFFF;
+ for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++)
+ {
+ uint32 VOff = LineData [Y].BG[2].VOffset - 1;
+ uint32 HOff = LineData [Y].BG[2].HOffset;
+ int VirtAlign;
+ int ScreenLine = VOff >> 3;
+ uint16 *s0;
+ uint16 *s1;
+ uint16 *s2;
+
+ if (ScreenLine & 0x20)
+ s1 = BPS2, s2 = BPS3;
+ else
+ s1 = BPS0, s2 = BPS1;
+
+ s1 += (ScreenLine & 0x1f) << 5;
+ s2 += (ScreenLine & 0x1f) << 5;
+
+ if(BGMode != 4)
+ {
+ if((ScreenLine & 0x1f) == 0x1f)
+ {
+ if(ScreenLine & 0x20)
+ VOffsetOffset = BPS0 - BPS2 - 0x1f*32;
+ else
+ VOffsetOffset = BPS2 - BPS0 - 0x1f*32;
+ }
+ else
+ {
+ VOffsetOffset = 32;
+ }
+ }
+ int clipcount = GFX.pCurrentClip->Count [bg];
+ if (!clipcount)
+ clipcount = 1;
+
+ for (int clip = 0; clip < clipcount; clip++)
+ {
+ uint32 Left;
+ uint32 Right;
+
+ if (!GFX.pCurrentClip->Count [bg])
+ {
+ Left = 0;
+ Right = 256;
+ }
+ else
+ {
+ Left = GFX.pCurrentClip->Left [clip][bg];
+ Right = GFX.pCurrentClip->Right [clip][bg];
+
+ if (Right <= Left)
+ continue;
+ }
+
+ uint32 VOffset;
+ uint32 HOffset;
+ uint32 LineHOffset=LineData [Y].BG[bg].HOffset;
+ uint32 Offset;
+ uint32 HPos;
+ uint32 Quot;
+ uint32 Count;
+ uint16 *t;
+ uint32 Quot2;
+ uint32 VCellOffset;
+ uint32 HCellOffset;
+ uint16 *b1;
+ uint16 *b2;
+ uint32 TotalCount = 0;
+ uint32 MaxCount = 8;
+
+ uint32 s = Left * GFX_PIXSIZE + Y * GFX_PPL;
+ bool8_32 left_hand_edge = (Left == 0);
+ Width = Right - Left;
+
+ if (Left & 7)
+ MaxCount = 8 - (Left & 7);
+
+ while (Left < Right)
+ {
+ if (left_hand_edge)
+ {
+ // The SNES offset-per-tile background mode has a
+ // hardware limitation that the offsets cannot be set
+ // for the tile at the left-hand edge of the screen.
+ VOffset = LineData [Y].BG[bg].VOffset;
+ HOffset = LineHOffset;
+ left_hand_edge = FALSE;
+ }
+ else
+ {
+ // All subsequent offset tile data is shifted left by one,
+ // hence the - 1 below.
+ Quot2 = ((HOff + Left - 1) & OffsetMask) >> 3;
+
+ if (Quot2 > 31)
+ s0 = s2 + (Quot2 & 0x1f);
+ else
+ s0 = s1 + Quot2;
+
+ HCellOffset = READ_2BYTES (s0);
+
+ if (BGMode == 4)
+ {
+ VOffset = LineData [Y].BG[bg].VOffset;
+ HOffset=LineHOffset;
+ if ((HCellOffset & OffsetEnableMask))
+ {
+ if (HCellOffset & 0x8000)
+ VOffset = HCellOffset + 1;
+ else
+ HOffset = HCellOffset;
+ }
+ }
+ else
+ {
+ VCellOffset = READ_2BYTES (s0 + VOffsetOffset);
+ if ((VCellOffset & OffsetEnableMask))
+ VOffset = VCellOffset + 1;
+ else
+ VOffset = LineData [Y].BG[bg].VOffset;
+
+ if ((HCellOffset & OffsetEnableMask))
+ HOffset = (HCellOffset & ~7)|(LineHOffset&7);
+ else
+ HOffset=LineHOffset;
+ }
+ }
+ VirtAlign = ((Y + VOffset) & 7) << 3;
+ ScreenLine = (VOffset + Y) >> OffsetShift;
+
+ int tx_index;
+ tx_index = ( ((VOffset + Y) & 15) <= 7 ) << 3;
+
+ if (ScreenLine & 0x20)
+ b1 = SC2, b2 = SC3;
+ else
+ b1 = SC0, b2 = SC1;
+
+ b1 += (ScreenLine & 0x1f) << 5;
+ b2 += (ScreenLine & 0x1f) << 5;
+
+ HPos = (HOffset + Left) & OffsetMask;
+
+ Quot = HPos >> 3;
+
+ if (BG.TileSize == 8)
+ {
+ if (Quot > 31)
+ t = b2 + (Quot & 0x1f);
+ else
+ t = b1 + Quot;
+ }
+ else
+ {
+ if (Quot > 63)
+ t = b2 + ((Quot >> 1) & 0x1f);
+ else
+ t = b1 + (Quot >> 1);
+ }
+
+ if (MaxCount + TotalCount > Width)
+ MaxCount = Width - TotalCount;
+
+ Offset = HPos & 7;
+
+ Count = 8 - Offset;
+ if (Count > MaxCount)
+ Count = MaxCount;
+
+ s -= Offset * GFX_PIXSIZE;
+ Tile = READ_2BYTES(t);
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+
+ if (Tile != TileBlank)
+ if (BG.TileSize == 8)
+ (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines);
+ else
+ {
+ Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)];
+ if (Tile != TileBlank){
+ (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines);
+ }
+ }
+
+ Left += Count;
+ TotalCount += Count;
+ s += (Offset + Count) * GFX_PIXSIZE;
+ MaxCount = 8;
+ }
+ }
+ }
+}
+
+void DrawBackgroundMode5 (uint32 /* BGMODE */, uint32 bg, uint8 Z1, uint8 Z2)
+{
+#ifdef __DEBUG__
+ printf("DrawBackgroundMode5(?, %i, %i, %i)\n", bg, Z1, Z2);
+#endif
+
+ CHECK_SOUND();
+
+ uint8 depths [2] = {Z1, Z2};
+
+ uint32 Tile;
+ uint16 *SC0;
+ uint16 *SC1;
+ uint16 *SC2;
+ uint16 *SC3;
+ uint32 Width;
+
+ BG.StartPalette = 0;
+ SelectPalette();
+
+ SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
+
+ if ((PPU.BG[bg].SCSize & 1))
+ SC1 = SC0 + 1024;
+ else
+ SC1 = SC0;
+
+ if((SC1-(unsigned short*)Memory.VRAM)>0x10000)
+ SC1=(uint16*)&Memory.VRAM[(((uint8*)SC1)-Memory.VRAM)%0x10000];
+
+ if ((PPU.BG[bg].SCSize & 2))
+ SC2 = SC1 + 1024;
+ else SC2 = SC0;
+
+ if(((uint8*)SC2-Memory.VRAM)>=0x10000)
+ SC2-=0x08000;
+
+ if ((PPU.BG[bg].SCSize & 1))
+ SC3 = SC2 + 1024;
+ else
+ SC3 = SC2;
+
+ if(((uint8*)SC3-Memory.VRAM)>=0x10000)
+ SC3-=0x08000;
+ int Lines;
+ int VOffsetMask;
+ int VOffsetShift;
+
+ if (BG.TileSize == 16)
+ {
+ VOffsetMask = 0x3ff;
+ VOffsetShift = 4;
+ }
+ else
+ {
+ VOffsetMask = 0x1ff;
+ VOffsetShift = 3;
+ }
+ int endy = GFX.EndY;
+
+ for (int Y = GFX.StartY; Y <= endy; Y += Lines)
+ {
+ //int y = Y;
+ uint32 VOffset = LineData [Y].BG[bg].VOffset;
+ uint32 HOffset = LineData [Y].BG[bg].HOffset;
+ int VirtAlign = (Y + VOffset) & 7;
+
+ for (Lines = 1; Lines < 8 - VirtAlign; Lines++)
+ if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
+ (HOffset != LineData [Y + Lines].BG[bg].HOffset))
+ break;
+
+ HOffset <<= 1;
+ if (Y + Lines > endy)
+ Lines = endy + 1 - Y;
+
+ int ScreenLine = (VOffset + Y) >> VOffsetShift;
+ int t1;
+ int t2;
+ if (((VOffset + Y) & 15) > 7)
+ {
+ t1 = 16;
+ t2 = 0;
+ }
+ else
+ {
+ t1 = 0;
+ t2 = 16;
+ }
+ uint16 *b1;
+ uint16 *b2;
+
+ if (ScreenLine & 0x20)
+ b1 = SC2, b2 = SC3;
+ else
+ b1 = SC0, b2 = SC1;
+
+ b1 += (ScreenLine & 0x1f) << 5;
+ b2 += (ScreenLine & 0x1f) << 5;
+
+ int clipcount = GFX.pCurrentClip->Count [bg];
+ if (!clipcount)
+ clipcount = 1;
+ for (int clip = 0; clip < clipcount; clip++)
+ {
+ int Left;
+ int Right;
+
+ if (!GFX.pCurrentClip->Count [bg])
+ {
+ Left = 0;
+ Right = 512;
+ }
+ else
+ {
+ Left = GFX.pCurrentClip->Left [clip][bg] * 2;
+ Right = GFX.pCurrentClip->Right [clip][bg] * 2;
+
+ if (Right <= Left)
+ continue;
+ }
+
+ uint32 s = (Left>>1) * GFX_PIXSIZE + Y * GFX_PPL;
+ uint32 HPos = (HOffset + Left * GFX_PIXSIZE) & 0x3ff;
+
+ uint32 Quot = HPos >> 3;
+ uint32 Count = 0;
+
+ uint16 *t;
+ if (Quot > 63)
+ t = b2 + ((Quot >> 1) & 0x1f);
+ else
+ t = b1 + (Quot >> 1);
+
+ Width = Right - Left;
+ // Left hand edge clipped tile
+ if (HPos & 7)
+ {
+ int Offset = (HPos & 7);
+ Count = 8 - Offset;
+ if (Count > Width)
+ Count = Width;
+ s -= (Offset>>1);
+ Tile = READ_2BYTES (t);
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+
+ if (BG.TileSize == 8)
+ {
+ if (!(Tile & H_FLIP))
+ {
+ // Normal, unflipped
+ (*DrawHiResClippedTilePtr) (Tile + (Quot & 1),
+ s, Offset, Count, VirtAlign, Lines);
+ }
+ else
+ {
+ // H flip
+ (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1),
+ s, Offset, Count, VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ if (!(Tile & (V_FLIP | H_FLIP)))
+ {
+ // Normal, unflipped
+ (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1),
+ s, Offset, Count, VirtAlign, Lines);
+ }
+ else
+ if (Tile & H_FLIP)
+ {
+ if (Tile & V_FLIP)
+ {
+ // H & V flip
+ (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
+ s, Offset, Count, VirtAlign, Lines);
+ }
+ else
+ {
+ // H flip only
+ (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
+ s, Offset, Count, VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ // V flip only
+ (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1),
+ s, Offset, Count, VirtAlign, Lines);
+ }
+ }
+
+ t += Quot & 1;
+ if (Quot == 63)
+ t = b2;
+ else if (Quot == 127)
+ t = b1;
+ Quot++;
+ s += 4;
+ }
+
+ // Middle, unclipped tiles
+ Count = Width - Count;
+ int Middle = Count >> 3;
+ Count &= 7;
+ for (int C = Middle; C > 0; s += 4, Quot++, C--)
+ {
+ Tile = READ_2BYTES(t);
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ if (BG.TileSize == 8)
+ {
+ if (!(Tile & H_FLIP))
+ {
+ // Normal, unflipped
+ (*DrawHiResTilePtr) (Tile + (Quot & 1),
+ s, VirtAlign, Lines);
+ }
+ else
+ {
+ // H flip
+ (*DrawHiResTilePtr) (Tile + 1 - (Quot & 1),
+ s, VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ if (!(Tile & (V_FLIP | H_FLIP)))
+ {
+ // Normal, unflipped
+ (*DrawHiResTilePtr) (Tile + t1 + (Quot & 1),
+ s, VirtAlign, Lines);
+ }
+ else
+ if (Tile & H_FLIP)
+ {
+ if (Tile & V_FLIP)
+ {
+ // H & V flip
+ (*DrawHiResTilePtr) (Tile + t2 + 1 - (Quot & 1),
+ s, VirtAlign, Lines);
+ }
+ else
+ {
+ // H flip only
+ (*DrawHiResTilePtr) (Tile + t1 + 1 - (Quot & 1),
+ s, VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ // V flip only
+ (*DrawHiResTilePtr) (Tile + t2 + (Quot & 1),
+ s, VirtAlign, Lines);
+ }
+ }
+
+ t += Quot & 1;
+ if (Quot == 63)
+ t = b2;
+ else
+ if (Quot == 127)
+ t = b1;
+ }
+
+ // Right-hand edge clipped tiles
+ if (Count)
+ {
+ Tile = READ_2BYTES(t);
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ if (BG.TileSize == 8)
+ {
+ if (!(Tile & H_FLIP))
+ {
+ // Normal, unflipped
+ (*DrawHiResClippedTilePtr) (Tile + (Quot & 1),
+ s, 0, Count, VirtAlign, Lines);
+ }
+ else
+ {
+ // H flip
+ (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1),
+ s, 0, Count, VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ if (!(Tile & (V_FLIP | H_FLIP)))
+ {
+ // Normal, unflipped
+ (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1),
+ s, 0, Count, VirtAlign, Lines);
+ }
+ else
+ if (Tile & H_FLIP)
+ {
+ if (Tile & V_FLIP)
+ {
+ // H & V flip
+ (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
+ s, 0, Count, VirtAlign, Lines);
+ }
+ else
+ {
+ // H flip only
+ (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
+ s, 0, Count, VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ // V flip only
+ (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1),
+ s, 0, Count, VirtAlign, Lines);
+ }
+ }
+ }
+ }
+ }
+}
+
+void DrawBackground_8(uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
+{
+#ifdef __DEBUG__
+ printf("DrawBackground_8(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2);
+#endif
+ //uint32 Tile;
+ uint16 *SC0;
+ uint16 *SC1;
+ uint16 *SC2;
+ uint16 *SC3;
+ uint32 depths [2] = {Z1, Z2};
+
+ SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
+
+ SC1 = SC0 + ((PPU.BG[bg].SCSize & 1) << 10);
+
+ if(SC1 >= (unsigned short*)(Memory.VRAM+0x10000)) SC1 = (uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0]) & 0xffff];
+
+ if (PPU.BG[bg].SCSize & 2)
+ SC2 = SC1 + 1024;
+ else
+ SC2 = SC0;
+
+ if(((uint8*)SC2-Memory.VRAM)>=0x10000) SC2 -= 0x08000;
+
+ SC3 = SC2 + ((PPU.BG[bg].SCSize & 1) << 10);
+
+ if(((uint8*)SC3-Memory.VRAM)>=0x10000) SC3 -= 0x08000;
+
+ int Lines;
+
+ TileBlank = 0xFFFFFFFF;
+ for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines){
+ int y_ppl = Y * GFX_PPL;
+ uint32 VOffset = LineData [Y].BG[bg].VOffset;
+ uint32 HOffset = LineData [Y].BG[bg].HOffset;
+ int VirtAlign = (Y + VOffset) & 7;
+
+ int maxLines = GFX.EndY - Y + 1;
+ if ((8 - VirtAlign) < maxLines) maxLines = (8 - VirtAlign);
+
+ for (Lines = 1; Lines < maxLines; Lines++)
+ if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
+ (HOffset != LineData [Y + Lines].BG[bg].HOffset))
+ break;
+
+
+ VirtAlign <<= 3;
+
+ uint32 ScreenLine = (VOffset + Y) >> 3;
+ uint16 *b1;
+ uint16 *b2;
+
+ if (ScreenLine & 0x20)
+ b1 = SC2, b2 = SC3;
+ else
+ b1 = SC0, b2 = SC1;
+
+ b1 += (ScreenLine & 0x1f) << 5;
+ b2 += (ScreenLine & 0x1f) << 5;
+
+ uint32 Left;
+ uint32 Right;
+ int clip = 0;
+ int clipcount = GFX.pCurrentClip->Count [bg];
+ if (!clipcount) {
+ Left = 0;
+ Right = 256;
+ }
+
+ do {
+ if (clipcount) {
+ Left = GFX.pCurrentClip->Left [clip][bg];
+ Right = GFX.pCurrentClip->Right [clip][bg];
+
+ if (Right <= Left) {clip++; continue;}
+ }
+
+ uint32 s = Left + y_ppl;
+ uint32 HPos = (HOffset + Left) & 0x1ff;
+ uint32 Quot = HPos >> 3;
+ uint32 Count = 0;
+ uint16 *t;
+ uint16 *b;
+
+ if (Quot > 31) {
+ t = b2 + (Quot & 0x1f);
+ b = b1;
+ Quot -= 32;
+ }
+ else {
+ t = b1 + Quot;
+ b = b2;
+ }
+
+ uint32 Width = Right - Left;
+
+ // Left hand edge clipped tile
+ uint32 Offset = (HPos & 7);
+ if (Offset){
+ Count = 8 - Offset;
+ if (Count > Width) Count = Width;
+ s -= Offset;
+ //Tile = READ_2BYTES(t);
+ register uint32 Tile = *(t++);
+ if (Tile != TileBlank){
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines);
+ }
+ //t++;
+ if (Quot == 31) t = b;
+ //else if (Quot == 63) t = b1;
+ Quot++;
+ s += 8;
+ }
+
+ // Middle, unclipped tiles
+ Count = Width - Count;
+ for (int C = Count >> 3; C > 0; s += 8, Quot++, C--){
+ //Tile = READ_2BYTES(t);
+ register uint32 Tile = *(t++);
+ if (Tile != TileBlank){
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ (*DrawTilePtr) (Tile, s, VirtAlign, Lines);
+ }
+
+ //t++;
+ if (Quot == 31) t = b;
+ //else if (Quot == 63) t = b1;
+ }
+
+ // Right-hand edge clipped tiles
+ if (Count & 7){
+ //Tile = READ_2BYTES(t);
+ register uint32 Tile = *t;
+ if (Tile != TileBlank){
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ (*DrawClippedTilePtr) (Tile, s, 0, Count & 7, VirtAlign, Lines);
+ }
+ }
+ clip ++;
+ } while (clip < clipcount);
+ }
+}
+
+void DrawBackground_16 (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
+{
+#ifdef __DEBUG__
+ printf("DrawBackground_16(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2);
+#endif
+ //uint32 Tile;
+ uint16 *SC0;
+ uint16 *SC1;
+ uint16 *SC2;
+ uint16 *SC3;
+ uint32 depths [2] = {Z1, Z2};
+
+ SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
+
+ SC1 = SC0 + ((PPU.BG[bg].SCSize & 1) << 10);
+
+ if(SC1 >= (unsigned short*)(Memory.VRAM+0x10000)) SC1 = (uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0]) & 0xffff];
+
+ if (PPU.BG[bg].SCSize & 2)
+ SC2 = SC1 + 1024;
+ else
+ SC2 = SC0;
+
+ if(((uint8*)SC2-Memory.VRAM)>=0x10000) SC2 -= 0x08000;
+
+ SC3 = SC2 + ((PPU.BG[bg].SCSize & 1) << 10);
+
+ if(((uint8*)SC3-Memory.VRAM)>=0x10000) SC3 -= 0x08000;
+
+ int Lines;
+
+ TileBlank = 0xFFFFFFFF;
+ for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines){
+ int y_ppl = Y * GFX_PPL;
+ uint32 VOffset = LineData [Y].BG[bg].VOffset;
+ uint32 HOffset = LineData [Y].BG[bg].HOffset;
+ int VirtAlign = (Y + VOffset) & 7;
+
+ int maxLines = GFX.EndY - Y + 1;
+ if ((8 - VirtAlign) < maxLines) maxLines = (8 - VirtAlign);
+
+ for (Lines = 1; Lines < maxLines; Lines++)
+ if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
+ (HOffset != LineData [Y + Lines].BG[bg].HOffset))
+ break;
+
+
+ VirtAlign <<= 3;
+
+ uint32 ScreenLine = (VOffset + Y) >> 4;
+ int tx_index = ( ((VOffset + Y) & 15) <= 7 ) << 3;
+ uint16 *b1;
+ uint16 *b2;
+
+ if (ScreenLine & 0x20)
+ b1 = SC2, b2 = SC3;
+ else
+ b1 = SC0, b2 = SC1;
+
+ b1 += (ScreenLine & 0x1f) << 5;
+ b2 += (ScreenLine & 0x1f) << 5;
+
+ uint32 Left;
+ uint32 Right;
+ int clip = 0;
+ int clipcount = GFX.pCurrentClip->Count [bg];
+ if (!clipcount) {
+ Left = 0;
+ Right = 256;
+ }
+
+ do {
+ if (clipcount) {
+ Left = GFX.pCurrentClip->Left [clip][bg];
+ Right = GFX.pCurrentClip->Right [clip][bg];
+
+ if (Right <= Left) {clip++; continue;}
+ }
+
+ uint32 s = Left + y_ppl;
+ uint32 HPos = (HOffset + Left) & 0x3ff;
+ uint32 Quot = HPos >> 3;
+ uint32 Count = 0;
+ uint16 *t;
+ uint16 *b;
+
+ if (Quot > 63) {
+ t = b2 + ((Quot >> 1) & 0x1f);
+ b = b1;
+ Quot -= 64;
+ }
+ else {
+ t = b1 + (Quot >> 1);
+ b = b2;
+ }
+
+
+ uint32 Width = Right - Left;
+
+ // Left hand edge clipped tile
+ uint32 Offset = (HPos & 7);
+ if (Offset){
+ Count = 8 - Offset;
+ if (Count > Width) Count = Width;
+ s -= Offset;
+ //Tile = READ_2BYTES(t);
+ uint32 Tile = *(t);
+ Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)];
+ if (Tile != TileBlank){
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines);
+ }
+ //t++;
+ t += Quot & 1;
+ if (Quot == 63) t = b;
+ Quot++;
+ s += 8;
+ }
+
+ // Middle, unclipped tiles
+ Count = Width - Count;
+ for (int C = Count >> 3; C > 0; s += 8, Quot++, C--){
+ //Tile = READ_2BYTES(t);
+ uint32 Tile = *(t);
+ Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)];
+ if (Tile != TileBlank){
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ //(*DrawTilePtr) (Tile, s, VirtAlign, Lines);
+ }
+
+ //t++;
+ t += Quot & 1;
+ if (Quot == 63) t = b;
+ }
+
+ // Right-hand edge clipped tiles
+ if (Count & 7){
+ //Tile = READ_2BYTES(t);
+ uint32 Tile = *(t);
+ Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)];
+ if (Tile != TileBlank){
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ (*DrawClippedTilePtr) (Tile, s, 0, Count & 7, VirtAlign, Lines);
+ }
+ }
+ clip ++;
+ } while (clip < clipcount);
+ }
+}
+
+
+inline void DrawBackground (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
+{
+//StartAnalyze();
+
+ BG.TileSize = BGSizes [PPU.BG[bg].BGSize];
+ BG.BitShift = BitShifts[BGMode][bg];
+ SelectConvertTile();
+ BG.TileShift = TileShifts[BGMode][bg];
+ BG.TileAddress = PPU.BG[bg].NameBase << 1;
+ BG.NameSelect = 0;
+ BG.Buffer = IPPU.TileCache [Depths [BGMode][bg]];
+ BG.Buffered = IPPU.TileCached [Depths [BGMode][bg]];
+ BG.PaletteShift = PaletteShifts[BGMode][bg];
+ BG.PaletteMask = PaletteMasks[BGMode][bg];
+ BG.DirectColourMode = (BGMode == 3 || BGMode == 4) && bg == 0 && (GFX.r2130 & 1);
+
+ if (IPPU.DirectColourMapsNeedRebuild && BG.DirectColourMode) S9xBuildDirectColourMaps ();
+
+ if (PPU.BGMosaic [bg] && PPU.Mosaic > 1){
+ DrawBackgroundMosaic (BGMode, bg, Z1, Z2);
+ return;
+
+ }
+ switch (BGMode)
+ {
+ case 2:
+ case 4: // Used by Puzzle Bobble
+ DrawBackgroundOffset (BGMode, bg, Z1, Z2);
+ break;
+
+ case 5:
+ case 6: // XXX: is also offset per tile.
+ DrawBackgroundMode5 (BGMode, bg, Z1, Z2);
+ break;
+ case 0:
+ case 1:
+ case 3:
+ CHECK_SOUND();
+
+ if (BGMode == 0) BG.StartPalette = bg << 5;
+ else BG.StartPalette = 0;
+ SelectPalette();
+
+ if (BG.TileSize == 8) DrawBackground_8 (BGMode, bg, Z1, Z2);
+ else DrawBackground_16 (BGMode, bg, Z1, Z2);
+ break;
+ }
+}
+
+#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; \
+GREEN_HI_BIT = ((MAX_GREEN_##F + 1) >> 1); \
+SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_##F; \
+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);
+
+void RenderScreen (uint8 *Screen, bool8_32 sub, bool8_32 force_no_add, uint8 D)
+{
+ bool8_32 BG0;
+ bool8_32 BG1;
+ bool8_32 BG2;
+ bool8_32 BG3;
+ bool8_32 OB;
+
+ GFX.S = Screen;
+
+ if (!sub)
+ {
+ GFX.pCurrentClip = &IPPU.Clip [0];
+ BG0 = ON_MAIN (0) && !(Settings.os9x_hack & GFX_IGNORE_BG0);
+ BG1 = ON_MAIN (1) && !(Settings.os9x_hack & GFX_IGNORE_BG1);
+ BG2 = ON_MAIN (2) && !(Settings.os9x_hack & GFX_IGNORE_BG2);
+ BG3 = ON_MAIN (3) && !(Settings.os9x_hack & GFX_IGNORE_BG3);
+ OB = ON_MAIN (4) && !(Settings.os9x_hack & GFX_IGNORE_OBJ);
+ }
+ else
+ {
+ GFX.pCurrentClip = &IPPU.Clip [1];
+ BG0 = ON_SUB (0) && !(Settings.os9x_hack & GFX_IGNORE_BG0);
+ BG1 = ON_SUB (1) && !(Settings.os9x_hack & GFX_IGNORE_BG1);
+ BG2 = ON_SUB (2) && !(Settings.os9x_hack & GFX_IGNORE_BG2);
+ BG3 = ON_SUB (3) && !(Settings.os9x_hack & GFX_IGNORE_BG3);
+ OB = ON_SUB (4) && !(Settings.os9x_hack & GFX_IGNORE_OBJ);
+ }
+
+#ifdef __DEBUG__
+ printf("Screen[y1,y2]:[%i,%i],Mode:%i, BG0:%i,BG1:%i,BG2:%i,BG3:%i,OBJ:%i\n", GFX.StartY, GFX.EndY, PPU.BGMode, BG0, BG1, BG2, BG3, OB);
+#endif
+
+ sub |= force_no_add;
+
+ if (PPU.BGMode <= 1)
+ {
+ if (OB)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(4), true);
+ DrawOBJS (!sub, D);
+ }
+ if (BG0)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(0));
+ DrawBackground (PPU.BGMode, 0, D + 10, D + 14);
+ }
+ if (BG1)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(1));
+ DrawBackground (PPU.BGMode, 1, D + 9, D + 13);
+ }
+ if (BG2)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(2));
+ DrawBackground (PPU.BGMode, 2, D + 3,
+ PPU.BG3Priority ? D + 17 : D + 6);
+ }
+ if (BG3 && PPU.BGMode == 0)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(3));
+ DrawBackground (PPU.BGMode, 3, D + 2, D + 5);
+ }
+ }
+ else if (PPU.BGMode != 7)
+ {
+ if (OB)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(4), true);
+ DrawOBJS (!sub, D);
+ }
+ if (BG0)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(0));
+ DrawBackground (PPU.BGMode, 0, D + 5, D + 13);
+ }
+ if (PPU.BGMode != 6 && BG1)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(1));
+ DrawBackground (PPU.BGMode, 1, D + 2, D + 9);
+ }
+ }
+ else
+ {
+ if (OB && ((SNESGameFixes.Mode7Hack && D) || !SNESGameFixes.Mode7Hack))
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(4), true);
+ DrawOBJS (!sub, D);
+ }
+ if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1))
+ {
+ int bg;
+
+ if ((Memory.FillRAM [0x2133] & 0x40)&&BG1)
+ {
+ Mode7Depths [0] = (BG0?5:1) + D;
+ Mode7Depths [1] = 9 + D;
+ bg = 1;
+ if (sub || !SUB_OR_ADD(0))
+ {
+ DrawBGMode7Background16Prio (Screen, bg);
+ }
+ else
+ {
+ if (GFX.r2131 & 0x80)
+ {
+ if (GFX.r2131 & 0x40)
+ {
+ DrawBGMode7Background16PrioSub1_2 (Screen, bg);
+ }
+ else
+ {
+ DrawBGMode7Background16PrioSub (Screen, bg);
+ }
+ }
+ else
+ {
+ if (GFX.r2131 & 0x40)
+ {
+ DrawBGMode7Background16PrioAdd1_2 (Screen, bg);
+ }
+ else
+ {
+ DrawBGMode7Background16PrioAdd (Screen, bg);
+ }
+ }
+ }
+ }
+ else
+ {
+ bg = 0;
+ if (sub || !SUB_OR_ADD(0))
+ {
+ if (D || !SNESGameFixes.Mode7Hack) DrawBGMode7Background16 (Screen, bg, D+5);
+ else DrawBGMode7Background16New (Screen);
+ }
+ else
+ {
+ if (GFX.r2131 & 0x80)
+ {
+ if (GFX.r2131 & 0x40)
+ {
+ DrawBGMode7Background16Sub1_2 (Screen, bg, D+5);
+ }
+ else
+ {
+ DrawBGMode7Background16Sub (Screen, bg, D+5);
+ }
+ }
+ else
+ {
+ if (GFX.r2131 & 0x40)
+ {
+ DrawBGMode7Background16Add1_2 (Screen, bg, D+5);
+ }
+ else
+ {
+ DrawBGMode7Background16Add (Screen, bg, D+5);
+ }
+ }
+ }
+ }
+ }
+ if (OB && SNESGameFixes.Mode7Hack && D==0)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(4), true);
+ DrawOBJS (!sub, D);
+ }
+ }
+}
+
+#include "font.h"
+
+void DisplayChar (uint8 *Screen, uint8 c)
+{
+ int line = (((c & 0x7f) - 32) >> 4) * font_height;
+ int offset = (((c & 0x7f) - 32) & 15) * font_width;
+ int h, w;
+ uint16 *s = (uint16 *) Screen;
+ for (h = 0; h < font_height; h++, line++,
+ s += GFX_PPL - font_width)
+ {
+ for (w = 0; w < font_width; w++, s++)
+ {
+ uint8 p = font [line][offset + w];
+
+ if (p == '#')
+ *s = 0xffff;
+ else
+ if (p == '.')
+ *s = BLACK;
+ }
+ }
+}
+
+static void S9xDisplayFrameRate ()
+{
+ uint8 *Screen = GFX.Screen + 2 +
+ (IPPU.RenderedScreenHeight - font_height - 1) * GFX_PITCH;
+ char string [10];
+ int len = 5;
+
+ sprintf (string, "%02d/%02d", IPPU.DisplayedRenderedFrameCount,
+ (int) Memory.ROMFramesPerSecond);
+
+ int i;
+ for (i = 0; i < len; i++)
+ {
+ DisplayChar (Screen, string [i]);
+ Screen += (font_width - 1) * sizeof (uint16);
+ }
+}
+
+static void S9xDisplayString (const char *string)
+{
+ uint8 *Screen = GFX.Screen + 2 +
+ (IPPU.RenderedScreenHeight - font_height * 5) * GFX_PITCH;
+ int len = strlen (string);
+ int max_chars = IPPU.RenderedScreenWidth / (font_width - 1);
+ int char_count = 0;
+ int i;
+
+ for (i = 0; i < len; i++, char_count++)
+ {
+ if (char_count >= max_chars || string [i] < 32)
+ {
+ Screen -= (font_width - 1) * sizeof (uint16) * max_chars;
+ Screen += font_height * GFX_PITCH;
+ if (Screen >= GFX.Screen + GFX_PITCH * IPPU.RenderedScreenHeight)
+ break;
+ char_count -= max_chars;
+ }
+ if (string [i] < 32)
+ continue;
+ DisplayChar (Screen, string [i]);
+ Screen += (font_width - 1) * sizeof (uint16);
+ }
+}
+
+
+void S9xUpdateScreen () // ~30-50ms! (called from FLUSH_REDRAW())
+{
+ GFX.S = GFX.Screen;
+
+ unsigned char *memoryfillram = Memory.FillRAM;
+
+ // get local copies of vid registers to be used later
+ GFX.r2131 = memoryfillram [0x2131]; // ADDITION/SUBTRACTION & SUBTRACTION DESIGNATION FOR EACH SCREEN
+ GFX.r212c = memoryfillram [0x212c]; // MAIN SCREEN, DESIGNATION - used to enable BGS
+ GFX.r212d = memoryfillram [0x212d]; // SUB SCREEN DESIGNATION - used to enable sub BGS
+ GFX.r2130 = memoryfillram [0x2130]; // INITIAL SETTINGS FOR FIXED COLOR ADDITION OR SCREEN ADDITION
+
+ // If external sync is off and
+ // main screens have not been configured the same as the sub screen and
+ // color addition and subtraction has been diabled then
+ // Pseudo is 1
+ // anything else it is 0
+ GFX.Pseudo = (memoryfillram [0x2133] & 8) != 0 && // Use EXTERNAL SYNCHRONIZATION?
+ (GFX.r212c & 15) != (GFX.r212d & 15) && // Are the main screens different from the sub screens?
+ (GFX.r2131 & 0x3f) == 0; // Is colour data addition/subtraction disabled on all BGS?
+
+ // If sprite data has been changed then go through and
+ // refresh the sprites.
+ if (IPPU.OBJChanged) S9xSetupOBJ ();
+
+ if (PPU.RecomputeClipWindows) ComputeClipWindows ();
+
+ GFX.StartY = IPPU.PreviousLine;
+ if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight)
+ GFX.EndY = PPU.ScreenHeight - 1;
+
+ uint32 starty = GFX.StartY;
+ uint32 endy = GFX.EndY;
+ uint32 black = BLACK | (BLACK << 16);
+
+
+ if (GFX.Pseudo)
+ {
+ GFX.r2131 = 0x5f; //0101 1111 - enable addition/subtraction on all BGS and sprites and "1/2 OF COLOR DATA" DESIGNATION
+ GFX.r212c &= (Memory.FillRAM [0x212d] | 0xf0);
+ GFX.r212d |= (Memory.FillRAM [0x212c] & 0x0f);
+ GFX.r2130 |= 2; // enable ADDITION/SUBTRACTION FOR SUB SCREEN
+ }
+
+ // Check to see if any transparency effects are currently in use
+ if (!PPU.ForcedBlanking && ADD_OR_SUB_ON_ANYTHING &&
+ (GFX.r2130 & 0x30) != 0x30 &&
+ !((GFX.r2130 & 0x30) == 0x10 && IPPU.Clip[1].Count[5] == 0))
+ {
+ // transparency effects in use, so lets get busy!
+ struct ClipData *pClip;
+ uint32 fixedColour;
+ GFX.FixedColour = BUILD_PIXEL (IPPU.XB [PPU.FixedColourRed],
+ IPPU.XB [PPU.FixedColourGreen],
+ IPPU.XB [PPU.FixedColourBlue]);
+ fixedColour = (GFX.FixedColour<<16|GFX.FixedColour);
+ // Clear the z-buffer, marking areas 'covered' by the fixed
+ // colour as depth 1.
+ pClip = &IPPU.Clip [1];
+
+ // Clear the z-buffer
+
+ if (pClip->Count [5])
+ {
+
+ // Colour window enabled.
+ // loop around all of the lines being updated
+ for (uint32 y = starty; y <= endy; y++)
+ {
+ // Clear the subZbuffer
+ memset32 ((uint32_t*)(GFX.SubZBuffer + y * GFX_ZPITCH),0, (256>>2));
+ // Clear the Zbuffer
+ memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH),0, (256>>2));
+ if (IPPU.Clip[0].Count [5]) {
+ // if there is clipping then clear subscreen to a black color
+ memset32 ((uint32_t*)(GFX.SubScreen + y * GFX_PITCH), black, (256>>1));
+ }
+
+ // loop through all window clippings
+ for (uint32 c = 0; c < pClip->Count [5]; c++)
+ {
+ if (pClip->Right [c][5] > pClip->Left [c][5])
+ {
+ memset (GFX.SubZBuffer + y * GFX_ZPITCH + pClip->Left [c][5],
+ 1, pClip->Right [c][5] - pClip->Left [c][5]);
+
+ if (IPPU.Clip [0].Count [5])
+ {
+ // Blast, have to clear the sub-screen to the fixed-colour
+ // because there is a colour window in effect clipping
+ // the main screen that will allow the sub-screen
+ // 'underneath' to show through.
+
+ register unsigned int width = pClip->Right [c][5] - pClip->Left [c][5];
+ if (width > 0) {
+ asm volatile (
+ " mov r0, %[fixedcolour] \n"
+ " subs %[width], %[width], #4 \n"
+ " bmi 2f \n"
+
+ "1: \n"
+ " subs %[width], %[width], #4 \n"
+ " stmia %[p]!, {r0, %[fixedcolour]}\n"
+ " bpl 1b \n"
+
+ "2: \n"
+ " tst %[width], #1 \n"
+ " strneh %[fixedcolour], [%[p]], #2 \n"
+
+ " tst %[width], #2 \n"
+ " strne %[fixedcolour], [%[p]], #4 \n"
+
+ : [width] "+r" (width)
+ : [fixedcolour] "r" (fixedColour),
+ [p] "r" (((uint16 *) (GFX.SubScreen + y * GFX_PITCH)) + pClip->Left [c][5])
+ : "r0", "cc"
+ );
+ }
+ }
+ }
+ }
+ }
+
+ }
+ else
+ {
+ // No windows are clipping the main screen
+ // this simplifies the screen clearing process
+ // loop through all of the lines to be updated
+ for (uint32 y = starty; y <= endy; y++) {
+ // Clear the Zbuffer
+ memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH),0, (256>>2));
+ // clear the sub Zbuffer to 1
+ memset32 ((uint32_t*)(GFX.SubZBuffer + y * GFX_ZPITCH), 0x01010101, (256>>2));
+
+ if (IPPU.Clip [0].Count [5]) {
+ // Blast, have to clear the sub-screen to the fixed-colour
+ // because there is a colour window in effect clipping
+ // the main screen that will allow the sub-screen
+ // 'underneath' to show through.
+
+ memset32 ((uint32_t*)(GFX.SubScreen + y * GFX_PITCH), fixedColour, (256>>1));
+ }
+ }
+ }
+ if (ANYTHING_ON_SUB)
+ {
+ GFX.DB = GFX.SubZBuffer;
+ RenderScreen (GFX.SubScreen, TRUE, TRUE, SUB_SCREEN_DEPTH);
+ }
+
+ if (IPPU.Clip [0].Count [5])
+ {
+ asm volatile (
+ "1: \n"
+ " mov r1, #(256 >> 2) \n"
+
+ "2: \n"
+ // four pixels at once
+ " ldrb r0, [%[d]], #1 \n"
+ " ldrb r4, [%[d]], #1 \n"
+
+ " bics r0, r0, #1 \n"
+ " ldrneh r0, [%[p], %[delta]] \n"
+
+ " bics r4, r4, #1 \n"
+ " ldrneh r4, [%[p], %[delta2]] \n"
+
+ " strh r0, [%[p]], #2 \n"
+ " strh r4, [%[p]], #2 \n"
+
+ " ldrb r0, [%[d]], #1 \n"
+ " ldrb r4, [%[d]], #1 \n"
+
+ " bics r0, r0, #1 \n"
+ " ldrneh r0, [%[p], %[delta]] \n"
+
+ " bics r4, r4, #1 \n"
+ " ldrneh r4, [%[p], %[delta2]] \n"
+
+ " strh r0, [%[p]], #2 \n"
+ " strh r4, [%[p]], #2 \n"
+
+ " subs r1, r1, #1 \n"
+ " bne 2b \n"
+ "3: \n"
+ " subs %[lines], %[lines], #1 \n"
+ " add %[p], %[p], #(640 - 512) \n"
+ " add %[d], %[d], #(320 - 256) \n"
+ " bne 1b \n"
+ "4: \n"
+
+ :
+ : [p] "r" ((uint16 *) (GFX.Screen + starty * GFX_PITCH)),
+ [d] "r" (GFX.SubZBuffer + starty * GFX_ZPITCH),
+ [delta] "r" (GFX.Delta << 1),
+ [delta2] "r" ((GFX.Delta << 1) + 2),
+ [lines] "r" (endy - starty + 1)
+ : "r0", "r1", "r3", "r4", "cc"
+ );
+ }
+
+ GFX.DB = GFX.ZBuffer;
+ RenderScreen (GFX.Screen, FALSE, FALSE, MAIN_SCREEN_DEPTH);
+ if (SUB_OR_ADD(5))
+ {
+ uint32 back = IPPU.ScreenColors [0];
+ uint32 Left = 0;
+ uint32 Right = 256;
+ uint32 Count;
+
+ pClip = &IPPU.Clip [0];
+
+ for (uint32 y = starty; y <= endy; y++)
+ {
+ if (!(Count = pClip->Count [5]))
+ {
+ Left = 0;
+ Right = 256;
+ Count = 1;
+ }
+
+ for (uint32 b = 0; b < Count; b++)
+ {
+ if (pClip->Count [5])
+ {
+ Left = pClip->Left [b][5];
+ Right = pClip->Right [b][5];
+ if (Right <= Left)
+ continue;
+ }
+#define SUBSCREEN_BG(rop, half) \
+\
+asm volatile (\
+" ldrb r0, [%[d]], #1 \n"\
+"71: \n"\
+\
+" movs r0, r0 \n"\
+" ldreqb r1, [%[d], %[zdelta]] \n"\
+" bne 72f \n"\
+\
+" cmp r1, #1 \n"\
+" beq 74f \n"\
+" ldrh r1, [%[p], %[delta]] \n"\
+" mov r0, %[back] \n"\
+\
+ROP_##rop##half (r0, r1)\
+\
+" strh r0, [%[p]] \n"\
+"72: \n"\
+" add %[p], %[p], #2 \n"\
+" subs %[c], %[c], #1 \n"\
+" ldrneb r0, [%[d]], #1 \n"\
+" bne 71b \n"\
+" b 75f \n"\
+"74: \n"\
+" streqh %[fixedcolour], [%[p]], #2 \n"\
+" strloh %[back], [%[p]], #2 \n"\
+" subs %[c], %[c], #1 \n"\
+" ldrneb r0, [%[d]], #1 \n"\
+" bne 71b \n"\
+"75: \n"\
+:\
+:[p] "r" ((uint16 *) (GFX.Screen + y * GFX_PITCH) + Left),\
+ [d] "r" (GFX.ZBuffer + y * GFX_ZPITCH + Left),\
+ [zdelta] "r" (GFX.DepthDelta),\
+ [back] "r" (back),\
+ [delta] "r" (GFX.Delta << 1),\
+ [fixedcolour] "r" (COLOR_##rop (back, GFX.FixedColour)),\
+ [c] "r" (Right - Left) \
+: "r0", "r1", "cc"\
+);
+ if (GFX.r2131 & 0x80)
+ {
+ if (GFX.r2131 & 0x40)
+ {
+ SUBSCREEN_BG(SUB, 1_2)
+ }
+ else
+ {
+ SUBSCREEN_BG(SUB, )
+
+ }
+ }
+ else
+ if (GFX.r2131 & 0x40)
+ {
+ SUBSCREEN_BG(ADD, 1_2)
+ }
+ else if (back != 0) {
+ SUBSCREEN_BG(ADD, )
+ }
+ else
+ {
+ if (!pClip->Count [5])
+ {
+ // The backdrop has not been cleared yet - so
+ // copy the sub-screen to the main screen
+ // or fill it with the back-drop colour if the
+ // sub-screen is clear.
+ asm volatile (
+ " ldrb r0, [%[d]], #1 \n"
+ "31: \n"
+
+ " movs r0, r0 \n"
+ " ldreqb r1, [%[d], %[zdelta]] \n"
+ " bne 32f \n"
+
+ " cmp r1, #1 \n"
+ " ldrhih r0, [%[p], %[delta]] \n"
+ " strloh %[back], [%[p]] \n"
+ " streqh %[fixedcolour], [%[p]] \n"
+ " strhih r0, [%[p]] \n"
+
+ "32: \n"
+ " subs %[c], %[c], #1 \n"
+ " add %[p], %[p], #2 \n"
+ " ldrneb r0, [%[d]], #1 \n"
+ " bne 31b \n"
+ " \n"
+ :
+ :[p] "r" ((uint16 *) (GFX.Screen + y * GFX_PITCH) + Left),
+ [d] "r" (GFX.ZBuffer + y * GFX_ZPITCH + Left),
+ [zdelta] "r" (GFX.DepthDelta),
+ [back] "r" (back),
+ [delta] "r" (GFX.Delta << 1),
+ [fixedcolour] "r" (GFX.FixedColour),
+ [c] "r" (Right - Left)
+ : "r0", "r1", "cc"
+
+ );
+
+ }
+ }
+ }
+ }
+
+ }
+ else
+ {
+ // Subscreen not being added to back
+ uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16);
+ pClip = &IPPU.Clip [0];
+
+ if (pClip->Count [5])
+ {
+ for (uint32 y = starty; y <= endy; y++)
+ {
+ for (uint32 b = 0; b < pClip->Count [5]; b++)
+ {
+ uint32 Left = pClip->Left [b][5];
+ uint32 Right = pClip->Right [b][5];
+ if (Left >= Right) continue;
+ asm volatile (
+
+ " tst %[c], #1 \n"
+ " bne 21f \n"
+
+ " ldrb r0, [%[d]], #1 \n"
+ " add %[p], %[p], #2 \n"
+ " movs r0, r0 \n"
+ " streqh %[back], [%[p], #-2] \n"
+ " subs %[c], %[c], #1 \n"
+ " beq 22f \n"
+
+ "21: \n"
+
+ " ldrb r0, [%[d]], #1 \n"
+ " ldrb r1, [%[d]], #1 \n"
+ " add %[p], %[p], #4 \n"
+
+ " movs r0, r0 \n"
+ " streqh %[back], [%[p], #-4] \n"
+
+ " movs r1, r1 \n"
+ " streqh %[back], [%[p], #-2] \n"
+
+ " subs %[c], %[c], #2 \n"
+ " bhi 21b \n"
+ "22: \n"
+ :
+ :[p] "r" ((uint16 *) (GFX.Screen + y * GFX_PITCH) + Left),
+ [d] "r" (GFX.ZBuffer + y * GFX_ZPITCH + Left),
+ [back] "r" (back),
+ [c] "r" (Right - Left)
+ : "r0", "r1", "cc"
+
+ );
+ }
+ }
+ }
+ else
+ {
+ asm volatile (
+ "@ -- SubScreen clear \n"
+ "1113: \n"
+ " mov r1, #(256/8) \n"
+ "1112: \n"
+ " ldr r0, [%[d]], #4 \n"
+
+ " add %[p], %[p], #8 \n"
+
+ " tst r0, #0x0ff \n"
+ " streqh %[back], [%[p], #-8] \n"
+
+ " tst r0, #0x0ff00 \n"
+ " streqh %[back], [%[p], #-6] \n"
+
+ " tst r0, #0x0ff0000 \n"
+ " streqh %[back], [%[p], #-4] \n"
+
+ " tst r0, #0x0ff000000 \n"
+ " streqh %[back], [%[p], #-2] \n"
+
+ " ldr r0, [%[d]], #4 \n"
+
+ " add %[p], %[p], #8 \n"
+
+ " tst r0, #0x0ff \n"
+ " streqh %[back], [%[p], #-8] \n"
+
+ " tst r0, #0x0ff00 \n"
+ " streqh %[back], [%[p], #-6] \n"
+
+ " tst r0, #0x0ff0000 \n"
+ " streqh %[back], [%[p], #-4] \n"
+
+ " tst r0, #0x0ff000000 \n"
+ " streqh %[back], [%[p], #-2] \n"
+
+ " subs r1, r1, #1 \n"
+ " bne 1112b \n"
+
+ " subs %[lines], %[lines], #1 \n"
+ " add %[p], %[p], #(640-512) \n"
+ " add %[d], %[d], #(320-256) \n"
+ " bne 1113b \n"
+ "1114:"
+ :
+ :[p] "r" (GFX.Screen + starty * GFX_PITCH),
+ [d] "r" (GFX.ZBuffer + starty * GFX_ZPITCH),
+ [back] "r" (back),
+ [lines] "r" (endy - starty + 1)
+ : "r0", "r1", "cc"
+ );
+ }
+ }
+ }
+ else
+ {
+ // 16bit and transparency but currently no transparency effects in
+ // operation.
+
+ // get the back colour of the current screen
+ uint32 back = IPPU.ScreenColors [0] |
+ (IPPU.ScreenColors [0] << 16);
+
+ // if forceblanking in use then use black instead of the back color
+ if (PPU.ForcedBlanking)
+ back = black;
+
+ // not sure what Clip is used for yet
+ // could be a check to see if there is any clipping present?
+ if (IPPU.Clip [0].Count[5])
+ {
+
+ // loop through all of the lines that are going to be updated as part of this screen update
+ for (uint32 y = starty; y <= endy; y++)
+ {
+ memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), black,
+ IPPU.RenderedScreenWidth>>1);
+
+ if (black!=back)
+ {
+ for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++)
+ {
+ if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5])
+ {
+ register unsigned int width = IPPU.Clip [0].Right [c][5] - IPPU.Clip [0].Left [c][5];
+ if (width > 0) {
+ asm volatile (
+ " mov r0, %[back] \n"
+ " subs %[width], %[width], #4 \n"
+ " bmi 2f \n"
+
+ "1: \n"
+ " subs %[width], %[width], #4 \n"
+ " stmia %[p]!, {r0, %[back]} \n"
+ " bpl 1b \n"
+
+ "2: \n"
+ " tst %[width], #1 \n"
+ " strneh %[back], [%[p]], #2 \n"
+
+ " tst %[width], #2 \n"
+ " strne %[back], [%[p]], #4 \n"
+ : [width] "+r" (width)
+ : [back] "r" (back | (back << 16)),
+ [p] "r" (((uint16 *) (GFX.SubScreen + y * GFX_PITCH)) + IPPU.Clip [0].Left [c][5])
+ : "r0", "cc"
+ );
+ }
+
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // there is no clipping to worry about so just fill with the back colour
+ for (uint32 y = starty; y <= endy; y++) {
+ memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), back, (256>>1));
+ }
+
+ }
+
+ // If Forced blanking is not in effect
+ if (!PPU.ForcedBlanking)
+ {
+ // Clear the Zbuffer for each of the lines which are going to be updated
+ for (uint32 y = starty; y <= endy; y++) {
+ memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH), 0, (256>>2));
+ }
+ GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object
+ RenderScreen (GFX.Screen, FALSE, TRUE, SUB_SCREEN_DEPTH);
+ }
+ }
+ IPPU.PreviousLine = IPPU.CurrentLine;
+}
+
+// -x-
+void S9xUpdateScreenNoTransparency () // ~30-50ms! (called from FLUSH_REDRAW())
+{
+ GFX.S = GFX.Screen;
+
+ unsigned char *memoryfillram = Memory.FillRAM;
+
+ // get local copies of vid registers to be used later
+ GFX.r2131 = memoryfillram [0x2131]; // ADDITION/SUBTRACTION & SUBTRACTION DESIGNATION FOR EACH SCREEN
+ GFX.r212c = memoryfillram [0x212c]; // MAIN SCREEN, DESIGNATION - used to enable BGS
+ GFX.r212d = memoryfillram [0x212d]; // SUB SCREEN DESIGNATION - used to enable sub BGS
+ GFX.r2130 = memoryfillram [0x2130]; // INITIAL SETTINGS FOR FIXED COLOR ADDITION OR SCREEN ADDITION
+
+ // If external sync is off and
+ // main screens have not been configured the same as the sub screen and
+ // color addition and subtraction has been diabled then
+ // Pseudo is 1
+ // anything else it is 0
+ GFX.Pseudo = (memoryfillram [0x2133] & 8) != 0 && // Use EXTERNAL SYNCHRONIZATION?
+ (GFX.r212c & 15) != (GFX.r212d & 15) && // Are the main screens different from the sub screens?
+ (GFX.r2131 & 0x3f) == 0; // Is colour data addition/subtraction disabled on all BGS?
+
+ // If sprite data has been changed then go through and
+ // refresh the sprites.
+ if (IPPU.OBJChanged)
+ {
+ S9xSetupOBJ ();
+ }
+
+ if (PPU.RecomputeClipWindows) ComputeClipWindows();
+
+ GFX.StartY = IPPU.PreviousLine;
+ if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight)
+ GFX.EndY = PPU.ScreenHeight - 1;
+
+ uint32 starty = GFX.StartY;
+ uint32 endy = GFX.EndY;
+
+ uint32 black = BLACK | (BLACK << 16);
+
+ // get back colour to be used in clearing the screen
+ register uint32 back;
+ if (!(Memory.FillRAM [0x2131] & 0x80) &&(Memory.FillRAM[0x2131] & 0x20) &&
+ (PPU.FixedColourRed || PPU.FixedColourGreen || PPU.FixedColourBlue))
+ {
+ back = (IPPU.XB[PPU.FixedColourRed]<<11) |
+ (IPPU.XB[PPU.FixedColourGreen] << 6) |
+ (IPPU.XB[PPU.FixedColourBlue] << 1) | 1;
+ back = (back << 16) | back;
+ }
+ else
+ {
+ back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16);
+ }
+
+ // if Forcedblanking in use then back colour becomes black
+ if (PPU.ForcedBlanking)
+ back = black;
+ else
+ {
+ SelectTileRenderer (TRUE); //selects the tile renderers to be used
+ // TRUE means to use the default
+ // FALSE means use best renderer based on current
+ // graphics register settings
+ }
+
+ // now clear all graphics lines which are being updated using the back colour
+ for (register uint32 y = starty; y <= endy; y++)
+ {
+ memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), back,
+ IPPU.RenderedScreenWidth>>1);
+ }
+
+ if (!PPU.ForcedBlanking)
+ {
+ // Loop through all lines being updated and clear the
+ // zbuffer for each of the lines
+ for (uint32 y = starty; y <= endy; y++)
+ {
+ memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH), 0,
+ IPPU.RenderedScreenWidth>>2);
+ }
+ GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object
+ GFX.pCurrentClip = &IPPU.Clip [0];
+
+// Define an inline function to handle clipping
+#define FIXCLIP(n) \
+if (GFX.r212c & (1 << (n))) \
+ GFX.pCurrentClip = &IPPU.Clip [0]; \
+else \
+ GFX.pCurrentClip = &IPPU.Clip [1]
+
+// Define an inline function to handle which BGs are being displayed
+#define DISPLAY(n) ((GFX.r212c & n) || ((GFX.r212d & n) && subadd))
+
+ uint8 subadd = GFX.r2131 & 0x3f;
+
+ // go through all BGS are check if they need to be displayed
+ bool8_32 BG0 = DISPLAY(1) && !(Settings.os9x_hack & GFX_IGNORE_BG0);
+ bool8_32 BG1 = DISPLAY(2) && !(Settings.os9x_hack & GFX_IGNORE_BG1);
+ bool8_32 BG2 = DISPLAY(4) && !(Settings.os9x_hack & GFX_IGNORE_BG2);
+ bool8_32 BG3 = DISPLAY(8) && !(Settings.os9x_hack & GFX_IGNORE_BG3);
+ bool8_32 OB = DISPLAY(16) && !(Settings.os9x_hack & GFX_IGNORE_OBJ);
+
+ if (PPU.BGMode <= 1)
+ {
+ // screen modes 0 and 1
+ if (OB)
+ {
+ FIXCLIP(4);
+ DrawOBJS ();
+ }
+ if (BG0)
+ {
+ FIXCLIP(0);
+ DrawBackground (PPU.BGMode, 0, 10, 14);
+ }
+ if (BG1)
+ {
+ FIXCLIP(1);
+ DrawBackground (PPU.BGMode, 1, 9, 13);
+ }
+ if (BG2)
+ {
+ FIXCLIP(2);
+ DrawBackground (PPU.BGMode, 2, 3,
+ PPU.BG3Priority ? 17 : 6);
+ }
+ if (BG3 && PPU.BGMode == 0)
+ {
+ FIXCLIP(3);
+ DrawBackground (PPU.BGMode, 3, 2, 5);
+ }
+ }
+ else if (PPU.BGMode != 7)
+ {
+ // screen modes 2 and up but not mode 7
+ if (OB)
+ {
+ FIXCLIP(4);
+ DrawOBJS ();
+ }
+ if (BG0)
+ {
+ FIXCLIP(0);
+ DrawBackground (PPU.BGMode, 0, 5, 13);
+ }
+ if (BG1 && PPU.BGMode != 6)
+ {
+ FIXCLIP(1);
+ DrawBackground (PPU.BGMode, 1, 2, 9);
+ }
+ }
+ else
+ {
+ // screen mode 7
+ DrawBGMode7Background16New (GFX.Screen);
+ if (OB)
+ {
+ FIXCLIP(4);
+ DrawOBJS ();
+ }
+ }
+ }
+ IPPU.PreviousLine = IPPU.CurrentLine;
+}
+
+// -x-
+
+#ifdef GFX_MULTI_FORMAT
+
+#define _BUILD_PIXEL(F) \
+uint32 BuildPixel##F(uint32 R, uint32 G, uint32 B) \
+{ \
+ return (BUILD_PIXEL_##F(R,G,B)); \
+}\
+uint32 BuildPixel2##F(uint32 R, uint32 G, uint32 B) \
+{ \
+ return (BUILD_PIXEL2_##F(R,G,B)); \
+} \
+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)
+
+bool8_32 S9xSetRenderPixelFormat (int format)
+{
+ extern uint32 current_graphic_format;
+
+ current_graphic_format = 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/old/gfx16.cpp.old2 b/old/gfx16.cpp.old2
new file mode 100644
index 0000000..5a9fcb8
--- /dev/null
+++ b/old/gfx16.cpp.old2
@@ -0,0 +1,3201 @@
+/*
+ * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
+ *
+ * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
+ * Jerremy Koot (jkoot@snes9x.com)
+ *
+ * Super FX C emulator code
+ * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
+ * Gary Henderson.
+ * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
+ *
+ * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
+ * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
+ * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
+ *
+ * DOS port code contains the works of other authors. See headers in
+ * individual files.
+ *
+ * Snes9x homepage: http://www.snes9x.com
+ *
+ * Permission to use, copy, modify and 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.
+ *
+ * Snes9x is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Snes9x or software derived from Snes9x.
+ *
+ * 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 "ppu.h"
+#include "cpuexec.h"
+#include "display.h"
+#include "gfx.h"
+#include "apu.h"
+#include "cheats.h"
+#include <stdint.h>
+#include "asmmemfuncs.h"
+#include "mode7.h"
+#include "rops.h"
+#include "tile16.h"
+uint32 TileBlank;
+// V_FLIP 0x8000
+// H_FLIP 0x4000
+//Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)];
+// (((Tile & H_FLIP) >> 14) ^ (Quot & 1)) + (((Tile & V_FLIP) >> 11) ^ (16) ^ tx_index)
+
+
+const int tx_table[16] = {
+// t1 = 16, t2 = 0
+ // FLIP = 0x00
+ 16 + 0, // 0x00
+ 16 + 1, // 0x01
+
+ // FLIP = 0x01
+ 16 + 1 - 0, // 0x02
+ 16 + 1 - 1, // 0x03
+
+ // FLIP = 0x02
+ 0 + 0, // 0x04
+ 0 + 1, // 0x05
+
+ // FLIP = 0x03
+ 0 + 1 - 0, // 0x06
+ 0 + 1 - 1, // 0x07
+
+// t1 = 0, t2 = 16
+ // FLIP = 0x00
+ 0 + 0, // 0x08
+ 0 + 1, // 0x09
+
+ // FLIP = 0x01
+ 0 + 1 - 0, // 0x0A
+ 0 + 1 - 1, // 0x0B
+
+ // FLIP = 0x02
+ 16 + 0, // 0x0C
+ 16 + 1, // 0x0D
+
+ // FLIP = 0x03
+ 16 + 1 - 0, // 0x0E
+ 16 + 1 - 1 // 0x0F
+};
+
+#define M7 19
+#define M8 19
+
+void ComputeClipWindows ();
+static void S9xDisplayFrameRate ();
+static void S9xDisplayString (const char *string);
+
+extern uint8 BitShifts[8][4];
+extern uint8 TileShifts[8][4];
+extern uint8 PaletteShifts[8][4];
+extern uint8 PaletteMasks[8][4];
+extern uint8 Depths[8][4];
+extern uint8 BGSizes [2];
+
+extern NormalTileRenderer DrawTilePtr;
+extern ClippedTileRenderer DrawClippedTilePtr;
+extern NormalTileRenderer DrawHiResTilePtr;
+extern ClippedTileRenderer DrawHiResClippedTilePtr;
+extern LargePixelRenderer DrawLargePixelPtr;
+
+extern struct SBG BG;
+
+extern struct SLineData LineData[240];
+extern struct SLineMatrixData LineMatrixData [240];
+
+extern uint8 Mode7Depths [2];
+
+#define ON_MAIN(N) (GFX.r212c & (1 << (N)))
+
+#define SUB_OR_ADD(N) \
+(GFX.r2131 & (1 << (N)))
+
+#define ON_SUB(N) \
+((GFX.r2130 & 0x30) != 0x30 && \
+ (GFX.r2130 & 2) && \
+ (GFX.r212d & (1 << N)))
+
+#define ANYTHING_ON_SUB \
+((GFX.r2130 & 0x30) != 0x30 && \
+ (GFX.r2130 & 2) && \
+ (GFX.r212d & 0x1f))
+
+#define ADD_OR_SUB_ON_ANYTHING \
+(GFX.r2131 & 0x3f)
+
+#define BLACK BUILD_PIXEL(0,0,0)
+
+void DrawNoZTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount);
+void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+void DrawClippedTile16 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+void DrawTile16x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+void DrawClippedTile16x2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+void DrawTile16x2x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+void DrawClippedTile16x2x2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+void DrawLargePixel16 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Pixels,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawNoZTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawClippedTile16Add (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawNoZTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawClippedTile16Add1_2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawClippedTile16FixedAdd1_2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawNoZTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+
+void DrawTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawClippedTile16Sub (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawNoZTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+
+void DrawTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawClippedTile16Sub1_2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
+ uint32 LineCount);
+
+void DrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawLargePixel16Add (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Pixels,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Pixels,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawLargePixel16Sub (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Pixels,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Pixels,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawHiResClippedTile16 (uint32 Tile, uint32 Offset,
+ uint32 StartPixel, uint32 Width,
+ uint32 StartLine, uint32 LineCount);
+
+void DrawHiResTile16 (uint32 Tile, uint32 Offset,
+ uint32 StartLine, uint32 LineCount);
+
+bool8_32 S9xGraphicsInit ()
+{
+ register uint32 PixelOdd = 1;
+ register uint32 PixelEven = 2;
+
+#ifdef GFX_MULTI_FORMAT
+ if (GFX.BuildPixel == NULL)
+ S9xSetRenderPixelFormat (RGB565);
+#endif
+
+ for (uint8 bitshift = 0; bitshift < 4; bitshift++)
+ {
+ for (register int i = 0; i < 16; i++)
+ {
+ register uint32 h = 0;
+ register uint32 l = 0;
+
+#if defined(LSB_FIRST)
+// Wiz usa LSB_FIRST
+ if (i & 8)
+ h |= PixelOdd;
+ if (i & 4)
+ h |= PixelOdd << 8;
+ if (i & 2)
+ h |= PixelOdd << 16;
+ if (i & 1)
+ h |= PixelOdd << 24;
+ if (i & 8)
+ l |= PixelOdd;
+ if (i & 4)
+ l |= PixelOdd << 8;
+ if (i & 2)
+ l |= PixelOdd << 16;
+ if (i & 1)
+ l |= PixelOdd << 24;
+#else
+ if (i & 8)
+ h |= (PixelOdd << 24);
+ if (i & 4)
+ h |= (PixelOdd << 16);
+ if (i & 2)
+ h |= (PixelOdd << 8);
+ if (i & 1)
+ h |= PixelOdd;
+ if (i & 8)
+ l |= (PixelOdd << 24);
+ if (i & 4)
+ l |= (PixelOdd << 16);
+ if (i & 2)
+ l |= (PixelOdd << 8);
+ if (i & 1)
+ l |= PixelOdd;
+#endif
+
+ odd_high[bitshift][i] = h;
+ odd_low[bitshift][i] = l;
+ h = l = 0;
+
+#if defined(LSB_FIRST)
+ if (i & 8)
+ h |= PixelEven;
+ if (i & 4)
+ h |= PixelEven << 8;
+ if (i & 2)
+ h |= PixelEven << 16;
+ if (i & 1)
+ h |= PixelEven << 24;
+ if (i & 8)
+ l |= PixelEven;
+ if (i & 4)
+ l |= PixelEven << 8;
+ if (i & 2)
+ l |= PixelEven << 16;
+ if (i & 1)
+ l |= PixelEven << 24;
+#else
+ if (i & 8)
+ h |= (PixelEven << 24);
+ if (i & 4)
+ h |= (PixelEven << 16);
+ if (i & 2)
+ h |= (PixelEven << 8);
+ if (i & 1)
+ h |= PixelEven;
+ if (i & 8)
+ l |= (PixelEven << 24);
+ if (i & 4)
+ l |= (PixelEven << 16);
+ if (i & 2)
+ l |= (PixelEven << 8);
+ if (i & 1)
+ l |= PixelEven;
+#endif
+
+ even_high[bitshift][i] = h;
+ even_low[bitshift][i] = l;
+ }
+ PixelEven <<= 2;
+ PixelOdd <<= 2;
+ }
+
+ GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
+ GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
+ //GFX.InfoStringTimeout = 0;
+ //GFX.InfoString = NULL;
+
+ PPU.BG_Forced = 0;
+ IPPU.OBJChanged = TRUE;
+
+ IPPU.DirectColourMapsNeedRebuild = TRUE;
+ DrawTilePtr = DrawTile16;
+ DrawClippedTilePtr = DrawClippedTile16;
+ DrawLargePixelPtr = DrawLargePixel16;
+ DrawHiResTilePtr= DrawHiResTile16;
+ DrawHiResClippedTilePtr = DrawHiResClippedTile16;
+ S9xFixColourBrightness ();
+
+ if (!(GFX.X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)))
+ return (FALSE);
+
+ if (!(GFX.ZERO_OR_X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)) ||
+ !(GFX.ZERO = (uint16 *) malloc (sizeof (uint16) * 0x10000)))
+ {
+ if (GFX.ZERO_OR_X2)
+ {
+ free ((char *) GFX.ZERO_OR_X2);
+ GFX.ZERO_OR_X2 = NULL;
+ }
+ if (GFX.X2)
+ {
+ free ((char *) GFX.X2);
+ GFX.X2 = NULL;
+ }
+ return (FALSE);
+ }
+ uint32 r, g, b;
+
+ // Build a lookup table that multiplies a packed RGB value by 2 with
+ // saturation.
+ for (r = 0; r <= MAX_RED; r++)
+ {
+ uint32 r2 = r << 1;
+ if (r2 > MAX_RED)
+ r2 = MAX_RED;
+ for (g = 0; g <= MAX_GREEN; g++)
+ {
+ uint32 g2 = g << 1;
+ if (g2 > MAX_GREEN)
+ g2 = MAX_GREEN;
+ for (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);
+ }
+ }
+ }
+ ZeroMemory (GFX.ZERO, 0x10000 * sizeof (uint16));
+ ZeroMemory (GFX.ZERO_OR_X2, 0x10000 * sizeof (uint16));
+ // Build a lookup table that if the top bit of the color value is zero
+ // then the value is zero, otherwise multiply the value by 2. Used by
+ // the color subtraction code.
+
+#if defined(OLD_COLOUR_BLENDING)
+ for (r = 0; r <= MAX_RED; r++)
+ {
+ uint32 r2 = r;
+ if ((r2 & 0x10) == 0)
+ r2 = 0;
+ else
+ r2 = (r2 << 1) & MAX_RED;
+
+ for (g = 0; g <= MAX_GREEN; g++)
+ {
+ uint32 g2 = g;
+ if ((g2 & GREEN_HI_BIT) == 0)
+ g2 = 0;
+ else
+ g2 = (g2 << 1) & MAX_GREEN;
+
+ for (b = 0; b <= MAX_BLUE; b++)
+ {
+ uint32 b2 = b;
+ if ((b2 & 0x10) == 0)
+ b2 = 0;
+ else
+ b2 = (b2 << 1) & MAX_BLUE;
+
+ GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
+ GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
+ }
+ }
+ }
+#else
+ for (r = 0; r <= MAX_RED; r++)
+ {
+ uint32 r2 = r;
+ if ((r2 & 0x10) == 0)
+ r2 = 0;
+ else
+ r2 = (r2 << 1) & MAX_RED;
+
+ if (r2 == 0)
+ r2 = 1;
+ for (g = 0; g <= MAX_GREEN; g++)
+ {
+ uint32 g2 = g;
+ if ((g2 & GREEN_HI_BIT) == 0)
+ g2 = 0;
+ else
+ g2 = (g2 << 1) & MAX_GREEN;
+
+ if (g2 == 0)
+ g2 = 1;
+ for (b = 0; b <= MAX_BLUE; b++)
+ {
+ uint32 b2 = b;
+ if ((b2 & 0x10) == 0)
+ b2 = 0;
+ else
+ b2 = (b2 << 1) & MAX_BLUE;
+
+ if (b2 == 0)
+ b2 = 1;
+ GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
+ GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
+ }
+ }
+ }
+#endif
+
+ // Build a lookup table that if the top bit of the color value is zero
+ // then the value is zero, otherwise its just the value.
+ for (r = 0; r <= MAX_RED; r++)
+ {
+ uint32 r2 = r;
+ if ((r2 & 0x10) == 0)
+ r2 = 0;
+ else
+ r2 &= ~0x10;
+
+ for (g = 0; g <= MAX_GREEN; g++)
+ {
+ uint32 g2 = g;
+ if ((g2 & GREEN_HI_BIT) == 0)
+ g2 = 0;
+ else
+ g2 &= ~GREEN_HI_BIT;
+ for (b = 0; b <= MAX_BLUE; b++)
+ {
+ uint32 b2 = b;
+ if ((b2 & 0x10) == 0)
+ b2 = 0;
+ else
+ b2 &= ~0x10;
+
+ 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)
+{
+ // Free any memory allocated in S9xGraphicsInit
+ if (GFX.X2)
+ {
+ free ((char *) GFX.X2);
+ GFX.X2 = NULL;
+ }
+ if (GFX.ZERO_OR_X2)
+ {
+ free ((char *) GFX.ZERO_OR_X2);
+ GFX.ZERO_OR_X2 = NULL;
+ }
+ if (GFX.ZERO)
+ {
+ free ((char *) GFX.ZERO);
+ GFX.ZERO = NULL;
+ }
+}
+
+void S9xBuildDirectColourMaps ()
+{
+ for (uint32 p = 0; p < 8; p++)
+ {
+ for (uint32 c = 0; c < 256; c++)
+ {
+// XXX: Brightness
+ DirectColourMaps [p][c] = BUILD_PIXEL (((c & 7) << 2) | ((p & 1) << 1),
+ ((c & 0x38) >> 1) | (p & 2),
+ ((c & 0xc0) >> 3) | (p & 4));
+ }
+ }
+ IPPU.DirectColourMapsNeedRebuild = FALSE;
+}
+
+void S9xStartScreenRefresh ()
+{
+ if (IPPU.RenderThisFrame)
+ {
+#ifndef _SNESPPC
+ if (!S9xInitUpdate ())
+ {
+ IPPU.RenderThisFrame = FALSE;
+ return;
+ }
+#endif
+ IPPU.RenderedFramesCount++;
+ IPPU.PreviousLine = IPPU.CurrentLine = 0;
+ IPPU.MaxBrightness = PPU.Brightness;
+ IPPU.LatchedBlanking = PPU.ForcedBlanking;
+ IPPU.LatchedInterlace = (Memory.FillRAM[0x2133] & 1);
+ IPPU.RenderedScreenWidth = 256;
+ IPPU.RenderedScreenHeight = PPU.ScreenHeight;
+ IPPU.DoubleWidthPixels = FALSE;
+
+ PPU.RecomputeClipWindows = TRUE;
+ GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
+ GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
+
+ }
+ if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0)
+ {
+ IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount;
+ IPPU.RenderedFramesCount = 0;
+ IPPU.FrameCount = 0;
+ }
+}
+
+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;
+ }
+ else
+ {
+ if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 &&
+ PPU.BG[2].HOffset == 0xe000)
+ {
+ LineData[C].BG[2].VOffset = 0xe1;
+ LineData[C].BG[2].HOffset = 0;
+ }
+ 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;
+ }
+}
+
+
+void S9xEndScreenRefresh()
+{
+ IPPU.HDMAStarted = FALSE;
+
+//RC
+ if (IPPU.RenderThisFrame)
+ {
+ FLUSH_REDRAW ();
+ //if (IPPU.ColorsChanged)
+ //{
+ IPPU.ColorsChanged = FALSE;
+ //}
+
+
+ S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight,
+ 1);
+ }
+#ifndef RC_OPTIMIZED
+ S9xApplyCheats ();
+#endif
+
+
+#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 S9xSetInfoString (const char *string)
+{
+ }
+
+
+
+int TileRenderer;
+TileRendererSet TileRenderers[] = {
+ {DrawTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 0 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 0
+ {DrawTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 1 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 1
+ {DrawTile16FixedAdd1_2, DrawClippedTile16FixedAdd1_2, DrawLargePixel16Add1_2}, // 2 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 0
+ {DrawTile16Add1_2, DrawClippedTile16Add1_2, DrawLargePixel16Add1_2}, // 3 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 1
+ {DrawTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 4 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 0
+ {DrawTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 5 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 1
+ {DrawTile16FixedSub1_2, DrawClippedTile16FixedSub1_2, DrawLargePixel16Sub1_2}, // 6 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 0
+ {DrawTile16Sub1_2, DrawClippedTile16Sub1_2, DrawLargePixel16Sub1_2}, // 7 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 1
+ {DrawTile16, DrawClippedTile16, DrawLargePixel16} // 8 -> normal
+ };
+TileRendererSet TileRenderersNoZ[] = {
+ {DrawNoZTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 0 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 0
+ {DrawNoZTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 1 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 1
+ {DrawTile16FixedAdd1_2, DrawClippedTile16FixedAdd1_2, DrawLargePixel16Add1_2}, // 2 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 0
+ {DrawNoZTile16Add1_2, DrawClippedTile16Add1_2, DrawLargePixel16Add1_2}, // 3 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 1
+ {DrawNoZTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 4 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 0
+ {DrawNoZTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 5 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 1
+ {DrawTile16FixedSub1_2, DrawClippedTile16FixedSub1_2, DrawLargePixel16Sub1_2}, // 6 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 0
+ {DrawNoZTile16Sub1_2, DrawClippedTile16Sub1_2, DrawLargePixel16Sub1_2}, // 7 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 1
+ {DrawNoZTile16, DrawClippedTile16, DrawLargePixel16} // 8 -> normal
+ };
+INLINE void SelectTileRenderer (bool8_32 normal, bool NoZ = false)
+{
+ if (normal) {
+ TileRenderer = 8;
+ }
+ else {
+ TileRenderer = (((GFX.r2131 >> 5) & 0x06) | ((GFX.r2130 >> 1) & 1));
+ }
+
+#ifdef __DEBUG__
+ char *TRName[] = {
+ "Add", "Add", "FixedAdd1_2", "Add1_2",
+ "Sub", "Sub", "FixedSub1_2", "Sub1_2",
+ "Normal"
+ };
+ printf("SelectTileRenderer: %s\n", TRName[TileRenderer]);
+#endif
+
+ if (NoZ) {
+ DrawTilePtr = TileRenderersNoZ[TileRenderer].Normal;
+ DrawClippedTilePtr = TileRenderersNoZ[TileRenderer].Clipped;
+ DrawLargePixelPtr = TileRenderersNoZ[TileRenderer].Large;
+ }
+ else {
+ DrawTilePtr = TileRenderers[TileRenderer].Normal;
+ DrawClippedTilePtr = TileRenderers[TileRenderer].Clipped;
+ DrawLargePixelPtr = TileRenderers[TileRenderer].Large;
+ }
+}
+
+void S9xSetupOBJ ()
+{
+ int SmallSize;
+ int LargeSize;
+
+ switch (PPU.OBJSizeSelect)
+ {
+ case 0:
+ SmallSize = 8;
+ LargeSize = 16;
+ break;
+ case 1:
+ SmallSize = 8;
+ LargeSize = 32;
+ break;
+ case 2:
+ SmallSize = 8;
+ LargeSize = 64;
+ break;
+ case 3:
+ SmallSize = 16;
+ LargeSize = 32;
+ break;
+ case 4:
+ SmallSize = 16;
+ LargeSize = 64;
+ break;
+ case 5:
+ default:
+ SmallSize = 32;
+ LargeSize = 64;
+ break;
+ }
+
+ int C = 0;
+
+ int FirstSprite = PPU.FirstSprite & 0x7f;
+ int S = FirstSprite;
+ do
+ {
+ int Size;
+ if (PPU.OBJ [S].Size)
+ Size = LargeSize;
+ else
+ Size = SmallSize;
+
+ long VPos = PPU.OBJ [S].VPos;
+
+ if (VPos >= PPU.ScreenHeight)
+ VPos -= 256;
+ if (PPU.OBJ [S].HPos < 256 && PPU.OBJ [S].HPos > -Size &&
+ VPos < PPU.ScreenHeight && VPos > -Size)
+ {
+ int x = 0;
+ int a, b;
+ //GFX.OBJList[C++] = S;
+ // -- Sort objects (from low to high priority)
+
+ while (x < C) {
+ a = GFX.OBJList[x];
+ if (PPU.OBJ[a].Priority >= PPU.OBJ[S].Priority) break;
+ x++;
+ }
+
+ GFX.OBJList[x] = S;
+ x++; C++;
+
+ while (x < C) {
+ b = GFX.OBJList[x];
+ GFX.OBJList[x] = a;
+ a = b;
+ x++;
+ }
+ // --
+ GFX.Sizes[S] = Size;
+ GFX.VPositions[S] = VPos;
+ }
+ S = (S + 1) & 0x7f;
+ } while (S != FirstSprite);
+
+ // Terminate the list
+ GFX.OBJList [C] = -1;
+ IPPU.OBJChanged = FALSE;
+}
+
+void DrawOBJS (bool8_32 OnMain = FALSE, uint8 D = 0)
+{
+ int bg_ta_ns;
+ int bg_ta;
+ uint32 O;
+ uint32 BaseTile, Tile;
+
+ CHECK_SOUND();
+
+ BG.BitShift = 4;
+ SelectConvertTile();
+ BG.TileShift = 5;
+ //BG.TileAddress = PPU.OBJNameBase;
+ BG.StartPalette = 128;
+ BG.PaletteShift = 4;
+ BG.PaletteMask = 7;
+ BG.Buffer = IPPU.TileCache [TILE_4BIT];
+ BG.Buffered = IPPU.TileCached [TILE_4BIT];
+ //BG.NameSelect = PPU.OBJNameSelect;
+ BG.DirectColourMode = FALSE;
+
+ SelectPalette();
+ bg_ta = PPU.OBJNameBase;
+ bg_ta_ns = bg_ta + PPU.OBJNameSelect;
+
+ GFX.Z1 = D + 2;
+
+ int I = 0;
+ for (int S = GFX.OBJList [I++]; S >= 0; S = GFX.OBJList [I++])
+ {
+ int VPos = GFX.VPositions [S];
+ int Size = GFX.Sizes[S];
+ int TileInc = 1;
+ int Offset;
+
+ if (VPos + Size <= (int) GFX.StartY || VPos > (int) GFX.EndY)
+ continue;
+
+ if (OnMain && SUB_OR_ADD(4))
+ {
+ SelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4, true);
+ }
+
+ BaseTile = PPU.OBJ[S].Name | (PPU.OBJ[S].Palette << 10);
+
+ if (PPU.OBJ[S].HFlip)
+ {
+ BaseTile += ((Size >> 3) - 1) | H_FLIP;
+ TileInc = -1;
+ }
+
+ if (PPU.OBJ[S].VFlip) BaseTile |= V_FLIP;
+ //BaseTile |= PPU.OBJ[S].VFlip << 15;
+
+ int clipcount = GFX.pCurrentClip->Count [4];
+ if (!clipcount) clipcount = 1;
+
+ GFX.Z2 = (PPU.OBJ[S].Priority + 1) * 4 + D;
+
+ for (int clip = 0; clip < clipcount; clip++)
+ {
+ int Left;
+ int Right;
+ if (!GFX.pCurrentClip->Count [4])
+ {
+ Left = 0;
+ Right = 256;
+ }
+ else
+ {
+ Left = GFX.pCurrentClip->Left [clip][4];
+ Right = GFX.pCurrentClip->Right [clip][4];
+ }
+
+ if (Right <= Left || PPU.OBJ[S].HPos + Size <= Left ||
+ PPU.OBJ[S].HPos >= Right)
+ continue;
+
+ for (int Y = 0; Y < Size; Y += 8)
+ {
+ if (VPos + Y + 7 >= (int) GFX.StartY && VPos + Y <= (int) GFX.EndY)
+ {
+ int StartLine;
+ int TileLine;
+ int LineCount;
+ int Last;
+
+ if ((StartLine = VPos + Y) < (int) GFX.StartY)
+ {
+ StartLine = GFX.StartY - StartLine;
+ LineCount = 8 - StartLine;
+ }
+ else
+ {
+ StartLine = 0;
+ LineCount = 8;
+ }
+ if ((Last = VPos + Y + 7 - GFX.EndY) > 0)
+ if ((LineCount -= Last) <= 0)
+ break;
+
+ TileLine = StartLine << 3;
+
+ //-NoZ-----
+ //CheckNoZ(VPos + Y + StartLine, LineCount);
+ //-NoZ-----
+
+ O = (VPos + Y + StartLine) * GFX_PPL;
+ if (!PPU.OBJ[S].VFlip) Tile = BaseTile + (Y << 1);
+ else Tile = BaseTile + ((Size - Y - 8) << 1);
+
+ if (Tile & 0x100) BG.TileAddress = bg_ta_ns;
+ else BG.TileAddress = bg_ta;
+
+ int Middle = Size >> 3;
+ if (PPU.OBJ[S].HPos < Left)
+ {
+ Tile += ((Left - PPU.OBJ[S].HPos) >> 3) * TileInc;
+ Middle -= (Left - PPU.OBJ[S].HPos) >> 3;
+ O += Left * GFX_PIXSIZE;
+ if ((Offset = (Left - PPU.OBJ[S].HPos) & 7))
+ {
+ O -= Offset * GFX_PIXSIZE;
+ int W = 8 - Offset;
+ int Width = Right - Left;
+ if (W > Width) W = Width;
+ //if (Tile & 0x100) BG.TileAddress = bg_ta_ns;
+ //else BG.TileAddress = bg_ta;
+ (*DrawClippedTilePtr) (Tile, O, Offset, W, TileLine, LineCount);
+
+ if (W >= Width)
+ continue;
+ Tile += TileInc;
+ Middle--;
+ O += 8 * GFX_PIXSIZE;
+ }
+ }
+ else
+ O += PPU.OBJ[S].HPos * GFX_PIXSIZE;
+
+ if (PPU.OBJ[S].HPos + Size >= Right)
+ {
+ Middle -= ((PPU.OBJ[S].HPos + Size + 7) -
+ Right) >> 3;
+ Offset = (Right - (PPU.OBJ[S].HPos + Size)) & 7;
+ }
+ else
+ Offset = 0;
+
+ for (int X = 0; X < Middle; X++, O += 8 * GFX_PIXSIZE,
+ Tile += TileInc)
+ {
+ //if (Tile & 0x100) BG.TileAddress = bg_ta_ns;
+ //else BG.TileAddress = bg_ta;
+ (*DrawTilePtr) (Tile, O, TileLine, LineCount);
+ }
+ if (Offset)
+ {
+ //if (Tile & 0x100) BG.TileAddress = bg_ta_ns;
+ //else BG.TileAddress = bg_ta;
+ (*DrawClippedTilePtr) (Tile, O, 0, Offset, TileLine, LineCount);
+ }
+ }
+ }
+ }
+ }
+}
+void DrawBackgroundMosaic (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
+{
+#ifdef __DEBUG__
+ printf("DrawBackgroundMosaic(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2);
+#endif
+ CHECK_SOUND();
+
+ uint32 Tile;
+ uint16 *SC0;
+ uint16 *SC1;
+ uint16 *SC2;
+ uint16 *SC3;
+ uint8 depths [2] = {Z1, Z2};
+
+ if (BGMode == 0)
+ BG.StartPalette = bg << 5;
+ else
+ BG.StartPalette = 0;
+ SelectPalette();
+
+ SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
+
+ if (PPU.BG[bg].SCSize & 1)
+ SC1 = SC0 + 1024;
+ else
+ SC1 = SC0;
+
+ if(((uint8*)SC1-Memory.VRAM)>=0x10000)
+ SC1-=0x08000;
+
+
+ if (PPU.BG[bg].SCSize & 2)
+ SC2 = SC1 + 1024;
+ else
+ SC2 = SC0;
+
+ if(((uint8*)SC2-Memory.VRAM)>=0x10000)
+ SC2-=0x08000;
+
+
+ if (PPU.BG[bg].SCSize & 1)
+ SC3 = SC2 + 1024;
+ else
+ SC3 = SC2;
+
+ if(((uint8*)SC3-Memory.VRAM)>=0x10000)
+ SC3-=0x08000;
+
+ uint32 Lines;
+ uint32 OffsetMask;
+ uint32 OffsetShift;
+
+ if (BG.TileSize == 16)
+ {
+ OffsetMask = 0x3ff;
+ OffsetShift = 4;
+ }
+ else
+ {
+ OffsetMask = 0x1ff;
+ OffsetShift = 3;
+ }
+
+ for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
+ {
+ uint32 VOffset = LineData [Y].BG[bg].VOffset;
+ uint32 HOffset = LineData [Y].BG[bg].HOffset;
+ uint32 MosaicOffset = Y % PPU.Mosaic;
+
+ for (Lines = 1; Lines < PPU.Mosaic - MosaicOffset; Lines++)
+ if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
+ (HOffset != LineData [Y + Lines].BG[bg].HOffset))
+ break;
+
+ uint32 MosaicLine = VOffset + Y - MosaicOffset;
+
+ if (Y + Lines > GFX.EndY)
+ Lines = GFX.EndY + 1 - Y;
+ uint32 VirtAlign = (MosaicLine & 7) << 3;
+
+ uint16 *b1;
+ uint16 *b2;
+
+ uint32 ScreenLine = MosaicLine >> OffsetShift;
+ uint32 Rem16 = MosaicLine & 15;
+
+ if (ScreenLine & 0x20)
+ b1 = SC2, b2 = SC3;
+ else
+ b1 = SC0, b2 = SC1;
+
+ b1 += (ScreenLine & 0x1f) << 5;
+ b2 += (ScreenLine & 0x1f) << 5;
+ uint16 *t;
+ uint32 Left = 0;
+ uint32 Right = 256;
+
+ uint32 ClipCount = GFX.pCurrentClip->Count [bg];
+ uint32 HPos = HOffset;
+ uint32 PixWidth = PPU.Mosaic;
+
+ if (!ClipCount)
+ ClipCount = 1;
+
+ for (uint32 clip = 0; clip < ClipCount; clip++)
+ {
+ if (GFX.pCurrentClip->Count [bg])
+ {
+ Left = GFX.pCurrentClip->Left [clip][bg];
+ Right = GFX.pCurrentClip->Right [clip][bg];
+ uint32 r = Left % PPU.Mosaic;
+ HPos = HOffset + Left;
+ PixWidth = PPU.Mosaic - r;
+ }
+ uint32 s = Y * GFX_PPL + Left * GFX_PIXSIZE;
+ for (uint32 x = Left; x < Right; x += PixWidth,
+ s += PixWidth * GFX_PIXSIZE,
+ HPos += PixWidth, PixWidth = PPU.Mosaic)
+ {
+ uint32 Quot = (HPos & OffsetMask) >> 3;
+
+ if (x + PixWidth >= Right)
+ PixWidth = Right - x;
+
+ if (BG.TileSize == 8)
+ {
+ if (Quot > 31)
+ t = b2 + (Quot & 0x1f);
+ else
+ t = b1 + Quot;
+ }
+ else
+ {
+ if (Quot > 63)
+ t = b2 + ((Quot >> 1) & 0x1f);
+ else
+ t = b1 + (Quot >> 1);
+ }
+
+ Tile = READ_2BYTES (t);
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+
+ // Draw tile...
+ if (BG.TileSize != 8)
+ {
+ if (Tile & H_FLIP)
+ {
+ // Horizontal flip, but what about vertical flip ?
+ if (Tile & V_FLIP)
+ {
+ // Both horzontal & vertical flip
+ if (Rem16 < 8)
+ {
+ (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ else
+ {
+ (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ // Horizontal flip only
+ if (Rem16 > 7)
+ {
+ (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ else
+ {
+ (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ }
+ }
+ else
+ {
+ // No horizontal flip, but is there a vertical flip ?
+ if (Tile & V_FLIP)
+ {
+ // Vertical flip only
+ if (Rem16 < 8)
+ {
+ (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ else
+ {
+ (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ // Normal unflipped
+ if (Rem16 > 7)
+ {
+ (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ else
+ {
+ (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
+ HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ }
+ }
+ }
+ else
+ (*DrawLargePixelPtr) (Tile, s, HPos & 7, PixWidth,
+ VirtAlign, Lines);
+ }
+ }
+ }
+}
+
+void DrawBackgroundOffset (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
+{
+#ifdef __DEBUG__
+ printf("DrawBackgroundOffse(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2);
+#endif
+
+ CHECK_SOUND();
+
+ uint32 Tile;
+ uint16 *SC0;
+ uint16 *SC1;
+ uint16 *SC2;
+ uint16 *SC3;
+ uint16 *BPS0;
+ uint16 *BPS1;
+ uint16 *BPS2;
+ uint16 *BPS3;
+ uint32 Width;
+ int VOffsetOffset = BGMode == 4 ? 0 : 32;
+ uint8 depths [2] = {Z1, Z2};
+
+ BG.StartPalette = 0;
+ SelectPalette();
+
+ BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1];
+
+ if (PPU.BG[2].SCSize & 1)
+ BPS1 = BPS0 + 1024;
+ else
+ BPS1 = BPS0;
+
+ if (PPU.BG[2].SCSize & 2)
+ BPS2 = BPS1 + 1024;
+ else
+ BPS2 = BPS0;
+
+ if (PPU.BG[2].SCSize & 1)
+ BPS3 = BPS2 + 1024;
+ else
+ BPS3 = BPS2;
+
+ SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
+
+ if (PPU.BG[bg].SCSize & 1)
+ SC1 = SC0 + 1024;
+ else
+ SC1 = SC0;
+
+ if(((uint8*)SC1-Memory.VRAM)>=0x10000)
+ SC1-=0x08000;
+
+
+ if (PPU.BG[bg].SCSize & 2)
+ SC2 = SC1 + 1024;
+ else
+ SC2 = SC0;
+
+ if(((uint8*)SC2-Memory.VRAM)>=0x10000)
+ SC2-=0x08000;
+
+
+ if (PPU.BG[bg].SCSize & 1)
+ SC3 = SC2 + 1024;
+ else
+ SC3 = SC2;
+
+ if(((uint8*)SC3-Memory.VRAM)>=0x10000)
+ SC3-=0x08000;
+
+ static const int Lines = 1;
+ int OffsetMask;
+ int OffsetShift;
+ int OffsetEnableMask = 1 << (bg + 13);
+
+ if (BG.TileSize == 16)
+ {
+ OffsetMask = 0x3ff;
+ OffsetShift = 4;
+ }
+ else
+ {
+ OffsetMask = 0x1ff;
+ OffsetShift = 3;
+ }
+
+ TileBlank = 0xFFFFFFFF;
+ for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++)
+ {
+ uint32 VOff = LineData [Y].BG[2].VOffset - 1;
+ uint32 HOff = LineData [Y].BG[2].HOffset;
+ int VirtAlign;
+ int ScreenLine = VOff >> 3;
+ uint16 *s0;
+ uint16 *s1;
+ uint16 *s2;
+
+ if (ScreenLine & 0x20)
+ s1 = BPS2, s2 = BPS3;
+ else
+ s1 = BPS0, s2 = BPS1;
+
+ s1 += (ScreenLine & 0x1f) << 5;
+ s2 += (ScreenLine & 0x1f) << 5;
+
+ if(BGMode != 4)
+ {
+ if((ScreenLine & 0x1f) == 0x1f)
+ {
+ if(ScreenLine & 0x20)
+ VOffsetOffset = BPS0 - BPS2 - 0x1f*32;
+ else
+ VOffsetOffset = BPS2 - BPS0 - 0x1f*32;
+ }
+ else
+ {
+ VOffsetOffset = 32;
+ }
+ }
+ int clipcount = GFX.pCurrentClip->Count [bg];
+ if (!clipcount)
+ clipcount = 1;
+
+ for (int clip = 0; clip < clipcount; clip++)
+ {
+ uint32 Left;
+ uint32 Right;
+
+ if (!GFX.pCurrentClip->Count [bg])
+ {
+ Left = 0;
+ Right = 256;
+ }
+ else
+ {
+ Left = GFX.pCurrentClip->Left [clip][bg];
+ Right = GFX.pCurrentClip->Right [clip][bg];
+
+ if (Right <= Left)
+ continue;
+ }
+
+ uint32 VOffset;
+ uint32 HOffset;
+ uint32 LineHOffset=LineData [Y].BG[bg].HOffset;
+ uint32 Offset;
+ uint32 HPos;
+ uint32 Quot;
+ uint32 Count;
+ uint16 *t;
+ uint32 Quot2;
+ uint32 VCellOffset;
+ uint32 HCellOffset;
+ uint16 *b1;
+ uint16 *b2;
+ uint32 TotalCount = 0;
+ uint32 MaxCount = 8;
+
+ uint32 s = Left * GFX_PIXSIZE + Y * GFX_PPL;
+ bool8_32 left_hand_edge = (Left == 0);
+ Width = Right - Left;
+
+ if (Left & 7)
+ MaxCount = 8 - (Left & 7);
+
+ while (Left < Right)
+ {
+ if (left_hand_edge)
+ {
+ // The SNES offset-per-tile background mode has a
+ // hardware limitation that the offsets cannot be set
+ // for the tile at the left-hand edge of the screen.
+ VOffset = LineData [Y].BG[bg].VOffset;
+ HOffset = LineHOffset;
+ left_hand_edge = FALSE;
+ }
+ else
+ {
+ // All subsequent offset tile data is shifted left by one,
+ // hence the - 1 below.
+ Quot2 = ((HOff + Left - 1) & OffsetMask) >> 3;
+
+ if (Quot2 > 31)
+ s0 = s2 + (Quot2 & 0x1f);
+ else
+ s0 = s1 + Quot2;
+
+ HCellOffset = READ_2BYTES (s0);
+
+ if (BGMode == 4)
+ {
+ VOffset = LineData [Y].BG[bg].VOffset;
+ HOffset=LineHOffset;
+ if ((HCellOffset & OffsetEnableMask))
+ {
+ if (HCellOffset & 0x8000)
+ VOffset = HCellOffset + 1;
+ else
+ HOffset = HCellOffset;
+ }
+ }
+ else
+ {
+ VCellOffset = READ_2BYTES (s0 + VOffsetOffset);
+ if ((VCellOffset & OffsetEnableMask))
+ VOffset = VCellOffset + 1;
+ else
+ VOffset = LineData [Y].BG[bg].VOffset;
+
+ if ((HCellOffset & OffsetEnableMask))
+ HOffset = (HCellOffset & ~7)|(LineHOffset&7);
+ else
+ HOffset=LineHOffset;
+ }
+ }
+ VirtAlign = ((Y + VOffset) & 7) << 3;
+ ScreenLine = (VOffset + Y) >> OffsetShift;
+
+ int tx_index;
+ tx_index = ( ((VOffset + Y) & 15) <= 7 ) << 3;
+
+ if (ScreenLine & 0x20)
+ b1 = SC2, b2 = SC3;
+ else
+ b1 = SC0, b2 = SC1;
+
+ b1 += (ScreenLine & 0x1f) << 5;
+ b2 += (ScreenLine & 0x1f) << 5;
+
+ HPos = (HOffset + Left) & OffsetMask;
+
+ Quot = HPos >> 3;
+
+ if (BG.TileSize == 8)
+ {
+ if (Quot > 31)
+ t = b2 + (Quot & 0x1f);
+ else
+ t = b1 + Quot;
+ }
+ else
+ {
+ if (Quot > 63)
+ t = b2 + ((Quot >> 1) & 0x1f);
+ else
+ t = b1 + (Quot >> 1);
+ }
+
+ if (MaxCount + TotalCount > Width)
+ MaxCount = Width - TotalCount;
+
+ Offset = HPos & 7;
+
+ Count = 8 - Offset;
+ if (Count > MaxCount)
+ Count = MaxCount;
+
+ s -= Offset * GFX_PIXSIZE;
+ Tile = READ_2BYTES(t);
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+
+ if (Tile != TileBlank)
+ if (BG.TileSize == 8)
+ (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines);
+ else
+ {
+ Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)];
+ if (Tile != TileBlank){
+ (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines);
+ }
+ }
+
+ Left += Count;
+ TotalCount += Count;
+ s += (Offset + Count) * GFX_PIXSIZE;
+ MaxCount = 8;
+ }
+ }
+ }
+}
+
+void DrawBackgroundMode5 (uint32 /* BGMODE */, uint32 bg, uint8 Z1, uint8 Z2)
+{
+#ifdef __DEBUG__
+ printf("DrawBackgroundMode5(?, %i, %i, %i)\n", bg, Z1, Z2);
+#endif
+
+ CHECK_SOUND();
+
+ uint8 depths [2] = {Z1, Z2};
+
+ uint32 Tile;
+ uint16 *SC0;
+ uint16 *SC1;
+ uint16 *SC2;
+ uint16 *SC3;
+ uint32 Width;
+
+ BG.StartPalette = 0;
+ SelectPalette();
+
+ SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
+
+ if ((PPU.BG[bg].SCSize & 1))
+ SC1 = SC0 + 1024;
+ else
+ SC1 = SC0;
+
+ if((SC1-(unsigned short*)Memory.VRAM)>0x10000)
+ SC1=(uint16*)&Memory.VRAM[(((uint8*)SC1)-Memory.VRAM)%0x10000];
+
+ if ((PPU.BG[bg].SCSize & 2))
+ SC2 = SC1 + 1024;
+ else SC2 = SC0;
+
+ if(((uint8*)SC2-Memory.VRAM)>=0x10000)
+ SC2-=0x08000;
+
+ if ((PPU.BG[bg].SCSize & 1))
+ SC3 = SC2 + 1024;
+ else
+ SC3 = SC2;
+
+ if(((uint8*)SC3-Memory.VRAM)>=0x10000)
+ SC3-=0x08000;
+ int Lines;
+ int VOffsetMask;
+ int VOffsetShift;
+
+ if (BG.TileSize == 16)
+ {
+ VOffsetMask = 0x3ff;
+ VOffsetShift = 4;
+ }
+ else
+ {
+ VOffsetMask = 0x1ff;
+ VOffsetShift = 3;
+ }
+ int endy = GFX.EndY;
+
+ for (int Y = GFX.StartY; Y <= endy; Y += Lines)
+ {
+ //int y = Y;
+ uint32 VOffset = LineData [Y].BG[bg].VOffset;
+ uint32 HOffset = LineData [Y].BG[bg].HOffset;
+ int VirtAlign = (Y + VOffset) & 7;
+
+ for (Lines = 1; Lines < 8 - VirtAlign; Lines++)
+ if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
+ (HOffset != LineData [Y + Lines].BG[bg].HOffset))
+ break;
+
+ HOffset <<= 1;
+ if (Y + Lines > endy)
+ Lines = endy + 1 - Y;
+
+ int ScreenLine = (VOffset + Y) >> VOffsetShift;
+ int t1;
+ int t2;
+ if (((VOffset + Y) & 15) > 7)
+ {
+ t1 = 16;
+ t2 = 0;
+ }
+ else
+ {
+ t1 = 0;
+ t2 = 16;
+ }
+ uint16 *b1;
+ uint16 *b2;
+
+ if (ScreenLine & 0x20)
+ b1 = SC2, b2 = SC3;
+ else
+ b1 = SC0, b2 = SC1;
+
+ b1 += (ScreenLine & 0x1f) << 5;
+ b2 += (ScreenLine & 0x1f) << 5;
+
+ int clipcount = GFX.pCurrentClip->Count [bg];
+ if (!clipcount)
+ clipcount = 1;
+ for (int clip = 0; clip < clipcount; clip++)
+ {
+ int Left;
+ int Right;
+
+ if (!GFX.pCurrentClip->Count [bg])
+ {
+ Left = 0;
+ Right = 512;
+ }
+ else
+ {
+ Left = GFX.pCurrentClip->Left [clip][bg] * 2;
+ Right = GFX.pCurrentClip->Right [clip][bg] * 2;
+
+ if (Right <= Left)
+ continue;
+ }
+
+ uint32 s = (Left>>1) * GFX_PIXSIZE + Y * GFX_PPL;
+ uint32 HPos = (HOffset + Left * GFX_PIXSIZE) & 0x3ff;
+
+ uint32 Quot = HPos >> 3;
+ uint32 Count = 0;
+
+ uint16 *t;
+ if (Quot > 63)
+ t = b2 + ((Quot >> 1) & 0x1f);
+ else
+ t = b1 + (Quot >> 1);
+
+ Width = Right - Left;
+ // Left hand edge clipped tile
+ if (HPos & 7)
+ {
+ int Offset = (HPos & 7);
+ Count = 8 - Offset;
+ if (Count > Width)
+ Count = Width;
+ s -= (Offset>>1);
+ Tile = READ_2BYTES (t);
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+
+ if (BG.TileSize == 8)
+ {
+ if (!(Tile & H_FLIP))
+ {
+ // Normal, unflipped
+ (*DrawHiResClippedTilePtr) (Tile + (Quot & 1),
+ s, Offset, Count, VirtAlign, Lines);
+ }
+ else
+ {
+ // H flip
+ (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1),
+ s, Offset, Count, VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ if (!(Tile & (V_FLIP | H_FLIP)))
+ {
+ // Normal, unflipped
+ (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1),
+ s, Offset, Count, VirtAlign, Lines);
+ }
+ else
+ if (Tile & H_FLIP)
+ {
+ if (Tile & V_FLIP)
+ {
+ // H & V flip
+ (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
+ s, Offset, Count, VirtAlign, Lines);
+ }
+ else
+ {
+ // H flip only
+ (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
+ s, Offset, Count, VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ // V flip only
+ (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1),
+ s, Offset, Count, VirtAlign, Lines);
+ }
+ }
+
+ t += Quot & 1;
+ if (Quot == 63)
+ t = b2;
+ else if (Quot == 127)
+ t = b1;
+ Quot++;
+ s += 4;
+ }
+
+ // Middle, unclipped tiles
+ Count = Width - Count;
+ int Middle = Count >> 3;
+ Count &= 7;
+ for (int C = Middle; C > 0; s += 4, Quot++, C--)
+ {
+ Tile = READ_2BYTES(t);
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ if (BG.TileSize == 8)
+ {
+ if (!(Tile & H_FLIP))
+ {
+ // Normal, unflipped
+ (*DrawHiResTilePtr) (Tile + (Quot & 1),
+ s, VirtAlign, Lines);
+ }
+ else
+ {
+ // H flip
+ (*DrawHiResTilePtr) (Tile + 1 - (Quot & 1),
+ s, VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ if (!(Tile & (V_FLIP | H_FLIP)))
+ {
+ // Normal, unflipped
+ (*DrawHiResTilePtr) (Tile + t1 + (Quot & 1),
+ s, VirtAlign, Lines);
+ }
+ else
+ if (Tile & H_FLIP)
+ {
+ if (Tile & V_FLIP)
+ {
+ // H & V flip
+ (*DrawHiResTilePtr) (Tile + t2 + 1 - (Quot & 1),
+ s, VirtAlign, Lines);
+ }
+ else
+ {
+ // H flip only
+ (*DrawHiResTilePtr) (Tile + t1 + 1 - (Quot & 1),
+ s, VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ // V flip only
+ (*DrawHiResTilePtr) (Tile + t2 + (Quot & 1),
+ s, VirtAlign, Lines);
+ }
+ }
+
+ t += Quot & 1;
+ if (Quot == 63)
+ t = b2;
+ else
+ if (Quot == 127)
+ t = b1;
+ }
+
+ // Right-hand edge clipped tiles
+ if (Count)
+ {
+ Tile = READ_2BYTES(t);
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ if (BG.TileSize == 8)
+ {
+ if (!(Tile & H_FLIP))
+ {
+ // Normal, unflipped
+ (*DrawHiResClippedTilePtr) (Tile + (Quot & 1),
+ s, 0, Count, VirtAlign, Lines);
+ }
+ else
+ {
+ // H flip
+ (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1),
+ s, 0, Count, VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ if (!(Tile & (V_FLIP | H_FLIP)))
+ {
+ // Normal, unflipped
+ (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1),
+ s, 0, Count, VirtAlign, Lines);
+ }
+ else
+ if (Tile & H_FLIP)
+ {
+ if (Tile & V_FLIP)
+ {
+ // H & V flip
+ (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
+ s, 0, Count, VirtAlign, Lines);
+ }
+ else
+ {
+ // H flip only
+ (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
+ s, 0, Count, VirtAlign, Lines);
+ }
+ }
+ else
+ {
+ // V flip only
+ (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1),
+ s, 0, Count, VirtAlign, Lines);
+ }
+ }
+ }
+ }
+ }
+}
+
+void DrawBackground_8 (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
+{
+#ifdef __DEBUG__
+ printf("DrawBackground_8(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2);
+#endif
+ //uint32 Tile;
+ uint16 *SC0;
+ uint16 *SC1;
+ uint16 *SC2;
+ uint16 *SC3;
+ uint32 depths [2] = {Z1, Z2};
+
+ SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
+
+ SC1 = (uint16 *) &Memory.VRAM[((PPU.BG[bg].SCBase << 1) + ((PPU.BG[bg].SCSize & 1) << 10)) & 0xffff];
+ //SC1 = SC0 + ((PPU.BG[bg].SCSize & 1) << 10);
+
+ //if(SC1 >= (unsigned short*)(Memory.VRAM+0x10000)) SC1 = (uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0]) & 0xffff];
+
+ if (PPU.BG[bg].SCSize & 2)
+ SC2 = SC1 + 1024;
+ else
+ SC2 = SC0;
+
+ if(((uint8*)SC2-Memory.VRAM)>=0x10000) SC2 -= 0x08000;
+
+ SC3 = SC2 + ((PPU.BG[bg].SCSize & 1) << 10);
+
+ if(((uint8*)SC3-Memory.VRAM)>=0x10000) SC3 -= 0x08000;
+
+ int Lines;
+
+ TileBlank = 0xFFFFFFFF;
+ for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines){
+ int y_ppl = Y * GFX_PPL;
+ uint32 VOffset = LineData [Y].BG[bg].VOffset;
+ uint32 HOffset = LineData [Y].BG[bg].HOffset;
+ int VirtAlign = (Y + VOffset) & 7;
+
+ int maxLines = GFX.EndY - Y + 1;
+ if ((8 - VirtAlign) < maxLines) maxLines = (8 - VirtAlign);
+
+ for (Lines = 1; Lines < maxLines; Lines++)
+ if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
+ (HOffset != LineData [Y + Lines].BG[bg].HOffset))
+ break;
+
+
+ VirtAlign <<= 3;
+
+ uint32 ScreenLine = (VOffset + Y) >> 3;
+ uint16 *b1;
+ uint16 *b2;
+
+ if (ScreenLine & 0x20)
+ b1 = SC2, b2 = SC3;
+ else
+ b1 = SC0, b2 = SC1;
+
+ b1 += (ScreenLine & 0x1f) << 5;
+ b2 += (ScreenLine & 0x1f) << 5;
+
+ uint32 Left;
+ uint32 Right;
+ int clip = 0;
+ int clipcount = GFX.pCurrentClip->Count [bg];
+ if (!clipcount) {
+ Left = 0;
+ Right = 256;
+ }
+
+ do {
+ if (clipcount) {
+ Left = GFX.pCurrentClip->Left [clip][bg];
+ Right = GFX.pCurrentClip->Right [clip][bg];
+
+ if (Right <= Left) {clip++; continue;}
+ }
+
+ uint32 s = Left + y_ppl;
+ uint32 HPos = (HOffset + Left) & 0x1ff;
+ uint32 Quot = HPos >> 3;
+ uint32 Count = 0;
+ uint16 *t;
+ uint16 *b;
+
+ if (Quot > 31) {
+ t = b2 + (Quot & 0x1f);
+ b = b1;
+ Quot -= 32;
+ }
+ else {
+ t = b1 + Quot;
+ b = b2;
+ }
+
+ uint32 Width = Right - Left;
+
+ // Left hand edge clipped tile
+ uint32 Offset = (HPos & 7);
+ if (Offset){
+ Count = 8 - Offset;
+ if (Count > Width) Count = Width;
+ s -= Offset;
+ //Tile = READ_2BYTES(t);
+ register uint32 Tile = *(t++);
+ if (Tile != TileBlank){
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines);
+ }
+ //t++;
+ if (Quot == 31) t = b;
+ //else if (Quot == 63) t = b1;
+ Quot++;
+ s += 8;
+ }
+
+ // Middle, unclipped tiles
+ Count = Width - Count;
+ for (int C = Count >> 3; C > 0; s += 8, Quot++, C--){
+ //Tile = READ_2BYTES(t);
+ register uint32 Tile = *(t++);
+ if (Tile != TileBlank){
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ (*DrawTilePtr) (Tile, s, VirtAlign, Lines);
+ }
+
+ //t++;
+ if (Quot == 31) t = b;
+ //else if (Quot == 63) t = b1;
+ }
+
+ // Right-hand edge clipped tiles
+ if (Count & 7){
+ //Tile = READ_2BYTES(t);
+ register uint32 Tile = *t;
+ if (Tile != TileBlank){
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ (*DrawClippedTilePtr) (Tile, s, 0, Count & 7, VirtAlign, Lines);
+ }
+ }
+ clip ++;
+ } while (clip < clipcount);
+ }
+}
+
+void DrawBackground_16 (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
+{
+#ifdef __DEBUG__
+ printf("DrawBackground_16(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2);
+#endif
+ //uint32 Tile;
+ uint16 *SC0;
+ uint16 *SC1;
+ uint16 *SC2;
+ uint16 *SC3;
+ uint32 depths [2] = {Z1, Z2};
+
+ SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
+
+ SC1 = (uint16 *) &Memory.VRAM[((PPU.BG[bg].SCBase << 1) + ((PPU.BG[bg].SCSize & 1) << 10)) & 0xffff];
+ //SC1 = SC0 + ((PPU.BG[bg].SCSize & 1) << 10);
+
+ //if(SC1 >= (unsigned short*)(Memory.VRAM+0x10000)) SC1 = (uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0]) & 0xffff];
+
+ if (PPU.BG[bg].SCSize & 2)
+ SC2 = SC1 + 1024;
+ else
+ SC2 = SC0;
+
+ if(((uint8*)SC2-Memory.VRAM)>=0x10000) SC2 -= 0x08000;
+
+ SC3 = SC2 + ((PPU.BG[bg].SCSize & 1) << 10);
+
+ if(((uint8*)SC3-Memory.VRAM)>=0x10000) SC3 -= 0x08000;
+
+ int Lines;
+
+ TileBlank = 0xFFFFFFFF;
+ for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines){
+ int y_ppl = Y * GFX_PPL;
+ uint32 VOffset = LineData [Y].BG[bg].VOffset;
+ uint32 HOffset = LineData [Y].BG[bg].HOffset;
+ int VirtAlign = (Y + VOffset) & 7;
+
+ int maxLines = GFX.EndY - Y + 1;
+ if ((8 - VirtAlign) < maxLines) maxLines = (8 - VirtAlign);
+
+ for (Lines = 1; Lines < maxLines; Lines++)
+ if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
+ (HOffset != LineData [Y + Lines].BG[bg].HOffset))
+ break;
+
+
+ VirtAlign <<= 3;
+
+ uint32 ScreenLine = (VOffset + Y) >> 4;
+ //int tx_index = ( ((VOffset + Y) & 15) <= 7 ) << 3;
+ int tx_index = ((((VOffset + Y) & 15) <= 7 ) << 4) ^ (16);
+ uint16 *b1;
+ uint16 *b2;
+
+ if (ScreenLine & 0x20)
+ b1 = SC2, b2 = SC3;
+ else
+ b1 = SC0, b2 = SC1;
+
+ b1 += (ScreenLine & 0x1f) << 5;
+ b2 += (ScreenLine & 0x1f) << 5;
+
+ uint32 Left;
+ uint32 Right;
+ int clip = 0;
+ int clipcount = GFX.pCurrentClip->Count [bg];
+ if (!clipcount) {
+ Left = 0;
+ Right = 256;
+ }
+
+ do {
+ if (clipcount) {
+ Left = GFX.pCurrentClip->Left [clip][bg];
+ Right = GFX.pCurrentClip->Right [clip][bg];
+
+ if (Right <= Left) {clip++; continue;}
+ }
+
+ uint32 s = Left + y_ppl;
+ uint32 HPos = (HOffset + Left) & 0x3ff;
+ uint32 Quot = HPos >> 3;
+ uint32 Count = 0;
+ uint16 *t;
+ uint16 *b;
+
+ if (Quot > 63) {
+ t = b2 + ((Quot >> 1) & 0x1f);
+ b = b1;
+ Quot -= 64;
+ }
+ else {
+ t = b1 + (Quot >> 1);
+ b = b2;
+ }
+
+
+ uint32 Width = Right - Left;
+
+ // Left hand edge clipped tile
+ uint32 Offset = (HPos & 7);
+ if (Offset){
+ Count = 8 - Offset;
+ if (Count > Width) Count = Width;
+ s -= Offset;
+ //Tile = READ_2BYTES(t);
+ uint32 Tile = *(t);
+ t += Quot & 1;
+ Tile += (((Tile & H_FLIP) >> 14) ^ (Quot & 1)) + (((Tile & V_FLIP) >> 11) ^ tx_index);
+ //Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)];
+ if (Tile != TileBlank){
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines);
+ }
+ //t++;
+ if (Quot == 63) t = b;
+ Quot++;
+ s += 8;
+ }
+
+
+ // Middle, unclipped tiles
+ Count = Width - Count;
+ for (int C = Count >> 3; C > 0; s += 8, Quot++, C--){
+ //Tile = READ_2BYTES(t);
+ uint32 Tile = *(t);
+ t += Quot & 1;
+ Tile += (((Tile & H_FLIP) >> 14) ^ (Quot & 1)) + (((Tile & V_FLIP) >> 11) ^ tx_index);
+ //Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)];
+ if (Tile != TileBlank){
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ (*DrawTilePtr) (Tile, s, VirtAlign, Lines);
+ }
+
+ //t++;
+ if (Quot == 63) t = b;
+ }
+
+ // Right-hand edge clipped tiles
+ if (Count & 7){
+ //Tile = READ_2BYTES(t);
+ uint32 Tile = *(t);
+ Tile += (((Tile & H_FLIP) >> 14) ^ (Quot & 1)) + (((Tile & V_FLIP) >> 11) ^ tx_index);
+ //Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)];
+ if (Tile != TileBlank){
+ GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
+ (*DrawClippedTilePtr) (Tile, s, 0, Count & 7, VirtAlign, Lines);
+ }
+ }
+ clip ++;
+ } while (clip < clipcount);
+ }
+}
+
+inline void DrawBackground (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
+{
+//StartAnalyze();
+
+ BG.TileSize = BGSizes [PPU.BG[bg].BGSize];
+ BG.BitShift = BitShifts[BGMode][bg];
+ SelectConvertTile();
+ BG.TileShift = TileShifts[BGMode][bg];
+ BG.TileAddress = PPU.BG[bg].NameBase << 1;
+ BG.NameSelect = 0;
+ BG.Buffer = IPPU.TileCache [Depths [BGMode][bg]];
+ BG.Buffered = IPPU.TileCached [Depths [BGMode][bg]];
+ BG.PaletteShift = PaletteShifts[BGMode][bg];
+ BG.PaletteMask = PaletteMasks[BGMode][bg];
+ BG.DirectColourMode = (BGMode == 3 || BGMode == 4) && bg == 0 && (GFX.r2130 & 1);
+
+ if (IPPU.DirectColourMapsNeedRebuild && BG.DirectColourMode) S9xBuildDirectColourMaps ();
+
+ if (PPU.BGMosaic [bg] && PPU.Mosaic > 1){
+ DrawBackgroundMosaic (BGMode, bg, Z1, Z2);
+ return;
+
+ }
+ switch (BGMode)
+ {
+ case 2:
+ case 4: // Used by Puzzle Bobble
+ DrawBackgroundOffset (BGMode, bg, Z1, Z2);
+ break;
+
+ case 5:
+ case 6: // XXX: is also offset per tile.
+ DrawBackgroundMode5 (BGMode, bg, Z1, Z2);
+ break;
+ case 0:
+ case 1:
+ case 3:
+ CHECK_SOUND();
+
+ if (BGMode == 0) BG.StartPalette = bg << 5;
+ else BG.StartPalette = 0;
+ SelectPalette();
+
+ if (BG.TileSize == 8) DrawBackground_8 (BGMode, bg, Z1, Z2);
+ else DrawBackground_16 (BGMode, bg, Z1, Z2);
+ break;
+ }
+}
+
+#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; \
+GREEN_HI_BIT = ((MAX_GREEN_##F + 1) >> 1); \
+SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_##F; \
+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);
+
+void RenderScreen (uint8 *Screen, bool8_32 sub, bool8_32 force_no_add, uint8 D)
+{
+ bool8_32 BG0;
+ bool8_32 BG1;
+ bool8_32 BG2;
+ bool8_32 BG3;
+ bool8_32 OB;
+
+ GFX.S = Screen;
+
+ if (!sub)
+ {
+ GFX.pCurrentClip = &IPPU.Clip [0];
+ BG0 = ON_MAIN (0) && !(Settings.os9x_hack & GFX_IGNORE_BG0);
+ BG1 = ON_MAIN (1) && !(Settings.os9x_hack & GFX_IGNORE_BG1);
+ BG2 = ON_MAIN (2) && !(Settings.os9x_hack & GFX_IGNORE_BG2);
+ BG3 = ON_MAIN (3) && !(Settings.os9x_hack & GFX_IGNORE_BG3);
+ OB = ON_MAIN (4) && !(Settings.os9x_hack & GFX_IGNORE_OBJ);
+ }
+ else
+ {
+ GFX.pCurrentClip = &IPPU.Clip [1];
+ BG0 = ON_SUB (0) && !(Settings.os9x_hack & GFX_IGNORE_BG0);
+ BG1 = ON_SUB (1) && !(Settings.os9x_hack & GFX_IGNORE_BG1);
+ BG2 = ON_SUB (2) && !(Settings.os9x_hack & GFX_IGNORE_BG2);
+ BG3 = ON_SUB (3) && !(Settings.os9x_hack & GFX_IGNORE_BG3);
+ OB = ON_SUB (4) && !(Settings.os9x_hack & GFX_IGNORE_OBJ);
+ }
+
+#ifdef __DEBUG__
+ printf("Screen[y1,y2]:[%i,%i],Mode:%i, BG0:%i,BG1:%i,BG2:%i,BG3:%i,OBJ:%i\n", GFX.StartY, GFX.EndY, PPU.BGMode, BG0, BG1, BG2, BG3, OB);
+#endif
+
+ sub |= force_no_add;
+
+ if (PPU.BGMode <= 1)
+ {
+ if (OB)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(4), true);
+ DrawOBJS (!sub, D);
+ }
+ if (BG0)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(0));
+ DrawBackground (PPU.BGMode, 0, D + 10, D + 14);
+ }
+ if (BG1)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(1));
+ DrawBackground (PPU.BGMode, 1, D + 9, D + 13);
+ }
+ if (BG2)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(2));
+ DrawBackground (PPU.BGMode, 2, D + 3,
+ PPU.BG3Priority ? D + 17 : D + 6);
+ }
+ if (BG3 && PPU.BGMode == 0)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(3));
+ DrawBackground (PPU.BGMode, 3, D + 2, D + 5);
+ }
+ }
+ else if (PPU.BGMode != 7)
+ {
+ if (OB)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(4), true);
+ DrawOBJS (!sub, D);
+ }
+ if (BG0)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(0));
+ DrawBackground (PPU.BGMode, 0, D + 5, D + 13);
+ }
+ if (PPU.BGMode != 6 && BG1)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(1));
+ DrawBackground (PPU.BGMode, 1, D + 2, D + 9);
+ }
+ }
+ else
+ {
+ if (OB && ((SNESGameFixes.Mode7Hack && D) || !SNESGameFixes.Mode7Hack))
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(4), true);
+ DrawOBJS (!sub, D);
+ }
+ if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1))
+ {
+ int bg;
+
+ if ((Memory.FillRAM [0x2133] & 0x40)&&BG1)
+ {
+ Mode7Depths [0] = (BG0?5:1) + D;
+ Mode7Depths [1] = 9 + D;
+ bg = 1;
+ if (sub || !SUB_OR_ADD(0))
+ {
+ DrawBGMode7Background16Prio (Screen, bg);
+ }
+ else
+ {
+ if (GFX.r2131 & 0x80)
+ {
+ if (GFX.r2131 & 0x40)
+ {
+ DrawBGMode7Background16PrioSub1_2 (Screen, bg);
+ }
+ else
+ {
+ DrawBGMode7Background16PrioSub (Screen, bg);
+ }
+ }
+ else
+ {
+ if (GFX.r2131 & 0x40)
+ {
+ DrawBGMode7Background16PrioAdd1_2 (Screen, bg);
+ }
+ else
+ {
+ DrawBGMode7Background16PrioAdd (Screen, bg);
+ }
+ }
+ }
+ }
+ else
+ {
+ bg = 0;
+ if (sub || !SUB_OR_ADD(0))
+ {
+ if (D || !SNESGameFixes.Mode7Hack) DrawBGMode7Background16 (Screen, bg, D+5);
+ else DrawBGMode7Background16New (Screen);
+ }
+ else
+ {
+ if (GFX.r2131 & 0x80)
+ {
+ if (GFX.r2131 & 0x40)
+ {
+ DrawBGMode7Background16Sub1_2 (Screen, bg, D+5);
+ }
+ else
+ {
+ DrawBGMode7Background16Sub (Screen, bg, D+5);
+ }
+ }
+ else
+ {
+ if (GFX.r2131 & 0x40)
+ {
+ DrawBGMode7Background16Add1_2 (Screen, bg, D+5);
+ }
+ else
+ {
+ DrawBGMode7Background16Add (Screen, bg, D+5);
+ }
+ }
+ }
+ }
+ }
+ if (OB && SNESGameFixes.Mode7Hack && D==0)
+ {
+ SelectTileRenderer (sub || !SUB_OR_ADD(4), true);
+ DrawOBJS (!sub, D);
+ }
+ }
+}
+
+#include "font.h"
+
+void DisplayChar (uint8 *Screen, uint8 c)
+{
+ int line = (((c & 0x7f) - 32) >> 4) * font_height;
+ int offset = (((c & 0x7f) - 32) & 15) * font_width;
+ int h, w;
+ uint16 *s = (uint16 *) Screen;
+ for (h = 0; h < font_height; h++, line++,
+ s += GFX_PPL - font_width)
+ {
+ for (w = 0; w < font_width; w++, s++)
+ {
+ uint8 p = font [line][offset + w];
+
+ if (p == '#')
+ *s = 0xffff;
+ else
+ if (p == '.')
+ *s = BLACK;
+ }
+ }
+}
+
+static void S9xDisplayFrameRate ()
+{
+ uint8 *Screen = GFX.Screen + 2 +
+ (IPPU.RenderedScreenHeight - font_height - 1) * GFX_PITCH;
+ char string [10];
+ int len = 5;
+
+ sprintf (string, "%02d/%02d", IPPU.DisplayedRenderedFrameCount,
+ (int) Memory.ROMFramesPerSecond);
+
+ int i;
+ for (i = 0; i < len; i++)
+ {
+ DisplayChar (Screen, string [i]);
+ Screen += (font_width - 1) * sizeof (uint16);
+ }
+}
+
+static void S9xDisplayString (const char *string)
+{
+ uint8 *Screen = GFX.Screen + 2 +
+ (IPPU.RenderedScreenHeight - font_height * 5) * GFX_PITCH;
+ int len = strlen (string);
+ int max_chars = IPPU.RenderedScreenWidth / (font_width - 1);
+ int char_count = 0;
+ int i;
+
+ for (i = 0; i < len; i++, char_count++)
+ {
+ if (char_count >= max_chars || string [i] < 32)
+ {
+ Screen -= (font_width - 1) * sizeof (uint16) * max_chars;
+ Screen += font_height * GFX_PITCH;
+ if (Screen >= GFX.Screen + GFX_PITCH * IPPU.RenderedScreenHeight)
+ break;
+ char_count -= max_chars;
+ }
+ if (string [i] < 32)
+ continue;
+ DisplayChar (Screen, string [i]);
+ Screen += (font_width - 1) * sizeof (uint16);
+ }
+}
+
+
+void S9xUpdateScreen () // ~30-50ms! (called from FLUSH_REDRAW())
+{
+ GFX.S = GFX.Screen;
+
+ unsigned char *memoryfillram = Memory.FillRAM;
+
+ // get local copies of vid registers to be used later
+ GFX.r2131 = memoryfillram [0x2131]; // ADDITION/SUBTRACTION & SUBTRACTION DESIGNATION FOR EACH SCREEN
+ GFX.r212c = memoryfillram [0x212c]; // MAIN SCREEN, DESIGNATION - used to enable BGS
+ GFX.r212d = memoryfillram [0x212d]; // SUB SCREEN DESIGNATION - used to enable sub BGS
+ GFX.r2130 = memoryfillram [0x2130]; // INITIAL SETTINGS FOR FIXED COLOR ADDITION OR SCREEN ADDITION
+
+ // If external sync is off and
+ // main screens have not been configured the same as the sub screen and
+ // color addition and subtraction has been diabled then
+ // Pseudo is 1
+ // anything else it is 0
+ GFX.Pseudo = (memoryfillram [0x2133] & 8) != 0 && // Use EXTERNAL SYNCHRONIZATION?
+ (GFX.r212c & 15) != (GFX.r212d & 15) && // Are the main screens different from the sub screens?
+ (GFX.r2131 & 0x3f) == 0; // Is colour data addition/subtraction disabled on all BGS?
+
+ // If sprite data has been changed then go through and
+ // refresh the sprites.
+ if (IPPU.OBJChanged) S9xSetupOBJ ();
+
+ if (PPU.RecomputeClipWindows) ComputeClipWindows ();
+
+ GFX.StartY = IPPU.PreviousLine;
+ if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight)
+ GFX.EndY = PPU.ScreenHeight - 1;
+
+ uint32 starty = GFX.StartY;
+ uint32 endy = GFX.EndY;
+ uint32 black = BLACK | (BLACK << 16);
+
+
+ if (GFX.Pseudo)
+ {
+ GFX.r2131 = 0x5f; //0101 1111 - enable addition/subtraction on all BGS and sprites and "1/2 OF COLOR DATA" DESIGNATION
+ GFX.r212c &= (Memory.FillRAM [0x212d] | 0xf0);
+ GFX.r212d |= (Memory.FillRAM [0x212c] & 0x0f);
+ GFX.r2130 |= 2; // enable ADDITION/SUBTRACTION FOR SUB SCREEN
+ }
+
+ // Check to see if any transparency effects are currently in use
+ if (!PPU.ForcedBlanking && ADD_OR_SUB_ON_ANYTHING &&
+ (GFX.r2130 & 0x30) != 0x30 &&
+ !((GFX.r2130 & 0x30) == 0x10 && IPPU.Clip[1].Count[5] == 0))
+ {
+ // transparency effects in use, so lets get busy!
+ struct ClipData *pClip;
+ uint32 fixedColour;
+ GFX.FixedColour = BUILD_PIXEL (IPPU.XB [PPU.FixedColourRed],
+ IPPU.XB [PPU.FixedColourGreen],
+ IPPU.XB [PPU.FixedColourBlue]);
+ fixedColour = (GFX.FixedColour<<16|GFX.FixedColour);
+ // Clear the z-buffer, marking areas 'covered' by the fixed
+ // colour as depth 1.
+ pClip = &IPPU.Clip [1];
+
+ // Clear the z-buffer
+
+ if (pClip->Count [5])
+ {
+
+ // Colour window enabled.
+ // loop around all of the lines being updated
+ for (uint32 y = starty; y <= endy; y++)
+ {
+ // Clear the subZbuffer
+ memset32 ((uint32_t*)(GFX.SubZBuffer + y * GFX_ZPITCH),0, (256>>2));
+ // Clear the Zbuffer
+ memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH),0, (256>>2));
+ if (IPPU.Clip[0].Count [5]) {
+ // if there is clipping then clear subscreen to a black color
+ memset32 ((uint32_t*)(GFX.SubScreen + y * GFX_PITCH), black, (256>>1));
+ }
+
+ // loop through all window clippings
+ for (uint32 c = 0; c < pClip->Count [5]; c++)
+ {
+ if (pClip->Right [c][5] > pClip->Left [c][5])
+ {
+ memset (GFX.SubZBuffer + y * GFX_ZPITCH + pClip->Left [c][5],
+ 1, pClip->Right [c][5] - pClip->Left [c][5]);
+
+ if (IPPU.Clip [0].Count [5])
+ {
+ // Blast, have to clear the sub-screen to the fixed-colour
+ // because there is a colour window in effect clipping
+ // the main screen that will allow the sub-screen
+ // 'underneath' to show through.
+
+ register unsigned int width = pClip->Right [c][5] - pClip->Left [c][5];
+ if (width > 0) {
+ asm volatile (
+ " mov r0, %[fixedcolour] \n"
+ " subs %[width], %[width], #4 \n"
+ " bmi 2f \n"
+
+ "1: \n"
+ " subs %[width], %[width], #4 \n"
+ " stmia %[p]!, {r0, %[fixedcolour]}\n"
+ " bpl 1b \n"
+
+ "2: \n"
+ " tst %[width], #1 \n"
+ " strneh %[fixedcolour], [%[p]], #2 \n"
+
+ " tst %[width], #2 \n"
+ " strne %[fixedcolour], [%[p]], #4 \n"
+
+ : [width] "+r" (width)
+ : [fixedcolour] "r" (fixedColour),
+ [p] "r" (((uint16 *) (GFX.SubScreen + y * GFX_PITCH)) + pClip->Left [c][5])
+ : "r0", "cc"
+ );
+ }
+ }
+ }
+ }
+ }
+
+ }
+ else
+ {
+ // No windows are clipping the main screen
+ // this simplifies the screen clearing process
+ // loop through all of the lines to be updated
+ for (uint32 y = starty; y <= endy; y++) {
+ // Clear the Zbuffer
+ memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH),0, (256>>2));
+ // clear the sub Zbuffer to 1
+ memset32 ((uint32_t*)(GFX.SubZBuffer + y * GFX_ZPITCH), 0x01010101, (256>>2));
+
+ if (IPPU.Clip [0].Count [5]) {
+ // Blast, have to clear the sub-screen to the fixed-colour
+ // because there is a colour window in effect clipping
+ // the main screen that will allow the sub-screen
+ // 'underneath' to show through.
+
+ memset32 ((uint32_t*)(GFX.SubScreen + y * GFX_PITCH), fixedColour, (256>>1));
+ }
+ }
+ }
+ if (ANYTHING_ON_SUB)
+ {
+ GFX.DB = GFX.SubZBuffer;
+ RenderScreen (GFX.SubScreen, TRUE, TRUE, SUB_SCREEN_DEPTH);
+ }
+
+ if (IPPU.Clip [0].Count [5])
+ {
+ asm volatile (
+ "1: \n"
+ " mov r1, #(256 >> 2) \n"
+
+ "2: \n"
+ // four pixels at once
+ " ldrb r0, [%[d]], #1 \n"
+ " ldrb r4, [%[d]], #1 \n"
+
+ " bics r0, r0, #1 \n"
+ " ldrneh r0, [%[p], %[delta]] \n"
+
+ " bics r4, r4, #1 \n"
+ " ldrneh r4, [%[p], %[delta2]] \n"
+
+ " strh r0, [%[p]], #2 \n"
+ " strh r4, [%[p]], #2 \n"
+
+ " ldrb r0, [%[d]], #1 \n"
+ " ldrb r4, [%[d]], #1 \n"
+
+ " bics r0, r0, #1 \n"
+ " ldrneh r0, [%[p], %[delta]] \n"
+
+ " bics r4, r4, #1 \n"
+ " ldrneh r4, [%[p], %[delta2]] \n"
+
+ " strh r0, [%[p]], #2 \n"
+ " strh r4, [%[p]], #2 \n"
+
+ " subs r1, r1, #1 \n"
+ " bne 2b \n"
+ "3: \n"
+ " subs %[lines], %[lines], #1 \n"
+ " add %[p], %[p], #(640 - 512) \n"
+ " add %[d], %[d], #(320 - 256) \n"
+ " bne 1b \n"
+ "4: \n"
+
+ :
+ : [p] "r" ((uint16 *) (GFX.Screen + starty * GFX_PITCH)),
+ [d] "r" (GFX.SubZBuffer + starty * GFX_ZPITCH),
+ [delta] "r" (GFX.Delta << 1),
+ [delta2] "r" ((GFX.Delta << 1) + 2),
+ [lines] "r" (endy - starty + 1)
+ : "r0", "r1", "r3", "r4", "cc"
+ );
+ }
+
+ GFX.DB = GFX.ZBuffer;
+ RenderScreen (GFX.Screen, FALSE, FALSE, MAIN_SCREEN_DEPTH);
+ if (SUB_OR_ADD(5))
+ {
+ uint32 back = IPPU.ScreenColors [0];
+ uint32 Left = 0;
+ uint32 Right = 256;
+ uint32 Count;
+
+ pClip = &IPPU.Clip [0];
+
+ for (uint32 y = starty; y <= endy; y++)
+ {
+ if (!(Count = pClip->Count [5]))
+ {
+ Left = 0;
+ Right = 256;
+ Count = 1;
+ }
+
+ for (uint32 b = 0; b < Count; b++)
+ {
+ if (pClip->Count [5])
+ {
+ Left = pClip->Left [b][5];
+ Right = pClip->Right [b][5];
+ if (Right <= Left)
+ continue;
+ }
+#define SUBSCREEN_BG(rop, half) \
+\
+asm volatile (\
+" ldrb r0, [%[d]], #1 \n"\
+"71: \n"\
+\
+" movs r0, r0 \n"\
+" ldreqb r1, [%[d], %[zdelta]] \n"\
+" bne 72f \n"\
+\
+" cmp r1, #1 \n"\
+" beq 74f \n"\
+" ldrh r1, [%[p], %[delta]] \n"\
+" mov r0, %[back] \n"\
+\
+ROP_##rop##half (r0, r1)\
+\
+" strh r0, [%[p]] \n"\
+"72: \n"\
+" add %[p], %[p], #2 \n"\
+" subs %[c], %[c], #1 \n"\
+" ldrneb r0, [%[d]], #1 \n"\
+" bne 71b \n"\
+" b 75f \n"\
+"74: \n"\
+" streqh %[fixedcolour], [%[p]], #2 \n"\
+" strloh %[back], [%[p]], #2 \n"\
+" subs %[c], %[c], #1 \n"\
+" ldrneb r0, [%[d]], #1 \n"\
+" bne 71b \n"\
+"75: \n"\
+:\
+:[p] "r" ((uint16 *) (GFX.Screen + y * GFX_PITCH) + Left),\
+ [d] "r" (GFX.ZBuffer + y * GFX_ZPITCH + Left),\
+ [zdelta] "r" (GFX.DepthDelta),\
+ [back] "r" (back),\
+ [delta] "r" (GFX.Delta << 1),\
+ [fixedcolour] "r" (COLOR_##rop (back, GFX.FixedColour)),\
+ [c] "r" (Right - Left) \
+: "r0", "r1", "cc"\
+);
+ if (GFX.r2131 & 0x80)
+ {
+ if (GFX.r2131 & 0x40)
+ {
+ SUBSCREEN_BG(SUB, 1_2)
+ }
+ else
+ {
+ SUBSCREEN_BG(SUB, )
+
+ }
+ }
+ else
+ if (GFX.r2131 & 0x40)
+ {
+ SUBSCREEN_BG(ADD, 1_2)
+ }
+ else if (back != 0) {
+ SUBSCREEN_BG(ADD, )
+ }
+ else
+ {
+ if (!pClip->Count [5])
+ {
+ // The backdrop has not been cleared yet - so
+ // copy the sub-screen to the main screen
+ // or fill it with the back-drop colour if the
+ // sub-screen is clear.
+ asm volatile (
+ " ldrb r0, [%[d]], #1 \n"
+ "31: \n"
+
+ " movs r0, r0 \n"
+ " ldreqb r1, [%[d], %[zdelta]] \n"
+ " bne 32f \n"
+
+ " cmp r1, #1 \n"
+ " ldrhih r0, [%[p], %[delta]] \n"
+ " strloh %[back], [%[p]] \n"
+ " streqh %[fixedcolour], [%[p]] \n"
+ " strhih r0, [%[p]] \n"
+
+ "32: \n"
+ " subs %[c], %[c], #1 \n"
+ " add %[p], %[p], #2 \n"
+ " ldrneb r0, [%[d]], #1 \n"
+ " bne 31b \n"
+ " \n"
+ :
+ :[p] "r" ((uint16 *) (GFX.Screen + y * GFX_PITCH) + Left),
+ [d] "r" (GFX.ZBuffer + y * GFX_ZPITCH + Left),
+ [zdelta] "r" (GFX.DepthDelta),
+ [back] "r" (back),
+ [delta] "r" (GFX.Delta << 1),
+ [fixedcolour] "r" (GFX.FixedColour),
+ [c] "r" (Right - Left)
+ : "r0", "r1", "cc"
+
+ );
+
+ }
+ }
+ }
+ }
+
+ }
+ else
+ {
+ // Subscreen not being added to back
+ uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16);
+ pClip = &IPPU.Clip [0];
+
+ if (pClip->Count [5])
+ {
+ for (uint32 y = starty; y <= endy; y++)
+ {
+ for (uint32 b = 0; b < pClip->Count [5]; b++)
+ {
+ uint32 Left = pClip->Left [b][5];
+ uint32 Right = pClip->Right [b][5];
+ if (Left >= Right) continue;
+ asm volatile (
+
+ " tst %[c], #1 \n"
+ " bne 21f \n"
+
+ " ldrb r0, [%[d]], #1 \n"
+ " add %[p], %[p], #2 \n"
+ " movs r0, r0 \n"
+ " streqh %[back], [%[p], #-2] \n"
+ " subs %[c], %[c], #1 \n"
+ " beq 22f \n"
+
+ "21: \n"
+
+ " ldrb r0, [%[d]], #1 \n"
+ " ldrb r1, [%[d]], #1 \n"
+ " add %[p], %[p], #4 \n"
+
+ " movs r0, r0 \n"
+ " streqh %[back], [%[p], #-4] \n"
+
+ " movs r1, r1 \n"
+ " streqh %[back], [%[p], #-2] \n"
+
+ " subs %[c], %[c], #2 \n"
+ " bhi 21b \n"
+ "22: \n"
+ :
+ :[p] "r" ((uint16 *) (GFX.Screen + y * GFX_PITCH) + Left),
+ [d] "r" (GFX.ZBuffer + y * GFX_ZPITCH + Left),
+ [back] "r" (back),
+ [c] "r" (Right - Left)
+ : "r0", "r1", "cc"
+
+ );
+ }
+ }
+ }
+ else
+ {
+ asm volatile (
+ "@ -- SubScreen clear \n"
+ "1113: \n"
+ " mov r1, #(256/8) \n"
+ "1112: \n"
+ " ldr r0, [%[d]], #4 \n"
+
+ " add %[p], %[p], #8 \n"
+
+ " tst r0, #0x0ff \n"
+ " streqh %[back], [%[p], #-8] \n"
+
+ " tst r0, #0x0ff00 \n"
+ " streqh %[back], [%[p], #-6] \n"
+
+ " tst r0, #0x0ff0000 \n"
+ " streqh %[back], [%[p], #-4] \n"
+
+ " tst r0, #0x0ff000000 \n"
+ " streqh %[back], [%[p], #-2] \n"
+
+ " ldr r0, [%[d]], #4 \n"
+
+ " add %[p], %[p], #8 \n"
+
+ " tst r0, #0x0ff \n"
+ " streqh %[back], [%[p], #-8] \n"
+
+ " tst r0, #0x0ff00 \n"
+ " streqh %[back], [%[p], #-6] \n"
+
+ " tst r0, #0x0ff0000 \n"
+ " streqh %[back], [%[p], #-4] \n"
+
+ " tst r0, #0x0ff000000 \n"
+ " streqh %[back], [%[p], #-2] \n"
+
+ " subs r1, r1, #1 \n"
+ " bne 1112b \n"
+
+ " subs %[lines], %[lines], #1 \n"
+ " add %[p], %[p], #(640-512) \n"
+ " add %[d], %[d], #(320-256) \n"
+ " bne 1113b \n"
+ "1114:"
+ :
+ :[p] "r" (GFX.Screen + starty * GFX_PITCH),
+ [d] "r" (GFX.ZBuffer + starty * GFX_ZPITCH),
+ [back] "r" (back),
+ [lines] "r" (endy - starty + 1)
+ : "r0", "r1", "cc"
+ );
+ }
+ }
+ }
+ else
+ {
+ // 16bit and transparency but currently no transparency effects in
+ // operation.
+
+ // get the back colour of the current screen
+ uint32 back = IPPU.ScreenColors [0] |
+ (IPPU.ScreenColors [0] << 16);
+
+ // if forceblanking in use then use black instead of the back color
+ if (PPU.ForcedBlanking)
+ back = black;
+
+ // not sure what Clip is used for yet
+ // could be a check to see if there is any clipping present?
+ if (IPPU.Clip [0].Count[5])
+ {
+
+ // loop through all of the lines that are going to be updated as part of this screen update
+ for (uint32 y = starty; y <= endy; y++)
+ {
+ memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), black,
+ IPPU.RenderedScreenWidth>>1);
+
+ if (black!=back)
+ {
+ for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++)
+ {
+ if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5])
+ {
+ register unsigned int width = IPPU.Clip [0].Right [c][5] - IPPU.Clip [0].Left [c][5];
+ if (width > 0) {
+ asm volatile (
+ " mov r0, %[back] \n"
+ " subs %[width], %[width], #4 \n"
+ " bmi 2f \n"
+
+ "1: \n"
+ " subs %[width], %[width], #4 \n"
+ " stmia %[p]!, {r0, %[back]} \n"
+ " bpl 1b \n"
+
+ "2: \n"
+ " tst %[width], #1 \n"
+ " strneh %[back], [%[p]], #2 \n"
+
+ " tst %[width], #2 \n"
+ " strne %[back], [%[p]], #4 \n"
+ : [width] "+r" (width)
+ : [back] "r" (back | (back << 16)),
+ [p] "r" (((uint16 *) (GFX.SubScreen + y * GFX_PITCH)) + IPPU.Clip [0].Left [c][5])
+ : "r0", "cc"
+ );
+ }
+
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // there is no clipping to worry about so just fill with the back colour
+ for (uint32 y = starty; y <= endy; y++) {
+ memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), back, (256>>1));
+ }
+
+ }
+
+ // If Forced blanking is not in effect
+ if (!PPU.ForcedBlanking)
+ {
+ // Clear the Zbuffer for each of the lines which are going to be updated
+ for (uint32 y = starty; y <= endy; y++) {
+ memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH), 0, (256>>2));
+ }
+ GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object
+ RenderScreen (GFX.Screen, FALSE, TRUE, SUB_SCREEN_DEPTH);
+ }
+ }
+ IPPU.PreviousLine = IPPU.CurrentLine;
+}
+
+// -x-
+void S9xUpdateScreenNoTransparency () // ~30-50ms! (called from FLUSH_REDRAW())
+{
+ GFX.S = GFX.Screen;
+
+ unsigned char *memoryfillram = Memory.FillRAM;
+
+ // get local copies of vid registers to be used later
+ GFX.r2131 = memoryfillram [0x2131]; // ADDITION/SUBTRACTION & SUBTRACTION DESIGNATION FOR EACH SCREEN
+ GFX.r212c = memoryfillram [0x212c]; // MAIN SCREEN, DESIGNATION - used to enable BGS
+ GFX.r212d = memoryfillram [0x212d]; // SUB SCREEN DESIGNATION - used to enable sub BGS
+ GFX.r2130 = memoryfillram [0x2130]; // INITIAL SETTINGS FOR FIXED COLOR ADDITION OR SCREEN ADDITION
+
+ // If external sync is off and
+ // main screens have not been configured the same as the sub screen and
+ // color addition and subtraction has been diabled then
+ // Pseudo is 1
+ // anything else it is 0
+ GFX.Pseudo = (memoryfillram [0x2133] & 8) != 0 && // Use EXTERNAL SYNCHRONIZATION?
+ (GFX.r212c & 15) != (GFX.r212d & 15) && // Are the main screens different from the sub screens?
+ (GFX.r2131 & 0x3f) == 0; // Is colour data addition/subtraction disabled on all BGS?
+
+ // If sprite data has been changed then go through and
+ // refresh the sprites.
+ if (IPPU.OBJChanged)
+ {
+ S9xSetupOBJ ();
+ }
+
+ if (PPU.RecomputeClipWindows) ComputeClipWindows();
+
+ GFX.StartY = IPPU.PreviousLine;
+ if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight)
+ GFX.EndY = PPU.ScreenHeight - 1;
+
+ uint32 starty = GFX.StartY;
+ uint32 endy = GFX.EndY;
+
+ uint32 black = BLACK | (BLACK << 16);
+
+ // get back colour to be used in clearing the screen
+ register uint32 back;
+ if (!(Memory.FillRAM [0x2131] & 0x80) &&(Memory.FillRAM[0x2131] & 0x20) &&
+ (PPU.FixedColourRed || PPU.FixedColourGreen || PPU.FixedColourBlue))
+ {
+ back = (IPPU.XB[PPU.FixedColourRed]<<11) |
+ (IPPU.XB[PPU.FixedColourGreen] << 6) |
+ (IPPU.XB[PPU.FixedColourBlue] << 1) | 1;
+ back = (back << 16) | back;
+ }
+ else
+ {
+ back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16);
+ }
+
+ // if Forcedblanking in use then back colour becomes black
+ if (PPU.ForcedBlanking)
+ back = black;
+ else
+ {
+ SelectTileRenderer (TRUE); //selects the tile renderers to be used
+ // TRUE means to use the default
+ // FALSE means use best renderer based on current
+ // graphics register settings
+ }
+
+ // now clear all graphics lines which are being updated using the back colour
+ for (register uint32 y = starty; y <= endy; y++)
+ {
+ memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), back,
+ IPPU.RenderedScreenWidth>>1);
+ }
+
+ if (!PPU.ForcedBlanking)
+ {
+ // Loop through all lines being updated and clear the
+ // zbuffer for each of the lines
+ for (uint32 y = starty; y <= endy; y++)
+ {
+ memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH), 0,
+ IPPU.RenderedScreenWidth>>2);
+ }
+ GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object
+ GFX.pCurrentClip = &IPPU.Clip [0];
+
+// Define an inline function to handle clipping
+#define FIXCLIP(n) \
+if (GFX.r212c & (1 << (n))) \
+ GFX.pCurrentClip = &IPPU.Clip [0]; \
+else \
+ GFX.pCurrentClip = &IPPU.Clip [1]
+
+// Define an inline function to handle which BGs are being displayed
+#define DISPLAY(n) ((GFX.r212c & n) || ((GFX.r212d & n) && subadd))
+
+ uint8 subadd = GFX.r2131 & 0x3f;
+
+ // go through all BGS are check if they need to be displayed
+ bool8_32 BG0 = DISPLAY(1) && !(Settings.os9x_hack & GFX_IGNORE_BG0);
+ bool8_32 BG1 = DISPLAY(2) && !(Settings.os9x_hack & GFX_IGNORE_BG1);
+ bool8_32 BG2 = DISPLAY(4) && !(Settings.os9x_hack & GFX_IGNORE_BG2);
+ bool8_32 BG3 = DISPLAY(8) && !(Settings.os9x_hack & GFX_IGNORE_BG3);
+ bool8_32 OB = DISPLAY(16) && !(Settings.os9x_hack & GFX_IGNORE_OBJ);
+
+ if (PPU.BGMode <= 1)
+ {
+ // screen modes 0 and 1
+ if (OB)
+ {
+ FIXCLIP(4);
+ DrawOBJS ();
+ }
+ if (BG0)
+ {
+ FIXCLIP(0);
+ DrawBackground (PPU.BGMode, 0, 10, 14);
+ }
+ if (BG1)
+ {
+ FIXCLIP(1);
+ DrawBackground (PPU.BGMode, 1, 9, 13);
+ }
+ if (BG2)
+ {
+ FIXCLIP(2);
+ DrawBackground (PPU.BGMode, 2, 3,
+ PPU.BG3Priority ? 17 : 6);
+ }
+ if (BG3 && PPU.BGMode == 0)
+ {
+ FIXCLIP(3);
+ DrawBackground (PPU.BGMode, 3, 2, 5);
+ }
+ }
+ else if (PPU.BGMode != 7)
+ {
+ // screen modes 2 and up but not mode 7
+ if (OB)
+ {
+ FIXCLIP(4);
+ DrawOBJS ();
+ }
+ if (BG0)
+ {
+ FIXCLIP(0);
+ DrawBackground (PPU.BGMode, 0, 5, 13);
+ }
+ if (BG1 && PPU.BGMode != 6)
+ {
+ FIXCLIP(1);
+ DrawBackground (PPU.BGMode, 1, 2, 9);
+ }
+ }
+ else
+ {
+ // screen mode 7
+ DrawBGMode7Background16New (GFX.Screen);
+ if (OB)
+ {
+ FIXCLIP(4);
+ DrawOBJS ();
+ }
+ }
+ }
+ IPPU.PreviousLine = IPPU.CurrentLine;
+}
+
+// -x-
+
+#ifdef GFX_MULTI_FORMAT
+
+#define _BUILD_PIXEL(F) \
+uint32 BuildPixel##F(uint32 R, uint32 G, uint32 B) \
+{ \
+ return (BUILD_PIXEL_##F(R,G,B)); \
+}\
+uint32 BuildPixel2##F(uint32 R, uint32 G, uint32 B) \
+{ \
+ return (BUILD_PIXEL2_##F(R,G,B)); \
+} \
+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)
+
+bool8_32 S9xSetRenderPixelFormat (int format)
+{
+ extern uint32 current_graphic_format;
+
+ current_graphic_format = 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