diff options
| author | SND\gschwind_cp <SND\gschwind_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2010-12-07 16:07:53 +0000 |
|---|---|---|
| committer | SND\gschwind_cp <SND\gschwind_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2010-12-07 16:07:53 +0000 |
| commit | f03cd2c04ac944d672444a6562d8f1593264a794 (patch) | |
| tree | 210489249db84419f8f5a23473877262913c4bfa /plugins | |
| parent | 2461ae5676a3898492c3d87b07f495a37f829c2a (diff) | |
| download | pcsxr-f03cd2c04ac944d672444a6562d8f1593264a794.tar.gz | |
first commit of gxvideo plugin (fork of dfxvideo)
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@60768 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/gxvideo/Makefile | 701 | ||||
| -rw-r--r-- | plugins/gxvideo/Makefile.am | 43 | ||||
| -rw-r--r-- | plugins/gxvideo/cfg.c | 261 | ||||
| -rw-r--r-- | plugins/gxvideo/cfg.h | 50 | ||||
| -rw-r--r-- | plugins/gxvideo/draw.c | 757 | ||||
| -rw-r--r-- | plugins/gxvideo/draw.h | 110 | ||||
| -rw-r--r-- | plugins/gxvideo/fps.c | 69 | ||||
| -rw-r--r-- | plugins/gxvideo/fps.h | 27 | ||||
| -rw-r--r-- | plugins/gxvideo/globals.c | 28 | ||||
| -rw-r--r-- | plugins/gxvideo/globals.h | 38 | ||||
| -rw-r--r-- | plugins/gxvideo/gpu.c | 1555 | ||||
| -rw-r--r-- | plugins/gxvideo/gpu.h | 116 | ||||
| -rw-r--r-- | plugins/gxvideo/gpu_utils.h | 76 | ||||
| -rw-r--r-- | plugins/gxvideo/gpucfg/gxvideo.glade | 542 | ||||
| -rw-r--r-- | plugins/gxvideo/gpucfg/main.c | 367 | ||||
| -rw-r--r-- | plugins/gxvideo/i386.asm | 67 | ||||
| -rw-r--r-- | plugins/gxvideo/interp.h | 294 | ||||
| -rw-r--r-- | plugins/gxvideo/key.c | 43 | ||||
| -rw-r--r-- | plugins/gxvideo/key.h | 24 | ||||
| -rw-r--r-- | plugins/gxvideo/macros.inc | 40 | ||||
| -rw-r--r-- | plugins/gxvideo/menu.c | 57 | ||||
| -rw-r--r-- | plugins/gxvideo/menu.h | 27 | ||||
| -rw-r--r-- | plugins/gxvideo/prim.c | 1615 | ||||
| -rw-r--r-- | plugins/gxvideo/prim.h | 43 | ||||
| -rw-r--r-- | plugins/gxvideo/soft.c | 9931 | ||||
| -rw-r--r-- | plugins/gxvideo/soft.h | 60 | ||||
| -rw-r--r-- | plugins/gxvideo/swap.h | 26 |
27 files changed, 16967 insertions, 0 deletions
diff --git a/plugins/gxvideo/Makefile b/plugins/gxvideo/Makefile new file mode 100644 index 00000000..32ac7da1 --- /dev/null +++ b/plugins/gxvideo/Makefile @@ -0,0 +1,701 @@ +# Makefile.in generated by automake 1.10.3 from Makefile.am. +# plugins/gxvideo/Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + + + + + +pkgdatadir = $(datadir)/pcsx +pkglibdir = $(libdir)/pcsx +pkgincludedir = $(includedir)/pcsx +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = x86_64-unknown-linux-gnu +host_triplet = x86_64-unknown-linux-gnu +target_triplet = x86_64-unknown-linux-gnu +#am__append_1 = i386.asm +#am__append_2 = -DUSE_NASM=1 +bin_PROGRAMS = cfgGXVideo$(EXEEXT) +subdir = plugins/gxvideo +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = cru +libcfg_a_AR = $(AR) $(ARFLAGS) +libcfg_a_LIBADD = +am_libcfg_a_OBJECTS = libcfg_a-cfg.$(OBJEXT) +libcfg_a_OBJECTS = $(am_libcfg_a_OBJECTS) +libglobals_a_AR = $(AR) $(ARFLAGS) +libglobals_a_LIBADD = +am_libglobals_a_OBJECTS = libglobals_a-globals.$(OBJEXT) +libglobals_a_OBJECTS = $(am_libglobals_a_OBJECTS) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(gladedir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +libGXVideo_la_LIBADD = +am__libGXVideo_la_SOURCES_DIST = gpu.c draw.c fps.c key.c menu.c \ + prim.c soft.c i386.asm +#am__objects_1 = i386.lo +am_libGXVideo_la_OBJECTS = gpu.lo draw.lo fps.lo key.lo menu.lo \ + prim.lo soft.lo $(am__objects_1) +libGXVideo_la_OBJECTS = $(am_libGXVideo_la_OBJECTS) +libGXVideo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libGXVideo_la_LDFLAGS) $(LDFLAGS) -o $@ +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_cfgGXVideo_OBJECTS = main.$(OBJEXT) +cfgGXVideo_OBJECTS = $(am_cfgGXVideo_OBJECTS) +am__DEPENDENCIES_1 = +cfgGXVideo_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + libcfg.a libglobals.a +DEFAULT_INCLUDES = -I. -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libcfg_a_SOURCES) $(libglobals_a_SOURCES) \ + $(libGXVideo_la_SOURCES) $(cfgGXVideo_SOURCES) +DIST_SOURCES = $(libcfg_a_SOURCES) $(libglobals_a_SOURCES) \ + $(am__libGXVideo_la_SOURCES_DIST) $(cfgGXVideo_SOURCES) +gladeDATA_INSTALL = $(INSTALL_DATA) +DATA = $(glade_DATA) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = ${SHELL} /home/gschwind/pcsxr.svn/missing --run aclocal-1.10 +ALSA_CFLAGS = +ALSA_LIBS = +AMTAR = ${SHELL} /home/gschwind/pcsxr.svn/missing --run tar +AR = ar +AUTOCONF = ${SHELL} /home/gschwind/pcsxr.svn/missing --run autoconf +AUTOHEADER = ${SHELL} /home/gschwind/pcsxr.svn/missing --run autoheader +AUTOMAKE = ${SHELL} /home/gschwind/pcsxr.svn/missing --run automake-1.10 +AWK = gawk +CC = gcc +CCAS = gcc +CCASDEPMODE = depmode=gcc3 +CCASFLAGS = -O2 -march=native -Wall +CCDEPMODE = depmode=gcc3 +CFLAGS = -O2 -march=native -Wall +CPP = gcc -E +CPPFLAGS = +CYGPATH_W = echo +DEFS = -DHAVE_CONFIG_H +DEPDIR = .deps +DLLTOOL = false +DSYMUTIL = +DUMPBIN = +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = /bin/grep -E +EXEEXT = +FGREP = /bin/grep -F +GETTEXT_MACRO_VERSION = 0.18 +GETTEXT_PACKAGE = pcsx +GLADE2_CFLAGS = -pthread -DQT_SHARED -I/usr/include/libglade-2.0 -I/usr/include/gtk-2.0 -I/usr/include/libxml2 -I/usr/lib64/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng14 -I/usr/include/qt4 -I/usr/include/qt4/QtGui -I/usr/include/libdrm -I/usr/include/qt4/QtCore +GLADE2_LIBS = -pthread -lglade-2.0 -lgtk-x11-2.0 -lxml2 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lgdk_pixbuf-2.0 -lpangocairo-1.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lrt -lglib-2.0 +GLIB2_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include +GLIB2_LIBS = -lglib-2.0 +GMSGFMT = /usr/bin/gmsgfmt +GMSGFMT_015 = /usr/bin/gmsgfmt +GREP = /bin/grep +GTK2_CFLAGS = -pthread -DQT_SHARED -I/usr/include/gtk-2.0 -I/usr/lib64/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng14 -I/usr/include/qt4 -I/usr/include/qt4/QtGui -I/usr/include/libdrm -I/usr/include/qt4/QtCore +GTK2_LIBS = -pthread -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lgdk_pixbuf-2.0 -lpangocairo-1.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lrt -lglib-2.0 +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = $(install_sh) -c -s +INTLLIBS = +INTL_MACOSX_LIBS = +LD = /usr/x86_64-pc-linux-gnu/bin/ld -m elf_x86_64 +LDFLAGS = -ldl -lnsl +LIBCDIO_CFLAGS = +LIBCDIO_LIBS = +LIBICONV = -liconv +LIBINTL = +LIBOBJS = +LIBS = +LIBTOOL = $(SHELL) $(top_builddir)/libtool +LIPO = +LN_S = ln -s +LTLIBICONV = -liconv +LTLIBINTL = +LTLIBOBJS = +MAINT = # +MAKEINFO = ${SHELL} /home/gschwind/pcsxr.svn/missing --run makeinfo +MANIFEST_TOOL = : +MKDIR_P = /bin/mkdir -p +MSGFMT = /usr/bin/msgfmt +MSGFMT_015 = /usr/bin/msgfmt +MSGMERGE = /usr/bin/msgmerge +NASM = +NM = /usr/bin/nm -B +NMEDIT = +OBJDUMP = objdump +OBJEXT = o +OTOOL = +OTOOL64 = +PACKAGE = pcsx +PACKAGE_BUGREPORT = +PACKAGE_NAME = pcsx +PACKAGE_STRING = pcsx 1.9 +PACKAGE_TARNAME = pcsx +PACKAGE_URL = +PACKAGE_VERSION = 1.9 +PATH_SEPARATOR = : +PEOPSXGL = +PKG_CONFIG = /usr/bin/pkg-config +PKG_CONFIG_LIBDIR = +PKG_CONFIG_PATH = +POSUB = po +PULSEAUDIO_CFLAGS = +PULSEAUDIO_LIBS = +RANLIB = ranlib +SDL_CFLAGS = -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT +SDL_CONFIG = /usr/bin/sdl-config +SDL_LIBS = -lSDL -lpthread +SED = /bin/sed +SET_MAKE = +SHELL = /bin/sh +STRIP = strip +USE_NLS = yes +VERSION = 1.9 +XGETTEXT = /usr/bin/xgettext +XGETTEXT_015 = /usr/bin/xgettext +XGETTEXT_EXTRA_OPTIONS = +abs_builddir = /home/gschwind/pcsxr.svn/plugins/gxvideo +abs_srcdir = /home/gschwind/pcsxr.svn/plugins/gxvideo +abs_top_builddir = /home/gschwind/pcsxr.svn +abs_top_srcdir = /home/gschwind/pcsxr.svn +ac_ct_AR = ar +ac_ct_CC = gcc +ac_ct_DUMPBIN = +am__include = include +am__leading_dot = . +am__quote = +am__tar = ${AMTAR} chof - "$$tardir" +am__untar = ${AMTAR} xf - +bindir = ${exec_prefix}/lib/games/psemu/ +build = x86_64-unknown-linux-gnu +build_alias = +build_cpu = x86_64 +build_os = linux-gnu +build_vendor = unknown +builddir = . +datadir = ${datarootdir} +datarootdir = ${prefix}/share +docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} +dvidir = ${docdir} +exec_prefix = ${prefix} +host = x86_64-unknown-linux-gnu +host_alias = +host_cpu = x86_64 +host_os = linux-gnu +host_vendor = unknown +htmldir = ${docdir} +includedir = ${prefix}/include +infodir = ${datarootdir}/info +install_sh = $(SHELL) /home/gschwind/pcsxr.svn/install-sh +libdir = ${exec_prefix}/lib/games/psemu/ +libexecdir = ${exec_prefix}/libexec +localedir = ${datarootdir}/locale +localstatedir = ${prefix}/var +mandir = ${datarootdir}/man +mkdir_p = /bin/mkdir -p +oldincludedir = /usr/include +pdfdir = ${docdir} +prefix = /home/gschwind/local +program_transform_name = s,x,x, +psdir = ${docdir} +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +srcdir = . +sysconfdir = ${prefix}/etc +target = x86_64-unknown-linux-gnu +target_alias = +target_cpu = x86_64 +target_os = linux-gnu +target_vendor = unknown +top_build_prefix = ../../ +top_builddir = ../.. +top_srcdir = ../.. +STRIP_FPIC = sh $(top_srcdir)/strip_fPIC.sh +SUFFIXES = .asm +INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ + -DLOCALE_DIR=\"${datadir}/locale/\" \ + -DDATADIR=\"${datadir}/psemu/\" $(GTK2_CFLAGS) \ + $(GLADE2_CFLAGS) -I/usr/X11R6/include -I../../libpcsxcore \ + -I../../include $(am__append_2) +noinst_LIBRARIES = libcfg.a libglobals.a +libcfg_a_SOURCES = cfg.c +libcfg_a_CFLAGS = -fPIC +libglobals_a_SOURCES = globals.c +libglobals_a_CFLAGS = -fPIC +lib_LTLIBRARIES = libGXVideo.la +libGXVideo_la_SOURCES = gpu.c draw.c fps.c key.c menu.c prim.c soft.c \ + $(am__append_1) +libGXVideo_la_LDFLAGS = -module -avoid-version -L/usr/X11R6/lib64 \ + -L/usr/X11R6/lib -lX11 -lXv -lXext -lm libcfg.a libglobals.a +cfgGXVideo_SOURCES = gpucfg/main.c +cfgGXVideo_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) -L/usr/X11R6/lib -lXext libcfg.a libglobals.a +glade_DATA = gpucfg/gxvideo.glade +gladedir = $(datadir)/psemu/ +EXTRA_DIST = $(glade_DATA) +all: all-am + +.SUFFIXES: +.SUFFIXES: .asm .c .lo .o .obj +$(srcdir)/Makefile.in: # $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/gxvideo/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu plugins/gxvideo/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: # $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): # $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libcfg.a: $(libcfg_a_OBJECTS) $(libcfg_a_DEPENDENCIES) + -rm -f libcfg.a + $(libcfg_a_AR) libcfg.a $(libcfg_a_OBJECTS) $(libcfg_a_LIBADD) + $(RANLIB) libcfg.a +libglobals.a: $(libglobals_a_OBJECTS) $(libglobals_a_DEPENDENCIES) + -rm -f libglobals.a + $(libglobals_a_AR) libglobals.a $(libglobals_a_OBJECTS) $(libglobals_a_LIBADD) + $(RANLIB) libglobals.a +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libGXVideo.la: $(libGXVideo_la_OBJECTS) $(libGXVideo_la_DEPENDENCIES) + $(libGXVideo_la_LINK) -rpath $(libdir) $(libGXVideo_la_OBJECTS) $(libGXVideo_la_LIBADD) $(LIBS) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +cfgGXVideo$(EXEEXT): $(cfgGXVideo_OBJECTS) $(cfgGXVideo_DEPENDENCIES) + @rm -f cfgGXVideo$(EXEEXT) + $(LINK) $(cfgGXVideo_OBJECTS) $(cfgGXVideo_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +include ./$(DEPDIR)/draw.Plo +include ./$(DEPDIR)/fps.Plo +include ./$(DEPDIR)/gpu.Plo +include ./$(DEPDIR)/key.Plo +include ./$(DEPDIR)/libcfg_a-cfg.Po +include ./$(DEPDIR)/libglobals_a-globals.Po +include ./$(DEPDIR)/main.Po +include ./$(DEPDIR)/menu.Plo +include ./$(DEPDIR)/prim.Plo +include ./$(DEPDIR)/soft.Plo + +.c.o: + $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(COMPILE) -c $< + +.c.obj: + $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` + mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: + $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +# source='$<' object='$@' libtool=yes \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(LTCOMPILE) -c -o $@ $< + +libcfg_a-cfg.o: cfg.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfg_a_CFLAGS) $(CFLAGS) -MT libcfg_a-cfg.o -MD -MP -MF $(DEPDIR)/libcfg_a-cfg.Tpo -c -o libcfg_a-cfg.o `test -f 'cfg.c' || echo '$(srcdir)/'`cfg.c + mv -f $(DEPDIR)/libcfg_a-cfg.Tpo $(DEPDIR)/libcfg_a-cfg.Po +# source='cfg.c' object='libcfg_a-cfg.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfg_a_CFLAGS) $(CFLAGS) -c -o libcfg_a-cfg.o `test -f 'cfg.c' || echo '$(srcdir)/'`cfg.c + +libcfg_a-cfg.obj: cfg.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfg_a_CFLAGS) $(CFLAGS) -MT libcfg_a-cfg.obj -MD -MP -MF $(DEPDIR)/libcfg_a-cfg.Tpo -c -o libcfg_a-cfg.obj `if test -f 'cfg.c'; then $(CYGPATH_W) 'cfg.c'; else $(CYGPATH_W) '$(srcdir)/cfg.c'; fi` + mv -f $(DEPDIR)/libcfg_a-cfg.Tpo $(DEPDIR)/libcfg_a-cfg.Po +# source='cfg.c' object='libcfg_a-cfg.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfg_a_CFLAGS) $(CFLAGS) -c -o libcfg_a-cfg.obj `if test -f 'cfg.c'; then $(CYGPATH_W) 'cfg.c'; else $(CYGPATH_W) '$(srcdir)/cfg.c'; fi` + +libglobals_a-globals.o: globals.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglobals_a_CFLAGS) $(CFLAGS) -MT libglobals_a-globals.o -MD -MP -MF $(DEPDIR)/libglobals_a-globals.Tpo -c -o libglobals_a-globals.o `test -f 'globals.c' || echo '$(srcdir)/'`globals.c + mv -f $(DEPDIR)/libglobals_a-globals.Tpo $(DEPDIR)/libglobals_a-globals.Po +# source='globals.c' object='libglobals_a-globals.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglobals_a_CFLAGS) $(CFLAGS) -c -o libglobals_a-globals.o `test -f 'globals.c' || echo '$(srcdir)/'`globals.c + +libglobals_a-globals.obj: globals.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglobals_a_CFLAGS) $(CFLAGS) -MT libglobals_a-globals.obj -MD -MP -MF $(DEPDIR)/libglobals_a-globals.Tpo -c -o libglobals_a-globals.obj `if test -f 'globals.c'; then $(CYGPATH_W) 'globals.c'; else $(CYGPATH_W) '$(srcdir)/globals.c'; fi` + mv -f $(DEPDIR)/libglobals_a-globals.Tpo $(DEPDIR)/libglobals_a-globals.Po +# source='globals.c' object='libglobals_a-globals.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglobals_a_CFLAGS) $(CFLAGS) -c -o libglobals_a-globals.obj `if test -f 'globals.c'; then $(CYGPATH_W) 'globals.c'; else $(CYGPATH_W) '$(srcdir)/globals.c'; fi` + +main.o: gpucfg/main.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT main.o -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.o `test -f 'gpucfg/main.c' || echo '$(srcdir)/'`gpucfg/main.c + mv -f $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po +# source='gpucfg/main.c' object='main.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o main.o `test -f 'gpucfg/main.c' || echo '$(srcdir)/'`gpucfg/main.c + +main.obj: gpucfg/main.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT main.obj -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.obj `if test -f 'gpucfg/main.c'; then $(CYGPATH_W) 'gpucfg/main.c'; else $(CYGPATH_W) '$(srcdir)/gpucfg/main.c'; fi` + mv -f $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po +# source='gpucfg/main.c' object='main.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o main.obj `if test -f 'gpucfg/main.c'; then $(CYGPATH_W) 'gpucfg/main.c'; else $(CYGPATH_W) '$(srcdir)/gpucfg/main.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-gladeDATA: $(glade_DATA) + @$(NORMAL_INSTALL) + test -z "$(gladedir)" || $(MKDIR_P) "$(DESTDIR)$(gladedir)" + @list='$(glade_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(gladeDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(gladedir)/$$f'"; \ + $(gladeDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(gladedir)/$$f"; \ + done + +uninstall-gladeDATA: + @$(NORMAL_UNINSTALL) + @list='$(glade_DATA)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(gladedir)/$$f'"; \ + rm -f "$(DESTDIR)$(gladedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(PROGRAMS) $(DATA) +install-binPROGRAMS: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(gladedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ + clean-libtool clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-gladeDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-gladeDATA \ + uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-gladeDATA \ + install-html install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-gladeDATA uninstall-libLTLIBRARIES + + +.asm.lo: + $(LIBTOOL) --tag=CC --mode=compile \ + $(STRIP_FPIC) $(NASM) -f elf -d ELF -I${srcdir}/ $< +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/gxvideo/Makefile.am b/plugins/gxvideo/Makefile.am new file mode 100644 index 00000000..9e6e1a0f --- /dev/null +++ b/plugins/gxvideo/Makefile.am @@ -0,0 +1,43 @@ +STRIP_FPIC = sh $(top_srcdir)/strip_fPIC.sh + +SUFFIXES = .asm + +.asm.lo: + $(LIBTOOL) --tag=CC --mode=compile \ + $(STRIP_FPIC) $(NASM) -f elf -d ELF -I${srcdir}/ $< + +INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ + -DLOCALE_DIR=\"${datadir}/locale/\" \ + -DDATADIR=\"${datadir}/psemu/\" \ + $(GTK2_CFLAGS) $(GLADE2_CFLAGS) -I/usr/X11R6/include \ + -I../../libpcsxcore \ + -I../../include + +bindir = @libdir@/games/psemu/ +libdir = @libdir@/games/psemu/ + +noinst_LIBRARIES = libcfg.a libglobals.a +libcfg_a_SOURCES = cfg.c +libcfg_a_CFLAGS = -fPIC + +libglobals_a_SOURCES = globals.c +libglobals_a_CFLAGS = -fPIC + +lib_LTLIBRARIES = libGXVideo.la + +libGXVideo_la_SOURCES = gpu.c draw.c fps.c key.c menu.c prim.c soft.c +if X86_NASM +libGXVideo_la_SOURCES += i386.asm +INCLUDES += -DUSE_NASM=1 +endif +libGXVideo_la_LDFLAGS = -module -avoid-version +libGXVideo_la_LDFLAGS += -L/usr/X11R6/lib64 -L/usr/X11R6/lib \ + -lX11 -lXv -lXext -lm libcfg.a libglobals.a + +bin_PROGRAMS = cfgGXVideo +cfgGXVideo_SOURCES = gpucfg/main.c +cfgGXVideo_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) -L/usr/X11R6/lib -lXext libcfg.a libglobals.a + +glade_DATA = gpucfg/gxvideo.glade +gladedir = $(datadir)/psemu/ +EXTRA_DIST = $(glade_DATA) diff --git a/plugins/gxvideo/cfg.c b/plugins/gxvideo/cfg.c new file mode 100644 index 00000000..ffe0ff0e --- /dev/null +++ b/plugins/gxvideo/cfg.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2010 Benoit Gschwind + * Inspired by original author : Pete Bernert + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <sys/stat.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "globals.h" +#include "cfg.h" + +#define DEFAULT_CFG_NAME "gxvideo.cfg" + +int get_int_value (char const * file_buffer, char const * name, int dflt) { + char * p = strstr(file_buffer, name); + if (p != NULL) { + p += strlen(name); + while ((*p == ' ') || (*p == '=')) + ++p; + if (*p != '\n') + return atoi(p); + } + return dflt; +} + +double get_double_value(char const * file_buffer, char const * name, + double dflt) { + char * p = strstr(file_buffer, name); + if (p != NULL) { + p += strlen(name); + while ((*p == ' ') || (*p == '=')) + ++p; + if (*p != '\n') + return atof(p); + } + return dflt; +} + +void write_int_value (FILE * f, char const * name, int val) { + fprintf(f, "%s = %d\n", name, val); +} + +void write_double_value (FILE * f, char const * name, double val) { + fprintf(f, "%s = %.1f\n", name, val); +} + +void ReadConfigFile() { + struct stat buf; + FILE * f_in; + char cfg_file_name[256]; + int len, size; + char * file_buffer; + + if (g_file_name) + strcpy(cfg_file_name, g_file_name); + else { + strcpy(cfg_file_name, DEFAULT_CFG_NAME); + f_in = fopen(cfg_file_name, "rb"); + if (!f_in) { + strcpy(cfg_file_name, "cfg/" DEFAULT_CFG_NAME); + f_in = fopen(cfg_file_name, "rb"); + if (!f_in) + snprintf(cfg_file_name, 255, "%s/.pcsx/plugins/" DEFAULT_CFG_NAME, getenv("HOME")); + else + fclose(f_in); + } else + fclose(f_in); + } + + if (stat(cfg_file_name, &buf) == -1) + return; + size = buf.st_size; + + f_in = fopen(cfg_file_name, "rb"); + if (!f_in) + return; + + file_buffer = (char *) malloc(size + 1); + len = fread(file_buffer, 1, size, f_in); + /* ensure end_of_string */ + file_buffer[len] = 0; + fclose(f_in); + + g_cfg.ResX = get_int_value(file_buffer, "ResX", g_cfg.ResX); + if (g_cfg.ResX < 20) + g_cfg.ResX = 20; + g_cfg.ResX = (g_cfg.ResX / 4) * 4; + g_cfg.ResY = get_int_value(file_buffer, "ResY", g_cfg.ResY); + if (g_cfg.ResY < 20) + g_cfg.ResY = 20; + g_cfg.ResY = (g_cfg.ResY / 4) * 4; + g_cfg.Dithering = get_int_value(file_buffer, "Dithering", g_cfg.Dithering); + g_cfg.FullScreen = get_int_value(file_buffer, "FullScreen", g_cfg.FullScreen); + g_cfg.ShowFPS = get_int_value(file_buffer, "ShowFPS", g_cfg.ShowFPS); + if (g_cfg.ShowFPS < 0) + g_cfg.ShowFPS = 0; + if (g_cfg.ShowFPS > 1) + g_cfg.ShowFPS = 1; + + g_cfg.Maintain43 = get_int_value(file_buffer, "Maintain43", g_cfg.Maintain43); + if (g_cfg.Maintain43 < 0) + g_cfg.Maintain43 = 0; + if (g_cfg.Maintain43 > 1) + g_cfg.Maintain43 = 1; + + g_cfg.UseFrameLimit = get_int_value(file_buffer, "UseFrameLimit", g_cfg.UseFrameLimit); + if (g_cfg.UseFrameLimit < 0) + g_cfg.UseFrameLimit = 0; + if (g_cfg.UseFrameLimit > 1) + g_cfg.UseFrameLimit = 1; + + g_cfg.UseFrameSkip = 0; + + g_cfg.FPSDetection = get_int_value(file_buffer, "FPSDetection", g_cfg.FPSDetection); + if (g_cfg.FPSDetection < 1) + g_cfg.FPSDetection = 1; + if (g_cfg.FPSDetection > 2) + g_cfg.FPSDetection = 2; + + g_cfg.FrameRate = get_double_value(file_buffer, "FrameRate", g_cfg.FrameRate); + g_cfg.FrameRate /= 10; + if (g_cfg.FrameRate < 10.0f) + g_cfg.FrameRate = 10.0f; + if (g_cfg.FrameRate > 1000.0f) + g_cfg.FrameRate = 1000.0f; + + g_cfg.CfgFixes = get_int_value(file_buffer, "CfgFixes", g_cfg.CfgFixes); + + g_cfg.UseFixes = get_int_value(file_buffer, "UseFixes", g_cfg.UseFixes); + if (g_cfg.UseFixes < 0) + g_cfg.UseFixes = 0; + if (g_cfg.UseFixes > 1) + g_cfg.UseFixes = 1; + + free(file_buffer); +} + +void ExecCfg(char const * arg) { + char cfg[256]; + struct stat buf; + + strcpy(cfg, "./cfgGXVideo"); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgGXVideo", arg, NULL); + exit(0); + } + return; + } + + strcpy(cfg, "./cfg/cfgGXVideo"); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgGXVideo", arg, NULL); + exit(0); + } + return; + } + + sprintf(cfg, "%s/.pcsx/plugins/cfg/cfgGXVideo", getenv("HOME")); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgGXVideo", arg, NULL); + exit(0); + } + return; + } + + printf("ERROR: cfgGXVideo file not found!\n"); +} + +void SoftDlgProc(void) { + ExecCfg("CFG"); +} + +void AboutDlgProc(void) { + char args[256]; + sprintf(args, "ABOUT"); + ExecCfg(args); +} + +void ReadConfig(void) { + /* set defaults */ + g_cfg.ResX = 640; + g_cfg.ResY = 480; + g_cfg.NoStretch = 0; + g_cfg.Dithering = 0; + g_cfg.FullScreen = 0; + g_cfg.ShowFPS = 0; + g_cfg.Maintain43 = 0; + g_cfg.UseFrameLimit = 1; + g_cfg.UseFrameSkip = 0; + g_cfg.FPSDetection = 1; + g_cfg.FrameRate = 200.0; + g_cfg.CfgFixes = 0; + g_cfg.UseFixes = 0; + + // read sets + ReadConfigFile(); +} + +void WriteConfig(void) { + FILE *f_out; + char cfg_file_name[256]; + + if (g_file_name) + strcpy(cfg_file_name, g_file_name); + else { + strcpy(cfg_file_name, DEFAULT_CFG_NAME); + f_out = fopen(cfg_file_name, "rb"); + if (!f_out) { + strcpy(cfg_file_name, "cfg/" DEFAULT_CFG_NAME); + f_out = fopen(cfg_file_name, "rb"); + if (!f_out) + snprintf(cfg_file_name, 255, "%s/.pcsx/plugins/" DEFAULT_CFG_NAME, getenv("HOME")); + else + fclose(f_out); + } else + fclose(f_out); + } + + f_out = fopen(cfg_file_name, "wb"); + if (!f_out) + return; + +#define WRITE_VALUE(type, name) write_##type##_value(f_out, #name, g_cfg.name) + + WRITE_VALUE(int, ResX); + WRITE_VALUE(int, ResY); + WRITE_VALUE(int, NoStretch); + WRITE_VALUE(int, Dithering); + WRITE_VALUE(int, FullScreen); + WRITE_VALUE(int, ShowFPS); + WRITE_VALUE(int, Maintain43); + WRITE_VALUE(int, UseFrameLimit); + WRITE_VALUE(int, UseFrameSkip); + WRITE_VALUE(int, FPSDetection); + WRITE_VALUE(double, FrameRate); + WRITE_VALUE(int, CfgFixes); + WRITE_VALUE(int, UseFixes); + + fclose(f_out); +} diff --git a/plugins/gxvideo/cfg.h b/plugins/gxvideo/cfg.h new file mode 100644 index 00000000..1e1c456c --- /dev/null +++ b/plugins/gxvideo/cfg.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010 Benoit Gschwind + * Inspired by original author : Pete Bernert + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _GPU_CFG_H_ +#define _GPU_CFG_H_ + +#include <stdint.h> + +typedef struct { + int ResX; + int ResY; + int NoStretch; + int Dithering; + int FullScreen; + int ShowFPS; + int Maintain43; + int UseFrameLimit; + int UseFrameSkip; + int FPSDetection; + double FrameRate; + int CfgFixes; + int UseFixes; + int video_output; +} gxv_cfg_t; + +void ReadConfig(void); +void WriteConfig(void); +void ReadWinSizeConfig(void); +
+void SoftDlgProc(void);
+void AboutDlgProc(void);
+ +#endif diff --git a/plugins/gxvideo/draw.c b/plugins/gxvideo/draw.c new file mode 100644 index 00000000..c8d6c7e0 --- /dev/null +++ b/plugins/gxvideo/draw.c @@ -0,0 +1,757 @@ +/* + * Copyright (C) 2010 Benoit Gschwind + * Inspired by original author : Pete Bernert + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <math.h> +#include <sys/shm.h> +#include <X11/cursorfont.h> + +#include "globals.h" +#include "swap.h" + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + +enum { + GXV_YUV_PORT = 0, GXV_RGB_PORT = 1, GXV_MAX_PORT = 2, +}; + +gxv_blit_t available_port[GXV_MAX_PORT]; + +/* Convert RGB to YUV */ +inline uint32_t rgb_to_yuv(uint8_t R, uint8_t G, uint8_t B) { + uint8_t Y, U, V; + Y = abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13; + Y = MIN(Y, 235); + U = abs(R * -1214 + G * -2384 + B * 3598 + 4096 + 1048576) >> 13; + U = MIN(U, 240); + V = abs(R * 3598 + G * -3013 + B * -585 + 4096 + 1048576) >> 13; + V = MIN(V, 240); + return Y << 24 | V << 16 | Y << 8 | U; +} + +inline uint32_t rgb_to_yuv2(uint8_t R0, uint8_t G0, uint8_t B0, uint8_t R1, + uint8_t G1, uint8_t B1) { + int32_t Y0, U0, V0; + int32_t Y1, U1, V1; + int32_t U, V; + Y0 = abs(R0 * 2104 + G0 * 4130 + B0 * 802 + 4096 + 131072) >> 13; + Y0 = MIN(Y0, 235); + U0 = abs(R0 * -1214 + G0 * -2384 + B0 * 3598 + 4096 + 1048576) >> 13; + U0 = MIN(U0, 240); + V0 = abs(R0 * 3598 + G0 * -3013 + B0 * -585 + 4096 + 1048576) >> 13; + V0 = MIN(V0, 240); + Y1 = abs(R1 * 2104 + G1 * 4130 + B1 * 802 + 4096 + 131072) >> 13; + Y1 = MIN(Y1, 235); + U1 = abs(R1 * -1214 + G1 * -2384 + B1 * 3598 + 4096 + 1048576) >> 13; + U1 = MIN(U1, 240); + V1 = abs(R1 * 3598 + G1 * -3013 + B1 * -585 + 4096 + 1048576) >> 13; + V1 = MIN(V1, 240); + U = (U0 + U1) / 2; + V = (V0 + V1) / 2; + return Y1 << 24 | V << 16 | Y0 << 8 | U; +} + +#define colorMask8 0x00FEFEFE +#define lowPixelMask8 0x00010101 +#define qcolorMask8 0x00FCFCFC +#define qlowpixelMask8 0x00030303 + +static Atom xv_intern_atom_if_exists(Display *display, char const * atom_name) { + XvAttribute * attributes; + int attrib_count, i; + Atom xv_atom = None; + + attributes = XvQueryPortAttributes(display, g_draw.xv_port, &attrib_count); + if (attributes != NULL) { + for (i = 0; i < attrib_count; ++i) { + if (strcmp(attributes[i].name, atom_name) == 0) { + xv_atom = XInternAtom(display, atom_name, False); + break; // found what we want, break out + } + } + XFree(attributes); + } + + return xv_atom; +} + +// close display + +void DestroyDisplay(void) { + if (g_draw.display) { + XFreeColormap(g_draw.display, g_draw.colormap); + if (g_draw.hGC) { + XFreeGC(g_draw.display, g_draw.hGC); + g_draw.hGC = 0; + } + if (g_draw.Ximage) { + XDestroyImage(g_draw.Ximage); + g_draw.Ximage = 0; + } + if (g_draw.XCimage) { + XFree(g_draw.XCimage); + g_draw.XCimage = 0; + } + if (g_draw.XFimage) { + XDestroyImage(g_draw.XFimage); + g_draw.XFimage = 0; + } + + XShmDetach(g_draw.display, &g_draw.shminfo); + shmdt(g_draw.shminfo.shmaddr); + shmctl(g_draw.shminfo.shmid, IPC_RMID, NULL); + + Atom atom_vsync = xv_intern_atom_if_exists(g_draw.display, + "XV_SYNC_TO_VBLANK"); + if (atom_vsync != None) { + XvSetPortAttribute(g_draw.display, g_draw.xv_port, atom_vsync, + g_draw.xv_vsync); + } + + XSync(g_draw.display, False); + + XCloseDisplay(g_draw.display); + } +} + +// Create display + +void create_display(void) { + //fprintf(stderr, "Entering %s\n", __FUNCTION__); + XSetWindowAttributes winattr; + int myscreen; + Screen * screen; + XEvent event; + XSizeHints hints; + XWMHints wm_hints; + MotifWmHints mwmhints; + Atom mwmatom; + + Atom delwindow; + + XGCValues gcv; + int i; + + int ret, j, p; + int formats; + unsigned int p_num_adaptors = 0, p_num_ports = 0; + + XvAdaptorInfo *ai; + XvImageFormatValues *fo; + + // Open display + g_draw.display = XOpenDisplay(NULL); + + if (!g_draw.display) { + fprintf(stderr, "Failed to open display!!!\n"); + DestroyDisplay(); + return; + } + + myscreen = DefaultScreen(g_draw.display); + + // desktop fullscreen switch + if (g_cfg.FullScreen) + g_draw.fx = 1; + + screen = DefaultScreenOfDisplay(g_draw.display); + + g_draw.root_window_id = RootWindow(g_draw.display, myscreen); + + //Look for an Xvideo RGB port + ret = XvQueryAdaptors(g_draw.display, g_draw.root_window_id, + &p_num_adaptors, &ai); + if (ret != Success) { + if (ret == XvBadExtension) + fprintf(stderr, "XvBadExtension returned at XvQueryExtension.\n"); + else if (ret == XvBadAlloc) + fprintf(stderr, "XvBadAlloc returned at XvQueryExtension.\n"); + else + fprintf(stderr, "other error happaned at XvQueryAdaptors.\n"); + exit(EXIT_FAILURE); + } + + g_draw.depth = DefaultDepth(g_draw.display, myscreen); + + g_draw.xv_id = -1; + g_draw.xv_port = -1; + g_draw.xv = -1; + + for (i = 0; i < p_num_adaptors; i++) { + p_num_ports = ai[i].base_id + ai[i].num_ports; + for (p = ai[i].base_id; p < p_num_ports; p++) { + fo = XvListImageFormats(g_draw.display, p, &formats); + for (j = 0; j < formats; ++j) { + + if (fo[j].type == XvYUV && fo[j].bits_per_pixel == 16 + && fo[j].format == XvPacked && strncmp("UYVY", + fo[j].component_order, 4) == 0) { + g_draw.xv_port = p; + g_draw.xv_id = fo[j].id; + + g_draw.xv = GXV_YUV_PORT; + j = formats; + p = p_num_ports; + i = p_num_adaptors; + break; + } + + if (fo[j].type == XvRGB && fo[j].bits_per_pixel == 32) { + g_draw.xv_port = p; + g_draw.xv_id = fo[j].id; + printf("RGB mode found. id: %x\n", g_draw.xv_id); + g_draw.xv = GXV_RGB_PORT; + //break out of loops + j = formats; + p = p_num_ports; + i = p_num_adaptors; + } + } + + if (fo) + XFree(fo); + } + } + + if (p_num_adaptors > 0) + XvFreeAdaptorInfo(ai); + + if (g_draw.xv < 0) { + fprintf(stderr, "RGB & YUV not found. Quitting.\n"); + exit(EXIT_FAILURE); + } + + Atom atom_vsync = xv_intern_atom_if_exists(g_draw.display, + "XV_SYNC_TO_VBLANK"); + if (atom_vsync != None) { + XvGetPortAttribute(g_draw.display, g_draw.xv_port, atom_vsync, + &g_draw.xv_vsync); + XvSetPortAttribute(g_draw.display, g_draw.xv_port, atom_vsync, 0); + } + + g_draw.myvisual = 0; + + if (XMatchVisualInfo(g_draw.display, myscreen, g_draw.depth, TrueColor, + &g_draw.vi)) + g_draw.myvisual = &g_draw.vi; + + if (!g_draw.myvisual) { + fprintf(stderr, "Failed to obtain visual!\n"); + DestroyDisplay(); + return; + } + + if (!g_cfg.FullScreen) + g_draw.cursor = XCreateFontCursor(g_draw.display, XC_trek); + else { + g_draw.cursor = None; + } + + g_draw.colormap = XCreateColormap(g_draw.display, g_draw.root_window_id, + g_draw.myvisual->visual, AllocNone); + + winattr.background_pixel = BlackPixelOfScreen(screen); + winattr.border_pixel = WhitePixelOfScreen(screen); + winattr.bit_gravity = ForgetGravity; + winattr.win_gravity = NorthWestGravity; + winattr.backing_store = NotUseful; + + winattr.override_redirect = False; + winattr.save_under = False; + winattr.event_mask = 0; + winattr.do_not_propagate_mask = 0; + winattr.colormap = g_draw.colormap; + winattr.cursor = None; + + g_draw.window = XCreateWindow(g_draw.display, g_draw.root_window_id, 0, 0, + g_cfg.ResX, g_cfg.ResY, 0, g_draw.myvisual->depth, InputOutput, + g_draw.myvisual->visual, CWBorderPixel | CWBackPixel | CWEventMask + | CWDontPropagate | CWColormap | CWCursor, &winattr); + + if (!g_draw.window) { + fprintf(stderr, "Failed in XCreateWindow()!!!\n"); + DestroyDisplay(); + return; + } + + delwindow = XInternAtom(g_draw.display, "WM_DELETE_WINDOW", 0); + XSetWMProtocols(g_draw.display, g_draw.window, &delwindow, 1); + + hints.flags = USPosition | USSize; + hints.base_width = g_cfg.ResX; + hints.base_height = g_cfg.ResY; + + wm_hints.input = 1; + wm_hints.flags = InputHint; + + XSetWMHints(g_draw.display, g_draw.window, &wm_hints); + XSetWMNormalHints(g_draw.display, g_draw.window, &hints); + //if (pCaptionText) + // XStoreName(draw_ctx.display, draw_ctx.window, pCaptionText); + //else + XStoreName(g_draw.display, g_draw.window, "GXVideo GPU"); + + XDefineCursor(g_draw.display, g_draw.window, g_draw.cursor); + + // hack to get rid of window title bar + if (g_draw.fx) { + mwmhints.flags = MWM_HINTS_DECORATIONS; + mwmhints.decorations = 0; + mwmatom = XInternAtom(g_draw.display, "_MOTIF_WM_HINTS", 0); + XChangeProperty(g_draw.display, g_draw.window, mwmatom, mwmatom, 32, + PropModeReplace, (unsigned char *) &mwmhints, 4); + } + + // key stuff + XSelectInput(g_draw.display, g_draw.window, FocusChangeMask | ExposureMask + | KeyPressMask | KeyReleaseMask); + + XMapRaised(g_draw.display, g_draw.window); + XClearWindow(g_draw.display, g_draw.window); + XWindowEvent(g_draw.display, g_draw.window, ExposureMask, &event); + + if (g_draw.fx) { + XResizeWindow(g_draw.display, g_draw.window, screen->width, + screen->height); + + hints.min_width = hints.max_width = hints.base_width = screen->width; + hints.min_height = hints.max_height = hints.base_height + = screen->height; + + XSetWMNormalHints(g_draw.display, g_draw.window, &hints); + + // set the window layer for GNOME + { + XEvent xev; + + memset(&xev, 0, sizeof(xev)); + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = 1; + xev.xclient.message_type = XInternAtom(g_draw.display, + "_NET_WM_STATE", 0); + xev.xclient.window = g_draw.window; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 1; + xev.xclient.data.l[1] = XInternAtom(g_draw.display, + "_NET_WM_STATE_FULLSCREEN", 0); + xev.xclient.data.l[2] = 0; + xev.xclient.data.l[3] = 0; + xev.xclient.data.l[4] = 0; + + XSendEvent(g_draw.display, g_draw.root_window_id, 0, + SubstructureRedirectMask | SubstructureNotifyMask, &xev); + } + } + + gcv.graphics_exposures = False; + gcv.foreground = WhitePixelOfScreen(screen); + gcv.background = BlackPixelOfScreen(screen); + g_draw.hGC = XCreateGC(g_draw.display, g_draw.window, GCGraphicsExposures + |GCForeground | GCBackground, &gcv); + if (!g_draw.hGC) { + fprintf(stderr, "No gfx context!!!\n"); + DestroyDisplay(); + } + + g_draw.Xpixels = (char *) malloc(600 * 15 * 4); + + uint32_t color; + if (g_draw.xv == GXV_YUV_PORT) + color = rgb_to_yuv(0x00, 0x00, 0xff); + else + color = 0x0000ff; + + for (i = 0; i < 600 * 15; ++i) + ((uint32_t *) g_draw.Xpixels)[i] = color; + + g_draw.XFimage = XCreateImage(g_draw.display, g_draw.myvisual->visual, + g_draw.depth, ZPixmap, 0, (char *) g_draw.Xpixels, 600, 15, + g_draw.depth > 16 ? 32 : 16, 0); + + /* fix the green back ground in YUV mode */ + if (g_draw.xv == GXV_YUV_PORT) + color = rgb_to_yuv(0x00, 0x00, 0x00); + else + color = 0; + + g_draw.Xpixels = (char *) malloc(8 * 8 * 4); + for (i = 0; i < 8 * 8; ++i) + ((uint32_t *) g_draw.Xpixels)[i] = color; + + g_draw.XCimage = XvCreateImage(g_draw.display, g_draw.xv_port, + g_draw.xv_id, (char *) g_draw.Xpixels, 8, 8); + + /* + Allocate max that could be needed: + Big(est?) PSX res: 640x512 + 32bpp (times 4) + 2xsai func= 3xwidth,3xheight + = approx 11.8mb + */ + g_draw.shminfo.shmid + = shmget(IPC_PRIVATE, 1024 * 512 * 4, IPC_CREAT | 0777); + g_draw.shminfo.shmaddr = shmat(g_draw.shminfo.shmid, 0, 0); + g_draw.shminfo.readOnly = 0; + + if (!XShmAttach(g_draw.display, &g_draw.shminfo)) { + printf("XShmAttach failed !\n"); + exit(-1); + } + + uint32_t *pShmaddr = (uint32_t *) g_draw.shminfo.shmaddr; + for (i = 0; i < 1024 * 512; ++i) + pShmaddr[i] = color; + + //fprintf(stderr, "Return %s\n", __FUNCTION__); + return; +} + +int rgb_check_port(XvImageFormatValues const * fo) { + if (fo->type == XvRGB && fo->bits_per_pixel == 32) { + g_draw.xv_id = fo->id; + return 1; + } + return 0; +} + +void rgb_blit_16(int8_t * buff, int32_t x, int32_t y, int32_t w, int32_t h) { + //fprintf(stderr, "BlitToYUV\n"); + int16_t * src_pxl; + int8_t * dst_pxl; + int32_t startxy; + int32_t _x, _y; + + startxy = 0; + dst_pxl = buff; + for (_y = y; _y < h; ++_y) { + src_pxl = &g_gpu.psx_vram.s16[startxy]; + for (_x = x; _x < w; ++_x) { + dst_pxl[0] = ((*src_pxl) << 3) & 0xf8; + dst_pxl[1] = ((*src_pxl) >> 2) & 0xf8; + dst_pxl[2] = ((*src_pxl) >> 7) & 0xf8; + dst_pxl += 3; + src_pxl += 1; + } + startxy += 2048; + } +} + +void rgb_blit_24(int8_t * buff, int32_t x, int32_t y, int32_t w, int32_t h) { + //fprintf(stderr, "BlitToYUV\n"); + int8_t * src_pxl; + int8_t * dst_pxl; + int32_t startxy; + int32_t _x, _y; + + dst_pxl = buff; + startxy = 0; + for (_y = y; _y < h; ++_y) { + src_pxl = &g_gpu.psx_vram.s8[startxy]; + for (_x = x; _x < w; ++_x) { + dst_pxl[0] = src_pxl[0]; + dst_pxl[1] = src_pxl[1]; + dst_pxl[2] = src_pxl[2]; + dst_pxl += 3; + src_pxl += 3; + } + startxy += 2048; + } +} + +int yuyv_check_port(XvImageFormatValues * fo) { + if (fo->type == XvYUV && fo->bits_per_pixel == 16 && fo->format == XvPacked + && strncmp("UYVY", fo->component_order, 4) == 0) { + g_draw.xv_id = fo->id; + return 1; + } + return 0; +} + +void yuyv_blit_24(int8_t * buff, int32_t x, int32_t y, int32_t w, int32_t h) { + //fprintf(stderr, "yuyv_blit_24 %d %d %d %d\n", x, y, w, h); + uint8_t * src_pxl; + int8_t R0, G0, B0; + int8_t R1, G1, B1; + uint32_t * dst_pxl; + int32_t _x, _y; + + /* x and w should be multiple of 2 to be align */ + x = x & 0xfffffffe; + w = (w + 1) & 0xfffffffe; + + dst_pxl = (uint32_t *) (buff); + for (_y = y; _y < (y + h); _y += 1) { + src_pxl = &g_gpu.psx_vram.u8[x * 3 + (_y * 2048)]; + for (_x = 0; _x < (w / 2); ++_x) { + R0 = src_pxl[0]; + G0 = src_pxl[1]; + B0 = src_pxl[2]; + R1 = src_pxl[3]; + G1 = src_pxl[4]; + B1 = src_pxl[5]; + *dst_pxl++ = rgb_to_yuv2(R0, G0, B0, R1, G1, B1); + src_pxl += 6; + } + } +} + +void yuyv_blit_16(int8_t * buff, int32_t x, int32_t y, int32_t w, int32_t h) { + //fprintf(stderr, "yuyv_blit_16 %d %d %d %d\n", x, y, w, h); + int8_t R0, G0, B0; + int8_t R1, G1, B1; + uint32_t * dst_pxl; + int32_t _x, _y; + int32_t s; + uint16_t * src_pxl; + + /* x must be a multiple of 2 */ + /* x and w must be a multiple of 2 */ + x = x & 0xfffffffe; + w = (w + 1) & 0xfffffffe; + + dst_pxl = (uint32_t *) (buff); + for (_y = y; _y < (y + h); _y += 1) { + src_pxl = &g_gpu.psx_vram.u16[x + (_y * 1024)]; + for (_x = 0; _x < (w / 2); ++_x) { + s = GETLE16(src_pxl++); + R0 = (s << 3) & 0xf8; + G0 = (s >> 2) & 0xf8; + B0 = (s >> 7) & 0xf8; + s = GETLE16(src_pxl++); + R1 = (s << 3) & 0xf8; + G1 = (s >> 2) & 0xf8; + B1 = (s >> 7) & 0xf8; + *dst_pxl++ = rgb_to_yuv2(R0, G0, B0, R1, G1, B1); + } + } +} + +/** + * compute the position and the size of output screen + * The aspect of the psx output mode is preserved. + * Note: dest dx,dy,dw,dh are both input and output variables + */ +inline void maintain_aspect(uint32_t * dx, uint32_t * dy, uint32_t * dw, + uint32_t * dh, int32_t w, int32_t h) { + + double ratio_x = ((double) *dw) / ((double) w); + double ratio_y = ((double) *dh) / ((double) h); + + double ratio; + if (ratio_x < ratio_y) { + ratio = ratio_x; + } else { + ratio = ratio_y; + } + + uint32_t tw = (uint32_t) floor(w * ratio); + uint32_t th = (uint32_t) floor(h * ratio); + + *dx += (uint32_t) floor((*dw - tw) / 2.0); + *dy += (uint32_t) floor((*dh - th) / 2.0); + *dw = tw; + *dh = th; +} + +void do_buffer_swap(void) { + //Screen *screen; + Window _dw; + XvImage *xvi; + unsigned int dstx, dsty; + unsigned int _d, _w, _h; //don't care about _d + + dstx = 0; + dsty = 0; + + XSync(g_draw.display, False); + + XGetGeometry(g_draw.display, g_draw.window, &_dw, (int *) &_d, (int *) &_d, + &_w, &_h, &_d, &_d); + + if (g_cfg.ShowFPS) { + dsty += 15; + _h -= 15; + compute_fps(); + snprintf(g_draw.msg, 511, "FPS : %f", g_draw.fps); + XDrawImageString(g_draw.display, g_draw.window, g_draw.hGC, 0, 12, + g_draw.msg, strlen(g_draw.msg)); + } + + uint32_t _x_, _y_, _w_, _h_; + + /* if video mode is valid */ + if (g_gpu.dsp.mode.x) { + + if (g_gpu.status_reg & STATUS_RGB24) { + _x_ = (g_gpu.dsp.position.x * 2) / 3; + } else { + _x_ = g_gpu.dsp.position.x; + } + _y_ = g_gpu.dsp.position.y; + _w_ = (g_gpu.dsp.range.x1 - g_gpu.dsp.range.x0) / g_gpu.dsp.mode.x; + _h_ = (g_gpu.dsp.range.y1 - g_gpu.dsp.range.y0) * g_gpu.dsp.mode.y; + + if (g_gpu.status_reg & STATUS_RGB24) { + available_port[g_draw.xv].blit_24_bits( + (int8_t *) g_draw.shminfo.shmaddr, _x_, _y_, _w_, _h_); + } else { + available_port[GXV_YUV_PORT].blit_16_bits( + (int8_t *) g_draw.shminfo.shmaddr, _x_, _y_, _w_, _h_); + } + + xvi = XvShmCreateImage(g_draw.display, g_draw.xv_port, g_draw.xv_id, 0, + _w_, _h_, &g_draw.shminfo); + + xvi->data = g_draw.shminfo.shmaddr; + + //screen = DefaultScreenOfDisplay(g_draw.display); + //screennum = DefaultScreen(display); + + // if (g_cfg.FullScreen) { + // _w = screen->width; + // _h = screen->height; + // } + + if (g_cfg.Maintain43) + maintain_aspect(&dstx, &dsty, &_w, &_h, _w_, (g_gpu.dsp.range.y1 + - g_gpu.dsp.range.y0)); + + // int _i; + // int32_t * dst_pxl; + // dst_pxl = (int32_t *) &g_draw.shminfo.shmaddr[2048 * _y_]; + // for (_i = _x_ / 2; _i < (_x_ + _w_) / 2; ++_i) + // dst_pxl[_i] = rgb_to_yuv2(255, 0, 0, 255, 0, 0); + // dst_pxl = (int32_t *) &g_draw.shminfo.shmaddr[2048 * (_y_ + _h_)]; + // for (_i = _x_ / 2; _i < (_x_ + _w_) / 2; ++_i) + // dst_pxl[_i] = rgb_to_yuv2(255, 0, 0, 255, 0, 0); + // dst_pxl = (int32_t *) &g_draw.shminfo.shmaddr[4 * (_x_ / 2)]; + // for (_i = _y_; _i < (_y_ + _h_); ++_i) + // dst_pxl[_i * 512] = rgb_to_yuv2(255, 0, 0, 255, 0, 0); + // dst_pxl = (int32_t *) &g_draw.shminfo.shmaddr[4 * ((_x_ + _w_) / 2)]; + // for (_i = _y_; _i < (_y_ + _h_); ++_i) + // dst_pxl[_i * 512] = rgb_to_yuv2(255, 0, 0, 255, 0, 0); + + //fprintf(stderr, "From %d,%d,%d,%d\n", _x_, _y_, _w_, _h_); + XvShmPutImage(g_draw.display, g_draw.xv_port, g_draw.window, + g_draw.hGC, xvi, 0, 0, _w_, _h_, + //0, 0, 1024, 512, + /* dst */ + dstx, dsty, _w, _h, 1); + XFree(xvi); + } +} + +void do_clear_screen_buffer(void) // CLEAR DX BUFFER +{ + XClearWindow(g_draw.display, g_draw.window); +} + +void Xcleanup() // X CLEANUP +{ + //CloseMenu(); +} + +/** + * Call on GPUopen + * Return the current display. + **/ +unsigned long init_display() { + + available_port[GXV_YUV_PORT].blit_24_bits = yuyv_blit_24; + available_port[GXV_YUV_PORT].blit_16_bits = yuyv_blit_16; + + available_port[GXV_RGB_PORT].blit_24_bits = rgb_blit_24; + available_port[GXV_RGB_PORT].blit_16_bits = rgb_blit_16; + + create_display(); // x stuff + g_draw.bIsFirstFrame = 0; + return (unsigned long) g_draw.display; +} + +void CloseDisplay(void) { + Xcleanup(); // cleanup dx + DestroyDisplay(); +} + +void CreatePic(unsigned char * pMem) { + unsigned char * p = (unsigned char *) malloc(128 * 96 * 4); + unsigned char * ps; + //int x, y; + + ps = p; + + // if (iDesktopCol == 16) { + // unsigned short s; + // for (y = 0; y < 96; y++) { + // for (x = 0; x < 128; x++) { + // s = (*(pMem + 0)) >> 3; + // s |= ((*(pMem + 1)) & 0xfc) << 3; + // s |= ((*(pMem + 2)) & 0xf8) << 8; + // pMem += 3; + // *((unsigned short *) (ps + y * 256 + x * 2)) = s; + // } + // } + // } else if (iDesktopCol == 15) { + // unsigned short s; + // for (y = 0; y < 96; y++) { + // for (x = 0; x < 128; x++) { + // s = (*(pMem + 0)) >> 3; + // s |= ((*(pMem + 1)) & 0xfc) << 2; + // s |= ((*(pMem + 2)) & 0xf8) << 7; + // pMem += 3; + // *((unsigned short *) (ps + y * 256 + x * 2)) = s; + // } + // } + // } else if (iDesktopCol == 32) { + // uint32_t l; + // for (y = 0; y < 96; y++) { + // for (x = 0; x < 128; x++) { + // l = *(pMem + 0); + // l |= (*(pMem + 1)) << 8; + // l |= (*(pMem + 2)) << 16; + // pMem += 3; + // *((uint32_t *) (ps + y * 512 + x * 4)) = l; + // } + // } + // } + + g_draw.XPimage = XCreateImage(g_draw.display, g_draw.myvisual->visual, + g_draw.depth, ZPixmap, 0, (char *) p, 128, 96, + g_draw.depth > 16 ? 32 : 16, 0); +} + +void DestroyPic(void) { + if (g_draw.XPimage) { /* + XPutImage(display,window,hGC, XCimage, + 0, 0, 0, 0, iResX, iResY);*/ + XDestroyImage(g_draw.XPimage); + g_draw.XPimage = 0; + } +} + +void ShowGpuPic(void) { +} + +void ShowTextGpuPic(void) { +} diff --git a/plugins/gxvideo/draw.h b/plugins/gxvideo/draw.h new file mode 100644 index 00000000..edeb1e6e --- /dev/null +++ b/plugins/gxvideo/draw.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2010 Benoit Gschwind + * Inspired by original author : Pete Bernert + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _GPU_DRAW_H_ +#define _GPU_DRAW_H_ + +#include <time.h> +#include <stdint.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/extensions/Xvlib.h> + +#include "gpu_utils.h" + +typedef struct { + int iResX; + int iResY; + long lLowerpart; + int bIsFirstFrame; + int bCheckMask; + uint16_t sSetMask; + uint32_t lSetMask; + int iDesktopCol; + int iShowFPS; + int iWinSize; + int iMaintainAspect; + int iUseNoStretchBlt; + int iFastFwd; + int iDebugMode; + int iFVDisplay; + gxv_point_t ptCursorPoint[8]; + unsigned short usCursorActive; + + int xv_port; + int xv_id; + int xv_vsync; + int xv; + + XShmSegmentInfo shminfo; + int finalw, finalh; + + /* X Stuff */ + Cursor cursor; + XVisualInfo vi; + XVisualInfo * myvisual; + Display * display; + Colormap colormap; + Window window; + GC hGC; + XImage * Ximage; + XvImage * XCimage; + XImage * XFimage; + XImage * XPimage; + char * Xpixels; + char * pCaptionText; + + int fx; + + int depth; + int root_window_id; + + time_t tStart; + + double fps; + char msg[512]; + +} gxv_draw_t; + +typedef struct { + void (*blit_24_bits)(int8_t * buff, int32_t x, int32_t y, int32_t w, int32_t h); + void (*blit_16_bits)(int8_t * buff, int32_t x, int32_t y, int32_t w, int32_t h); +} gxv_blit_t; + +void do_buffer_swap(void); +void do_clear_screen_buffer(void); +void do_clear_front_buffer(void); +unsigned long init_display(void); +void CloseDisplay(void); +void CreatePic(unsigned char * pMem); +void DestroyPic(void); +void DisplayPic(void); +void ShowGpuPic(void); +void ShowTextGpuPic(void); + +typedef struct { +#define MWM_HINTS_DECORATIONS 2 + long flags; + long functions; + long decorations; + long input_mode; +} MotifWmHints; + +#endif // _GPU_DRAW_H_ diff --git a/plugins/gxvideo/fps.c b/plugins/gxvideo/fps.c new file mode 100644 index 00000000..151ff72e --- /dev/null +++ b/plugins/gxvideo/fps.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Benoit Gschwind + * Inspired by original author : Pete Bernert + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <unistd.h> +#include <sys/time.h> + +#include "globals.h" +#include "fps.h" +#include "gpu.h" + +#define TIMEBASE 100000 + +unsigned long time_get_time() { + struct timeval tv; + gettimeofday(&tv, 0); // well, maybe there are better ways + return tv.tv_sec * 100000 + tv.tv_usec / 10; // to do that, but at least it works +} + +void frame_cap(int fps) { + static unsigned int last_time = 0; + unsigned int c = time_get_time(); + + if (!fps) { + last_time = c; + return; + } + + if (last_time + (100000/fps) < c) { + last_time = c; + return; + } + + while (last_time + (100000/fps) - 20 > c) { + usleep(((100000/fps) - 20 - (c - last_time)) * 10 ); + c = time_get_time(); + } + + last_time = c; + +} + +void compute_fps() { + static int count = 0; + static unsigned int last_time = 0; + unsigned int c = time_get_time(); + ++count; + if((c - last_time) > 100000) { + g_draw.fps = ((double)count) / ((double)(c - last_time)) * 100000; + count = 0; + last_time = c; + } +} diff --git a/plugins/gxvideo/fps.h b/plugins/gxvideo/fps.h new file mode 100644 index 00000000..c1aec335 --- /dev/null +++ b/plugins/gxvideo/fps.h @@ -0,0 +1,27 @@ +/*
+ * Copyright (C) 2010 Benoit Gschwind
+ * Inspired by original author : Pete Bernert
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _FPS_INTERNALS_H
+#define _FPS_INTERNALS_H
+
+void frame_cap(int fps);
+void compute_fps();
+
+#endif // _FPS_INTERNALS_H
diff --git a/plugins/gxvideo/globals.c b/plugins/gxvideo/globals.c new file mode 100644 index 00000000..1ad6b142 --- /dev/null +++ b/plugins/gxvideo/globals.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2010 Benoit Gschwind + * Inspired by original author : Pete Bernert + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include "globals.h" + +char * g_file_name = 0; +gxv_cfg_t g_cfg = { }; +gxv_gpu_t g_gpu = { }; +gxv_draw_t g_draw = { }; +gxv_prim_t g_prim = { }; +gxv_soft_t g_soft = { }; diff --git a/plugins/gxvideo/globals.h b/plugins/gxvideo/globals.h new file mode 100644 index 00000000..299548c7 --- /dev/null +++ b/plugins/gxvideo/globals.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2010 Benoit Gschwind + * Inspired by original author : Pete Bernert + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef GLOBALS_H_ +#define GLOBALS_H_ + +#include "cfg.h" +#include "fps.h" +#include "gpu.h" +#include "draw.h" +#include "prim.h" +#include "soft.h" + +extern char * g_file_name; +extern gxv_cfg_t g_cfg; +extern gxv_gpu_t g_gpu; +extern gxv_draw_t g_draw; +extern gxv_prim_t g_prim; +extern gxv_soft_t g_soft; + +#endif /* GLOBALS_H_ */ diff --git a/plugins/gxvideo/gpu.c b/plugins/gxvideo/gpu.c new file mode 100644 index 00000000..590bdb8c --- /dev/null +++ b/plugins/gxvideo/gpu.c @@ -0,0 +1,1555 @@ +/* + * Copyright (C) 2010 Benoit Gschwind + * Inspired by original author : Pete Bernert + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include "config.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "globals.h" +#include "gpu.h" +#include "swap.h" + +#define CALLBACK + +#define INFO_TW 0 +#define INFO_DRAWSTART 1 +#define INFO_DRAWEND 2 +#define INFO_DRAWOFF 3 + +#define SHADETEXBIT(x) ((x>>24) & 0x1) +#define SEMITRANSBIT(x) ((x>>25) & 0x1) +#define PSXRGB(r,g,b) ((g<<10)|(b<<5)|r) + +#define DATAREGISTERMODES unsigned short + +#define DR_NORMAL 0 +#define DR_VRAMTRANSFER 1 + +#define MIN(a,b) ((a) > (b) ? (b) : (a)) +#define MAX(a,b) ((a) < (b) ? (b) : (a)) + +#ifdef ENABLE_NLS +#include <libintl.h> +#include <locale.h> +#define _(x) gettext(x) +#define N_(x) (x) +#else +#define _(x) (x) +#define N_(x) (x) +#endif + +//////////////////////////////////////////////////////////////////////// +// PPDK developer must change libraryName field and can change revision and build +//////////////////////////////////////////////////////////////////////// + +unsigned char const version = 1; // do not touch - library for PSEmu 1.x +unsigned char const revision = 0; +unsigned char const build = 0; // increase that with each version + +static char const * libraryName = N_("GXVideo Driver"); +static char const * libraryInfo = N_("GXvideo Driver v1.00"); +//static char const * PluginAuthor = +// N_("gschwind (rewrite from Pete Bernert and the P.E.Op.S. team)"); + +//////////////////////////////////////////////////////////////////////// +// some misc external display funcs +//////////////////////////////////////////////////////////////////////// + +#include <time.h> + +//void CALLBACK GPUdisplayText(char * pText) { +// +//} + +//////////////////////////////////////////////////////////////////////// + +//void CALLBACK GPUdisplayFlags(unsigned long dwFlags) // some info func +//{ +//dwCoreFlags = dwFlags; +//BuildDispMenu(0); +//} + +//////////////////////////////////////////////////////////////////////// +// stuff to make this a true PDK module +//////////////////////////////////////////////////////////////////////// + +char * CALLBACK PSEgetLibName(void) { + return _(libraryName); +} + +unsigned long CALLBACK PSEgetLibType(void) { + //return PSE_LT_GPU; + return 2; /* GPU plugin */ +} + +unsigned long CALLBACK PSEgetLibVersion(void) { + return version << 16 | revision << 8 | build; +} + +char * GPUgetLibInfos(void) { + return _(libraryInfo); +} + +//////////////////////////////////////////////////////////////////////// +// Snapshot func +//////////////////////////////////////////////////////////////////////// + +//char * pGetConfigInfos(int iCfg) { +// char szO[2][4] = { "off", "on " }; +// char szTxt[256]; +// char * pB = (char *) malloc(32767); +// +// if (!pB) +// return NULL; +// *pB = 0; +// //----------------------------------------------------// +// sprintf(szTxt, "Plugin: %s %d.%d.%d\r\n", libraryName, version, revision, +// build); +// strcat(pB, szTxt); +// sprintf(szTxt, "Author: %s\r\n\r\n", PluginAuthor); +// strcat(pB, szTxt); +// //----------------------------------------------------// +// +// sprintf(szTxt, "Resolution/Color:\r\n- %dx%d ", g_cfg.ResX, g_cfg.ResY); +// +// strcat(pB, szTxt); +// if (iWindowMode && iCfg) +// strcpy(szTxt, "Window mode\r\n"); +// else if (iWindowMode) +// sprintf(szTxt, "Window mode - [%d Bit]\r\n", iDesktopCol); +// else +// sprintf(szTxt, "Fullscreen - [%d Bit]\r\n", iColDepth); +// strcat(pB, szTxt); +// +// sprintf(szTxt, "Stretch mode: %d\r\n", iUseNoStretchBlt); +// strcat(pB, szTxt); +// sprintf(szTxt, "Dither mode: %d\r\n\r\n", iUseDither); +// strcat(pB, szTxt); +// //----------------------------------------------------// +// sprintf(szTxt, "Framerate:\r\n- FPS limit: %s\r\n", szO[UseFrameLimit]); +// strcat(pB, szTxt); +// sprintf(szTxt, "- Frame skipping: %s", szO[UseFrameSkip]); +// strcat(pB, szTxt); +// if (iFastFwd) +// strcat(pB, " (fast forward)"); +// strcat(pB, "\r\n"); +// if (iFrameLimit == 2) +// strcpy(szTxt, "- FPS limit: Auto\r\n\r\n"); +// else +// sprintf(szTxt, "- FPS limit: %.1f\r\n\r\n", fFrameRate); +// strcat(pB, szTxt); +// //----------------------------------------------------// +//#if !defined (_MACGL) && !defined (_WINDOWS) +// strcpy(szTxt, "Misc:\r\n- MaintainAspect: "); +// if (iMaintainAspect == 0) +// strcat(szTxt, "disabled"); +// else if (iMaintainAspect == 1) +// strcat(szTxt, "enabled"); +// strcat(szTxt, "\r\n"); +// strcat(pB, szTxt); +//#endif +// sprintf(szTxt, "- Game fixes: %s [%08x]\r\n", szO[iUseFixes], dwCfgFixes); +// strcat(pB, szTxt); +// //----------------------------------------------------// +// return pB; +// return 0; +//} + +void CALLBACK GPUmakeSnapshot(void) { + // FILE *bmpfile; + // char filename[256]; + // unsigned char header[0x36]; + // long size, height; + // unsigned char line[1024 * 3]; + // short i, j; + // unsigned char empty[2] = { 0, 0 }; + // unsigned short color; + // unsigned long snapshotnr = 0; + // unsigned char *pD; + // + // height = gpu_ctx.PreviousPSXDisplay.DisplayMode.y; + // + // size = height * PreviousPSXDisplay.Range.x1 * 3 + 0x38; + // + // // fill in proper values for BMP + // + // // hardcoded BMP header + // memset(header, 0, 0x36); + // header[0] = 'B'; + // header[1] = 'M'; + // header[2] = size & 0xff; + // header[3] = (size >> 8) & 0xff; + // header[4] = (size >> 16) & 0xff; + // header[5] = (size >> 24) & 0xff; + // header[0x0a] = 0x36; + // header[0x0e] = 0x28; + // header[0x12] = gpu_ctx.PreviousPSXDisplay.Range.x1 % 256; + // header[0x13] = gpu_ctx.PreviousPSXDisplay.Range.x1 / 256; + // header[0x16] = height % 256; + // header[0x17] = height / 256; + // header[0x1a] = 0x01; + // header[0x1c] = 0x18; + // header[0x26] = 0x12; + // header[0x27] = 0x0B; + // header[0x2A] = 0x12; + // header[0x2B] = 0x0B; + // + // // increment snapshot value & try to get filename + // do { + // snapshotnr++; + //#ifdef _WINDOWS + // sprintf(filename,"snap\\pcsx%04ld.bmp",snapshotnr); + //#else + // sprintf(filename, "%s/pcsx%04ld.bmp", getenv("HOME"), snapshotnr); + //#endif + // + // bmpfile = fopen(filename, "rb"); + // if (bmpfile == NULL) + // break; + // + // fclose(bmpfile); + // } while (TRUE); + // + // // try opening new snapshot file + // if ((bmpfile = fopen(filename, "wb")) == NULL) + // return; + // + // fwrite(header, 0x36, 1, bmpfile); + // for (i = height + PSXDisplay.DisplayPosition.y - 1; i + // >= PSXDisplay.DisplayPosition.y; i--) { + // pD = (unsigned char *) &psxVuw[i * 1024 + PSXDisplay.DisplayPosition.x]; + // for (j = 0; j < PreviousPSXDisplay.Range.x1; j++) { + // if (PSXDisplay.RGB24) { + // uint32_t lu = *(uint32_t *) pD; + // line[j * 3 + 2] = (unsigned char) RED(lu); + // line[j * 3 + 1] = (unsigned char) GREEN(lu); + // line[j * 3 + 0] = (unsigned char) BLUE(lu); + // pD += 3; + // } else { + // color = GETLE16(pD); + // line[j * 3 + 2] = (color << 3) & 0xf1; + // line[j * 3 + 1] = (color >> 2) & 0xf1; + // line[j * 3 + 0] = (color >> 7) & 0xf1; + // pD += 2; + // } + // } + // fwrite(line, PreviousPSXDisplay.Range.x1 * 3, 1, bmpfile); + // } + // fwrite(empty, 0x2, 1, bmpfile); + // fclose(bmpfile); + // + // DoTextSnapShot(snapshotnr); +} + +//////////////////////////////////////////////////////////////////////// +// INIT, will be called after lib load... well, just do some var init... +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUinit() { + fprintf(stderr, "%s\n", __FUNCTION__); + memset(g_gpu.ulStatusControl, 0, 256 * sizeof(uint32_t)); // init save state scontrol field + g_gpu.psxVSecure.u8 = (uint8_t *) malloc((512 * 2) * 1024 + (1024 * 1024)); // always alloc one extra MB for soft drawing funcs security + if (!g_gpu.psxVSecure.u8) + return -1; + + //!!! ATTENTION !!! + g_gpu.psx_vram.u8 = g_gpu.psxVSecure.u8 + 512 * 1024; // security offset into double sized psx vram! + + g_gpu.psxVuw_eom.u16 = g_gpu.psx_vram.u16 + 1024 * 512; // pre-calc of end of vram + + memset(g_gpu.psxVSecure.s8, 0x00, (512 * 2) * 1024 + (1024 * 1024)); + memset(g_gpu.lGPUInfoVals, 0x00, 16 * sizeof(uint32_t)); + + g_gpu.dsp.range.x0 = 0; + g_gpu.dsp.range.x1 = 0; + g_gpu.lGPUdataRet = 0x400; + + g_gpu.DataWriteMode = DR_NORMAL; + + // Reset transfer values, to prevent mis-transfer of data + memset(&g_gpu.VRAMWrite, 0, sizeof(gxv_vram_load_t)); + memset(&g_gpu.VRAMRead, 0, sizeof(gxv_vram_load_t)); + + // device initialised already ! + g_gpu.status_reg = 0x14802000; + return 0; +} + +/* Here starts all... */ +long GPUopen(unsigned long * disp, char * CapText, char * CfgFile) { + unsigned long d; + + ReadConfig(); + + g_draw.bIsFirstFrame = 1; + + d = init_display(); // setup x + + if (disp) + *disp = d; // wanna x pointer? ok + + if (d) + return 0; + return -1; +} + +//////////////////////////////////////////////////////////////////////// +// time to leave... +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUclose() { + fprintf(stderr, "%s\n", __FUNCTION__); + //ReleaseKeyHandler(); // de-subclass window + CloseDisplay(); // shutdown direct draw + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// I shot the sheriff +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUshutdown() { + free(g_gpu.psxVSecure.s8); + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// roughly emulated screen centering bits... not complete !!! +//////////////////////////////////////////////////////////////////////// +// +//void ChangeDispOffsetsX(void) // X CENTER +//{ +// long lx, l; +// +// if (!g_gpu.dsp.range.x1) +// return; +// +// l = g_gpu.prev_dsp.DisplayMode.x; +// +// l *= (long) g_gpu.dsp.range.x1; +// l /= 2560; +// lx = l; +// l &= 0xfffffff8; +// +// if (l == g_gpu.prev_dsp.range.y1) +// return; // abusing range.y1 for +// g_gpu.prev_dsp.range.y1 = (short) l; // storing last x range and test +// +// if (lx >= g_gpu.prev_dsp.DisplayMode.x) { +// g_gpu.prev_dsp.range.x1 = (short) g_gpu.prev_dsp.DisplayMode.x; +// g_gpu.prev_dsp.range.x0 = 0; +// } else { +// g_gpu.prev_dsp.range.x1 = (short) l; +// +// g_gpu.prev_dsp.range.x0 = (g_gpu.dsp.range.x0 - 500) / 8; +// +// if (g_gpu.prev_dsp.range.x0 < 0) +// g_gpu.prev_dsp.range.x0 = 0; +// +// if ((g_gpu.prev_dsp.range.x0 + lx) > g_gpu.prev_dsp.DisplayMode.x) { +// g_gpu.prev_dsp.range.x0 = (short) (g_gpu.prev_dsp.DisplayMode.x +// - lx); +// g_gpu.prev_dsp.range.x0 += 2; //??? +// +// g_gpu.prev_dsp.range.x1 += (short) (lx - l); +// +// g_gpu.prev_dsp.range.x1 -= 2; // makes linux stretching easier +// } +// +// // some linux alignment security +// g_gpu.prev_dsp.range.x0 = g_gpu.prev_dsp.range.x0 >> 1; +// g_gpu.prev_dsp.range.x0 = g_gpu.prev_dsp.range.x0 << 1; +// g_gpu.prev_dsp.range.x1 = g_gpu.prev_dsp.range.x1 >> 1; +// g_gpu.prev_dsp.range.x1 = g_gpu.prev_dsp.range.x1 << 1; +// +// DoClearScreenBuffer(); +// } +// +// g_prim.bDoVSyncUpdate = 1; +//} + +//////////////////////////////////////////////////////////////////////// + +//void ChangeDispOffsetsY(void) // Y CENTER +//{ +// int iT, iO = g_gpu.prev_dsp.range.y0; +// int iOldYOffset = g_gpu.prev_dsp.DisplayModeNew.y; +// +// // new +// +// if ((g_gpu.prev_dsp.DisplayModeNew.x + g_gpu.dsp.DisplayModeNew.y) > 512) { +// int dy1 = 512 - g_gpu.prev_dsp.DisplayModeNew.x; +// int dy2 = +// (g_gpu.prev_dsp.DisplayModeNew.x + g_gpu.dsp.DisplayModeNew.y) +// - 512; +// +// if (dy1 >= dy2) { +// g_gpu.prev_dsp.DisplayModeNew.y = -dy2; +// } else { +// g_gpu.dsp.position.y = 0; +// g_gpu.prev_dsp.DisplayModeNew.y = -dy1; +// } +// } else +// g_gpu.prev_dsp.DisplayModeNew.y = 0; +// +// // eon +// +// if (g_gpu.prev_dsp.DisplayModeNew.y != iOldYOffset) // if old offset!=new offset: recalc height +// { +// g_gpu.dsp.Height = g_gpu.dsp.range.y1 - g_gpu.dsp.range.y0 +// + g_gpu.prev_dsp.DisplayModeNew.y; +// g_gpu.dsp.DisplayModeNew.y = g_gpu.dsp.Height * g_gpu.dsp.Double; +// } +// +// // +// +// if (g_gpu.dsp.PAL) +// iT = 48; +// else +// iT = 28; +// +// if (g_gpu.dsp.range.y0 >= iT) { +// g_gpu.prev_dsp.range.y0 = (short) ((g_gpu.dsp.range.y0 - iT - 4) +// * g_gpu.dsp.Double); +// if (g_gpu.prev_dsp.range.y0 < 0) +// g_gpu.prev_dsp.range.y0 = 0; +// g_gpu.dsp.DisplayModeNew.y += g_gpu.prev_dsp.range.y0; +// } else +// g_gpu.prev_dsp.range.y0 = 0; +// +// if (iO != g_gpu.prev_dsp.range.y0) { +// DoClearScreenBuffer(); +// } +//} + +//////////////////////////////////////////////////////////////////////// +// check if update needed +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// + +// TOGGLE FULLSCREEN - WINDOW DISABLED +//void ChangeWindowMode(void) { +// extern Display *display; +// extern Window window; +// extern int root_window_id; +// Screen *screen; +// XSizeHints hints; +// MotifWmHints mwmhints; +// Atom mwmatom; +// +// screen = DefaultScreenOfDisplay(display); +// iWindowMode = !iWindowMode; +// +// if (!iWindowMode) // fullscreen +// { +// mwmhints.flags = MWM_HINTS_DECORATIONS; +// mwmhints.functions = 0; +// mwmhints.decorations = 0; +// mwmhints.input_mode = 0; +// mwmatom = XInternAtom(display, "_MOTIF_WM_HINTS", 0); +// XChangeProperty(display, window, mwmatom, mwmatom, 32, PropModeReplace, +// (unsigned char *) &mwmhints, 5); +// +// XResizeWindow(display, window, screen->width, screen->height); +// +// hints.min_width = hints.max_width = hints.base_width = screen->width; +// hints.min_height = hints.max_height = hints.base_height +// = screen->height; +// +// XSetWMNormalHints(display, window, &hints); +// +// { +// XEvent xev; +// +// memset(&xev, 0, sizeof(xev)); +// xev.xclient.type = ClientMessage; +// xev.xclient.serial = 0; +// xev.xclient.send_event = 1; +// xev.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", 0); +// xev.xclient.window = window; +// xev.xclient.format = 32; +// xev.xclient.data.l[0] = 1; +// xev.xclient.data.l[1] = XInternAtom(display, +// "_NET_WM_STATE_FULLSCREEN", 0); +// xev.xclient.data.l[2] = 0; +// xev.xclient.data.l[3] = 0; +// xev.xclient.data.l[4] = 0; +// +// XSendEvent(display, root_window_id, 0, SubstructureRedirectMask +// | SubstructureNotifyMask, &xev); +// } +// } else { +// { +// XEvent xev; +// +// memset(&xev, 0, sizeof(xev)); +// xev.xclient.type = ClientMessage; +// xev.xclient.serial = 0; +// xev.xclient.send_event = 1; +// xev.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", 0); +// xev.xclient.window = window; +// xev.xclient.format = 32; +// xev.xclient.data.l[0] = 0; +// xev.xclient.data.l[1] = XInternAtom(display, +// "_NET_WM_STATE_FULLSCREEN", 0); +// xev.xclient.data.l[2] = 0; +// xev.xclient.data.l[3] = 0; +// xev.xclient.data.l[4] = 0; +// +// XSendEvent(display, root_window_id, 0, SubstructureRedirectMask +// | SubstructureNotifyMask, &xev); +// } +// +// mwmhints.flags = MWM_HINTS_DECORATIONS; +// mwmhints.functions = 0; +// mwmhints.decorations = 1; +// mwmhints.input_mode = 0; +// mwmatom = XInternAtom(display, "_MOTIF_WM_HINTS", 0); +// +// //This shouldn't work on 64 bit longs, but it does...in fact, it breaks when I change all the mwmhints to int. +// //I don't pretend to understand it. +// XChangeProperty(display, window, mwmatom, mwmatom, 32, PropModeReplace, +// (unsigned char *) &mwmhints, 5); +// +// hints.flags = USPosition | USSize; +// hints.base_width = iResX; +// hints.base_height = iResY; +// XSetWMNormalHints(display, window, &hints); +// +// XResizeWindow(display, window, iResX, iResY); +// } +// +// DoClearScreenBuffer(); +// +// bChangeWinMode = 0; +// bDoVSyncUpdate = 1; +//} + +//////////////////////////////////////////////////////////////////////// +// gun cursor func: player=0-7, x=0-511, y=0-255 +//////////////////////////////////////////////////////////////////////// + +/* disabled */ +void CALLBACK GPUcursor(int iPlayer, int x, int y) { + // if (iPlayer < 0) + // return; + // if (iPlayer > 7) + // return; + // + // usCursorActive |= (1 << iPlayer); + // + // if (x < 0) + // x = 0; + // if (x > 511) + // x = 511; + // if (y < 0) + // y = 0; + // if (y > 255) + // y = 255; + // + // ptCursorPoint[iPlayer].x = x; + // ptCursorPoint[iPlayer].y = y; +} + +//////////////////////////////////////////////////////////////////////// +// update lace is called evry VSync +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUupdateLace(void) // VSYNC +{ + + g_gpu.status_reg ^= STATUS_ODDLINES; + + if (g_gpu.status_reg & STATUS_DISPLAYDISABLED) { + do_clear_screen_buffer(); + return; + } + + /* I do not roughly emulate interlace, I just draw 1/2 frame + * to save CPU, and improve render */ + if (!(g_gpu.status_reg & STATUS_INTERLACED) || (g_gpu.status_reg + & STATUS_ODDLINES)) + do_buffer_swap(); + + frame_cap(g_gpu.fps); +} + +//////////////////////////////////////////////////////////////////////// +// process read request from GPU status register +//////////////////////////////////////////////////////////////////////// + + +uint32_t CALLBACK GPUreadStatus(void) // READ STATUS +{ + return g_gpu.status_reg; +} + +//////////////////////////////////////////////////////////////////////// +// processes data send to GPU status register +// these are always single packet commands. +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUwriteStatus(uint32_t gdata) { + uint32_t lCommand = (gdata >> 24) & 0xff; + g_gpu.ulStatusControl[lCommand] = gdata; // store command for freezing + switch (lCommand) { + case 0x00: + /* reset GPU */ + memset(g_gpu.lGPUInfoVals, 0x00, 16 * sizeof(uint32_t)); + /* STATUS_READYFORCOMMANDS | STATUS_IDLE | STATUS_DISPLAYDISABLED | UNKNOW13 */ + g_gpu.status_reg = 0x14802000; + g_gpu.DataWriteMode = DR_NORMAL; + g_gpu.DataReadMode = DR_NORMAL; + g_prim.drawX = 0; + g_prim.drawY = 0; + g_prim.drawW = 0; + g_prim.drawH = 0; + g_draw.sSetMask = 0; + g_draw.lSetMask = 0; + g_draw.bCheckMask = 0; + g_prim.usMirror = 0; + g_soft.GlobalTextAddrX = 0; + g_soft.GlobalTextAddrY = 0; + g_soft.GlobalTextTP = 0; + g_soft.GlobalTextABR = 0; + g_prim.bUsingTWin = 0; + return; + case 0x01: + /* reset command buffer */ + //fprintf(stderr, "Reset command buffer not implemented\n"); + return; + case 0x02: + /* reset IRQ */ + //fprintf(stderr, "Reset IRQ not implemented\n"); + return; + case 0x03: + /* Enable or disable the display */ + if (gdata & 0x01) + g_gpu.status_reg |= STATUS_DISPLAYDISABLED; + else + g_gpu.status_reg &= ~STATUS_DISPLAYDISABLED; + return; + case 0x04: + /* Set the transfering mode */ + gdata &= 0x03; // Only want the lower two bits + g_gpu.DataWriteMode = DR_NORMAL; + g_gpu.DataReadMode = DR_NORMAL; + if (gdata == 0x02) + g_gpu.DataWriteMode = DR_VRAMTRANSFER; + if (gdata == 0x03) + g_gpu.DataReadMode = DR_VRAMTRANSFER; + g_gpu.status_reg &= ~STATUS_DMABITS; // Clear the current settings of the DMA bits + g_gpu.status_reg |= (gdata << 29); // Set the DMA bits according to the received data + return; + case 0x05: + /* setting display position */ + g_gpu.dsp.position.y = (short) ((gdata >> 10) & 0x1ff); + g_gpu.dsp.position.x = (short) (gdata & 0x3ff); + //fprintf(stderr, "Update display position X=%d,Y=%d\n", + // g_gpu.dsp.position.x, g_gpu.dsp.position.y); + return; + case 0x06: + /* Set width */ + g_gpu.dsp.range.x0 = (short) (gdata & 0x03ff); + g_gpu.dsp.range.x1 = (short) ((gdata >> 12) & 0x0fff); + //fprintf(stderr, "Setrange x0 : %d, x1 : %d\n", g_gpu.dsp.range.x0, + // g_gpu.dsp.range.x1); + return; + case 0x07: + /* Set height */ + g_gpu.dsp.range.y0 = (short) (gdata & 0x3ff); + g_gpu.dsp.range.y1 = (short) ((gdata >> 10) & 0x3ff); + //fprintf(stderr, "Setrange y0 : %d, y1 : %d\n", g_gpu.dsp.range.y0, + // g_gpu.dsp.range.y1); + return; + case 0x08: + /* setting display infos */ + //fprintf(stderr, "command %x\n", gdata&0x000043); + switch (gdata & 0x000043) { + case 0x00: + g_gpu.dsp.mode.x = 10; + break; + case 0x01: + g_gpu.dsp.mode.x = 8; + break; + case 0x02: + g_gpu.dsp.mode.x = 5; + break; + case 0x03: + g_gpu.dsp.mode.x = 4; + break; + case 0x40: + g_gpu.dsp.mode.x = 7; + break; + default: + g_gpu.dsp.mode.x = 0; + } + + /* clear width status */ + g_gpu.status_reg &= ~STATUS_WIDTHBITS; + /* update status reg */ + g_gpu.status_reg |= ((gdata & 0x00000003) << 17) + | ((gdata & 0x00000040) << 10); + + switch (gdata & 0x000004) { + case 0x00: + g_gpu.status_reg &= ~STATUS_DOUBLEHEIGHT; + g_gpu.dsp.mode.y = 1; + break; + case 0x04: + g_gpu.status_reg |= STATUS_DOUBLEHEIGHT; + g_gpu.dsp.mode.y = 2; + break; + } + + switch (gdata & 0x08) { + case 0x00: + g_gpu.status_reg &= ~STATUS_PAL; + g_gpu.fps = 60; + break; + case 0x08: + g_gpu.status_reg |= STATUS_PAL; + g_gpu.fps = 50; + break; + } + //fprintf(stderr, "video mode %dx%d\n", g_gpu.dsp.mode.x, g_gpu.dsp.mode.y); + + if ((gdata & 0x10)) { + g_gpu.status_reg |= STATUS_RGB24; + } else { + g_gpu.status_reg &= ~STATUS_RGB24; + } + + if ((gdata & 0x20)) { + g_gpu.status_reg |= STATUS_INTERLACED; + } else { + g_gpu.status_reg &= ~STATUS_INTERLACED; + } + return; + case 0x10: + /* ask about GPU version and other stuff */ + gdata &= 0xff; + switch (gdata) { + case 0x02: + g_gpu.lGPUdataRet = g_gpu.lGPUInfoVals[INFO_TW]; // tw infos + return; + case 0x03: + g_gpu.lGPUdataRet = g_gpu.lGPUInfoVals[INFO_DRAWSTART]; // draw start + return; + case 0x04: + g_gpu.lGPUdataRet = g_gpu.lGPUInfoVals[INFO_DRAWEND]; // draw end + return; + case 0x05: + case 0x06: + g_gpu.lGPUdataRet = g_gpu.lGPUInfoVals[INFO_DRAWOFF]; // draw offset + return; + case 0x07: + if (0) + g_gpu.lGPUdataRet = 0x01; + else + g_gpu.lGPUdataRet = 0x02; // gpu type + return; + case 0x08: + case 0x0F: // some bios addr? + g_gpu.lGPUdataRet = 0xBFC03720; + return; + } + return; + default: + fprintf(stderr, "Unknow command %02x\n", lCommand); + } +} + +//////////////////////////////////////////////////////////////////////// +// vram read/write helpers, needed by LEWPY's optimized vram read/write :) +//////////////////////////////////////////////////////////////////////// + +inline void FinishedVRAMWrite(void) { + // Set register to NORMAL operation + g_gpu.DataWriteMode = DR_NORMAL; + // Reset transfer values, to prevent mis-transfer of data + g_gpu.VRAMWrite.x = 0; + g_gpu.VRAMWrite.y = 0; + g_gpu.VRAMWrite.Width = 0; + g_gpu.VRAMWrite.Height = 0; + g_gpu.VRAMWrite.ColsRemaining = 0; + g_gpu.VRAMWrite.RowsRemaining = 0; +} + +inline void FinishedVRAMRead(void) { + // Set register to NORMAL operation + g_gpu.DataReadMode = DR_NORMAL; + // Reset transfer values, to prevent mis-transfer of data + g_gpu.VRAMRead.x = 0; + g_gpu.VRAMRead.y = 0; + g_gpu.VRAMRead.Width = 0; + g_gpu.VRAMRead.Height = 0; + g_gpu.VRAMRead.ColsRemaining = 0; + g_gpu.VRAMRead.RowsRemaining = 0; + + // Indicate GPU is no longer ready for VRAM data in the STATUS REGISTER + g_gpu.status_reg &= ~STATUS_READYFORVRAM; +} + +//////////////////////////////////////////////////////////////////////// +// core read from vram +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUreadDataMem(uint32_t * pMem, int iSize) { + int i; + + if (g_gpu.DataReadMode != DR_VRAMTRANSFER) + return; + + g_gpu.status_reg &= ~STATUS_IDLE; + + // adjust read ptr, if necessary + + while (g_gpu.VRAMRead.ImagePtr >= g_gpu.psxVuw_eom.u16) + g_gpu.VRAMRead.ImagePtr -= 512 * 1024; + while (g_gpu.VRAMRead.ImagePtr < g_gpu.psx_vram.u16) + g_gpu.VRAMRead.ImagePtr += 512 * 1024; + + for (i = 0; i < iSize; i++) { + // do 2 seperate 16bit reads for compatibility (wrap issues) + if ((g_gpu.VRAMRead.ColsRemaining > 0) && (g_gpu.VRAMRead.RowsRemaining + > 0)) { + // lower 16 bit + g_gpu.lGPUdataRet = (uint32_t) GETLE16(g_gpu.VRAMRead.ImagePtr); + + g_gpu.VRAMRead.ImagePtr++; + if (g_gpu.VRAMRead.ImagePtr >= g_gpu.psxVuw_eom.u16) + g_gpu.VRAMRead.ImagePtr -= 512 * 1024; + g_gpu.VRAMRead.RowsRemaining--; + + if (g_gpu.VRAMRead.RowsRemaining <= 0) { + g_gpu.VRAMRead.RowsRemaining = g_gpu.VRAMRead.Width; + g_gpu.VRAMRead.ColsRemaining--; + g_gpu.VRAMRead.ImagePtr += 1024 - g_gpu.VRAMRead.Width; + if (g_gpu.VRAMRead.ImagePtr >= g_gpu.psxVuw_eom.u16) + g_gpu.VRAMRead.ImagePtr -= 512 * 1024; + } + + // higher 16 bit (always, even if it's an odd width) + g_gpu.lGPUdataRet |= (uint32_t) GETLE16(g_gpu.VRAMRead.ImagePtr) + << 16; + PUTLE32(pMem, g_gpu.lGPUdataRet); + pMem++; + + if (g_gpu.VRAMRead.ColsRemaining <= 0) { + FinishedVRAMRead(); + goto ENDREAD; + } + + g_gpu.VRAMRead.ImagePtr++; + if (g_gpu.VRAMRead.ImagePtr >= g_gpu.psxVuw_eom.u16) + g_gpu.VRAMRead.ImagePtr -= 512 * 1024; + g_gpu.VRAMRead.RowsRemaining--; + if (g_gpu.VRAMRead.RowsRemaining <= 0) { + g_gpu.VRAMRead.RowsRemaining = g_gpu.VRAMRead.Width; + g_gpu.VRAMRead.ColsRemaining--; + g_gpu.VRAMRead.ImagePtr += 1024 - g_gpu.VRAMRead.Width; + if (g_gpu.VRAMRead.ImagePtr >= g_gpu.psxVuw_eom.u16) + g_gpu.VRAMRead.ImagePtr -= 512 * 1024; + } + if (g_gpu.VRAMRead.ColsRemaining <= 0) { + FinishedVRAMRead(); + goto ENDREAD; + } + } else { + FinishedVRAMRead(); + goto ENDREAD; + } + } + + ENDREAD: g_gpu.status_reg |= STATUS_IDLE; +} + +//////////////////////////////////////////////////////////////////////// + +uint32_t CALLBACK GPUreadData(void) { + uint32_t l; + GPUreadDataMem(&l, 1); + return g_gpu.lGPUdataRet; +} + +//////////////////////////////////////////////////////////////////////// +// processes data send to GPU data register +// extra table entries for fixing polyline troubles +//////////////////////////////////////////////////////////////////////// + +const unsigned char primTableCX[256] = { +// 00 + 0, 0, 3, 0, 0, 0, 0, 0, + // 08 + 0, 0, 0, 0, 0, 0, 0, 0, + // 10 + 0, 0, 0, 0, 0, 0, 0, 0, + // 18 + 0, 0, 0, 0, 0, 0, 0, 0, + // 20 + 4, 4, 4, 4, 7, 7, 7, 7, + // 28 + 5, 5, 5, 5, 9, 9, 9, 9, + // 30 + 6, 6, 6, 6, 9, 9, 9, 9, + // 38 + 8, 8, 8, 8, 12, 12, 12, 12, + // 40 + 3, 3, 3, 3, 0, 0, 0, 0, + // 48 + // 5,5,5,5,6,6,6,6, // FLINE + 254, 254, 254, 254, 254, 254, 254, 254, + // 50 + 4, 4, 4, 4, 0, 0, 0, 0, + // 58 + // 7,7,7,7,9,9,9,9, // GLINE + 255, 255, 255, 255, 255, 255, 255, 255, + // 60 + 3, 3, 3, 3, 4, 4, 4, 4, + // 68 + 2, 2, 2, 2, 3, 3, 3, 3, // 3=SPRITE1??? + // 70 + 2, 2, 2, 2, 3, 3, 3, 3, + // 78 + 2, 2, 2, 2, 3, 3, 3, 3, + // 80 + 4, 0, 0, 0, 0, 0, 0, 0, + // 88 + 0, 0, 0, 0, 0, 0, 0, 0, + // 90 + 0, 0, 0, 0, 0, 0, 0, 0, + // 98 + 0, 0, 0, 0, 0, 0, 0, 0, + // a0 + 3, 0, 0, 0, 0, 0, 0, 0, + // a8 + 0, 0, 0, 0, 0, 0, 0, 0, + // b0 + 0, 0, 0, 0, 0, 0, 0, 0, + // b8 + 0, 0, 0, 0, 0, 0, 0, 0, + // c0 + 3, 0, 0, 0, 0, 0, 0, 0, + // c8 + 0, 0, 0, 0, 0, 0, 0, 0, + // d0 + 0, 0, 0, 0, 0, 0, 0, 0, + // d8 + 0, 0, 0, 0, 0, 0, 0, 0, + // e0 + 0, 1, 1, 1, 1, 1, 1, 0, + // e8 + 0, 0, 0, 0, 0, 0, 0, 0, + // f0 + 0, 0, 0, 0, 0, 0, 0, 0, + // f8 + 0, 0, 0, 0, 0, 0, 0, 0 }; + +void CALLBACK GPUwriteDataMem(uint32_t * pMem, int iSize) { + unsigned char command; + uint32_t gdata = 0; + int i = 0; + + g_gpu.status_reg &= ~STATUS_IDLE; + g_gpu.status_reg &= ~STATUS_READYFORCOMMANDS; + + STARTVRAM: + + if (g_gpu.DataWriteMode == DR_VRAMTRANSFER) { + char bFinished = 0; + + // make sure we are in vram + while (g_gpu.VRAMWrite.ImagePtr >= g_gpu.psxVuw_eom.u16) + g_gpu.VRAMWrite.ImagePtr -= 512 * 1024; + while (g_gpu.VRAMWrite.ImagePtr < g_gpu.psx_vram.u16) + g_gpu.VRAMWrite.ImagePtr += 512 * 1024; + + // now do the loop + while (g_gpu.VRAMWrite.ColsRemaining > 0) { + while (g_gpu.VRAMWrite.RowsRemaining > 0) { + if (i >= iSize) { + goto ENDVRAM; + } + i++; + + gdata = GETLE32(pMem); + pMem++; + + PUTLE16(g_gpu.VRAMWrite.ImagePtr, (unsigned short)gdata); + g_gpu.VRAMWrite.ImagePtr++; + if (g_gpu.VRAMWrite.ImagePtr >= g_gpu.psxVuw_eom.u16) + g_gpu.VRAMWrite.ImagePtr -= 512 * 1024; + g_gpu.VRAMWrite.RowsRemaining--; + + if (g_gpu.VRAMWrite.RowsRemaining <= 0) { + g_gpu.VRAMWrite.ColsRemaining--; + if (g_gpu.VRAMWrite.ColsRemaining <= 0) // last pixel is odd width + { + gdata + = (gdata & 0xFFFF) + | (((uint32_t) GETLE16(g_gpu.VRAMWrite.ImagePtr)) + << 16); + FinishedVRAMWrite(); + goto ENDVRAM; + } + g_gpu.VRAMWrite.RowsRemaining = g_gpu.VRAMWrite.Width; + g_gpu.VRAMWrite.ImagePtr += 1024 - g_gpu.VRAMWrite.Width; + } + + PUTLE16(g_gpu.VRAMWrite.ImagePtr, (unsigned short)(gdata>>16)); + g_gpu.VRAMWrite.ImagePtr++; + if (g_gpu.VRAMWrite.ImagePtr >= g_gpu.psxVuw_eom.u16) + g_gpu.VRAMWrite.ImagePtr -= 512 * 1024; + g_gpu.VRAMWrite.RowsRemaining--; + } + + g_gpu.VRAMWrite.RowsRemaining = g_gpu.VRAMWrite.Width; + g_gpu.VRAMWrite.ColsRemaining--; + g_gpu.VRAMWrite.ImagePtr += 1024 - g_gpu.VRAMWrite.Width; + bFinished = 1; + } + + FinishedVRAMWrite(); + } + + ENDVRAM: + + if (g_gpu.DataWriteMode == DR_NORMAL) { + void (* *primFunc)(unsigned char *); + primFunc = primTableJ; + + for (; i < iSize;) { + if (g_gpu.DataWriteMode == DR_VRAMTRANSFER) + goto STARTVRAM; + + gdata = GETLE32(pMem); + pMem++; + i++; + + if (g_gpu.gpuDataC == 0) { + command = (unsigned char) ((gdata >> 24) & 0xff); + + //if(command>=0xb0 && command<0xc0) auxprintf("b0 %x!!!!!!!!!\n",command); + + if (primTableCX[command]) { + g_gpu.gpuDataC = primTableCX[command]; + g_gpu.gpuCommand = command; + PUTLE32(&g_gpu.gpuDataM[0], gdata); + g_gpu.gpuDataP = 1; + } else { + //fprintf(stderr, "unknow command %02x \n", command); + continue; + } + } else { + PUTLE32(&g_gpu.gpuDataM[g_gpu.gpuDataP], gdata); + if (g_gpu.gpuDataC > 128) { + if ((g_gpu.gpuDataC == 254 && g_gpu.gpuDataP >= 3) + || (g_gpu.gpuDataC == 255 && g_gpu.gpuDataP >= 4 + && !(g_gpu.gpuDataP & 1))) { + if ((g_gpu.gpuDataM[g_gpu.gpuDataP] & 0xF000F000) + == 0x50005000) + g_gpu.gpuDataP = g_gpu.gpuDataC - 1; + } + } + g_gpu.gpuDataP++; + } + + if (g_gpu.gpuDataP == g_gpu.gpuDataC) { + g_gpu.gpuDataC = g_gpu.gpuDataP = 0; + primFunc[g_gpu.gpuCommand]((unsigned char *) g_gpu.gpuDataM); + } + } + } + + g_gpu.lGPUdataRet = gdata; + + g_gpu.status_reg |= STATUS_READYFORCOMMANDS; + g_gpu.status_reg |= STATUS_IDLE; +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUwriteData(uint32_t gdata) { + PUTLE32(&gdata, gdata); + GPUwriteDataMem(&gdata, 1); +} + +//////////////////////////////////////////////////////////////////////// +// this functions will be removed soon (or 'soonish')... not really needed, but some emus want them +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUsetMode(unsigned long gdata) { + // Peops does nothing here... + // DataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL; + // DataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL; +} + +long CALLBACK GPUgetMode(void) { + long iT = 0; + + if (g_gpu.DataWriteMode == DR_VRAMTRANSFER) + iT |= 0x1; + if (g_gpu.DataReadMode == DR_VRAMTRANSFER) + iT |= 0x2; + return iT; +} + +//////////////////////////////////////////////////////////////////////// +// call config dlg +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUconfigure(void) { + SoftDlgProc(); + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// sets all kind of act fixes +//////////////////////////////////////////////////////////////////////// + +void SetFixes(void) { + +} + +//////////////////////////////////////////////////////////////////////// +// process gpu commands +//////////////////////////////////////////////////////////////////////// + +unsigned long lUsedAddr[3]; + +inline char CheckForEndlessLoop(unsigned long laddr) { + if (laddr == lUsedAddr[1]) + return 1; + if (laddr == lUsedAddr[2]) + return 1; + + if (laddr < lUsedAddr[0]) + lUsedAddr[1] = laddr; + else + lUsedAddr[2] = laddr; + lUsedAddr[0] = laddr; + return 0; +} + +long CALLBACK GPUdmaChain(uint32_t * baseAddrL, uint32_t addr) { + uint32_t dmaMem; + unsigned char * baseAddrB; + short count; + unsigned int DMACommandCounter = 0; + + g_gpu.status_reg &= ~STATUS_IDLE; + + lUsedAddr[0] = lUsedAddr[1] = lUsedAddr[2] = 0xffffff; + + baseAddrB = (unsigned char*) baseAddrL; + + do { + if (1) + addr &= 0x1FFFFC; + if (DMACommandCounter++ > 2000000) + break; + if (CheckForEndlessLoop(addr)) + break; + + count = baseAddrB[addr + 3]; + + dmaMem = addr + 4; + + if (count > 0) + GPUwriteDataMem(&baseAddrL[dmaMem >> 2], count); + + addr = GETLE32(&baseAddrL[addr>>2]) & 0xffffff; + } while (addr != 0xffffff); + + g_gpu.status_reg |= STATUS_IDLE; + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// show about dlg +//////////////////////////////////////////////////////////////////////// + + +void CALLBACK GPUabout(void) // ABOUT +{ + AboutDlgProc(); + return; +} + +//////////////////////////////////////////////////////////////////////// +// We are ever fine ;) +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUtest(void) { + // if test fails this function should return negative value for error (unable to continue) + // and positive value for warning (can continue but output might be crappy) + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// Freeze +//////////////////////////////////////////////////////////////////////// + +typedef struct GPUFREEZETAG { + uint32_t ulFreezeVersion; // should be always 1 for now (set by main emu) + uint32_t ulStatus; // current gpu status + uint32_t ulControl[256]; // latest control register values + unsigned char psxVRam[1024 * 1024 * 2]; // current VRam image (full 2 MB for ZN) +} GPUFreeze_t; + +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUfreeze(uint32_t ulGetFreezeData, GPUFreeze_t * pF) { + //----------------------------------------------------// + if (ulGetFreezeData == 2) // 2: info, which save slot is selected? (just for display) + { + long lSlotNum = *((long *) pF); + if (lSlotNum < 0) + return 0; + if (lSlotNum > 8) + return 0; + //g_gpu.lSelectedSlot = lSlotNum + 1; + //BuildDispMenu(0); + return 1; + } + //----------------------------------------------------// + if (!pF) + return 0; // some checks + if (pF->ulFreezeVersion != 1) + return 0; + + if (ulGetFreezeData == 1) // 1: get data + { + pF->ulStatus = g_gpu.status_reg; + memcpy(pF->ulControl, g_gpu.ulStatusControl, 256 * sizeof(uint32_t)); + memcpy(pF->psxVRam, g_gpu.psx_vram.u8, 1024 * 512 * 2); + + return 1; + } + + if (ulGetFreezeData != 0) + return 0; // 0: set data + + g_gpu.status_reg = pF->ulStatus; + memcpy(g_gpu.ulStatusControl, pF->ulControl, 256 * sizeof(uint32_t)); + memcpy(g_gpu.psx_vram.u8, pF->psxVRam, 1024 * 512 * 2); + + // RESET TEXTURE STORE HERE, IF YOU USE SOMETHING LIKE THAT + + GPUwriteStatus(g_gpu.ulStatusControl[0]); + GPUwriteStatus(g_gpu.ulStatusControl[1]); + GPUwriteStatus(g_gpu.ulStatusControl[2]); + GPUwriteStatus(g_gpu.ulStatusControl[3]); + GPUwriteStatus(g_gpu.ulStatusControl[8]); // try to repair things + GPUwriteStatus(g_gpu.ulStatusControl[6]); + GPUwriteStatus(g_gpu.ulStatusControl[7]); + GPUwriteStatus(g_gpu.ulStatusControl[5]); + GPUwriteStatus(g_gpu.ulStatusControl[4]); + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// SAVE STATE DISPLAY STUFF +//////////////////////////////////////////////////////////////////////// + +// font 0-9, 24x20 pixels, 1 byte = 4 dots +// 00 = black +// 01 = white +// 10 = red +// 11 = transparent + +unsigned char cFont[10][120] = { +// 0 + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x05, 0x54, 0x00, 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, + 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, 0x00, 0x80, 0x00, 0x14, + 0x05, 0x00, 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, 0x00, 0x80, + 0x00, 0x14, 0x05, 0x00, 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, + 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, 0x00, 0x80, 0x00, 0x14, + 0x05, 0x00, 0x00, 0x80, 0x00, 0x05, 0x54, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, + // 1 + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x50, 0x00, 0x00, 0x80, 0x00, 0x05, 0x50, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x50, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x80, 0x00, 0x00, 0x50, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x50, 0x00, 0x00, 0x80, 0x00, 0x00, 0x50, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x50, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x80, 0x00, 0x05, 0x55, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, + // 2 + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x05, 0x54, 0x00, 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x50, 0x00, 0x00, 0x80, 0x00, 0x01, 0x40, 0x00, + 0x00, 0x80, 0x00, 0x05, 0x00, 0x00, 0x00, 0x80, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x15, 0x55, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, + // 3 + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x05, 0x54, 0x00, 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x80, 0x00, 0x01, 0x54, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x05, 0x00, 0x00, 0x80, 0x00, 0x00, 0x05, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x80, 0x00, 0x14, + 0x05, 0x00, 0x00, 0x80, 0x00, 0x05, 0x54, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, + // 4 + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x14, 0x00, 0x00, 0x80, 0x00, 0x00, 0x54, 0x00, + 0x00, 0x80, 0x00, 0x01, 0x54, 0x00, 0x00, 0x80, 0x00, 0x01, + 0x54, 0x00, 0x00, 0x80, 0x00, 0x05, 0x14, 0x00, 0x00, 0x80, + 0x00, 0x14, 0x14, 0x00, 0x00, 0x80, 0x00, 0x15, 0x55, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, + // 5 + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x15, 0x55, 0x00, 0x00, 0x80, 0x00, 0x14, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x14, 0x00, 0x00, 0x00, 0x80, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x15, 0x54, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x05, 0x00, 0x00, 0x80, 0x00, 0x00, 0x05, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x80, 0x00, 0x14, + 0x05, 0x00, 0x00, 0x80, 0x00, 0x05, 0x54, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, + // 6 + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x01, 0x54, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x14, 0x00, 0x00, 0x00, 0x80, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x15, 0x54, 0x00, 0x00, 0x80, + 0x00, 0x15, 0x05, 0x00, 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, + 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, 0x00, 0x80, 0x00, 0x14, + 0x05, 0x00, 0x00, 0x80, 0x00, 0x05, 0x54, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, + // 7 + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x15, 0x55, 0x00, 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x80, 0x00, 0x00, 0x50, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x50, 0x00, 0x00, 0x80, 0x00, 0x01, 0x40, 0x00, + 0x00, 0x80, 0x00, 0x01, 0x40, 0x00, 0x00, 0x80, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, + // 8 + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x05, 0x54, 0x00, 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, + 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, 0x00, 0x80, 0x00, 0x14, + 0x05, 0x00, 0x00, 0x80, 0x00, 0x05, 0x54, 0x00, 0x00, 0x80, + 0x00, 0x14, 0x05, 0x00, 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, + 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, 0x00, 0x80, 0x00, 0x14, + 0x05, 0x00, 0x00, 0x80, 0x00, 0x05, 0x54, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, + // 9 + { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x05, 0x54, 0x00, 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, + 0x00, 0x80, 0x00, 0x14, 0x05, 0x00, 0x00, 0x80, 0x00, 0x14, + 0x05, 0x00, 0x00, 0x80, 0x00, 0x14, 0x15, 0x00, 0x00, 0x80, + 0x00, 0x05, 0x55, 0x00, 0x00, 0x80, 0x00, 0x00, 0x05, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x80, 0x00, 0x05, 0x50, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa } }; + +//////////////////////////////////////////////////////////////////////// + +void PaintPicDot(unsigned char * p, unsigned char c) { + + if (c == 0) { + *p++ = 0x00; + *p++ = 0x00; + *p = 0x00; + return; + } // black + if (c == 1) { + *p++ = 0xff; + *p++ = 0xff; + *p = 0xff; + return; + } // white + if (c == 2) { + *p++ = 0x00; + *p++ = 0x00; + *p = 0xff; + return; + } // red + // transparent +} + +//////////////////////////////////////////////////////////////////////// +// the main emu allocs 128x96x3 bytes, and passes a ptr +// to it in pMem... the plugin has to fill it with +// 8-8-8 bit BGR screen data (Win 24 bit BMP format +// without header). +// Beware: the func can be called at any time, +// so you have to use the frontbuffer to get a fully +// rendered picture +// LINUX version: + +//extern char * Xpixels; + +void GPUgetScreenPic(unsigned char * pMem) { + /* + unsigned short c;unsigned char * pf;int x,y; + + float XS=(float)iResX/128; + float YS=(float)iResY/96; + + pf=pMem; + memset(pMem, 0, 128*96*3); + + if(Xpixels) + { + unsigned char * ps=(unsigned char *)Xpixels; + { + long lPitch=iResX<<2; + uint32_t sx; + + for(y=0;y<96;y++) + { + for(x=0;x<128;x++) + { + sx=*((uint32_t *)((ps)+ + (((int)((float)y*YS))*lPitch)+ + ((int)((float)x*XS))*4)); + *(pf+0)=(sx&0xff); + *(pf+1)=(sx&0xff00)>>8; + *(pf+2)=(sx&0xff0000)>>16; + pf+=3; + } + } + } + } + + + ///////////////////////////////////////////////////////////////////// + // generic number/border painter + + pf=pMem+(103*3); // offset to number rect + + for(y=0;y<20;y++) // loop the number rect pixel + { + for(x=0;x<6;x++) + { + c=cFont[lSelectedSlot][x+y*6]; // get 4 char dot infos at once (number depends on selected slot) + PaintPicDot(pf,(c&0xc0)>>6);pf+=3; // paint the dots into the rect + PaintPicDot(pf,(c&0x30)>>4);pf+=3; + PaintPicDot(pf,(c&0x0c)>>2);pf+=3; + PaintPicDot(pf,(c&0x03)); pf+=3; + } + pf+=104*3; // next rect y line + } + + pf=pMem; // ptr to first pos in 128x96 pic + for(x=0;x<128;x++) // loop top/bottom line + { + *(pf+(95*128*3))=0x00;*pf++=0x00; + *(pf+(95*128*3))=0x00;*pf++=0x00; // paint it red + *(pf+(95*128*3))=0xff;*pf++=0xff; + } + pf=pMem; // ptr to first pos + for(y=0;y<96;y++) // loop left/right line + { + *(pf+(127*3))=0x00;*pf++=0x00; + *(pf+(127*3))=0x00;*pf++=0x00; // paint it red + *(pf+(127*3))=0xff;*pf++=0xff; + pf+=127*3; // offset to next line + } + */ +} + +//////////////////////////////////////////////////////////////////////// +// func will be called with 128x96x3 BGR data. +// the plugin has to store the data and display +// it in the upper right corner. +// If the func is called with a NULL ptr, you can +// release your picture data and stop displaying +// the screen pic + +void CALLBACK GPUshowScreenPic(unsigned char * pMem) { + DestroyPic(); // destroy old pic data + if (pMem == 0) + return; // done + CreatePic(pMem); // create new pic... don't free pMem or something like that... just read from it +} + +void CALLBACK GPUsetfix(uint32_t dwFixBits) { + g_prim.dwEmuFixes = dwFixBits; +} + +void CALLBACK GPUvBlank(int val) { + //fprintf(stderr, "Vblanc %d\n", val); + //if(val) + // g_gpu.status_reg |= STATUS_ODDLINES; + //else + // g_gpu.status_reg &= ~STATUS_ODDLINES; +} diff --git a/plugins/gxvideo/gpu.h b/plugins/gxvideo/gpu.h new file mode 100644 index 00000000..cca177e2 --- /dev/null +++ b/plugins/gxvideo/gpu.h @@ -0,0 +1,116 @@ +/*************************************************************************** + gpu.h - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#ifndef _GPU_INTERNALS_H +#define _GPU_INTERNALS_H + +#include <gpu_utils.h> + +#define OPAQUEON 10 +#define OPAQUEOFF 11 + +#define KEY_RESETTEXSTORE 1 +#define KEY_SHOWFPS 2 +#define KEY_RESETOPAQUE 4 +#define KEY_RESETDITHER 8 +#define KEY_RESETFILTER 16 +#define KEY_RESETADVBLEND 32 +//#define KEY_BLACKWHITE 64 +#define KEY_BADTEXTURES 128 +#define KEY_CHECKTHISOUT 256 + +#if !defined(__BIG_ENDIAN__) || defined(__x86_64__) || defined(__i386__) +#ifndef __LITTLE_ENDIAN__ +#define __LITTLE_ENDIAN__ +#endif +#endif + +#define RED(x) (x & 0xff) +#define BLUE(x) ((x>>16) & 0xff) +#define GREEN(x) ((x>>8) & 0xff) +#define COLOR(x) (x & 0xffffff) + + +#define INFO_TW 0 +#define INFO_DRAWSTART 1 +#define INFO_DRAWEND 2 +#define INFO_DRAWOFF 3 + +#define SHADETEXBIT(x) ((x>>24) & 0x1) +#define SEMITRANSBIT(x) ((x>>25) & 0x1) +#define PSXRGB(r,g,b) ((g<<10)|(b<<5)|r) + +#define DATAREGISTERMODES unsigned short + +#define DR_NORMAL 0 +#define DR_VRAMTRANSFER 1 + +#define STATUS_ODDLINES 0x80000000 +#define STATUS_DMABITS 0x60000000 // Two bits +#define STATUS_READYFORCOMMANDS 0x10000000 +#define STATUS_READYFORVRAM 0x08000000 +#define STATUS_IDLE 0x04000000 +#define STATUS_DISPLAYDISABLED 0x00800000 +#define STATUS_INTERLACED 0x00400000 +#define STATUS_RGB24 0x00200000 +#define STATUS_PAL 0x00100000 +#define STATUS_DOUBLEHEIGHT 0x00080000 +#define STATUS_WIDTHBITS 0x00070000 // Three bits +#define STATUS_MASKENABLED 0x00001000 +#define STATUS_MASKDRAWN 0x00000800 +#define STATUS_DRAWINGALLOWED 0x00000400 +#define STATUS_DITHER 0x00000200 + +typedef struct { + short x; + short y; + short Width; + short Height; + short RowsRemaining; + short ColsRemaining; + unsigned short *ImagePtr; +} gxv_vram_load_t; + +typedef struct { + gxv_vram_load_t VRAMWrite; + gxv_vram_load_t VRAMRead; + uint16_t DataWriteMode; + uint16_t DataReadMode; + int iColDepth; + int iWindowMode; + int bDebugText; + + gxv_display_t dsp; + uint32_t status_reg; + long lGPUdataRet; + + gxv_pointer_t psxVSecure; + gxv_pointer_t psx_vram; + gxv_pointer_t psxVuw_eom; + uint32_t lGPUInfoVals[16]; + uint32_t ulStatusControl[256]; + + uint32_t gpuDataM[256]; + unsigned char gpuCommand; + long gpuDataC; + long gpuDataP; + + int fps; + +} gxv_gpu_t; + +#endif // _GPU_INTERNALS_H diff --git a/plugins/gxvideo/gpu_utils.h b/plugins/gxvideo/gpu_utils.h new file mode 100644 index 00000000..471cc9a5 --- /dev/null +++ b/plugins/gxvideo/gpu_utils.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010 Benoit Gschwind + * Inspired by original author : Pete Bernert + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef GPU_UTILS_H_ +#define GPU_UTILS_H_ + +#include <stdint.h> + +typedef struct { + uint16_t rgb16; +} __attribute__((__packed__)) gxv_rgb16; + +typedef struct { + uint8_t r; + uint8_t g; + uint8_t b; +} __attribute__((__packed__)) gxv_rgb24; + +/* for fast recast ^^ */ +typedef union { + uint8_t * u8; + int8_t * s8; + uint16_t * u16; + int16_t * s16; + uint32_t * u32; + int32_t * s32; + gxv_rgb16 * rgb16; + gxv_rgb24 * rgb24; +} gxv_pointer_t; + +typedef struct { + int32_t x; + int32_t y; +} gxv_point_t; + +typedef struct { + int16_t x; + int16_t y; +} gxv_spoint_t; + +typedef struct { + int16_t x0; + int16_t x1; + int16_t y0; + int16_t y1; +} gxv_rect_t; + +typedef struct { + gxv_point_t position; + gxv_point_t mode; + gxv_point_t DrawOffset; + gxv_rect_t range; +} gxv_display_t; + +typedef struct { + gxv_rect_t Position; +} gxv_win_t; + +#endif /* GPU_UTILS_H_ */ diff --git a/plugins/gxvideo/gpucfg/gxvideo.glade b/plugins/gxvideo/gpucfg/gxvideo.glade new file mode 100644 index 00000000..04bebb39 --- /dev/null +++ b/plugins/gxvideo/gpucfg/gxvideo.glade @@ -0,0 +1,542 @@ +<?xml version="1.0"?> +<interface> + <requires lib="gtk+" version="2.16"/> + <!-- interface-naming-policy project-wide --> + <object class="GtkListStore" id="resolution_liststore"> + <columns> + <!-- column-name gchararray1 --> + <column type="gchararray"/> + </columns> + <data> + <row> + <col id="0" translatable="yes">320x240</col> + </row> + <row> + <col id="0" translatable="yes">640x480</col> + </row> + <row> + <col id="0" translatable="yes">800x600</col> + </row> + <row> + <col id="0" translatable="yes">1024x768</col> + </row> + <row> + <col id="0" translatable="yes">1152x864</col> + </row> + <row> + <col id="0" translatable="yes">1280x960</col> + </row> + <row> + <col id="0" translatable="yes">1600x1200</col> + </row> + </data> + </object> + <object class="GtkDialog" id="config_window"> + <property name="border_width">5</property> + <property name="title" translatable="yes">Configure GXVideo plugin</property> + <property name="window_position">center</property> + <property name="type_hint">normal</property> + <child internal-child="vbox"> + <object class="GtkVBox" id="dialog-vbox1"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> + <child> + <object class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> + <child> + <object class="GtkFrame" id="frame1"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <child> + <object class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <object class="GtkVBox" id="vbox2"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkTable" id="table1"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">3</property> + <property name="column_spacing">2</property> + <property name="row_spacing">2</property> + <child> + <object class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Initial Window Size: </property> + </object> + <packing> + <property name="x_options">GTK_FILL</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Dithering: </property> + </object> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="dithering_combobox"> + <property name="visible">True</property> + <property name="model">dithering_liststore</property> + <child> + <object class="GtkCellRendererText" id="cellrenderertext1"/> + <attributes> + <attribute name="text">0</attribute> + </attributes> + </child> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">3</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="fullscreen_checkbutton"> + <property name="label" translatable="yes">Fullscreen</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="x_options">GTK_FILL</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="resolution_combobox"> + <property name="visible">True</property> + <property name="model">resolution_liststore</property> + <property name="active">3</property> + <child> + <object class="GtkCellRendererText" id="cellrenderertext2"/> + <attributes> + <attribute name="text">0</attribute> + </attributes> + </child> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + </packing> + </child> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="maintain_ratio_checkbutton"> + <property name="label" translatable="yes">Maintain original aspect ratio</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Screen</b></property> + <property name="use_markup">True</property> + </object> + </child> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkFrame" id="frame2"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <child> + <object class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <object class="GtkVBox" id="vbox3"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">3</property> + <child> + <object class="GtkCheckButton" id="show_fps_checkbutton"> + <property name="label" translatable="yes">Show FPS</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox2"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <object class="GtkCheckButton" id="set_fps_checkbutton"> + <property name="label" translatable="yes">Framerate Limit: </property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="fps_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="max_length">7</property> + <property name="invisible_char">●</property> + <property name="width_chars">6</property> + <property name="text" translatable="yes">200.0</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="auto_fps_limit_checkbutton"> + <property name="label" translatable="yes">Auto detect framerate</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Framerate</b></property> + <property name="use_markup">True</property> + </object> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkFrame" id="frame3"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <child> + <object class="GtkAlignment" id="alignment3"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <object class="GtkVBox" id="vbox4"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkCheckButton" id="use_game_fixes_checkbutton"> + <property name="label" translatable="yes">Use game fixes</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment4"> + <property name="visible">True</property> + <property name="top_padding">2</property> + <property name="bottom_padding">2</property> + <property name="left_padding">16</property> + <property name="right_padding">2</property> + <child> + <object class="GtkTable" id="fixes_table"> + <property name="visible">True</property> + <property name="n_rows">6</property> + <property name="n_columns">2</property> + <property name="column_spacing">2</property> + <property name="row_spacing">2</property> + <child> + <object class="GtkCheckButton" id="fix0_checkbutton"> + <property name="label" translatable="yes">Odd/even bit hack</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + </child> + <child> + <object class="GtkCheckButton" id="fix1_checkbutton"> + <property name="label" translatable="yes">Expand screen width</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="fix2_checkbutton"> + <property name="label" translatable="yes">Ignore brightness color</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="fix3_checkbutton"> + <property name="label" translatable="yes">Disable coordinate check</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="fix4_checkbutton"> + <property name="label" translatable="yes">Disable CPU Saving</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="fix5_checkbutton"> + <property name="label" translatable="yes">PC FPS calculation</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="fix6_checkbutton"> + <property name="label" translatable="yes">Lazy screen update</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="fix7_checkbutton"> + <property name="label" translatable="yes">Old frame skipping</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="fix8_checkbutton"> + <property name="label" translatable="yes">Repeated flat tex triangles</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="fix9_checkbutton"> + <property name="label" translatable="yes">Draw quads with triangles</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="fix10_checkbutton"> + <property name="label" translatable="yes">Fake 'gpu busy' states</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </object> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Compatibility</b></property> + <property name="use_markup">True</property> + </object> + </child> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child internal-child="action_area"> + <object class="GtkHButtonBox" id="dialog-action_area1"> + <property name="visible">True</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="cancel_button"> + <property name="label" translatable="yes">Cancel</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="save_button"> + <property name="label" translatable="yes">Save</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="0">cancel_button</action-widget> + <action-widget response="0">save_button</action-widget> + </action-widgets> + </object> + <object class="GtkListStore" id="dithering_liststore"> + <columns> + <!-- column-name gchararray1 --> + <column type="gchararray"/> + </columns> + <data> + <row> + <col id="0" translatable="yes">Off (fastest)</col> + </row> + <row> + <col id="0" translatable="yes">Game dependant</col> + </row> + <row> + <col id="0" translatable="yes">Always</col> + </row> + </data> + </object> +</interface> diff --git a/plugins/gxvideo/gpucfg/main.c b/plugins/gxvideo/gpucfg/main.c new file mode 100644 index 00000000..844d6ec5 --- /dev/null +++ b/plugins/gxvideo/gpucfg/main.c @@ -0,0 +1,367 @@ +/* + * Copyright (C) 2010 Benoit Gschwind + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <gtk/gtk.h> +#include <glade/glade.h> + +#include "globals.h" +#include "config.h" + +#ifdef ENABLE_NLS +#include <libintl.h> +#include <locale.h> +#endif + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> + +#define READBINARY "rb" +#define WRITEBINARY "wb" +#define CONFIG_FILENAME "dfxvideo.cfg" + +enum { + VIDMODE_320x200 = 0, + VIDMODE_640x480, + VIDMODE_800x600, + VIDMODE_1024x768, + VIDMODE_1152x864, + VIDMODE_1280x960, + VIDMODE_1600x1200 +}; /* Video_modes */ + +typedef struct { + GtkWidget * config_window; + GtkWidget * resolution_combobox; + GtkWidget * dithering_combobox; + GtkWidget * maintain_ratio_checkbutton; + GtkWidget * fullscreen_checkbutton; + GtkWidget * show_fps_checkbutton; + GtkWidget * set_fps_checkbutton; + GtkWidget * auto_fps_limit_checkbutton; + GtkWidget * fps_entry; + GtkWidget * use_game_fixes_checkbutton; + GtkWidget * save_button; + GtkWidget * cancel_button; + GtkWidget * fixes_table; + GtkWidget * fix_checkbutton[11]; +} cfg_window_t; + +void save_config(cfg_window_t *); + +/* This function checks for the value being outside the accepted range, + and returns the appropriate boundary value */ +int set_limit(char *p, int len, int lower, int upper) { + int val = 0; + + if (p) + val = atoi(p + len); + /* printf("Checking for val %d greater than %d and lower than %d, ", val, lower, upper);*/ + if (val < lower) + val = lower; + if (val > upper) + val = upper; + /* printf ("val is now %d\n", val);*/ + return val; +} + +void on_about_clicked(GtkWidget * widget, gpointer user_data) { + gtk_widget_destroy(widget); + exit(0); +} + +void set_widget_sensitive(GtkWidget * widget, gboolean * state) { + gtk_widget_set_sensitive(widget, *state); +} + +void on_fullscreen_toggled(GtkWidget * widget, cfg_window_t * w) { + gtk_widget_set_sensitive(w->resolution_combobox, + !gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON(w->fullscreen_checkbutton))); +} + +void update_fixes_stase(GtkWidget * ths, GtkWidget * w) { + gtk_widget_set_sensitive(ths, gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON(w))); +} + +void on_use_fixes_toggled(GtkWidget * widget, cfg_window_t * w) { + /* Set the state of each of the fixes to the value of the use fixes toggle */ + gtk_container_foreach(GTK_CONTAINER (w->fixes_table), + (GtkCallback) update_fixes_stase, w->use_game_fixes_checkbutton); +} + +void on_fps_toggled(GtkWidget * widget, cfg_window_t * w) { + gboolean state_set_fps = gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON(w->set_fps_checkbutton)); + gboolean state_auto_fps_limit = gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON(w->auto_fps_limit_checkbutton)); + gtk_widget_set_sensitive(w->fps_entry, state_set_fps + && !state_auto_fps_limit); + gtk_widget_set_sensitive(w->auto_fps_limit_checkbutton, state_set_fps); +} + +void on_destroy_window(GtkWidget * widget, cfg_window_t * w) { + free(w); +} + +void on_click_save_button(GtkWidget * widget, cfg_window_t * w) { + save_config(w); + gtk_widget_destroy(GTK_WIDGET(w->config_window)); + gtk_exit(0); +} + +void on_click_cancel_button(GtkWidget * widget, cfg_window_t * w) { + gtk_widget_destroy(GTK_WIDGET(w->config_window)); + gtk_exit(0); +} + +int main(int argc, char *argv[]) { + cfg_window_t * w = 0; + GtkWidget * widget; + GtkBuilder * builder; + int i, val; + char tempstr[50]; + +#ifdef ENABLE_NLS + setlocale(LC_ALL, ""); + bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + textdomain(GETTEXT_PACKAGE); +#endif + + if (argc != 2) { + printf("Usage: cfgGXVideo {ABOUT | CFG}\n"); + return 0; + } + if (strcmp(argv[1], "CFG") != 0 && strcmp(argv[1], "ABOUT") != 0) { + printf("Usage: cfgGXVideo {ABOUT | CFG}\n"); + return 0; + } + + gtk_set_locale(); + gtk_init(&argc, &argv); + + if (strcmp(argv[1], "ABOUT") == 0) { + const char *authors[] = { "Pete Bernert and the P.E.Op.S. team", + "Ryan Schultz", "Andrew Burton", NULL }; + widget = gtk_about_dialog_new(); + gtk_about_dialog_set_name(GTK_ABOUT_DIALOG (widget), + "P.E.Op.S PCSX Video Plugin"); + gtk_about_dialog_set_version(GTK_ABOUT_DIALOG (widget), "1.17"); + gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG (widget), authors); + gtk_about_dialog_set_website(GTK_ABOUT_DIALOG (widget), + "http://pcsx-df.sourceforge.net/"); + + g_signal_connect_data(GTK_OBJECT(widget), "response", + GTK_SIGNAL_FUNC(on_about_clicked), NULL, NULL, G_CONNECT_AFTER); + + gtk_widget_show(widget); + gtk_main(); + + return 0; + } + + builder = gtk_builder_new(); + if (!builder) { + g_warning("We could not load the interface!"); + return -1; + } + + gtk_builder_add_from_file(builder, DATADIR "gxvideo.glade", NULL); + w = (cfg_window_t *) malloc(sizeof(cfg_window_t)); +#define CFG_GET_WIDGET(name) w->name = GTK_WIDGET(gtk_builder_get_object(builder, #name)) + CFG_GET_WIDGET(config_window); + CFG_GET_WIDGET(config_window); + CFG_GET_WIDGET(resolution_combobox); + CFG_GET_WIDGET(dithering_combobox); + CFG_GET_WIDGET(maintain_ratio_checkbutton); + CFG_GET_WIDGET(fullscreen_checkbutton); + CFG_GET_WIDGET(show_fps_checkbutton); + CFG_GET_WIDGET(set_fps_checkbutton); + CFG_GET_WIDGET(auto_fps_limit_checkbutton); + CFG_GET_WIDGET(fps_entry); + CFG_GET_WIDGET(use_game_fixes_checkbutton); + CFG_GET_WIDGET(save_button); + CFG_GET_WIDGET(cancel_button); + CFG_GET_WIDGET(fixes_table); + + for (i = 0; i < 11; ++i) { + sprintf(tempstr, "fix%d_checkbutton", i); + w->fix_checkbutton[i] + = GTK_WIDGET(gtk_builder_get_object(builder, tempstr)); + } + + ReadConfig(); + + switch (g_cfg.ResX) { + case 1600: + val = VIDMODE_1600x1200; + break; + case 1280: + val = VIDMODE_1280x960; + break; + case 1152: + val = VIDMODE_1152x864; + break; + case 1024: + val = VIDMODE_1024x768; + break; + case 800: + val = VIDMODE_800x600; + break; + case 640: + val = VIDMODE_640x480; + break; + default: + val = VIDMODE_320x200; + } + + gtk_combo_box_set_active(GTK_COMBO_BOX (w->resolution_combobox), val); + gtk_combo_box_set_active(GTK_COMBO_BOX (w->dithering_combobox), + g_cfg.Dithering); + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON (w->maintain_ratio_checkbutton), g_cfg.Maintain43); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (w->fullscreen_checkbutton), + g_cfg.FullScreen); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (w->show_fps_checkbutton), + g_cfg.ShowFPS); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (w->set_fps_checkbutton), + g_cfg.UseFrameLimit); + + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON (w->auto_fps_limit_checkbutton), + g_cfg.FPSDetection); + + sprintf(tempstr, "%.1f", g_cfg.FrameRate); + gtk_entry_set_text(GTK_ENTRY(w->fps_entry), tempstr); + + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON (w->use_game_fixes_checkbutton), g_cfg.UseFixes); + + for (i = 0; i < 11; ++i) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (w->fix_checkbutton[i]), + (g_cfg.CfgFixes >> i) & 1); + } + + g_signal_connect_data(GTK_OBJECT(w->config_window), "destroy", + GTK_SIGNAL_FUNC(on_destroy_window), w, NULL, 0); + g_signal_connect_data(GTK_OBJECT(w->save_button), "clicked", + GTK_SIGNAL_FUNC(on_click_save_button), w, NULL, G_CONNECT_AFTER); + g_signal_connect_data(GTK_OBJECT(w->cancel_button), "clicked", + GTK_SIGNAL_FUNC(on_click_cancel_button), w, NULL, G_CONNECT_AFTER); + + g_signal_connect_data(GTK_OBJECT(w->fullscreen_checkbutton), "clicked", + GTK_SIGNAL_FUNC(on_fullscreen_toggled), w, NULL, G_CONNECT_AFTER); + + g_signal_connect_data(GTK_OBJECT(w->use_game_fixes_checkbutton), "clicked", + GTK_SIGNAL_FUNC(on_use_fixes_toggled), w, NULL, G_CONNECT_AFTER); + g_signal_connect_data(GTK_OBJECT(w->set_fps_checkbutton), "clicked", + GTK_SIGNAL_FUNC(on_fps_toggled), w, NULL, G_CONNECT_AFTER); + + g_signal_connect_data(GTK_OBJECT(w->auto_fps_limit_checkbutton), "clicked", + GTK_SIGNAL_FUNC(on_fps_toggled), w, NULL, G_CONNECT_AFTER); + + on_fullscreen_toggled(0, w); + on_fps_toggled(0, w); + on_use_fixes_toggled(0, w); + + gtk_widget_show_all(w->config_window); + gtk_main(); + return 0; +} + +void save_config(cfg_window_t * w) { + int val; + + val = gtk_combo_box_get_active(GTK_COMBO_BOX (w->resolution_combobox)); + + if (val == VIDMODE_320x200) { + g_cfg.ResX = 320; + g_cfg.ResY = 240; + } else if (val == VIDMODE_640x480) { + g_cfg.ResX = 640; + g_cfg.ResY = 480; + } else if (val == VIDMODE_800x600) { + g_cfg.ResX = 800; + g_cfg.ResY = 600; + } else if (val == VIDMODE_1024x768) { + g_cfg.ResX = 1024; + g_cfg.ResY = 768; + } else if (val == VIDMODE_1152x864) { + g_cfg.ResX = 1152; + g_cfg.ResY = 864; + } else if (val == VIDMODE_1280x960) { + g_cfg.ResX = 1280; + g_cfg.ResY = 960; + } else if (val == VIDMODE_1600x1200) { + g_cfg.ResX = 1600; + g_cfg.ResY = 1200; + } + + val = gtk_combo_box_get_active(GTK_COMBO_BOX (w->dithering_combobox)); + g_cfg.Dithering = val; + + val = gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON (w->maintain_ratio_checkbutton)); + g_cfg.Maintain43 = val; + + val = gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON (w->fullscreen_checkbutton)); + g_cfg.FullScreen = val; + + val = gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON(w->show_fps_checkbutton)); + g_cfg.ShowFPS = val; + + val = gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON (w->set_fps_checkbutton)); + g_cfg.UseFrameLimit = val; + + val = gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON (w->auto_fps_limit_checkbutton)); + g_cfg.FPSDetection = val; + + //Framerate stored *10 + val = atof(gtk_entry_get_text(GTK_ENTRY(w->fps_entry))) * 10; + g_cfg.FrameRate = val; + + val = gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON (w->use_game_fixes_checkbutton)); + g_cfg.UseFixes = val; + + val = 0; + int i; + for (i = 0; i < 11; ++i) { + if (gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON (w->fix_checkbutton[i]))) + val |= 1 << i; + } + g_cfg.CfgFixes = val; + + WriteConfig(); + free(w); + // Close the window and exit control from the plugin + gtk_exit(0); +} diff --git a/plugins/gxvideo/i386.asm b/plugins/gxvideo/i386.asm new file mode 100644 index 00000000..86d6e231 --- /dev/null +++ b/plugins/gxvideo/i386.asm @@ -0,0 +1,67 @@ +; i386.asm - description +; ------------------- +; begin : Sun Nov 08 2001 +; copyright : (C) 2001 by Pete Bernert +; email : BlackDove@addcom.de + +; ported from inline gcc to nasm by linuzappz + + +; This program is free software; you can redistribute it and/or modify * +; it under the terms of the GNU General Public License as published by * +; the Free Software Foundation; either version 2 of the License, or * +; (at your option) any later version. See also the license.txt file for * +; additional informations. * + + +bits 32 + +section .text + +%include "macros.inc" + +NEWSYM i386_BGR24to16 + push ebp + mov ebp, esp + push ebx + push edx + + mov eax, [ebp+8] ; this can hold the G value + mov ebx, eax ; this can hold the R value + mov edx, eax ; this can hold the B value + shr ebx, 3 ; move the R value + and edx, 00f80000h ; mask the B value + shr edx, 9 ; move the B value + and eax, 00f800h ; mask the G value + shr eax, 6 ; move the G value + and ebx, 0000001fh ; mask the R value + or eax, ebx ; add R to G value + or eax, edx ; add B to RG value + pop edx + pop ebx + mov esp, ebp + pop ebp + ret + +NEWSYM i386_shl10idiv + push ebp + mov ebp, esp + push ebx + push edx + + mov eax, [ebp+8] + mov ebx, [ebp+12] + mov edx, eax + shl eax, 10 + sar edx, 22 + idiv ebx + + pop edx + pop ebx + mov esp, ebp + pop ebp + ret +%ifidn __OUTPUT_FORMAT__,elf +section .note.GNU-stack noalloc noexec nowrite progbits +%endif + diff --git a/plugins/gxvideo/interp.h b/plugins/gxvideo/interp.h new file mode 100644 index 00000000..0e72983c --- /dev/null +++ b/plugins/gxvideo/interp.h @@ -0,0 +1,294 @@ +/* + * This file is part of the Advance project. + * + * Copyright (C) 2003 Andrea Mazzoleni + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * In addition, as a special exception, Andrea Mazzoleni + * gives permission to link the code of this program with + * the MAME library (or with modified versions of MAME that use the + * same license as MAME), and distribute linked combinations including + * the two. You must obey the GNU General Public License in all + * respects for all of the code used other than MAME. If you modify + * this file, you may extend this exception to your version of the + * file, but you are not obligated to do so. If you do not wish to + * do so, delete this exception statement from your version. + */ + +#ifndef __INTERP_H +#define __INTERP_H + +/***************************************************************************/ +/* Basic types */ + +/***************************************************************************/ +/* interpolation */ + +static unsigned interp_mask[2]; +static unsigned interp_bits_per_pixel; + +#define INTERP_16_MASK_1(v) (v & interp_mask[0]) +#define INTERP_16_MASK_2(v) (v & interp_mask[1]) + +static __inline unsigned short interp_16_521(unsigned short p1, unsigned short p2, unsigned short p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*2 + INTERP_16_MASK_1(p3)*1) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*2 + INTERP_16_MASK_2(p3)*1) / 8); +} + +static __inline unsigned short interp_16_332(unsigned short p1, unsigned short p2, unsigned short p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)*2) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)*2) / 8); +} + +static __inline unsigned short interp_16_611(unsigned short p1, unsigned short p2, unsigned short p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*6 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*6 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 8); +} + +static __inline unsigned short interp_16_71(unsigned short p1, unsigned short p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*7 + INTERP_16_MASK_1(p2)) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*7 + INTERP_16_MASK_2(p2)) / 8); +} + +static __inline unsigned short interp_16_211(unsigned short p1, unsigned short p2, unsigned short p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*2 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 4) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*2 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 4); +} + +static __inline unsigned short interp_16_772(unsigned short p1, unsigned short p2, unsigned short p3) +{ + return INTERP_16_MASK_1(((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2))*7 + INTERP_16_MASK_1(p3)*2) / 16) + | INTERP_16_MASK_2(((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2))*7 + INTERP_16_MASK_2(p3)*2) / 16); +} + +static __inline unsigned short interp_16_11(unsigned short p1, unsigned short p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2)) / 2) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2)) / 2); +} + +static __inline unsigned short interp_16_31(unsigned short p1, unsigned short p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)) / 4) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)) / 4); +} + +static __inline unsigned short interp_16_1411(unsigned short p1, unsigned short p2, unsigned short p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*14 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 16) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*14 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 16); +} + +static __inline unsigned short interp_16_431(unsigned short p1, unsigned short p2, unsigned short p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*4 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*4 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)) / 8); +} + +static __inline unsigned short interp_16_53(unsigned short p1, unsigned short p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*3) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*3) / 8); +} + +static __inline unsigned short interp_16_151(unsigned short p1, unsigned short p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*15 + INTERP_16_MASK_1(p2)) / 16) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*15 + INTERP_16_MASK_2(p2)) / 16); +} + +static __inline unsigned short interp_16_97(unsigned short p1, unsigned short p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*9 + INTERP_16_MASK_1(p2)*7) / 16) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*9 + INTERP_16_MASK_2(p2)*7) / 16); +} + +#define INTERP_32_MASK_1(v) (v & 0xFF00FF) +#define INTERP_32_MASK_2(v) (v & 0x00FF00) + +static __inline unsigned int interp_32_521(unsigned int p1, unsigned int p2, unsigned int p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*2 + INTERP_32_MASK_1(p3)*1) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*2 + INTERP_32_MASK_2(p3)*1) / 8); +} + +static __inline unsigned int interp_32_332(unsigned int p1, unsigned int p2, unsigned int p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)*2) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)*2) / 8); +} + +static __inline unsigned int interp_32_211(unsigned int p1, unsigned int p2, unsigned int p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*2 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 4) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*2 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 4); +} + +static __inline unsigned int interp_32_611(unsigned int p1, unsigned int p2, unsigned int p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*6 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*6 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 8); +} + +static __inline unsigned int interp_32_71(unsigned int p1, unsigned int p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*7 + INTERP_32_MASK_1(p2)) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*7 + INTERP_32_MASK_2(p2)) / 8); +} + +static __inline unsigned int interp_32_772(unsigned int p1, unsigned int p2, unsigned int p3) +{ + return INTERP_32_MASK_1(((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2))*7 + INTERP_32_MASK_1(p3)*2) / 16) + | INTERP_32_MASK_2(((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2))*7 + INTERP_32_MASK_2(p3)*2) / 16); +} + +static __inline unsigned int interp_32_11(unsigned int p1, unsigned int p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2)) / 2) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2)) / 2); +} + +static __inline unsigned int interp_32_31(unsigned int p1, unsigned int p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)) / 4) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)) / 4); +} + +static __inline unsigned int interp_32_1411(unsigned int p1, unsigned int p2, unsigned int p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*14 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 16) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*14 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 16); +} + +static __inline unsigned int interp_32_431(unsigned int p1, unsigned int p2, unsigned int p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*4 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*4 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)) / 8); +} + +static __inline unsigned int interp_32_53(unsigned int p1, unsigned int p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*3) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*3) / 8); +} + +static __inline unsigned int interp_32_151(unsigned int p1, unsigned int p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*15 + INTERP_32_MASK_1(p2)) / 16) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*15 + INTERP_32_MASK_2(p2)) / 16); +} + +static __inline unsigned int interp_32_97(unsigned int p1, unsigned int p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*9 + INTERP_32_MASK_1(p2)*7) / 16) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*9 + INTERP_32_MASK_2(p2)*7) / 16); +} + +/***************************************************************************/ +/* diff */ + +#define INTERP_Y_LIMIT (0x30*4) +#define INTERP_U_LIMIT (0x07*4) +#define INTERP_V_LIMIT (0x06*8) + +__inline static int interp_16_diff(unsigned short p1, unsigned short p2) +{ + int r, g, b; + int y, u, v; + + if (p1 == p2) + return 0; + + if (interp_bits_per_pixel == 16) { + b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3; + g = (int)((p1 & 0x7E0) - (p2 & 0x7E0)) >> 3; + r = (int)((p1 & 0xF800) - (p2 & 0xF800)) >> 8; + } else { + b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3; + g = (int)((p1 & 0x3E0) - (p2 & 0x3E0)) >> 2; + r = (int)((p1 & 0x7C00) - (p2 & 0x7C00)) >> 7; + } + + y = r + g + b; + u = r - b; + v = -r + 2*g - b; + + if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) + return 1; + + if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) + return 1; + + if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) + return 1; + + return 0; +} + +__inline static int interp_32_diff(unsigned int p1, unsigned int p2) +{ + int r, g, b; + int y, u, v; + + if ((p1 & 0xF8F8F8) == (p2 & 0xF8F8F8)) + return 0; + + b = (int)((p1 & 0xFF) - (p2 & 0xFF)); + g = (int)((p1 & 0xFF00) - (p2 & 0xFF00)) >> 8; + r = (int)((p1 & 0xFF0000) - (p2 & 0xFF0000)) >> 16; + + y = r + g + b; + u = r - b; + v = -r + 2*g - b; + + if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) + return 1; + + if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) + return 1; + + if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) + return 1; + + return 0; +} + +__inline static void interp_set(unsigned bits_per_pixel) +{ + interp_bits_per_pixel = bits_per_pixel; + + switch (bits_per_pixel) { + case 15 : + interp_mask[0] = 0x7C1F; + interp_mask[1] = 0x03E0; + break; + case 16 : + interp_mask[0] = 0xF81F; + interp_mask[1] = 0x07E0; + break; + case 32 : + interp_mask[0] = 0xFF00FF; + interp_mask[1] = 0x00FF00; + break; + } +} + +#endif diff --git a/plugins/gxvideo/key.c b/plugins/gxvideo/key.c new file mode 100644 index 00000000..2d56ae92 --- /dev/null +++ b/plugins/gxvideo/key.c @@ -0,0 +1,43 @@ +/*************************************************************************** + key.c - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "menu.h" +#include "gpu.h" +#include "draw.h" +#include "key.h" + +#define VK_INSERT 65379 +#define VK_HOME 65360 +#define VK_PRIOR 65365 +#define VK_NEXT 65366 +#define VK_END 65367 +#define VK_DEL 65535 +#define VK_F5 65474 + +void GPUmakeSnapshot(void); + +unsigned long ulKeybits = 0; + +void GPUkeypressed(int keycode) { + +} + +void SetKeyHandler(void) { +} + +void ReleaseKeyHandler(void) { +} diff --git a/plugins/gxvideo/key.h b/plugins/gxvideo/key.h new file mode 100644 index 00000000..5f85cb6f --- /dev/null +++ b/plugins/gxvideo/key.h @@ -0,0 +1,24 @@ +/*************************************************************************** + key.h - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#ifndef _KEY_INTERNALS_H +#define _KEY_INTERNALS_H + +void SetKeyHandler(void); +void ReleaseKeyHandler(void); + +#endif // _KEY_INTERNALS_H diff --git a/plugins/gxvideo/macros.inc b/plugins/gxvideo/macros.inc new file mode 100644 index 00000000..47829285 --- /dev/null +++ b/plugins/gxvideo/macros.inc @@ -0,0 +1,40 @@ +; macros.inc - description +; ------------------- +; begin : Sun Nov 08 2001 +; based on ZSNES macros.mac +; email : linuzappz@pcsx.net + +; This program is free software; you can redistribute it and/or modify * +; it under the terms of the GNU General Public License as published by * +; the Free Software Foundation; either version 2 of the License, or * +; (at your option) any later version. See also the license.txt file for * +; additional informations. * + + +%ifdef __WIN32__ + +%imacro EXTSYM 1-* +%rep %0 + extern _%1 + %define %1 _%1 +%rotate 1 +%endrep +%endmacro + +%imacro NEWSYM 1 + global _%1 + _%1: + %1: +%endmacro + +%else + +%define EXTSYM extern + +%imacro NEWSYM 1 + global %1 + %1: +%endmacro + +%endif + diff --git a/plugins/gxvideo/menu.c b/plugins/gxvideo/menu.c new file mode 100644 index 00000000..7a96cfc1 --- /dev/null +++ b/plugins/gxvideo/menu.c @@ -0,0 +1,57 @@ +/*************************************************************************** + menu.c - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "draw.h" +#include "menu.h" +#include "gpu.h"
+ +unsigned long dwCoreFlags = 0; + +// create lists/stuff for fonts (actually there are no more lists, but I am too lazy to change the func names ;) +void InitMenu(void) +{ +} + +// kill existing lists/fonts +void CloseMenu(void) +{
+ DestroyPic();
+} + +// DISPLAY FPS/MENU TEXT + +#include <time.h> +//extern time_t tStart; + +int iMPos=0; // menu arrow pos + +void DisplayText(void) // DISPLAY TEXT +{
+ +} + +// Build Menu buffer (== Dispbuffer without FPS)... +void BuildDispMenu(int iInc) +{ + +} + +// Some menu action... +void SwitchDispMenu(int iStep) // SWITCH DISP MENU +{ + // update info +} diff --git a/plugins/gxvideo/menu.h b/plugins/gxvideo/menu.h new file mode 100644 index 00000000..ac244180 --- /dev/null +++ b/plugins/gxvideo/menu.h @@ -0,0 +1,27 @@ +/*************************************************************************** + menu.h - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#ifndef _GPU_MENU_H_ +#define _GPU_MENU_H_ + +void DisplayText(void); +void CloseMenu(void); +void InitMenu(void); +void BuildDispMenu(int iInc); +void SwitchDispMenu(int iStep); + +#endif // _GPU_MENU_H_ diff --git a/plugins/gxvideo/prim.c b/plugins/gxvideo/prim.c new file mode 100644 index 00000000..de1bb9a2 --- /dev/null +++ b/plugins/gxvideo/prim.c @@ -0,0 +1,1615 @@ +/*************************************************************************** + prim.c - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ +#include <stdio.h> + +#include "globals.h" +#include "swap.h" + +#define INFO_TW 0 +#define INFO_DRAWSTART 1 +#define INFO_DRAWEND 2 +#define INFO_DRAWOFF 3 + +//////////////////////////////////////////////////////////////////////// +// globals +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// Some ASM color convertion by LEWPY +//////////////////////////////////////////////////////////////////////// + +#ifdef USE_NASM + +#define BGR24to16 i386_BGR24to16 +__inline unsigned short BGR24to16 (uint32_t BGR); + +#else + +inline unsigned short BGR24to16(uint32_t BGR) { + return (unsigned short) (((BGR >> 3) & 0x1f) | ((BGR & 0xf80000) >> 9) + | ((BGR & 0xf800) >> 6)); +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// Update global TP infos +//////////////////////////////////////////////////////////////////////// + +inline void UpdateGlobalTP(unsigned short gdata) { + g_soft.GlobalTextAddrX = (gdata << 6) & 0x3c0; // texture addr + + if (512 == 1024) { + if (1 == 2) { + g_soft.GlobalTextAddrY = ((gdata & 0x60) << 3); + //g_zn.GlobalTextIL = (gdata & 0x2000) >> 13; + g_soft.GlobalTextABR = (unsigned short) ((gdata >> 7) & 0x3); + g_soft.GlobalTextTP = (gdata >> 9) & 0x3; + if (g_soft.GlobalTextTP == 3) + g_soft.GlobalTextTP = 2; + g_prim.usMirror = 0; + g_gpu.status_reg = (g_gpu.status_reg & 0xffffe000) | (gdata + & 0x1fff); + + // tekken dithering? right now only if dithering is forced by user + if (g_cfg.Dithering == 2) + g_prim.iDither = 2; + else + g_prim.iDither = 0; + + return; + } else { + g_soft.GlobalTextAddrY = (unsigned short) (((gdata << 4) & 0x100) + | ((gdata >> 2) & 0x200)); + } + } else + g_soft.GlobalTextAddrY = (gdata << 4) & 0x100; + + g_soft.GlobalTextTP = (gdata >> 7) & 0x3; // tex mode (4,8,15) + + if (g_soft.GlobalTextTP == 3) + g_soft.GlobalTextTP = 2; // seen in Wild9 :( + + g_soft.GlobalTextABR = (gdata >> 5) & 0x3; // blend mode + + g_gpu.status_reg &= ~0x000001ff; // Clear the necessary bits + g_gpu.status_reg |= (gdata & 0x01ff); // set the necessary bits + + switch (g_cfg.Dithering) { + case 0: + g_prim.iDither = 0; + break; + case 1: + if (g_gpu.status_reg & 0x0200) + g_prim.iDither = 2; + else + g_prim.iDither = 0; + break; + case 2: + g_prim.iDither = 2; + break; + } +} + +//////////////////////////////////////////////////////////////////////// + +inline void SetRenderMode(uint32_t DrawAttributes) { + g_soft.DrawSemiTrans = (SEMITRANSBIT(DrawAttributes)) ? 1 : 0; + + if (SHADETEXBIT(DrawAttributes)) { + g_soft.g_m1 = g_soft.g_m2 = g_soft.g_m3 = 128; + } else { + if ((g_prim.dwActFixes & 4) && ((DrawAttributes & 0x00ffffff) == 0)) + DrawAttributes |= 0x007f7f7f; + + g_soft.g_m1 = (short) (DrawAttributes & 0xff); + g_soft.g_m2 = (short) ((DrawAttributes >> 8) & 0xff); + g_soft.g_m3 = (short) ((DrawAttributes >> 16) & 0xff); + } +} + +//////////////////////////////////////////////////////////////////////// + +// oki, here are the psx gpu coord rules: poly coords are +// 11 bit signed values (-1024...1023). If the x or y distance +// exceeds 1024, the polygon will not be drawn. +// Since quads are treated as two triangles by the real gpu, +// this 'discard rule' applies to each of the quad's triangle +// (so one triangle can be drawn, the other one discarded). +// Also, y drawing is wrapped at 512 one time, +// then it will get negative (and therefore not drawn). The +// 'CheckCoord' funcs are a simple (not comlete!) approach to +// do things right, I will add a better detection soon... the +// current approach will be easier to do in hw/accel plugins, imho + +// 11 bit signed +#define SIGNSHIFT 21 +#define CHKMAX_X 1024 +#define CHKMAX_Y 512 + +void AdjustCoord4() { + g_soft.lx0 = (short) (((int) g_soft.lx0 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.lx1 = (short) (((int) g_soft.lx1 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.lx2 = (short) (((int) g_soft.lx2 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.lx3 = (short) (((int) g_soft.lx3 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.ly0 = (short) (((int) g_soft.ly0 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.ly1 = (short) (((int) g_soft.ly1 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.ly2 = (short) (((int) g_soft.ly2 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.ly3 = (short) (((int) g_soft.ly3 << SIGNSHIFT) >> SIGNSHIFT); +} + +void AdjustCoord3() { + g_soft.lx0 = (short) (((int) g_soft.lx0 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.lx1 = (short) (((int) g_soft.lx1 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.lx2 = (short) (((int) g_soft.lx2 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.ly0 = (short) (((int) g_soft.ly0 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.ly1 = (short) (((int) g_soft.ly1 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.ly2 = (short) (((int) g_soft.ly2 << SIGNSHIFT) >> SIGNSHIFT); +} + +void AdjustCoord2() { + g_soft.lx0 = (short) (((int) g_soft.lx0 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.lx1 = (short) (((int) g_soft.lx1 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.ly0 = (short) (((int) g_soft.ly0 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.ly1 = (short) (((int) g_soft.ly1 << SIGNSHIFT) >> SIGNSHIFT); +} + +void AdjustCoord1() { + g_soft.lx0 = (short) (((int) g_soft.lx0 << SIGNSHIFT) >> SIGNSHIFT); + g_soft.ly0 = (short) (((int) g_soft.ly0 << SIGNSHIFT) >> SIGNSHIFT); + + if (g_soft.lx0 < -512 && g_gpu.dsp.DrawOffset.x <= -512) + g_soft.lx0 += 2048; + + if (g_soft.ly0 < -512 && g_gpu.dsp.DrawOffset.y <= -512) + g_soft.ly0 += 2048; +} + +/* + //////////////////////////////////////////////////////////////////////// + // special checks... nascar, syphon filter 2, mgs + //////////////////////////////////////////////////////////////////////// + + // xenogears FT4: not removed correctly right now... the tri 0,1,2 + // should get removed, the tri 1,2,3 should stay... pfff + + // x -466 1023 180 1023 + // y 20 -228 222 -100 + + // 0 __1 + // \ / \ + // 2___3 + */ +inline char CheckCoord4() { + if (g_soft.lx0 < 0) { + if (((g_soft.lx1 - g_soft.lx0) > CHKMAX_X) + || ((g_soft.lx2 - g_soft.lx0) > CHKMAX_X)) { + if (g_soft.lx3 < 0) { + if ((g_soft.lx1 - g_soft.lx3) > CHKMAX_X) + return 1; + if ((g_soft.lx2 - g_soft.lx3) > CHKMAX_X) + return 1; + } + } + } + if (g_soft.lx1 < 0) { + if ((g_soft.lx0 - g_soft.lx1) > CHKMAX_X) + return 1; + if ((g_soft.lx2 - g_soft.lx1) > CHKMAX_X) + return 1; + if ((g_soft.lx3 - g_soft.lx1) > CHKMAX_X) + return 1; + } + if (g_soft.lx2 < 0) { + if ((g_soft.lx0 - g_soft.lx2) > CHKMAX_X) + return 1; + if ((g_soft.lx1 - g_soft.lx2) > CHKMAX_X) + return 1; + if ((g_soft.lx3 - g_soft.lx2) > CHKMAX_X) + return 1; + } + if (g_soft.lx3 < 0) { + if (((g_soft.lx1 - g_soft.lx3) > CHKMAX_X) + || ((g_soft.lx2 - g_soft.lx3) > CHKMAX_X)) { + if (g_soft.lx0 < 0) { + if ((g_soft.lx1 - g_soft.lx0) > CHKMAX_X) + return 1; + if ((g_soft.lx2 - g_soft.lx0) > CHKMAX_X) + return 1; + } + } + } + + if (g_soft.ly0 < 0) { + if ((g_soft.ly1 - g_soft.ly0) > CHKMAX_Y) + return 1; + if ((g_soft.ly2 - g_soft.ly0) > CHKMAX_Y) + return 1; + } + if (g_soft.ly1 < 0) { + if ((g_soft.ly0 - g_soft.ly1) > CHKMAX_Y) + return 1; + if ((g_soft.ly2 - g_soft.ly1) > CHKMAX_Y) + return 1; + if ((g_soft.ly3 - g_soft.ly1) > CHKMAX_Y) + return 1; + } + if (g_soft.ly2 < 0) { + if ((g_soft.ly0 - g_soft.ly2) > CHKMAX_Y) + return 1; + if ((g_soft.ly1 - g_soft.ly2) > CHKMAX_Y) + return 1; + if ((g_soft.ly3 - g_soft.ly2) > CHKMAX_Y) + return 1; + } + if (g_soft.ly3 < 0) { + if ((g_soft.ly1 - g_soft.ly3) > CHKMAX_Y) + return 1; + if ((g_soft.ly2 - g_soft.ly3) > CHKMAX_Y) + return 1; + } + + return 0; +} + +inline char CheckCoord3() { + if (g_soft.lx0 < 0) { + if ((g_soft.lx1 - g_soft.lx0) > CHKMAX_X) + return 1; + if ((g_soft.lx2 - g_soft.lx0) > CHKMAX_X) + return 1; + } + if (g_soft.lx1 < 0) { + if ((g_soft.lx0 - g_soft.lx1) > CHKMAX_X) + return 1; + if ((g_soft.lx2 - g_soft.lx1) > CHKMAX_X) + return 1; + } + if (g_soft.lx2 < 0) { + if ((g_soft.lx0 - g_soft.lx2) > CHKMAX_X) + return 1; + if ((g_soft.lx1 - g_soft.lx2) > CHKMAX_X) + return 1; + } + if (g_soft.ly0 < 0) { + if ((g_soft.ly1 - g_soft.ly0) > CHKMAX_Y) + return 1; + if ((g_soft.ly2 - g_soft.ly0) > CHKMAX_Y) + return 1; + } + if (g_soft.ly1 < 0) { + if ((g_soft.ly0 - g_soft.ly1) > CHKMAX_Y) + return 1; + if ((g_soft.ly2 - g_soft.ly1) > CHKMAX_Y) + return 1; + } + if (g_soft.ly2 < 0) { + if ((g_soft.ly0 - g_soft.ly2) > CHKMAX_Y) + return 1; + if ((g_soft.ly1 - g_soft.ly2) > CHKMAX_Y) + return 1; + } + + return 0; +} + +inline char CheckCoord2() { + if (g_soft.lx0 < 0) { + if ((g_soft.lx1 - g_soft.lx0) > CHKMAX_X) + return 1; + } + if (g_soft.lx1 < 0) { + if ((g_soft.lx0 - g_soft.lx1) > CHKMAX_X) + return 1; + } + if (g_soft.ly0 < 0) { + if ((g_soft.ly1 - g_soft.ly0) > CHKMAX_Y) + return 1; + } + if (g_soft.ly1 < 0) { + if ((g_soft.ly0 - g_soft.ly1) > CHKMAX_Y) + return 1; + } + + return 0; +} + +inline char CheckCoordL(short slx0, short sly0, short slx1, short sly1) { + if (slx0 < 0) { + if ((slx1 - slx0) > CHKMAX_X) + return 1; + } + if (slx1 < 0) { + if ((slx0 - slx1) > CHKMAX_X) + return 1; + } + if (sly0 < 0) { + if ((sly1 - sly0) > CHKMAX_Y) + return 1; + } + if (sly1 < 0) { + if ((sly0 - sly1) > CHKMAX_Y) + return 1; + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// mask stuff... used in silent hill +//////////////////////////////////////////////////////////////////////// + +void cmdSTP(unsigned char * baseAddr) { + uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); + + g_gpu.status_reg &= ~0x1800; // Clear the necessary bits + g_gpu.status_reg |= ((gdata & 0x03) << 11); // Set the necessary bits + + if (gdata & 1) { + g_draw.sSetMask = 0x8000; + g_draw.lSetMask = 0x80008000; + } else { + g_draw.sSetMask = 0; + g_draw.lSetMask = 0; + } + + if (gdata & 2) + g_draw.bCheckMask = 1; + else + g_draw.bCheckMask = 0; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: Set texture page infos +//////////////////////////////////////////////////////////////////////// + +void cmdTexturePage(unsigned char * baseAddr) { + uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); + + g_gpu.status_reg &= ~0x000007ff; + g_gpu.status_reg |= (gdata & 0x07ff); + + g_prim.usMirror = (unsigned short) (gdata & 0x3000); + + UpdateGlobalTP((unsigned short) gdata); + g_soft.GlobalTextREST = (gdata & 0x00ffffff) >> 9; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: turn on/off texture window +//////////////////////////////////////////////////////////////////////// + +void cmdTextureWindow(unsigned char *baseAddr) { + uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); + + uint32_t YAlign, XAlign; + + g_gpu.lGPUInfoVals[INFO_TW] = gdata & 0xFFFFF; + + if (gdata & 0x020) + g_prim.TWin.Position.y1 = 8; // xxxx1 + else if (gdata & 0x040) + g_prim.TWin.Position.y1 = 16; // xxx10 + else if (gdata & 0x080) + g_prim.TWin.Position.y1 = 32; // xx100 + else if (gdata & 0x100) + g_prim.TWin.Position.y1 = 64; // x1000 + else if (gdata & 0x200) + g_prim.TWin.Position.y1 = 128; // 10000 + else + g_prim.TWin.Position.y1 = 256; // 00000 + + // Texture window size is determined by the least bit set of the relevant 5 bits + + if (gdata & 0x001) + g_prim.TWin.Position.x1 = 8; // xxxx1 + else if (gdata & 0x002) + g_prim.TWin.Position.x1 = 16; // xxx10 + else if (gdata & 0x004) + g_prim.TWin.Position.x1 = 32; // xx100 + else if (gdata & 0x008) + g_prim.TWin.Position.x1 = 64; // x1000 + else if (gdata & 0x010) + g_prim.TWin.Position.x1 = 128; // 10000 + else + g_prim.TWin.Position.x1 = 256; // 00000 + + // Re-calculate the bit field, because we can't trust what is passed in the data + + + YAlign = (uint32_t) (32 - (g_prim.TWin.Position.y1 >> 3)); + XAlign = (uint32_t) (32 - (g_prim.TWin.Position.x1 >> 3)); + + // Absolute position of the start of the texture window + + g_prim.TWin.Position.y0 = (short) (((gdata >> 15) & YAlign) << 3); + g_prim.TWin.Position.x0 = (short) (((gdata >> 10) & XAlign) << 3); + + if ((g_prim.TWin.Position.x0 == 0 && // tw turned off + g_prim.TWin.Position.y0 == 0 && g_prim.TWin.Position.x1 == 0 + && g_prim.TWin.Position.y1 == 0) || (g_prim.TWin.Position.x1 == 256 + && g_prim.TWin.Position.y1 == 256)) { + g_prim.bUsingTWin = 0; // -> just do it + } else // otherwise + { + g_prim.bUsingTWin = 1; // -> tw turned on + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: start of drawing area... primitives will be clipped inside +//////////////////////////////////////////////////////////////////////// + + +void cmdDrawAreaStart(unsigned char * baseAddr) { + uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); + g_prim.drawX = gdata & 0x3ff; // for soft drawing + g_gpu.lGPUInfoVals[INFO_DRAWSTART] = gdata & 0xFFFFF; + g_prim.drawY = (gdata >> 10) & 0x3ff; + if (g_prim.drawY >= 512) + g_prim.drawY = 511; // some security +} + +//////////////////////////////////////////////////////////////////////// +// cmd: end of drawing area... primitives will be clipped inside +//////////////////////////////////////////////////////////////////////// + +void cmdDrawAreaEnd(unsigned char * baseAddr) { + uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); + + g_prim.drawW = gdata & 0x3ff; // for soft drawing + + g_gpu.lGPUInfoVals[INFO_DRAWEND] = gdata & 0xFFFFF; + g_prim.drawH = (gdata >> 10) & 0x3ff; + if (g_prim.drawH >= 512) + g_prim.drawH = 511; // some security +} + +//////////////////////////////////////////////////////////////////////// +// cmd: draw offset... will be added to prim coords +//////////////////////////////////////////////////////////////////////// + +void cmdDrawOffset(unsigned char * baseAddr) { + uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); + + g_gpu.dsp.DrawOffset.x = (short) (gdata & 0x7ff); + + g_gpu.lGPUInfoVals[INFO_DRAWOFF] = gdata & 0x3FFFFF; + g_gpu.dsp.DrawOffset.y = (short) ((gdata >> 11) & 0x7ff); + + g_gpu.dsp.DrawOffset.y = (short) (((int) g_gpu.dsp.DrawOffset.y << 21) + >> 21); + g_gpu.dsp.DrawOffset.x = (short) (((int) g_gpu.dsp.DrawOffset.x << 21) + >> 21); +} + +//////////////////////////////////////////////////////////////////////// +// cmd: load image to vram +//////////////////////////////////////////////////////////////////////// + +void primLoadImage(unsigned char * baseAddr) { + unsigned short *sgpuData = ((unsigned short *) baseAddr); + + g_gpu.VRAMWrite.x = GETLEs16(&sgpuData[2]) & 0x3ff; + g_gpu.VRAMWrite.y = GETLEs16(&sgpuData[3]) & 0x1ff; + g_gpu.VRAMWrite.Width = GETLEs16(&sgpuData[4]); + g_gpu.VRAMWrite.Height = GETLEs16(&sgpuData[5]); + + g_gpu.DataWriteMode = DR_VRAMTRANSFER; + + g_gpu.VRAMWrite.ImagePtr = g_gpu.psx_vram.u16 + (g_gpu.VRAMWrite.y << 10) + + g_gpu.VRAMWrite.x; + g_gpu.VRAMWrite.RowsRemaining = g_gpu.VRAMWrite.Width; + g_gpu.VRAMWrite.ColsRemaining = g_gpu.VRAMWrite.Height; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: vram -> psx mem +//////////////////////////////////////////////////////////////////////// + +void primStoreImage(unsigned char * baseAddr) { + unsigned short *sgpuData = ((unsigned short *) baseAddr); + + g_gpu.VRAMRead.x = GETLEs16(&sgpuData[2]) & 0x03ff; + g_gpu.VRAMRead.y = GETLEs16(&sgpuData[3]) & 0x01ff; + g_gpu.VRAMRead.Width = GETLEs16(&sgpuData[4]); + g_gpu.VRAMRead.Height = GETLEs16(&sgpuData[5]); + + g_gpu.VRAMRead.ImagePtr = g_gpu.psx_vram.u16 + (g_gpu.VRAMRead.y << 10) + + g_gpu.VRAMRead.x; + g_gpu.VRAMRead.RowsRemaining = g_gpu.VRAMRead.Width; + g_gpu.VRAMRead.ColsRemaining = g_gpu.VRAMRead.Height; + + g_gpu.DataReadMode = DR_VRAMTRANSFER; + + g_gpu.status_reg |= STATUS_READYFORVRAM; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: blkfill - NO primitive! Doesn't care about draw areas... +//////////////////////////////////////////////////////////////////////// + +void primBlkFill(unsigned char * baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + short sX = GETLEs16(&sgpuData[2]); + short sY = GETLEs16(&sgpuData[3]); + short sW = GETLEs16(&sgpuData[4]) & 0x3ff; + short sH = GETLEs16(&sgpuData[5]) & 0x3ff; + + sW = (sW + 15) & ~15; + + // Increase H & W if they are one short of full values, because they never can be full values + if (sH >= 1023) + sH = 1024; + if (sW >= 1023) + sW = 1024; + + // x and y of end pos + sW += sX; + sH += sY; + + FillSoftwareArea(sX, sY, sW, sH, BGR24to16(GETLE32(&gpuData[0]))); + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: move image vram -> vram +//////////////////////////////////////////////////////////////////////// + +void primMoveImage(unsigned char * baseAddr) { + short *sgpuData = ((short *) baseAddr); + + short imageY0, imageX0, imageY1, imageX1, imageSX, imageSY, i, j; + + imageX0 = GETLEs16(&sgpuData[2]) & 0x03ff; + imageY0 = GETLEs16(&sgpuData[3]) & 0x01ff; + imageX1 = GETLEs16(&sgpuData[4]) & 0x03ff; + imageY1 = GETLEs16(&sgpuData[5]) & 0x01ff; + imageSX = GETLEs16(&sgpuData[6]); + imageSY = GETLEs16(&sgpuData[7]); + + if ((imageX0 == imageX1) && (imageY0 == imageY1)) + return; + if (imageSX <= 0) + return; + if (imageSY <= 0) + return; + + if ((imageY0 + imageSY) > 512 || (imageX0 + imageSX) > 1024 || (imageY1 + + imageSY) > 512 || (imageX1 + imageSX) > 1024) { + int i, j; + for (j = 0; j < imageSY; j++) + for (i = 0; i < imageSX; i++) + g_gpu.psx_vram.u16[(1024 * ((imageY1 + j) & 0x01ff)) + + ((imageX1 + i) & 0x3ff)] = g_gpu.psx_vram.u16[(1024 + * ((imageY0 + j) & 0x01ff)) + ((imageX0 + i) & 0x3ff)]; + + return; + } + + if (imageSX & 1) // not dword aligned? slower func + { + unsigned short *SRCPtr, *DSTPtr; + unsigned short LineOffset; + + SRCPtr = g_gpu.psx_vram.u16 + (1024 * imageY0) + imageX0; + DSTPtr = g_gpu.psx_vram.u16 + (1024 * imageY1) + imageX1; + + LineOffset = 1024 - imageSX; + + for (j = 0; j < imageSY; j++) { + for (i = 0; i < imageSX; i++) + *DSTPtr++ = *SRCPtr++; + SRCPtr += LineOffset; + DSTPtr += LineOffset; + } + } else // dword aligned + { + uint32_t *SRCPtr, *DSTPtr; + unsigned short LineOffset; + int dx = imageSX >> 1; + + SRCPtr = (uint32_t *) (g_gpu.psx_vram.u16 + (1024 * imageY0) + imageX0); + DSTPtr = (uint32_t *) (g_gpu.psx_vram.u16 + (1024 * imageY1) + imageX1); + + LineOffset = 512 - dx; + + for (j = 0; j < imageSY; j++) { + for (i = 0; i < dx; i++) + *DSTPtr++ = *SRCPtr++; + SRCPtr += LineOffset; + DSTPtr += LineOffset; + } + } + + imageSX += imageX1; + imageSY += imageY1; + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: draw free-size Tile +//////////////////////////////////////////////////////////////////////// +void primTileS(unsigned char * baseAddr) { + uint32_t *gpuData = ((uint32_t*) baseAddr); + short *sgpuData = ((short *) baseAddr); + short sW = GETLEs16(&sgpuData[4]) & 0x3ff; + short sH = GETLEs16(&sgpuData[5]) & 0x01ff; // mmm... limit tiles to 0x1ff or height? + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + + if (!(g_prim.dwActFixes & 8)) + AdjustCoord1(); + + // x and y of start + g_soft.ly2 = g_soft.ly3 = g_soft.ly0 + sH + g_gpu.dsp.DrawOffset.y; + g_soft.ly0 = g_soft.ly1 = g_soft.ly0 + g_gpu.dsp.DrawOffset.y; + g_soft.lx1 = g_soft.lx2 = g_soft.lx0 + sW + g_gpu.dsp.DrawOffset.x; + g_soft.lx0 = g_soft.lx3 = g_soft.lx0 + g_gpu.dsp.DrawOffset.x; + + g_soft.DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? 1 : 0; + + if (!(0 && sH == 32 && GETLE32(&gpuData[0]) == 0x60ffffff)) // special cheat for certain ZiNc games + FillSoftwareAreaTrans(g_soft.lx0, g_soft.ly0, g_soft.lx2, g_soft.ly2, + BGR24to16(GETLE32(&gpuData[0]))); + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: draw 1 dot Tile (point) +//////////////////////////////////////////////////////////////////////// + +void primTile1(unsigned char * baseAddr) { + uint32_t *gpuData = ((uint32_t*) baseAddr); + short *sgpuData = ((short *) baseAddr); + short sH = 1; + short sW = 1; + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + + if (!(g_prim.dwActFixes & 8)) + AdjustCoord1(); + + // x and y of start + g_soft.ly2 = g_soft.ly3 = g_soft.ly0 + sH + g_gpu.dsp.DrawOffset.y; + g_soft.ly0 = g_soft.ly1 = g_soft.ly0 + g_gpu.dsp.DrawOffset.y; + g_soft.lx1 = g_soft.lx2 = g_soft.lx0 + sW + g_gpu.dsp.DrawOffset.x; + g_soft.lx0 = g_soft.lx3 = g_soft.lx0 + g_gpu.dsp.DrawOffset.x; + + g_soft.DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? 1 : 0; + + FillSoftwareAreaTrans(g_soft.lx0, g_soft.ly0, g_soft.lx2, g_soft.ly2, + BGR24to16(GETLE32(&gpuData[0]))); // Takes Start and Offset + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: draw 8 dot Tile (small rect) +//////////////////////////////////////////////////////////////////////// + +void primTile8(unsigned char * baseAddr) { + uint32_t *gpuData = ((uint32_t*) baseAddr); + short *sgpuData = ((short *) baseAddr); + short sH = 8; + short sW = 8; + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + + if (!(g_prim.dwActFixes & 8)) + AdjustCoord1(); + + // x and y of start + g_soft.ly2 = g_soft.ly3 = g_soft.ly0 + sH + g_gpu.dsp.DrawOffset.y; + g_soft.ly0 = g_soft.ly1 = g_soft.ly0 + g_gpu.dsp.DrawOffset.y; + g_soft.lx1 = g_soft.lx2 = g_soft.lx0 + sW + g_gpu.dsp.DrawOffset.x; + g_soft.lx0 = g_soft.lx3 = g_soft.lx0 + g_gpu.dsp.DrawOffset.x; + + g_soft.DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? 1 : 0; + + FillSoftwareAreaTrans(g_soft.lx0, g_soft.ly0, g_soft.lx2, g_soft.ly2, + BGR24to16(GETLE32(&gpuData[0]))); // Takes Start and Offset + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: draw 16 dot Tile (medium rect) +//////////////////////////////////////////////////////////////////////// + +void primTile16(unsigned char * baseAddr) { + uint32_t *gpuData = ((uint32_t*) baseAddr); + short *sgpuData = ((short *) baseAddr); + short sH = 16; + short sW = 16; + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + + if (!(g_prim.dwActFixes & 8)) + AdjustCoord1(); + + // x and y of start + g_soft.ly2 = g_soft.ly3 = g_soft.ly0 + sH + g_gpu.dsp.DrawOffset.y; + g_soft.ly0 = g_soft.ly1 = g_soft.ly0 + g_gpu.dsp.DrawOffset.y; + g_soft.lx1 = g_soft.lx2 = g_soft.lx0 + sW + g_gpu.dsp.DrawOffset.x; + g_soft.lx0 = g_soft.lx3 = g_soft.lx0 + g_gpu.dsp.DrawOffset.x; + + g_soft.DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? 1 : 0; + + FillSoftwareAreaTrans(g_soft.lx0, g_soft.ly0, g_soft.lx2, g_soft.ly2, + BGR24to16(GETLE32(&gpuData[0]))); // Takes Start and Offset + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: small sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +void primSprt8(unsigned char * baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + + if (!(g_prim.dwActFixes & 8)) + AdjustCoord1(); + + SetRenderMode(GETLE32(&gpuData[0])); + + if (g_prim.bUsingTWin) + DrawSoftwareSpriteTWin(baseAddr, 8, 8); + else if (g_prim.usMirror) + DrawSoftwareSpriteMirror(baseAddr, 8, 8); + else + DrawSoftwareSprite(baseAddr, 8, 8, baseAddr[8], baseAddr[9]); + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: medium sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +void primSprt16(unsigned char * baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + + if (!(g_prim.dwActFixes & 8)) + AdjustCoord1(); + + SetRenderMode(GETLE32(&gpuData[0])); + + if (g_prim.bUsingTWin) + DrawSoftwareSpriteTWin(baseAddr, 16, 16); + else if (g_prim.usMirror) + DrawSoftwareSpriteMirror(baseAddr, 16, 16); + else + DrawSoftwareSprite(baseAddr, 16, 16, baseAddr[8], baseAddr[9]); + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: free-size sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +// func used on texture coord wrap +void primSprtSRest(unsigned char * baseAddr, unsigned short type) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + unsigned short sTypeRest = 0; + + short s; + short sX = GETLEs16(&sgpuData[2]); + short sY = GETLEs16(&sgpuData[3]); + short sW = GETLEs16(&sgpuData[6]) & 0x3ff; + short sH = GETLEs16(&sgpuData[7]) & 0x1ff; + short tX = baseAddr[8]; + short tY = baseAddr[9]; + + switch (type) { + case 1: + s = 256 - baseAddr[8]; + sW -= s; + sX += s; + tX = 0; + break; + case 2: + s = 256 - baseAddr[9]; + sH -= s; + sY += s; + tY = 0; + break; + case 3: + s = 256 - baseAddr[8]; + sW -= s; + sX += s; + tX = 0; + s = 256 - baseAddr[9]; + sH -= s; + sY += s; + tY = 0; + break; + case 4: + s = 512 - baseAddr[8]; + sW -= s; + sX += s; + tX = 0; + break; + case 5: + s = 512 - baseAddr[9]; + sH -= s; + sY += s; + tY = 0; + break; + case 6: + s = 512 - baseAddr[8]; + sW -= s; + sX += s; + tX = 0; + s = 512 - baseAddr[9]; + sH -= s; + sY += s; + tY = 0; + break; + } + + SetRenderMode(GETLE32(&gpuData[0])); + + if (tX + sW > 256) { + sW = 256 - tX; + sTypeRest += 1; + } + if (tY + sH > 256) { + sH = 256 - tY; + sTypeRest += 2; + } + + g_soft.lx0 = sX; + g_soft.ly0 = sY; + + if (!(g_prim.dwActFixes & 8)) + AdjustCoord1(); + + DrawSoftwareSprite(baseAddr, sW, sH, tX, tY); + + if (sTypeRest && type < 4) { + if (sTypeRest & 1 && type == 1) + primSprtSRest(baseAddr, 4); + if (sTypeRest & 2 && type == 2) + primSprtSRest(baseAddr, 5); + if (sTypeRest == 3 && type == 3) + primSprtSRest(baseAddr, 6); + } + +} + +//////////////////////////////////////////////////////////////////////// + +void primSprtS(unsigned char * baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + short sW, sH; + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + + if (!(g_prim.dwActFixes & 8)) + AdjustCoord1(); + + sW = GETLEs16(&sgpuData[6]) & 0x3ff; + sH = GETLEs16(&sgpuData[7]) & 0x1ff; + + SetRenderMode(GETLE32(&gpuData[0])); + + if (g_prim.bUsingTWin) + DrawSoftwareSpriteTWin(baseAddr, sW, sH); + else if (g_prim.usMirror) + DrawSoftwareSpriteMirror(baseAddr, sW, sH); + else { + unsigned short sTypeRest = 0; + short tX = baseAddr[8]; + short tY = baseAddr[9]; + + if (tX + sW > 256) { + sW = 256 - tX; + sTypeRest += 1; + } + if (tY + sH > 256) { + sH = 256 - tY; + sTypeRest += 2; + } + + DrawSoftwareSprite(baseAddr, sW, sH, tX, tY); + + if (sTypeRest) { + if (sTypeRest & 1) + primSprtSRest(baseAddr, 1); + if (sTypeRest & 2) + primSprtSRest(baseAddr, 2); + if (sTypeRest == 3) + primSprtSRest(baseAddr, 3); + } + + } + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Poly4 +//////////////////////////////////////////////////////////////////////// + +void primPolyF4(unsigned char *baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + g_soft.lx1 = GETLEs16(&sgpuData[4]); + g_soft.ly1 = GETLEs16(&sgpuData[5]); + g_soft.lx2 = GETLEs16(&sgpuData[6]); + g_soft.ly2 = GETLEs16(&sgpuData[7]); + g_soft.lx3 = GETLEs16(&sgpuData[8]); + g_soft.ly3 = GETLEs16(&sgpuData[9]); + + if (!(g_prim.dwActFixes & 8)) { + AdjustCoord4(); + if (CheckCoord4()) + return; + } + + offsetPSX4(); + g_soft.DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? 1 : 0; + + drawPoly4F(GETLE32(&gpuData[0])); + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly4 +//////////////////////////////////////////////////////////////////////// + +void primPolyG4(unsigned char * baseAddr) { + uint32_t *gpuData = (uint32_t *) baseAddr; + short *sgpuData = ((short *) baseAddr); + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + g_soft.lx1 = GETLEs16(&sgpuData[6]); + g_soft.ly1 = GETLEs16(&sgpuData[7]); + g_soft.lx2 = GETLEs16(&sgpuData[10]); + g_soft.ly2 = GETLEs16(&sgpuData[11]); + g_soft.lx3 = GETLEs16(&sgpuData[14]); + g_soft.ly3 = GETLEs16(&sgpuData[15]); + + if (!(g_prim.dwActFixes & 8)) { + AdjustCoord4(); + if (CheckCoord4()) + return; + } + + offsetPSX4(); + g_soft.DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? 1 : 0; + + drawPoly4G(GETLE32(&gpuData[0]), GETLE32(&gpuData[2]), + GETLE32(&gpuData[4]), GETLE32(&gpuData[6])); + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Texture3 +//////////////////////////////////////////////////////////////////////// + +void primPolyFT3(unsigned char * baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + g_soft.lx1 = GETLEs16(&sgpuData[6]); + g_soft.ly1 = GETLEs16(&sgpuData[7]); + g_soft.lx2 = GETLEs16(&sgpuData[10]); + g_soft.ly2 = GETLEs16(&sgpuData[11]); + + g_draw.lLowerpart = GETLE32(&gpuData[4]) >> 16; + UpdateGlobalTP((unsigned short) g_draw.lLowerpart); + + if (!(g_prim.dwActFixes & 8)) { + AdjustCoord3(); + if (CheckCoord3()) + return; + } + + offsetPSX3(); + SetRenderMode(GETLE32(&gpuData[0])); + + drawPoly3FT(baseAddr); + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Texture4 +//////////////////////////////////////////////////////////////////////// + +void primPolyFT4(unsigned char * baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + g_soft.lx1 = GETLEs16(&sgpuData[6]); + g_soft.ly1 = GETLEs16(&sgpuData[7]); + g_soft.lx2 = GETLEs16(&sgpuData[10]); + g_soft.ly2 = GETLEs16(&sgpuData[11]); + g_soft.lx3 = GETLEs16(&sgpuData[14]); + g_soft.ly3 = GETLEs16(&sgpuData[15]); + + g_draw.lLowerpart = GETLE32(&gpuData[4]) >> 16; + UpdateGlobalTP((unsigned short) g_draw.lLowerpart); + + if (!(g_prim.dwActFixes & 8)) { + AdjustCoord4(); + if (CheckCoord4()) + return; + } + + offsetPSX4(); + + SetRenderMode(GETLE32(&gpuData[0])); + + drawPoly4FT(baseAddr); + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Texture3 +//////////////////////////////////////////////////////////////////////// + +void primPolyGT3(unsigned char *baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + g_soft.lx1 = GETLEs16(&sgpuData[8]); + g_soft.ly1 = GETLEs16(&sgpuData[9]); + g_soft.lx2 = GETLEs16(&sgpuData[14]); + g_soft.ly2 = GETLEs16(&sgpuData[15]); + + g_draw.lLowerpart = GETLE32(&gpuData[5]) >> 16; + UpdateGlobalTP((unsigned short) g_draw.lLowerpart); + + if (!(g_prim.dwActFixes & 8)) { + AdjustCoord3(); + if (CheckCoord3()) + return; + } + + offsetPSX3(); + g_soft.DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? 1 : 0; + + if (SHADETEXBIT(GETLE32(&gpuData[0]))) { + gpuData[0] = (gpuData[0] & HOST2LE32(0xff000000)) + |HOST2LE32(0x00808080); + gpuData[3] = (gpuData[3] & HOST2LE32(0xff000000)) + |HOST2LE32(0x00808080); + gpuData[6] = (gpuData[6] & HOST2LE32(0xff000000)) + |HOST2LE32(0x00808080); + } + + drawPoly3GT(baseAddr); + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly3 +//////////////////////////////////////////////////////////////////////// + +void primPolyG3(unsigned char *baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + g_soft.lx1 = GETLEs16(&sgpuData[6]); + g_soft.ly1 = GETLEs16(&sgpuData[7]); + g_soft.lx2 = GETLEs16(&sgpuData[10]); + g_soft.ly2 = GETLEs16(&sgpuData[11]); + + if (!(g_prim.dwActFixes & 8)) { + AdjustCoord3(); + if (CheckCoord3()) + return; + } + + offsetPSX3(); + g_soft.DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? 1 : 0; + + drawPoly3G(GETLE32(&gpuData[0]), GETLE32(&gpuData[2]), GETLE32(&gpuData[4])); + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Texture4 +//////////////////////////////////////////////////////////////////////// + +void primPolyGT4(unsigned char *baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + g_soft.lx1 = GETLEs16(&sgpuData[8]); + g_soft.ly1 = GETLEs16(&sgpuData[9]); + g_soft.lx2 = GETLEs16(&sgpuData[14]); + g_soft.ly2 = GETLEs16(&sgpuData[15]); + g_soft.lx3 = GETLEs16(&sgpuData[20]); + g_soft.ly3 = GETLEs16(&sgpuData[21]); + + g_draw.lLowerpart = GETLE32(&gpuData[5]) >> 16; + UpdateGlobalTP((unsigned short) g_draw.lLowerpart); + + if (!(g_prim.dwActFixes & 8)) { + AdjustCoord4(); + if (CheckCoord4()) + return; + } + + offsetPSX4(); + g_soft.DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? 1 : 0; + + if (SHADETEXBIT(GETLE32(&gpuData[0]))) { + gpuData[0] = (gpuData[0] & HOST2LE32(0xff000000)) + |HOST2LE32(0x00808080); + gpuData[3] = (gpuData[3] & HOST2LE32(0xff000000)) + |HOST2LE32(0x00808080); + gpuData[6] = (gpuData[6] & HOST2LE32(0xff000000)) + |HOST2LE32(0x00808080); + gpuData[9] = (gpuData[9] & HOST2LE32(0xff000000)) + |HOST2LE32(0x00808080); + } + + drawPoly4GT(baseAddr); + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly3 +//////////////////////////////////////////////////////////////////////// + +void primPolyF3(unsigned char *baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + g_soft.lx1 = GETLEs16(&sgpuData[4]); + g_soft.ly1 = GETLEs16(&sgpuData[5]); + g_soft.lx2 = GETLEs16(&sgpuData[6]); + g_soft.ly2 = GETLEs16(&sgpuData[7]); + + if (!(g_prim.dwActFixes & 8)) { + AdjustCoord3(); + if (CheckCoord3()) + return; + } + + offsetPSX3(); + SetRenderMode(GETLE32(&gpuData[0])); + + drawPoly3F(GETLE32(&gpuData[0])); + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: skipping shaded polylines +//////////////////////////////////////////////////////////////////////// + +void primLineGSkip(unsigned char *baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + int iMax = 255; + int i = 2; + + g_soft.ly1 = (short) ((GETLE32(&gpuData[1]) >> 16) & 0xffff); + g_soft.lx1 = (short) (GETLE32(&gpuData[1]) & 0xffff); + + while (!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i >= 4)) { + i++; + g_soft.ly1 = (short) ((GETLE32(&gpuData[i]) >> 16) & 0xffff); + g_soft.lx1 = (short) (GETLE32(&gpuData[i]) & 0xffff); + i++; + if (i > iMax) + break; + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: shaded polylines +//////////////////////////////////////////////////////////////////////// + +void primLineGEx(unsigned char *baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + int iMax = 255; + uint32_t lc0, lc1; + short slx0, slx1, sly0, sly1; + int i = 2; + char bDraw = 1; + + sly1 = (short) ((GETLE32(&gpuData[1]) >> 16) & 0xffff); + slx1 = (short) (GETLE32(&gpuData[1]) & 0xffff); + + if (!(g_prim.dwActFixes & 8)) { + slx1 = (short) (((int) slx1 << SIGNSHIFT) >> SIGNSHIFT); + sly1 = (short) (((int) sly1 << SIGNSHIFT) >> SIGNSHIFT); + } + + lc1 = gpuData[0] & 0xffffff; + + g_soft.DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? 1 : 0; + + while (!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i >= 4)) { + sly0 = sly1; + slx0 = slx1; + lc0 = lc1; + lc1 = GETLE32(&gpuData[i]) & 0xffffff; + + i++; + + // no check needed on gshaded polyline positions + // if((gpuData[i] & 0xF000F000) == 0x50005000) break; + + sly1 = (short) ((GETLE32(&gpuData[i]) >> 16) & 0xffff); + slx1 = (short) (GETLE32(&gpuData[i]) & 0xffff); + + if (!(g_prim.dwActFixes & 8)) { + slx1 = (short) (((int) slx1 << SIGNSHIFT) >> SIGNSHIFT); + sly1 = (short) (((int) sly1 << SIGNSHIFT) >> SIGNSHIFT); + if (CheckCoordL(slx0, sly0, slx1, sly1)) + bDraw = 0; + else + bDraw = 1; + } + + if ((g_soft.lx0 != g_soft.lx1) || (g_soft.ly0 != g_soft.ly1)) { + g_soft.ly0 = sly0; + g_soft.lx0 = slx0; + g_soft.ly1 = sly1; + g_soft.lx1 = slx1; + + offsetPSX2(); + if (bDraw) + DrawSoftwareLineShade(lc0, lc1); + } + i++; + if (i > iMax) + break; + } + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: shaded polyline2 +//////////////////////////////////////////////////////////////////////// + +void primLineG2(unsigned char *baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + g_soft.lx1 = GETLEs16(&sgpuData[6]); + g_soft.ly1 = GETLEs16(&sgpuData[7]); + + if (!(g_prim.dwActFixes & 8)) { + AdjustCoord2(); + if (CheckCoord2()) + return; + } + + if ((g_soft.lx0 == g_soft.lx1) && (g_soft.ly0 == g_soft.ly1)) { + g_soft.lx1++; + g_soft.ly1++; + } + + g_soft.DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? 1 : 0; + offsetPSX2(); + DrawSoftwareLineShade(GETLE32(&gpuData[0]), GETLE32(&gpuData[2])); + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: skipping flat polylines +//////////////////////////////////////////////////////////////////////// + +void primLineFSkip(unsigned char *baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + int i = 2, iMax = 255; + + g_soft.ly1 = (short) ((GETLE32(&gpuData[1]) >> 16) & 0xffff); + g_soft.lx1 = (short) (GETLE32(&gpuData[1]) & 0xffff); + + while (!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i >= 3)) { + g_soft.ly1 = (short) ((GETLE32(&gpuData[i]) >> 16) & 0xffff); + g_soft.lx1 = (short) (GETLE32(&gpuData[i]) & 0xffff); + i++; + if (i > iMax) + break; + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: drawing flat polylines +//////////////////////////////////////////////////////////////////////// + +void primLineFEx(unsigned char *baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + int iMax; + short slx0, slx1, sly0, sly1; + int i = 2; + char bDraw = 1; + + iMax = 255; + + sly1 = (short) ((GETLE32(&gpuData[1]) >> 16) & 0xffff); + slx1 = (short) (GETLE32(&gpuData[1]) & 0xffff); + if (!(g_prim.dwActFixes & 8)) { + slx1 = (short) (((int) slx1 << SIGNSHIFT) >> SIGNSHIFT); + sly1 = (short) (((int) sly1 << SIGNSHIFT) >> SIGNSHIFT); + } + + SetRenderMode(GETLE32(&gpuData[0])); + + while (!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i >= 3)) { + sly0 = sly1; + slx0 = slx1; + sly1 = (short) ((GETLE32(&gpuData[i]) >> 16) & 0xffff); + slx1 = (short) (GETLE32(&gpuData[i]) & 0xffff); + if (!(g_prim.dwActFixes & 8)) { + slx1 = (short) (((int) slx1 << SIGNSHIFT) >> SIGNSHIFT); + sly1 = (short) (((int) sly1 << SIGNSHIFT) >> SIGNSHIFT); + + if (CheckCoordL(slx0, sly0, slx1, sly1)) + bDraw = 0; + else + bDraw = 1; + } + + g_soft.ly0 = sly0; + g_soft.lx0 = slx0; + g_soft.ly1 = sly1; + g_soft.lx1 = slx1; + + offsetPSX2(); + if (bDraw) + DrawSoftwareLineFlat(GETLE32(&gpuData[0])); + + i++; + if (i > iMax) + break; + } + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: drawing flat polyline2 +//////////////////////////////////////////////////////////////////////// + +void primLineF2(unsigned char *baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + g_soft.lx0 = GETLEs16(&sgpuData[2]); + g_soft.ly0 = GETLEs16(&sgpuData[3]); + g_soft.lx1 = GETLEs16(&sgpuData[4]); + g_soft.ly1 = GETLEs16(&sgpuData[5]); + + if (!(g_prim.dwActFixes & 8)) { + AdjustCoord2(); + if (CheckCoord2()) + return; + } + + if ((g_soft.lx0 == g_soft.lx1) && (g_soft.ly0 == g_soft.ly1)) { + g_soft.lx1++; + g_soft.ly1++; + } + + offsetPSX2(); + SetRenderMode(GETLE32(&gpuData[0])); + + DrawSoftwareLineFlat(GETLE32(&gpuData[0])); + +} + +//////////////////////////////////////////////////////////////////////// +// cmd: well, easiest command... not implemented +//////////////////////////////////////////////////////////////////////// + +void primNI(unsigned char *bA) { + fprintf(stderr, "Unknow GPU func \n"); +} + +//////////////////////////////////////////////////////////////////////// +// cmd func ptr table +//////////////////////////////////////////////////////////////////////// + + +void (*primTableJ[256])(unsigned char *) = { + /* 00 */ + primNI, + primNI, + primBlkFill, + primNI, + /* 04 */ + primNI, + primNI, + primNI, + primNI, + /* 08 */ + primNI, + primNI, + primNI, + primNI, + primNI, + primNI, + primNI, + primNI, + // 10 + primNI, + primNI, + primNI, + primNI, + primNI, + primNI, + primNI, + primNI, + // 18 + primNI, + primNI, + primNI, + primNI, + primNI, + primNI, + primNI, + primNI, + // 20 + primPolyF3, + primPolyF3, + primPolyF3, + primPolyF3, + primPolyFT3, + primPolyFT3, + primPolyFT3, + primPolyFT3, + // 28 + primPolyF4, + primPolyF4, + primPolyF4, + primPolyF4, + primPolyFT4, + primPolyFT4, + primPolyFT4, + primPolyFT4, + // 30 + primPolyG3, + primPolyG3, + primPolyG3, + primPolyG3, + primPolyGT3, + primPolyGT3, + primPolyGT3, + primPolyGT3, + // 38 + primPolyG4, + primPolyG4, + primPolyG4, + primPolyG4, + primPolyGT4, + primPolyGT4, + primPolyGT4, + primPolyGT4, + // 40 + primLineF2, + primLineF2, + primLineF2, + primLineF2, + primNI, + primNI, + primNI, + primNI, + // 48 + primLineFEx, + primLineFEx, + primLineFEx, + primLineFEx, + primLineFEx, + primLineFEx, + primLineFEx, + primLineFEx, + // 50 + primLineG2, primLineG2, + primLineG2, + primLineG2, + primNI, + primNI, + primNI, + primNI, + // 58 + primLineGEx, primLineGEx, primLineGEx, + primLineGEx, + primLineGEx, + primLineGEx, + primLineGEx, + primLineGEx, + // 60 + primTileS, primTileS, primTileS, primTileS, + primSprtS, + primSprtS, + primSprtS, + primSprtS, + // 68 + primTile1, primTile1, primTile1, primTile1, primNI, + primNI, + primNI, + primNI, + // 70 + primTile8, primTile8, primTile8, primTile8, primSprt8, primSprt8, + primSprt8, + primSprt8, + // 78 + primTile16, primTile16, primTile16, primTile16, primSprt16, primSprt16, + primSprt16, primSprt16, + // 80 + primMoveImage, primNI, primNI, primNI, primNI, primNI, primNI, primNI, + // 88 + primNI, primNI, primNI, primNI, primNI, primNI, primNI, primNI, + // 90 + primNI, primNI, primNI, primNI, primNI, primNI, primNI, primNI, + // 98 + primNI, primNI, primNI, primNI, primNI, primNI, primNI, primNI, + // a0 + primLoadImage, primNI, primNI, primNI, primNI, primNI, primNI, primNI, + // a8 + primNI, primNI, primNI, primNI, primNI, primNI, primNI, primNI, + // b0 + primNI, primNI, primNI, primNI, primNI, primNI, primNI, primNI, + // b8 + primNI, primNI, primNI, primNI, primNI, primNI, primNI, primNI, + // c0 + primStoreImage, primNI, primNI, primNI, primNI, primNI, primNI, primNI, + // c8 + primNI, primNI, primNI, primNI, primNI, primNI, primNI, primNI, + // d0 + primNI, primNI, primNI, primNI, primNI, primNI, primNI, primNI, + // d8 + primNI, primNI, primNI, primNI, primNI, primNI, primNI, primNI, + // e0 + primNI, cmdTexturePage, cmdTextureWindow, cmdDrawAreaStart, + cmdDrawAreaEnd, cmdDrawOffset, cmdSTP, primNI, + // e8 + primNI, primNI, primNI, primNI, primNI, primNI, primNI, primNI, + // f0 + primNI, primNI, primNI, primNI, primNI, primNI, primNI, primNI, + // f8 + primNI, primNI, primNI, primNI, primNI, primNI, primNI, primNI }; + diff --git a/plugins/gxvideo/prim.h b/plugins/gxvideo/prim.h new file mode 100644 index 00000000..8ee7e972 --- /dev/null +++ b/plugins/gxvideo/prim.h @@ -0,0 +1,43 @@ +/*************************************************************************** + prim.h - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#ifndef _PRIMDRAW_H_ +#define _PRIMDRAW_H_ + +typedef struct { + char bUsingTWin; + gxv_win_t TWin; + //unsigned long clutid; // global clut + unsigned short usMirror; // sprite mirror + int iDither; + int32_t drawX; + int32_t drawY; + int32_t drawW; + int32_t drawH; + uint32_t dwCfgFixes; + uint32_t dwActFixes; + uint32_t dwEmuFixes; + int iUseFixes; + int iUseDither; +} gxv_prim_t; + +extern void (*primTableJ[256])(unsigned char *); + +void UploadScreen (long Position); +void PrepareFullScreenUpload (long Position); + +#endif // _PRIMDRAW_H_ diff --git a/plugins/gxvideo/soft.c b/plugins/gxvideo/soft.c new file mode 100644 index 00000000..a0772745 --- /dev/null +++ b/plugins/gxvideo/soft.c @@ -0,0 +1,9931 @@ +/*************************************************************************** + soft.c - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "globals.h" +#include "soft.h" +#include "swap.h" + +#define MIN(a,b) ((a) > (b) ? (b) : (a)) +#define MAX(a,b) ((a) < (b) ? (b) : (a)) + +#define LOWORD(l) ((unsigned short)(l)) +#define HIWORD(l) ((unsigned short)(((uint32_t)(l) >> 16) & 0xFFFF)) + +//////////////////////////////////////////////////////////////////////////////////// +// "NO EDGE BUFFER" POLY VERSION... FUNCS BASED ON FATMAP.TXT FROM MRI / Doomsday +//////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////// +// defines +//////////////////////////////////////////////////////////////////////////////////// + +// switches for painting textured quads as 2 triangles (small glitches, but better shading!) +// can be toggled by game fix 0x200 in version 1.17 anyway, so let the defines enabled! + +#define POLYQUAD3 +#define POLYQUAD3GT + +// fast solid loops... a bit more additional code, of course + +#define FASTSOLID + +// psx blending mode 3 with 25% incoming color (instead 50% without the define) + +#define HALFBRIGHTMODE3 + +// color decode defines + +#define XCOL1(x) (x & 0x1f) +#define XCOL2(x) (x & 0x3e0) +#define XCOL3(x) (x & 0x7c00) + +#define XCOL1D(x) (x & 0x1f) +#define XCOL2D(x) ((x>>5) & 0x1f) +#define XCOL3D(x) ((x>>10) & 0x1f) + +#define X32TCOL1(x) ((x & 0x001f001f)<<7) +#define X32TCOL2(x) ((x & 0x03e003e0)<<2) +#define X32TCOL3(x) ((x & 0x7c007c00)>>3) + +#define X32COL1(x) (x & 0x001f001f) +#define X32COL2(x) ((x>>5) & 0x001f001f) +#define X32COL3(x) ((x>>10) & 0x001f001f) + +#define X32ACOL1(x) (x & 0x001e001e) +#define X32ACOL2(x) ((x>>5) & 0x001e001e) +#define X32ACOL3(x) ((x>>10) & 0x001e001e) + +#define X32BCOL1(x) (x & 0x001c001c) +#define X32BCOL2(x) ((x>>5) & 0x001c001c) +#define X32BCOL3(x) ((x>>10) & 0x001c001c) + +#define X32PSXCOL(r,g,b) ((g<<10)|(b<<5)|r) + +#define XPSXCOL(r,g,b) ((g&0x7c00)|(b&0x3e0)|(r&0x1f)) + +//////////////////////////////////////////////////////////////////////////////////// +// soft globals +//////////////////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +// POLYGON OFFSET FUNCS +//////////////////////////////////////////////////////////////////////// + +void offsetPSXLine(void) { + short x0, x1, y0, y1, dx, dy; + float px, py; + + x0 = g_soft.lx0 + 1 + g_gpu.dsp.DrawOffset.x; + x1 = g_soft.lx1 + 1 + g_gpu.dsp.DrawOffset.x; + y0 = g_soft.ly0 + 1 + g_gpu.dsp.DrawOffset.y; + y1 = g_soft.ly1 + 1 + g_gpu.dsp.DrawOffset.y; + + dx = x1 - x0; + dy = y1 - y0; + + // tricky line width without sqrt + + if (dx >= 0) { + if (dy >= 0) { + px = 0.5f; + if (dx > dy) + py = -0.5f; + else if (dx < dy) + py = 0.5f; + else + py = 0.0f; + } else { + py = -0.5f; + dy = -dy; + if (dx > dy) + px = 0.5f; + else if (dx < dy) + px = -0.5f; + else + px = 0.0f; + } + } else { + if (dy >= 0) { + py = 0.5f; + dx = -dx; + if (dx > dy) + px = -0.5f; + else if (dx < dy) + px = 0.5f; + else + px = 0.0f; + } else { + px = -0.5f; + if (dx > dy) + py = -0.5f; + else if (dx < dy) + py = 0.5f; + else + py = 0.0f; + } + } + + g_soft.lx0 = (short) ((float) x0 - px); + g_soft.lx3 = (short) ((float) x0 + py); + + g_soft.ly0 = (short) ((float) y0 - py); + g_soft.ly3 = (short) ((float) y0 - px); + + g_soft.lx1 = (short) ((float) x1 - py); + g_soft.lx2 = (short) ((float) x1 + px); + + g_soft.ly1 = (short) ((float) y1 + px); + g_soft.ly2 = (short) ((float) y1 + py); +} + +void offsetPSX2(void) { + g_soft.lx0 += g_gpu.dsp.DrawOffset.x; + g_soft.ly0 += g_gpu.dsp.DrawOffset.y; + g_soft.lx1 += g_gpu.dsp.DrawOffset.x; + g_soft.ly1 += g_gpu.dsp.DrawOffset.y; +} + +void offsetPSX3(void) { + g_soft.lx0 += g_gpu.dsp.DrawOffset.x; + g_soft.ly0 += g_gpu.dsp.DrawOffset.y; + g_soft.lx1 += g_gpu.dsp.DrawOffset.x; + g_soft.ly1 += g_gpu.dsp.DrawOffset.y; + g_soft.lx2 += g_gpu.dsp.DrawOffset.x; + g_soft.ly2 += g_gpu.dsp.DrawOffset.y; +} + +void offsetPSX4(void) { + g_soft.lx0 += g_gpu.dsp.DrawOffset.x; + g_soft.ly0 += g_gpu.dsp.DrawOffset.y; + g_soft.lx1 += g_gpu.dsp.DrawOffset.x; + g_soft.ly1 += g_gpu.dsp.DrawOffset.y; + g_soft.lx2 += g_gpu.dsp.DrawOffset.x; + g_soft.ly2 += g_gpu.dsp.DrawOffset.y; + g_soft.lx3 += g_gpu.dsp.DrawOffset.x; + g_soft.ly3 += g_gpu.dsp.DrawOffset.y; +} + +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +// PER PIXEL FUNCS +//////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// + + +uint8_t const dithertable[16] = { 7, 0, 6, 1, 2, 5, 3, 4, 1, 6, 0, 7, 4, 3, 5, + 2 }; + +void Dither16(uint16_t * pdest, uint32_t r, uint32_t g, uint32_t b, uint16_t sM) { + uint8_t coeff; + uint8_t rlow, glow, blow; + int x, y; + + x = pdest - g_gpu.psx_vram.u16; + y = x >> 10; + x -= (y << 10); + + coeff = dithertable[(y & 3) * 4 + (x & 3)]; + + rlow = r & 7; + glow = g & 7; + blow = b & 7; + + r >>= 3; + g >>= 3; + b >>= 3; + + if ((r < 0x1F) && rlow > coeff) + r++; + if ((g < 0x1F) && glow > coeff) + g++; + if ((b < 0x1F) && blow > coeff) + b++; + + PUTLE16(pdest, (b<<10) | (g<<5) | r | sM); +} + +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// + +inline void GetShadeTransCol_Dither(uint16_t * pdest, int32_t m1, + int32_t m2, int32_t m3) { + int32_t r, g, b; + + if (g_draw.bCheckMask && (*pdest & HOST2LE16(0x8000))) + return; + + if (g_soft.DrawSemiTrans) { + r = ((XCOL1D(GETLE16(pdest))) << 3); + b = ((XCOL2D(GETLE16(pdest))) << 3); + g = ((XCOL3D(GETLE16(pdest))) << 3); + + if (g_soft.GlobalTextABR == 0) { + r = (r >> 1) + (m1 >> 1); + b = (b >> 1) + (m2 >> 1); + g = (g >> 1) + (m3 >> 1); + } else if (g_soft.GlobalTextABR == 1) { + r += m1; + b += m2; + g += m3; + } else if (g_soft.GlobalTextABR == 2) { + r -= m1; + b -= m2; + g -= m3; + if (r & 0x80000000) + r = 0; + if (b & 0x80000000) + b = 0; + if (g & 0x80000000) + g = 0; + } else { +#ifdef HALFBRIGHTMODE3 + r += (m1 >> 2); + b += (m2 >> 2); + g += (m3 >> 2); +#else + r+=(m1>>1); + b+=(m2>>1); + g+=(m3>>1); +#endif + } + } else { + r = m1; + b = m2; + g = m3; + } + + if (r & 0x7FFFFF00) + r = 0xff; + if (b & 0x7FFFFF00) + b = 0xff; + if (g & 0x7FFFFF00) + g = 0xff; + + Dither16(pdest, r, b, g, g_draw.sSetMask); +} + +//////////////////////////////////////////////////////////////////////// + +inline void GetShadeTransCol(unsigned short * pdest, unsigned short color) { + if (g_draw.bCheckMask && (*pdest & HOST2LE16(0x8000))) + return; + + if (g_soft.DrawSemiTrans) { + int32_t r, g, b; + + if (g_soft.GlobalTextABR == 0) { + PUTLE16(pdest, (((GETLE16(pdest)&0x7bde)>>1)+(((color)&0x7bde)>>1))|g_draw.sSetMask);//0x8000; + return; + /* + r=(XCOL1(*pdest)>>1)+((XCOL1(color))>>1); + b=(XCOL2(*pdest)>>1)+((XCOL2(color))>>1); + g=(XCOL3(*pdest)>>1)+((XCOL3(color))>>1); + */ + } else if (g_soft.GlobalTextABR == 1) { + r = (XCOL1(GETLE16(pdest))) + ((XCOL1(color))); + b = (XCOL2(GETLE16(pdest))) + ((XCOL2(color))); + g = (XCOL3(GETLE16(pdest))) + ((XCOL3(color))); + } else if (g_soft.GlobalTextABR == 2) { + r = (XCOL1(GETLE16(pdest))) - ((XCOL1(color))); + b = (XCOL2(GETLE16(pdest))) - ((XCOL2(color))); + g = (XCOL3(GETLE16(pdest))) - ((XCOL3(color))); + if (r & 0x80000000) + r = 0; + if (b & 0x80000000) + b = 0; + if (g & 0x80000000) + g = 0; + } else { +#ifdef HALFBRIGHTMODE3 + r = (XCOL1(GETLE16(pdest))) + ((XCOL1(color)) >> 2); + b = (XCOL2(GETLE16(pdest))) + ((XCOL2(color)) >> 2); + g = (XCOL3(GETLE16(pdest))) + ((XCOL3(color)) >> 2); +#else + r=(XCOL1(GETLE16(pdest)))+((XCOL1(color))>>1); + b=(XCOL2(GETLE16(pdest)))+((XCOL2(color))>>1); + g=(XCOL3(GETLE16(pdest)))+((XCOL3(color))>>1); +#endif + } + + if (r & 0x7FFFFFE0) + r = 0x1f; + if (b & 0x7FFFFC00) + b = 0x3e0; + if (g & 0x7FFF8000) + g = 0x7c00; + + PUTLE16(pdest, (XPSXCOL(r,g,b))|g_draw.sSetMask);//0x8000; + } +else PUTLE16(pdest, color|g_draw.sSetMask); + } + + //////////////////////////////////////////////////////////////////////// + +inline void GetShadeTransCol32(uint32_t * pdest, uint32_t color) { + if (g_soft.DrawSemiTrans) { + int32_t r, g, b; + + if (g_soft.GlobalTextABR == 0) { + if (!g_draw.bCheckMask) { + PUTLE32(pdest, (((GETLE32(pdest)&0x7bde7bde)>>1)+(((color)&0x7bde7bde)>>1))|g_draw.lSetMask);//0x80008000; + return; + } + r = (X32ACOL1(GETLE32(pdest)) >> 1) + ((X32ACOL1(color)) >> 1); + b = (X32ACOL2(GETLE32(pdest)) >> 1) + ((X32ACOL2(color)) >> 1); + g = (X32ACOL3(GETLE32(pdest)) >> 1) + ((X32ACOL3(color)) >> 1); + } else if (g_soft.GlobalTextABR == 1) { + r = (X32COL1(GETLE32(pdest))) + ((X32COL1(color))); + b = (X32COL2(GETLE32(pdest))) + ((X32COL2(color))); + g = (X32COL3(GETLE32(pdest))) + ((X32COL3(color))); + } else if (g_soft.GlobalTextABR == 2) { + int32_t sr, sb, sg, src, sbc, sgc, c; + src = XCOL1(color); + sbc = XCOL2(color); + sgc = XCOL3(color); + c = GETLE32(pdest) >> 16; + sr = (XCOL1(c)) - src; + if (sr & 0x8000) + sr = 0; + sb = (XCOL2(c)) - sbc; + if (sb & 0x8000) + sb = 0; + sg = (XCOL3(c)) - sgc; + if (sg & 0x8000) + sg = 0; + r = ((int32_t) sr) << 16; + b = ((int32_t) sb) << 11; + g = ((int32_t) sg) << 6; + c = LOWORD(GETLE32(pdest)); + sr = (XCOL1(c)) - src; + if (sr & 0x8000) + sr = 0; + sb = (XCOL2(c)) - sbc; + if (sb & 0x8000) + sb = 0; + sg = (XCOL3(c)) - sgc; + if (sg & 0x8000) + sg = 0; + r |= sr; + b |= sb >> 5; + g |= sg >> 10; + } else { +#ifdef HALFBRIGHTMODE3 + r = (X32COL1(GETLE32(pdest))) + ((X32BCOL1(color)) >> 2); + b = (X32COL2(GETLE32(pdest))) + ((X32BCOL2(color)) >> 2); + g = (X32COL3(GETLE32(pdest))) + ((X32BCOL3(color)) >> 2); +#else + r=(X32COL1(GETLE32(pdest)))+((X32ACOL1(color))>>1); + b=(X32COL2(GETLE32(pdest)))+((X32ACOL2(color))>>1); + g=(X32COL3(GETLE32(pdest)))+((X32ACOL3(color))>>1); +#endif + } + + if (r & 0x7FE00000) + r = 0x1f0000 | (r & 0xFFFF); + if (r & 0x7FE0) + r = 0x1f | (r & 0xFFFF0000); + if (b & 0x7FE00000) + b = 0x1f0000 | (b & 0xFFFF); + if (b & 0x7FE0) + b = 0x1f | (b & 0xFFFF0000); + if (g & 0x7FE00000) + g = 0x1f0000 | (g & 0xFFFF); + if (g & 0x7FE0) + g = 0x1f | (g & 0xFFFF0000); + + if (g_draw.bCheckMask) { + uint32_t ma = GETLE32(pdest); + PUTLE32(pdest, (X32PSXCOL(r,g,b))|g_draw.lSetMask);//0x80008000; + if (ma & 0x80000000) + PUTLE32(pdest, (ma&0xFFFF0000)|(*pdest&0xFFFF)); + if (ma & 0x00008000) + PUTLE32(pdest, (ma&0xFFFF) |(*pdest&0xFFFF0000)); + return; + } + PUTLE32(pdest, (X32PSXCOL(r,g,b))|g_draw.lSetMask);//0x80008000; + } else { + if (g_draw.bCheckMask) { + uint32_t ma = GETLE32(pdest); + PUTLE32(pdest, color|g_draw.lSetMask);//0x80008000; + if (ma & 0x80000000) + PUTLE32(pdest, (ma&0xFFFF0000)|(GETLE32(pdest)&0xFFFF)); + if (ma & 0x00008000) + PUTLE32(pdest, (ma&0xFFFF) |(GETLE32(pdest)&0xFFFF0000)); + return; + } + + PUTLE32(pdest, color|g_draw.lSetMask);//0x80008000; + } +} + +//////////////////////////////////////////////////////////////////////// + +inline void GetTextureTransColG(unsigned short * pdest, unsigned short color) { + int32_t r, g, b; + unsigned short l; + + if (color == 0) + return; + + if (g_draw.bCheckMask && (*pdest & HOST2LE16(0x8000))) + return; + + l = g_draw.sSetMask | (color & 0x8000); + + if (g_soft.DrawSemiTrans && (color & 0x8000)) { + if (g_soft.GlobalTextABR == 0) { + unsigned short d; + d = (GETLE16(pdest) & 0x7bde) >> 1; + color = ((color) & 0x7bde) >> 1; + r = (XCOL1(d)) + ((((XCOL1(color))) * g_soft.g_m1) >> 7); + b = (XCOL2(d)) + ((((XCOL2(color))) * g_soft.g_m2) >> 7); + g = (XCOL3(d)) + ((((XCOL3(color))) * g_soft.g_m3) >> 7); + + /* + r=(XCOL1(*pdest)>>1)+((((XCOL1(color))>>1)* g_soft.g_m1)>>7); + b=(XCOL2(*pdest)>>1)+((((XCOL2(color))>>1)* g_soft.g_m2)>>7); + g=(XCOL3(*pdest)>>1)+((((XCOL3(color))>>1)* g_soft.g_m3)>>7); + */ + } else if (g_soft.GlobalTextABR == 1) { + r = (XCOL1(GETLE16(pdest))) + ((((XCOL1(color))) * g_soft.g_m1) + >> 7); + b = (XCOL2(GETLE16(pdest))) + ((((XCOL2(color))) * g_soft.g_m2) + >> 7); + g = (XCOL3(GETLE16(pdest))) + ((((XCOL3(color))) * g_soft.g_m3) + >> 7); + } else if (g_soft.GlobalTextABR == 2) { + r = (XCOL1(GETLE16(pdest))) - ((((XCOL1(color))) * g_soft.g_m1) + >> 7); + b = (XCOL2(GETLE16(pdest))) - ((((XCOL2(color))) * g_soft.g_m2) + >> 7); + g = (XCOL3(GETLE16(pdest))) - ((((XCOL3(color))) * g_soft.g_m3) + >> 7); + if (r & 0x80000000) + r = 0; + if (b & 0x80000000) + b = 0; + if (g & 0x80000000) + g = 0; + } else { +#ifdef HALFBRIGHTMODE3 + r = (XCOL1(GETLE16(pdest))) + + ((((XCOL1(color)) >> 2) * g_soft.g_m1) >> 7); + b = (XCOL2(GETLE16(pdest))) + + ((((XCOL2(color)) >> 2) * g_soft.g_m2) >> 7); + g = (XCOL3(GETLE16(pdest))) + + ((((XCOL3(color)) >> 2) * g_soft.g_m3) >> 7); +#else + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color))>>1)* g_soft.g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>1)* g_soft.g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>1)* g_soft.g_m3)>>7); +#endif + } + } else { + r = ((XCOL1(color)) * g_soft.g_m1) >> 7; + b = ((XCOL2(color)) * g_soft.g_m2) >> 7; + g = ((XCOL3(color)) * g_soft.g_m3) >> 7; + } + + if (r & 0x7FFFFFE0) + r = 0x1f; + if (b & 0x7FFFFC00) + b = 0x3e0; + if (g & 0x7FFF8000) + g = 0x7c00; + + PUTLE16(pdest, (XPSXCOL(r,g,b))|l); +} + +//////////////////////////////////////////////////////////////////////// + +inline void GetTextureTransColG_S(unsigned short * pdest, unsigned short color) { + int32_t r, g, b; + unsigned short l; + + if (color == 0) + return; + + l = g_draw.sSetMask | (color & 0x8000); + + r = ((XCOL1(color)) * g_soft.g_m1) >> 7; + b = ((XCOL2(color)) * g_soft.g_m2) >> 7; + g = ((XCOL3(color)) * g_soft.g_m3) >> 7; + + if (r & 0x7FFFFFE0) + r = 0x1f; + if (b & 0x7FFFFC00) + b = 0x3e0; + if (g & 0x7FFF8000) + g = 0x7c00; + + PUTLE16(pdest, (XPSXCOL(r,g,b))|l); +} + +//////////////////////////////////////////////////////////////////////// + +inline void GetTextureTransColG_SPR(unsigned short * pdest, + unsigned short color) { + int32_t r, g, b; + unsigned short l; + + if (color == 0) + return; + + if (g_draw.bCheckMask && (GETLE16(pdest) & 0x8000)) + return; + + l = g_draw.sSetMask | (color & 0x8000); + + if (g_soft.DrawSemiTrans && (color & 0x8000)) { + if (g_soft.GlobalTextABR == 0) { + unsigned short d; + d = (GETLE16(pdest) & 0x7bde) >> 1; + color = ((color) & 0x7bde) >> 1; + r = (XCOL1(d)) + ((((XCOL1(color))) * g_soft.g_m1) >> 7); + b = (XCOL2(d)) + ((((XCOL2(color))) * g_soft.g_m2) >> 7); + g = (XCOL3(d)) + ((((XCOL3(color))) * g_soft.g_m3) >> 7); + + /* + r=(XCOL1(*pdest)>>1)+((((XCOL1(color))>>1)* g_soft.g_m1)>>7); + b=(XCOL2(*pdest)>>1)+((((XCOL2(color))>>1)* g_soft.g_m2)>>7); + g=(XCOL3(*pdest)>>1)+((((XCOL3(color))>>1)* g_soft.g_m3)>>7); + */ + } else if (g_soft.GlobalTextABR == 1) { + r = (XCOL1(GETLE16(pdest))) + ((((XCOL1(color))) * g_soft.g_m1) + >> 7); + b = (XCOL2(GETLE16(pdest))) + ((((XCOL2(color))) * g_soft.g_m2) + >> 7); + g = (XCOL3(GETLE16(pdest))) + ((((XCOL3(color))) * g_soft.g_m3) + >> 7); + } else if (g_soft.GlobalTextABR == 2) { + r = (XCOL1(GETLE16(pdest))) - ((((XCOL1(color))) * g_soft.g_m1) + >> 7); + b = (XCOL2(GETLE16(pdest))) - ((((XCOL2(color))) * g_soft.g_m2) + >> 7); + g = (XCOL3(GETLE16(pdest))) - ((((XCOL3(color))) * g_soft.g_m3) + >> 7); + if (r & 0x80000000) + r = 0; + if (b & 0x80000000) + b = 0; + if (g & 0x80000000) + g = 0; + } else { +#ifdef HALFBRIGHTMODE3 + r = (XCOL1(GETLE16(pdest))) + + ((((XCOL1(color)) >> 2) * g_soft.g_m1) >> 7); + b = (XCOL2(GETLE16(pdest))) + + ((((XCOL2(color)) >> 2) * g_soft.g_m2) >> 7); + g = (XCOL3(GETLE16(pdest))) + + ((((XCOL3(color)) >> 2) * g_soft.g_m3) >> 7); +#else + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color))>>1)* g_soft.g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>1)* g_soft.g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>1)* g_soft.g_m3)>>7); +#endif + } + } else { + r = ((XCOL1(color)) * g_soft.g_m1) >> 7; + b = ((XCOL2(color)) * g_soft.g_m2) >> 7; + g = ((XCOL3(color)) * g_soft.g_m3) >> 7; + } + + if (r & 0x7FFFFFE0) + r = 0x1f; + if (b & 0x7FFFFC00) + b = 0x3e0; + if (g & 0x7FFF8000) + g = 0x7c00; + + PUTLE16(pdest, (XPSXCOL(r,g,b))|l); +} + +//////////////////////////////////////////////////////////////////////// + +inline void GetTextureTransColG32(uint32_t * pdest, uint32_t color) { + int32_t r, g, b, l; + + if (color == 0) + return; + + l = g_draw.lSetMask | (color & 0x80008000); + + if (g_soft.DrawSemiTrans && (color & 0x80008000)) { + if (g_soft.GlobalTextABR == 0) { + r = ((((X32TCOL1(GETLE32(pdest))) + + ((X32COL1(color)) * g_soft.g_m1)) & 0xFF00FF00) >> 8); + b = ((((X32TCOL2(GETLE32(pdest))) + + ((X32COL2(color)) * g_soft.g_m2)) & 0xFF00FF00) >> 8); + g = ((((X32TCOL3(GETLE32(pdest))) + + ((X32COL3(color)) * g_soft.g_m3)) & 0xFF00FF00) >> 8); + } else if (g_soft.GlobalTextABR == 1) { + r = (X32COL1(GETLE32(pdest))) + + (((((X32COL1(color))) * g_soft.g_m1) & 0xFF80FF80) >> 7); + b = (X32COL2(GETLE32(pdest))) + + (((((X32COL2(color))) * g_soft.g_m2) & 0xFF80FF80) >> 7); + g = (X32COL3(GETLE32(pdest))) + + (((((X32COL3(color))) * g_soft.g_m3) & 0xFF80FF80) >> 7); + } else if (g_soft.GlobalTextABR == 2) { + int32_t t; + r = (((((X32COL1(color))) * g_soft.g_m1) & 0xFF80FF80) >> 7); + t = (GETLE32(pdest) & 0x001f0000) - (r & 0x003f0000); + if (t & 0x80000000) + t = 0; + r = (GETLE32(pdest) & 0x0000001f) - (r & 0x0000003f); + if (r & 0x80000000) + r = 0; + r |= t; + + b = (((((X32COL2(color))) * g_soft.g_m2) & 0xFF80FF80) >> 7); + t = ((GETLE32(pdest) >> 5) & 0x001f0000) - (b & 0x003f0000); + if (t & 0x80000000) + t = 0; + b = ((GETLE32(pdest) >> 5) & 0x0000001f) - (b & 0x0000003f); + if (b & 0x80000000) + b = 0; + b |= t; + + g = (((((X32COL3(color))) * g_soft.g_m3) & 0xFF80FF80) >> 7); + t = ((GETLE32(pdest) >> 10) & 0x001f0000) - (g & 0x003f0000); + if (t & 0x80000000) + t = 0; + g = ((GETLE32(pdest) >> 10) & 0x0000001f) - (g & 0x0000003f); + if (g & 0x80000000) + g = 0; + g |= t; + } else { +#ifdef HALFBRIGHTMODE3 + r = (X32COL1(GETLE32(pdest))) + (((((X32BCOL1(color)) >> 2) + * g_soft.g_m1) & 0xFF80FF80) >> 7); + b = (X32COL2(GETLE32(pdest))) + (((((X32BCOL2(color)) >> 2) + * g_soft.g_m2) & 0xFF80FF80) >> 7); + g = (X32COL3(GETLE32(pdest))) + (((((X32BCOL3(color)) >> 2) + * g_soft.g_m3) & 0xFF80FF80) >> 7); +#else + r=(X32COL1(GETLE32(pdest)))+(((((X32ACOL1(color))>>1)* g_soft.g_m1)&0xFF80FF80)>>7); + b=(X32COL2(GETLE32(pdest)))+(((((X32ACOL2(color))>>1)* g_soft.g_m2)&0xFF80FF80)>>7); + g=(X32COL3(GETLE32(pdest)))+(((((X32ACOL3(color))>>1)* g_soft.g_m3)&0xFF80FF80)>>7); +#endif + } + + if (!(color & 0x8000)) { + r = (r & 0xffff0000) | ((((X32COL1(color)) * g_soft.g_m1) + & 0x0000FF80) >> 7); + b = (b & 0xffff0000) | ((((X32COL2(color)) * g_soft.g_m2) + & 0x0000FF80) >> 7); + g = (g & 0xffff0000) | ((((X32COL3(color)) * g_soft.g_m3) + & 0x0000FF80) >> 7); + } + if (!(color & 0x80000000)) { + r = (r & 0xffff) | ((((X32COL1(color)) * g_soft.g_m1) & 0xFF800000) + >> 7); + b = (b & 0xffff) | ((((X32COL2(color)) * g_soft.g_m2) & 0xFF800000) + >> 7); + g = (g & 0xffff) | ((((X32COL3(color)) * g_soft.g_m3) & 0xFF800000) + >> 7); + } + + } else { + r = (((X32COL1(color)) * g_soft.g_m1) & 0xFF80FF80) >> 7; + b = (((X32COL2(color)) * g_soft.g_m2) & 0xFF80FF80) >> 7; + g = (((X32COL3(color)) * g_soft.g_m3) & 0xFF80FF80) >> 7; + } + + if (r & 0x7FE00000) + r = 0x1f0000 | (r & 0xFFFF); + if (r & 0x7FE0) + r = 0x1f | (r & 0xFFFF0000); + if (b & 0x7FE00000) + b = 0x1f0000 | (b & 0xFFFF); + if (b & 0x7FE0) + b = 0x1f | (b & 0xFFFF0000); + if (g & 0x7FE00000) + g = 0x1f0000 | (g & 0xFFFF); + if (g & 0x7FE0) + g = 0x1f | (g & 0xFFFF0000); + + if (g_draw.bCheckMask) { + uint32_t ma = GETLE32(pdest); + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|l); + + if ((color & 0xffff) == 0) + PUTLE32(pdest, (ma&0xffff)|(GETLE32(pdest)&0xffff0000)); + if ((color & 0xffff0000) == 0) + PUTLE32(pdest, (ma&0xffff0000)|(GETLE32(pdest)&0xffff)); + if (ma & 0x80000000) + PUTLE32(pdest, (ma&0xFFFF0000)|(GETLE32(pdest)&0xFFFF)); + if (ma & 0x00008000) + PUTLE32(pdest, (ma&0xFFFF) |(GETLE32(pdest)&0xFFFF0000)); + + return; + } + if ((color & 0xffff) == 0) { + PUTLE32(pdest, (GETLE32(pdest)&0xffff)|(((X32PSXCOL(r,g,b))|l)&0xffff0000)); + return; + } + if ((color & 0xffff0000) == 0) { + PUTLE32(pdest, (GETLE32(pdest)&0xffff0000)|(((X32PSXCOL(r,g,b))|l)&0xffff)); + return; + } + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|l); +} + +//////////////////////////////////////////////////////////////////////// + +inline void GetTextureTransColG32_S(uint32_t * pdest, uint32_t color) { + int32_t r, g, b; + + if (color == 0) + return; + + r = (((X32COL1(color)) * g_soft.g_m1) & 0xFF80FF80) >> 7; + b = (((X32COL2(color)) * g_soft.g_m2) & 0xFF80FF80) >> 7; + g = (((X32COL3(color)) * g_soft.g_m3) & 0xFF80FF80) >> 7; + + if (r & 0x7FE00000) + r = 0x1f0000 | (r & 0xFFFF); + if (r & 0x7FE0) + r = 0x1f | (r & 0xFFFF0000); + if (b & 0x7FE00000) + b = 0x1f0000 | (b & 0xFFFF); + if (b & 0x7FE0) + b = 0x1f | (b & 0xFFFF0000); + if (g & 0x7FE00000) + g = 0x1f0000 | (g & 0xFFFF); + if (g & 0x7FE0) + g = 0x1f | (g & 0xFFFF0000); + + if ((color & 0xffff) == 0) { + PUTLE32(pdest, (GETLE32(pdest)&0xffff)|(((X32PSXCOL(r,g,b))|g_draw.lSetMask|(color&0x80008000))&0xffff0000)); + return; + } + if ((color & 0xffff0000) == 0) { + PUTLE32(pdest, (GETLE32(pdest)&0xffff0000)|(((X32PSXCOL(r,g,b))|g_draw.lSetMask|(color&0x80008000))&0xffff)); + return; + } + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|g_draw.lSetMask|(color&0x80008000)); +} + +//////////////////////////////////////////////////////////////////////// + +inline void GetTextureTransColG32_SPR(uint32_t * pdest, uint32_t color) { + int32_t r, g, b; + + if (color == 0) + return; + + if (g_soft.DrawSemiTrans && (color & 0x80008000)) { + if (g_soft.GlobalTextABR == 0) { + r = ((((X32TCOL1(GETLE32(pdest))) + + ((X32COL1(color)) * g_soft.g_m1)) & 0xFF00FF00) >> 8); + b = ((((X32TCOL2(GETLE32(pdest))) + + ((X32COL2(color)) * g_soft.g_m2)) & 0xFF00FF00) >> 8); + g = ((((X32TCOL3(GETLE32(pdest))) + + ((X32COL3(color)) * g_soft.g_m3)) & 0xFF00FF00) >> 8); + } else if (g_soft.GlobalTextABR == 1) { + r = (X32COL1(GETLE32(pdest))) + + (((((X32COL1(color))) * g_soft.g_m1) & 0xFF80FF80) >> 7); + b = (X32COL2(GETLE32(pdest))) + + (((((X32COL2(color))) * g_soft.g_m2) & 0xFF80FF80) >> 7); + g = (X32COL3(GETLE32(pdest))) + + (((((X32COL3(color))) * g_soft.g_m3) & 0xFF80FF80) >> 7); + } else if (g_soft.GlobalTextABR == 2) { + int32_t t; + r = (((((X32COL1(color))) * g_soft.g_m1) & 0xFF80FF80) >> 7); + t = (GETLE32(pdest) & 0x001f0000) - (r & 0x003f0000); + if (t & 0x80000000) + t = 0; + r = (GETLE32(pdest) & 0x0000001f) - (r & 0x0000003f); + if (r & 0x80000000) + r = 0; + r |= t; + + b = (((((X32COL2(color))) * g_soft.g_m2) & 0xFF80FF80) >> 7); + t = ((GETLE32(pdest) >> 5) & 0x001f0000) - (b & 0x003f0000); + if (t & 0x80000000) + t = 0; + b = ((GETLE32(pdest) >> 5) & 0x0000001f) - (b & 0x0000003f); + if (b & 0x80000000) + b = 0; + b |= t; + + g = (((((X32COL3(color))) * g_soft.g_m3) & 0xFF80FF80) >> 7); + t = ((GETLE32(pdest) >> 10) & 0x001f0000) - (g & 0x003f0000); + if (t & 0x80000000) + t = 0; + g = ((GETLE32(pdest) >> 10) & 0x0000001f) - (g & 0x0000003f); + if (g & 0x80000000) + g = 0; + g |= t; + } else { +#ifdef HALFBRIGHTMODE3 + r = (X32COL1(GETLE32(pdest))) + (((((X32BCOL1(color)) >> 2) + * g_soft.g_m1) & 0xFF80FF80) >> 7); + b = (X32COL2(GETLE32(pdest))) + (((((X32BCOL2(color)) >> 2) + * g_soft.g_m2) & 0xFF80FF80) >> 7); + g = (X32COL3(GETLE32(pdest))) + (((((X32BCOL3(color)) >> 2) + * g_soft.g_m3) & 0xFF80FF80) >> 7); +#else + r=(X32COL1(GETLE32(pdest)))+(((((X32ACOL1(color))>>1)* g_soft.g_m1)&0xFF80FF80)>>7); + b=(X32COL2(GETLE32(pdest)))+(((((X32ACOL2(color))>>1)* g_soft.g_m2)&0xFF80FF80)>>7); + g=(X32COL3(GETLE32(pdest)))+(((((X32ACOL3(color))>>1)* g_soft.g_m3)&0xFF80FF80)>>7); +#endif + } + + if (!(color & 0x8000)) { + r = (r & 0xffff0000) | ((((X32COL1(color)) * g_soft.g_m1) + & 0x0000FF80) >> 7); + b = (b & 0xffff0000) | ((((X32COL2(color)) * g_soft.g_m2) + & 0x0000FF80) >> 7); + g = (g & 0xffff0000) | ((((X32COL3(color)) * g_soft.g_m3) + & 0x0000FF80) >> 7); + } + if (!(color & 0x80000000)) { + r = (r & 0xffff) | ((((X32COL1(color)) * g_soft.g_m1) & 0xFF800000) + >> 7); + b = (b & 0xffff) | ((((X32COL2(color)) * g_soft.g_m2) & 0xFF800000) + >> 7); + g = (g & 0xffff) | ((((X32COL3(color)) * g_soft.g_m3) & 0xFF800000) + >> 7); + } + + } else { + r = (((X32COL1(color)) * g_soft.g_m1) & 0xFF80FF80) >> 7; + b = (((X32COL2(color)) * g_soft.g_m2) & 0xFF80FF80) >> 7; + g = (((X32COL3(color)) * g_soft.g_m3) & 0xFF80FF80) >> 7; + } + + if (r & 0x7FE00000) + r = 0x1f0000 | (r & 0xFFFF); + if (r & 0x7FE0) + r = 0x1f | (r & 0xFFFF0000); + if (b & 0x7FE00000) + b = 0x1f0000 | (b & 0xFFFF); + if (b & 0x7FE0) + b = 0x1f | (b & 0xFFFF0000); + if (g & 0x7FE00000) + g = 0x1f0000 | (g & 0xFFFF); + if (g & 0x7FE0) + g = 0x1f | (g & 0xFFFF0000); + + if (g_draw.bCheckMask) { + uint32_t ma = GETLE32(pdest); + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|g_draw.lSetMask|(color&0x80008000)); + + if ((color & 0xffff) == 0) + PUTLE32(pdest, (ma&0xffff)|(GETLE32(pdest)&0xffff0000)); + if ((color & 0xffff0000) == 0) + PUTLE32(pdest, (ma&0xffff0000)|(GETLE32(pdest)&0xffff)); + if (ma & 0x80000000) + PUTLE32(pdest, (ma&0xFFFF0000)|(GETLE32(pdest)&0xFFFF)); + if (ma & 0x00008000) + PUTLE32(pdest, (ma&0xFFFF) |(GETLE32(pdest)&0xFFFF0000)); + + return; + } + if ((color & 0xffff) == 0) { + PUTLE32(pdest, (GETLE32(pdest)&0xffff)|(((X32PSXCOL(r,g,b))|g_draw.lSetMask|(color&0x80008000))&0xffff0000)); + return; + } + if ((color & 0xffff0000) == 0) { + PUTLE32(pdest, (GETLE32(pdest)&0xffff0000)|(((X32PSXCOL(r,g,b))|g_draw.lSetMask|(color&0x80008000))&0xffff)); + return; + } + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|g_draw.lSetMask|(color&0x80008000)); +} + +//////////////////////////////////////////////////////////////////////// + +inline void GetTextureTransColGX_Dither(unsigned short * pdest, + unsigned short color, int32_t m1, int32_t m2, int32_t m3) { + int32_t r, g, b; + + if (color == 0) + return; + + if (g_draw.bCheckMask && (*pdest & HOST2LE16(0x8000))) + return; + + m1 = (((XCOL1D(color))) * m1) >> 4; + m2 = (((XCOL2D(color))) * m2) >> 4; + m3 = (((XCOL3D(color))) * m3) >> 4; + + if (g_soft.DrawSemiTrans && (color & 0x8000)) { + r = ((XCOL1D(GETLE16(pdest))) << 3); + b = ((XCOL2D(GETLE16(pdest))) << 3); + g = ((XCOL3D(GETLE16(pdest))) << 3); + + if (g_soft.GlobalTextABR == 0) { + r = (r >> 1) + (m1 >> 1); + b = (b >> 1) + (m2 >> 1); + g = (g >> 1) + (m3 >> 1); + } else if (g_soft.GlobalTextABR == 1) { + r += m1; + b += m2; + g += m3; + } else if (g_soft.GlobalTextABR == 2) { + r -= m1; + b -= m2; + g -= m3; + if (r & 0x80000000) + r = 0; + if (b & 0x80000000) + b = 0; + if (g & 0x80000000) + g = 0; + } else { +#ifdef HALFBRIGHTMODE3 + r += (m1 >> 2); + b += (m2 >> 2); + g += (m3 >> 2); +#else + r+=(m1>>1); + b+=(m2>>1); + g+=(m3>>1); +#endif + } + } else { + r = m1; + b = m2; + g = m3; + } + + if (r & 0x7FFFFF00) + r = 0xff; + if (b & 0x7FFFFF00) + b = 0xff; + if (g & 0x7FFFFF00) + g = 0xff; + + Dither16(pdest, r, b, g, g_draw.sSetMask | (color & 0x8000)); + +} + +//////////////////////////////////////////////////////////////////////// + +inline void GetTextureTransColGX(unsigned short * pdest, unsigned short color, + short m1, short m2, short m3) { + int32_t r, g, b; + unsigned short l; + + if (color == 0) + return; + + if (g_draw.bCheckMask && (*pdest & HOST2LE16(0x8000))) + return; + + l = g_draw.sSetMask | (color & 0x8000); + + if (g_soft.DrawSemiTrans && (color & 0x8000)) { + if (g_soft.GlobalTextABR == 0) { + unsigned short d; + d = (GETLE16(pdest) & 0x7bde) >> 1; + color = ((color) & 0x7bde) >> 1; + r = (XCOL1(d)) + ((((XCOL1(color))) * m1) >> 7); + b = (XCOL2(d)) + ((((XCOL2(color))) * m2) >> 7); + g = (XCOL3(d)) + ((((XCOL3(color))) * m3) >> 7); + /* + r=(XCOL1(*pdest)>>1)+((((XCOL1(color))>>1)* m1)>>7); + b=(XCOL2(*pdest)>>1)+((((XCOL2(color))>>1)* m2)>>7); + g=(XCOL3(*pdest)>>1)+((((XCOL3(color))>>1)* m3)>>7); + */ + } else if (g_soft.GlobalTextABR == 1) { + r = (XCOL1(GETLE16(pdest))) + ((((XCOL1(color))) * m1) >> 7); + b = (XCOL2(GETLE16(pdest))) + ((((XCOL2(color))) * m2) >> 7); + g = (XCOL3(GETLE16(pdest))) + ((((XCOL3(color))) * m3) >> 7); + } else if (g_soft.GlobalTextABR == 2) { + r = (XCOL1(GETLE16(pdest))) - ((((XCOL1(color))) * m1) >> 7); + b = (XCOL2(GETLE16(pdest))) - ((((XCOL2(color))) * m2) >> 7); + g = (XCOL3(GETLE16(pdest))) - ((((XCOL3(color))) * m3) >> 7); + if (r & 0x80000000) + r = 0; + if (b & 0x80000000) + b = 0; + if (g & 0x80000000) + g = 0; + } else { +#ifdef HALFBRIGHTMODE3 + r = (XCOL1(GETLE16(pdest))) + ((((XCOL1(color)) >> 2) * m1) >> 7); + b = (XCOL2(GETLE16(pdest))) + ((((XCOL2(color)) >> 2) * m2) >> 7); + g = (XCOL3(GETLE16(pdest))) + ((((XCOL3(color)) >> 2) * m3) >> 7); +#else + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color))>>1)* m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>1)* m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>1)* m3)>>7); +#endif + } + } else { + r = ((XCOL1(color)) * m1) >> 7; + b = ((XCOL2(color)) * m2) >> 7; + g = ((XCOL3(color)) * m3) >> 7; + } + + if (r & 0x7FFFFFE0) + r = 0x1f; + if (b & 0x7FFFFC00) + b = 0x3e0; + if (g & 0x7FFF8000) + g = 0x7c00; + + PUTLE16(pdest, (XPSXCOL(r,g,b))|l); +} + +//////////////////////////////////////////////////////////////////////// + +inline void GetTextureTransColGX_S(unsigned short * pdest, + unsigned short color, short m1, short m2, short m3) { + int32_t r, g, b; + + if (color == 0) + return; + + r = ((XCOL1(color)) * m1) >> 7; + b = ((XCOL2(color)) * m2) >> 7; + g = ((XCOL3(color)) * m3) >> 7; + + if (r & 0x7FFFFFE0) + r = 0x1f; + if (b & 0x7FFFFC00) + b = 0x3e0; + if (g & 0x7FFF8000) + g = 0x7c00; + + PUTLE16(pdest, (XPSXCOL(r,g,b))|g_draw.sSetMask|(color&0x8000)); +} + +//////////////////////////////////////////////////////////////////////// + +inline void GetTextureTransColGX32_S(uint32_t * pdest, uint32_t color, + short m1, short m2, short m3) { + int32_t r, g, b; + + if (color == 0) + return; + + r = (((X32COL1(color)) * m1) & 0xFF80FF80) >> 7; + b = (((X32COL2(color)) * m2) & 0xFF80FF80) >> 7; + g = (((X32COL3(color)) * m3) & 0xFF80FF80) >> 7; + + if (r & 0x7FE00000) + r = 0x1f0000 | (r & 0xFFFF); + if (r & 0x7FE0) + r = 0x1f | (r & 0xFFFF0000); + if (b & 0x7FE00000) + b = 0x1f0000 | (b & 0xFFFF); + if (b & 0x7FE0) + b = 0x1f | (b & 0xFFFF0000); + if (g & 0x7FE00000) + g = 0x1f0000 | (g & 0xFFFF); + if (g & 0x7FE0) + g = 0x1f | (g & 0xFFFF0000); + + if ((color & 0xffff) == 0) { + PUTLE32(pdest, (GETLE32(pdest)&0xffff)|(((X32PSXCOL(r,g,b))|g_draw.lSetMask|(color&0x80008000))&0xffff0000)); + return; + } + if ((color & 0xffff0000) == 0) { + PUTLE32(pdest, (GETLE32(pdest)&0xffff0000)|(((X32PSXCOL(r,g,b))|g_draw.lSetMask|(color&0x80008000))&0xffff)); + return; + } + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|g_draw.lSetMask|(color&0x80008000)); +} + +//////////////////////////////////////////////////////////////////////// +// FILL FUNCS +//////////////////////////////////////////////////////////////////////// + +void FillSoftwareAreaTrans(short x0, short y0, short x1, // FILL AREA TRANS + short y1, unsigned short col) { + short j, i, dx, dy; + + if (y0 > y1) + return; + if (x0 > x1) + return; + + if (x1 < g_prim.drawX) + return; + if (y1 < g_prim.drawY) + return; + if (x0 > g_prim.drawW) + return; + if (y0 > g_prim.drawH) + return; + + x1 = MIN(x1, g_prim.drawW + 1); + y1 = MIN(y1, g_prim.drawH + 1); + x0 = MAX(x0, g_prim.drawX); + y0 = MAX(y0, g_prim.drawY); + + if (y0 >= 512) + return; + if (x0 > 1023) + return; + + if (y1 > 512) + y1 = 512; + if (x1 > 1024) + x1 = 1024; + + dx = x1 - x0; + dy = y1 - y0; + + if (dx == 1 && dy == 1 && x0 == 1020 && y0 == 511) // special fix for pinball game... emu protection??? + { + /* + m->v 1020 511 1 1 + writedatamem 0x00000000 1 + tile1 newcol 7fff (orgcol 0xffffff), oldvram 0 + v->m 1020 511 1 1 + readdatamem 0x00007fff 1 + m->v 1020 511 1 1 + writedatamem 0x00000000 1 + tile1 newcol 8000 (orgcol 0xffffff), oldvram 0 + v->m 1020 511 1 1 + readdatamem 0x00008000 1 + */ + + static int iCheat = 0; + col += iCheat; + if (iCheat == 1) + iCheat = 0; + else + iCheat = 1; + } + + if (dx & 1) // slow fill + { + unsigned short *DSTPtr; + unsigned short LineOffset; + DSTPtr = g_gpu.psx_vram.u16 + (1024 * y0) + x0; + LineOffset = 1024 - dx; + for (i = 0; i < dy; i++) { + for (j = 0; j < dx; j++) + GetShadeTransCol(DSTPtr++, col); + DSTPtr += LineOffset; + } + } else // fast fill + { + uint32_t *DSTPtr; + unsigned short LineOffset; + uint32_t lcol = g_draw.lSetMask | (((uint32_t) (col)) << 16) | col; + dx >>= 1; + DSTPtr = (uint32_t *) (g_gpu.psx_vram.u16 + (1024 * y0) + x0); + LineOffset = 512 - dx; + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = 0; i < dy; i++) { + for (j = 0; j < dx; j++) { + PUTLE32(DSTPtr, lcol); + DSTPtr++; + } + DSTPtr += LineOffset; + } + } else { + for (i = 0; i < dy; i++) { + for (j = 0; j < dx; j++) + GetShadeTransCol32(DSTPtr++, lcol); + DSTPtr += LineOffset; + } + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void FillSoftwareArea(short x0, short y0, short x1, // FILL AREA (BLK FILL) + short y1, unsigned short col) // no draw area check here! +{ + short j, i, dx, dy; + + if (y0 > y1) + return; + if (x0 > x1) + return; + + if (y0 >= 512) + return; + if (x0 > 1023) + return; + + if (y1 > 512) + y1 = 512; + if (x1 > 1024) + x1 = 1024; + + dx = x1 - x0; + dy = y1 - y0; + if (dx & 1) { + unsigned short *DSTPtr; + unsigned short LineOffset; + + DSTPtr = g_gpu.psx_vram.u16 + (1024 * y0) + x0; + LineOffset = 1024 - dx; + + for (i = 0; i < dy; i++) { + for (j = 0; j < dx; j++) { + PUTLE16(DSTPtr, col); + DSTPtr++; + } + DSTPtr += LineOffset; + } + } else { + uint32_t *DSTPtr; + unsigned short LineOffset; + uint32_t lcol = (((int32_t) col) << 16) | col; + dx >>= 1; + DSTPtr = (uint32_t *) (g_gpu.psx_vram.u16 + (1024 * y0) + x0); + LineOffset = 512 - dx; + + for (i = 0; i < dy; i++) { + for (j = 0; j < dx; j++) { + PUTLE32(DSTPtr, lcol); + DSTPtr++; + } + DSTPtr += LineOffset; + } + } +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// EDGE INTERPOLATION +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +typedef struct SOFTVTAG { + int x, y; + int u, v; + int32_t R, G, B; +} soft_vertex; + +static soft_vertex vtx[4]; +static soft_vertex * left_array[4], *right_array[4]; +static int left_section, right_section; +static int left_section_height, right_section_height; +static int left_x, delta_left_x, right_x, delta_right_x; +static int left_u, delta_left_u, left_v, delta_left_v; +static int right_u, delta_right_u, right_v, delta_right_v; +static int left_R, delta_left_R, right_R, delta_right_R; +static int left_G, delta_left_G, right_G, delta_right_G; +static int left_B, delta_left_B, right_B, delta_right_B; + +#ifdef USE_NASM + +// NASM version (external): +#define shl10idiv i386_shl10idiv + +inline int shl10idiv(int x, int y); + +#else + +inline int shl10idiv(int x, int y) { + int64_t bi = x; + bi <<= 10; + return bi / y; +} + +#endif + +#if 0 + +// GNUC long long int version: + +inline int shl10idiv(int x, int y) +{ + long long int bi=x; + bi<<=10; + return bi/y; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +inline int RightSection_F(void) { + soft_vertex * v1 = right_array[right_section]; + soft_vertex * v2 = right_array[right_section - 1]; + + int height = v2->y - v1->y; + if (height == 0) + return 0; + delta_right_x = (v2->x - v1->x) / height; + right_x = v1->x; + + right_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +inline int LeftSection_F(void) { + soft_vertex * v1 = left_array[left_section]; + soft_vertex * v2 = left_array[left_section - 1]; + + int height = v2->y - v1->y; + if (height == 0) + return 0; + delta_left_x = (v2->x - v1->x) / height; + left_x = v1->x; + + left_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +inline char NextRow_F(void) { + if (--left_section_height <= 0) { + if (--left_section <= 0) { + return 1; + } + if (LeftSection_F() <= 0) { + return 1; + } + } else { + left_x += delta_left_x; + } + + if (--right_section_height <= 0) { + if (--right_section <= 0) { + return 1; + } + if (RightSection_F() <= 0) { + return 1; + } + } else { + right_x += delta_right_x; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////// + +inline char SetupSections_F(short x1, short y1, short x2, short y2, short x3, + short y3) { + soft_vertex * v1, *v2, *v3; + int height, longest; + + v1 = vtx; + v1->x = x1 << 16; + v1->y = y1; + v2 = vtx + 1; + v2->x = x2 << 16; + v2->y = y2; + v3 = vtx + 2; + v3->x = x3 << 16; + v3->y = y3; + + if (v1->y > v2->y) { + soft_vertex * v = v1; + v1 = v2; + v2 = v; + } + if (v1->y > v3->y) { + soft_vertex * v = v1; + v1 = v3; + v3 = v; + } + if (v2->y > v3->y) { + soft_vertex * v = v2; + v2 = v3; + v3 = v; + } + + height = v3->y - v1->y; + if (height == 0) { + return 0; + } + longest = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x) >> 16) + + (v1->x - v2->x); + if (longest == 0) { + return 0; + } + + if (longest < 0) { + right_array[0] = v3; + right_array[1] = v2; + right_array[2] = v1; + right_section = 2; + left_array[0] = v3; + left_array[1] = v1; + left_section = 1; + + if (LeftSection_F() <= 0) + return 0; + if (RightSection_F() <= 0) { + right_section--; + if (RightSection_F() <= 0) + return 0; + } + } else { + left_array[0] = v3; + left_array[1] = v2; + left_array[2] = v1; + left_section = 2; + right_array[0] = v3; + right_array[1] = v1; + right_section = 1; + + if (RightSection_F() <= 0) + return 0; + if (LeftSection_F() <= 0) { + left_section--; + if (LeftSection_F() <= 0) + return 0; + } + } + + g_soft.Ymin = v1->y; + g_soft.Ymax = MIN(v3->y - 1, g_prim.drawH); + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +inline int RightSection_G(void) { + soft_vertex * v1 = right_array[right_section]; + soft_vertex * v2 = right_array[right_section - 1]; + + int height = v2->y - v1->y; + if (height == 0) + return 0; + delta_right_x = (v2->x - v1->x) / height; + right_x = v1->x; + + right_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +inline int LeftSection_G(void) { + soft_vertex * v1 = left_array[left_section]; + soft_vertex * v2 = left_array[left_section - 1]; + + int height = v2->y - v1->y; + if (height == 0) + return 0; + delta_left_x = (v2->x - v1->x) / height; + left_x = v1->x; + + delta_left_R = ((v2->R - v1->R)) / height; + left_R = v1->R; + delta_left_G = ((v2->G - v1->G)) / height; + left_G = v1->G; + delta_left_B = ((v2->B - v1->B)) / height; + left_B = v1->B; + + left_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +inline char NextRow_G(void) { + if (--left_section_height <= 0) { + if (--left_section <= 0) { + return 1; + } + if (LeftSection_G() <= 0) { + return 1; + } + } else { + left_x += delta_left_x; + left_R += delta_left_R; + left_G += delta_left_G; + left_B += delta_left_B; + } + + if (--right_section_height <= 0) { + if (--right_section <= 0) { + return 1; + } + if (RightSection_G() <= 0) { + return 1; + } + } else { + right_x += delta_right_x; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////// + +inline char SetupSections_G(short x1, short y1, short x2, short y2, short x3, + short y3, int32_t rgb1, int32_t rgb2, int32_t rgb3) { + soft_vertex * v1, *v2, *v3; + int height, longest, temp; + + v1 = vtx; + v1->x = x1 << 16; + v1->y = y1; + v1->R = (rgb1) & 0x00ff0000; + v1->G = (rgb1 << 8) & 0x00ff0000; + v1->B = (rgb1 << 16) & 0x00ff0000; + v2 = vtx + 1; + v2->x = x2 << 16; + v2->y = y2; + v2->R = (rgb2) & 0x00ff0000; + v2->G = (rgb2 << 8) & 0x00ff0000; + v2->B = (rgb2 << 16) & 0x00ff0000; + v3 = vtx + 2; + v3->x = x3 << 16; + v3->y = y3; + v3->R = (rgb3) & 0x00ff0000; + v3->G = (rgb3 << 8) & 0x00ff0000; + v3->B = (rgb3 << 16) & 0x00ff0000; + + if (v1->y > v2->y) { + soft_vertex * v = v1; + v1 = v2; + v2 = v; + } + if (v1->y > v3->y) { + soft_vertex * v = v1; + v1 = v3; + v3 = v; + } + if (v2->y > v3->y) { + soft_vertex * v = v2; + v2 = v3; + v3 = v; + } + + height = v3->y - v1->y; + if (height == 0) { + return 0; + } + temp = (((v2->y - v1->y) << 16) / height); + longest = temp * ((v3->x - v1->x) >> 16) + (v1->x - v2->x); + if (longest == 0) { + return 0; + } + + if (longest < 0) { + right_array[0] = v3; + right_array[1] = v2; + right_array[2] = v1; + right_section = 2; + left_array[0] = v3; + left_array[1] = v1; + left_section = 1; + + if (LeftSection_G() <= 0) + return 0; + if (RightSection_G() <= 0) { + right_section--; + if (RightSection_G() <= 0) + return 0; + } + if (longest > -0x1000) + longest = -0x1000; + } else { + left_array[0] = v3; + left_array[1] = v2; + left_array[2] = v1; + left_section = 2; + right_array[0] = v3; + right_array[1] = v1; + right_section = 1; + + if (RightSection_G() <= 0) + return 0; + if (LeftSection_G() <= 0) { + left_section--; + if (LeftSection_G() <= 0) + return 0; + } + if (longest < 0x1000) + longest = 0x1000; + } + + g_soft.Ymin = v1->y; + g_soft.Ymax = MIN(v3->y - 1, g_prim.drawH); + + delta_right_R = shl10idiv(temp * ((v3->R - v1->R) >> 10) + ((v1->R - v2->R) + << 6), longest); + delta_right_G = shl10idiv(temp * ((v3->G - v1->G) >> 10) + ((v1->G - v2->G) + << 6), longest); + delta_right_B = shl10idiv(temp * ((v3->B - v1->B) >> 10) + ((v1->B - v2->B) + << 6), longest); + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +inline int RightSection_FT(void) { + soft_vertex * v1 = right_array[right_section]; + soft_vertex * v2 = right_array[right_section - 1]; + + int height = v2->y - v1->y; + if (height == 0) + return 0; + delta_right_x = (v2->x - v1->x) / height; + right_x = v1->x; + + right_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +inline int LeftSection_FT(void) { + soft_vertex * v1 = left_array[left_section]; + soft_vertex * v2 = left_array[left_section - 1]; + + int height = v2->y - v1->y; + if (height == 0) + return 0; + delta_left_x = (v2->x - v1->x) / height; + left_x = v1->x; + + delta_left_u = ((v2->u - v1->u)) / height; + left_u = v1->u; + delta_left_v = ((v2->v - v1->v)) / height; + left_v = v1->v; + + left_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +inline char NextRow_FT(void) { + if (--left_section_height <= 0) { + if (--left_section <= 0) { + return 1; + } + if (LeftSection_FT() <= 0) { + return 1; + } + } else { + left_x += delta_left_x; + left_u += delta_left_u; + left_v += delta_left_v; + } + + if (--right_section_height <= 0) { + if (--right_section <= 0) { + return 1; + } + if (RightSection_FT() <= 0) { + return 1; + } + } else { + right_x += delta_right_x; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////// + +inline char SetupSections_FT(short x1, short y1, short x2, short y2, short x3, + short y3, short tx1, short ty1, short tx2, short ty2, short tx3, + short ty3) { + soft_vertex * v1, *v2, *v3; + int height, longest, temp; + + v1 = vtx; + v1->x = x1 << 16; + v1->y = y1; + v1->u = tx1 << 16; + v1->v = ty1 << 16; + v2 = vtx + 1; + v2->x = x2 << 16; + v2->y = y2; + v2->u = tx2 << 16; + v2->v = ty2 << 16; + v3 = vtx + 2; + v3->x = x3 << 16; + v3->y = y3; + v3->u = tx3 << 16; + v3->v = ty3 << 16; + + if (v1->y > v2->y) { + soft_vertex * v = v1; + v1 = v2; + v2 = v; + } + if (v1->y > v3->y) { + soft_vertex * v = v1; + v1 = v3; + v3 = v; + } + if (v2->y > v3->y) { + soft_vertex * v = v2; + v2 = v3; + v3 = v; + } + + height = v3->y - v1->y; + if (height == 0) { + return 0; + } + + temp = (((v2->y - v1->y) << 16) / height); + longest = temp * ((v3->x - v1->x) >> 16) + (v1->x - v2->x); + + if (longest == 0) { + return 0; + } + + if (longest < 0) { + right_array[0] = v3; + right_array[1] = v2; + right_array[2] = v1; + right_section = 2; + left_array[0] = v3; + left_array[1] = v1; + left_section = 1; + + if (LeftSection_FT() <= 0) + return 0; + if (RightSection_FT() <= 0) { + right_section--; + if (RightSection_FT() <= 0) + return 0; + } + if (longest > -0x1000) + longest = -0x1000; + } else { + left_array[0] = v3; + left_array[1] = v2; + left_array[2] = v1; + left_section = 2; + right_array[0] = v3; + right_array[1] = v1; + right_section = 1; + + if (RightSection_FT() <= 0) + return 0; + if (LeftSection_FT() <= 0) { + left_section--; + if (LeftSection_FT() <= 0) + return 0; + } + if (longest < 0x1000) + longest = 0x1000; + } + + g_soft.Ymin = v1->y; + g_soft.Ymax = MIN(v3->y - 1, g_prim.drawH); + + delta_right_u = shl10idiv(temp * ((v3->u - v1->u) >> 10) + ((v1->u - v2->u) + << 6), longest); + delta_right_v = shl10idiv(temp * ((v3->v - v1->v) >> 10) + ((v1->v - v2->v) + << 6), longest); + + /* + Mmm... adjust neg tex deltas... will sometimes cause slight + texture distortions + + longest>>=16; + if(longest) + { + if(longest<0) longest=-longest; + if(delta_right_u<0) + delta_right_u-=delta_right_u/longest; + if(delta_right_v<0) + delta_right_v-=delta_right_v/longest; + } + */ + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +inline int RightSection_GT(void) { + soft_vertex * v1 = right_array[right_section]; + soft_vertex * v2 = right_array[right_section - 1]; + + int height = v2->y - v1->y; + if (height == 0) + return 0; + delta_right_x = (v2->x - v1->x) / height; + right_x = v1->x; + + right_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +inline int LeftSection_GT(void) { + soft_vertex * v1 = left_array[left_section]; + soft_vertex * v2 = left_array[left_section - 1]; + + int height = v2->y - v1->y; + if (height == 0) + return 0; + delta_left_x = (v2->x - v1->x) / height; + left_x = v1->x; + + delta_left_u = ((v2->u - v1->u)) / height; + left_u = v1->u; + delta_left_v = ((v2->v - v1->v)) / height; + left_v = v1->v; + + delta_left_R = ((v2->R - v1->R)) / height; + left_R = v1->R; + delta_left_G = ((v2->G - v1->G)) / height; + left_G = v1->G; + delta_left_B = ((v2->B - v1->B)) / height; + left_B = v1->B; + + left_section_height = height; + return height; +} + +//////////////////////////////////////////////////////////////////////// + +inline char NextRow_GT(void) { + if (--left_section_height <= 0) { + if (--left_section <= 0) { + return 1; + } + if (LeftSection_GT() <= 0) { + return 1; + } + } else { + left_x += delta_left_x; + left_u += delta_left_u; + left_v += delta_left_v; + left_R += delta_left_R; + left_G += delta_left_G; + left_B += delta_left_B; + } + + if (--right_section_height <= 0) { + if (--right_section <= 0) { + return 1; + } + if (RightSection_GT() <= 0) { + return 1; + } + } else { + right_x += delta_right_x; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////// + +inline char SetupSections_GT(short x1, short y1, short x2, short y2, short x3, + short y3, short tx1, short ty1, short tx2, short ty2, short tx3, + short ty3, int32_t rgb1, int32_t rgb2, int32_t rgb3) { + soft_vertex * v1, *v2, *v3; + int height, longest, temp; + + v1 = vtx; + v1->x = x1 << 16; + v1->y = y1; + v1->u = tx1 << 16; + v1->v = ty1 << 16; + v1->R = (rgb1) & 0x00ff0000; + v1->G = (rgb1 << 8) & 0x00ff0000; + v1->B = (rgb1 << 16) & 0x00ff0000; + + v2 = vtx + 1; + v2->x = x2 << 16; + v2->y = y2; + v2->u = tx2 << 16; + v2->v = ty2 << 16; + v2->R = (rgb2) & 0x00ff0000; + v2->G = (rgb2 << 8) & 0x00ff0000; + v2->B = (rgb2 << 16) & 0x00ff0000; + + v3 = vtx + 2; + v3->x = x3 << 16; + v3->y = y3; + v3->u = tx3 << 16; + v3->v = ty3 << 16; + v3->R = (rgb3) & 0x00ff0000; + v3->G = (rgb3 << 8) & 0x00ff0000; + v3->B = (rgb3 << 16) & 0x00ff0000; + + if (v1->y > v2->y) { + soft_vertex * v = v1; + v1 = v2; + v2 = v; + } + if (v1->y > v3->y) { + soft_vertex * v = v1; + v1 = v3; + v3 = v; + } + if (v2->y > v3->y) { + soft_vertex * v = v2; + v2 = v3; + v3 = v; + } + + height = v3->y - v1->y; + if (height == 0) { + return 0; + } + + temp = (((v2->y - v1->y) << 16) / height); + longest = temp * ((v3->x - v1->x) >> 16) + (v1->x - v2->x); + + if (longest == 0) { + return 0; + } + + if (longest < 0) { + right_array[0] = v3; + right_array[1] = v2; + right_array[2] = v1; + right_section = 2; + left_array[0] = v3; + left_array[1] = v1; + left_section = 1; + + if (LeftSection_GT() <= 0) + return 0; + if (RightSection_GT() <= 0) { + right_section--; + if (RightSection_GT() <= 0) + return 0; + } + + if (longest > -0x1000) + longest = -0x1000; + } else { + left_array[0] = v3; + left_array[1] = v2; + left_array[2] = v1; + left_section = 2; + right_array[0] = v3; + right_array[1] = v1; + right_section = 1; + + if (RightSection_GT() <= 0) + return 0; + if (LeftSection_GT() <= 0) { + left_section--; + if (LeftSection_GT() <= 0) + return 0; + } + if (longest < 0x1000) + longest = 0x1000; + } + + g_soft.Ymin = v1->y; + g_soft.Ymax = MIN(v3->y - 1, g_prim.drawH); + + delta_right_R = shl10idiv(temp * ((v3->R - v1->R) >> 10) + ((v1->R - v2->R) + << 6), longest); + delta_right_G = shl10idiv(temp * ((v3->G - v1->G) >> 10) + ((v1->G - v2->G) + << 6), longest); + delta_right_B = shl10idiv(temp * ((v3->B - v1->B) >> 10) + ((v1->B - v2->B) + << 6), longest); + + delta_right_u = shl10idiv(temp * ((v3->u - v1->u) >> 10) + ((v1->u - v2->u) + << 6), longest); + delta_right_v = shl10idiv(temp * ((v3->v - v1->v) >> 10) + ((v1->v - v2->v) + << 6), longest); + + /* + Mmm... adjust neg tex deltas... will sometimes cause slight + texture distortions + longest>>=16; + if(longest) + { + if(longest<0) longest=-longest; + if(delta_right_u<0) + delta_right_u-=delta_right_u/longest; + if(delta_right_v<0) + delta_right_v-=delta_right_v/longest; + } + */ + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +inline int RightSection_F4(void) { + soft_vertex * v1 = right_array[right_section]; + soft_vertex * v2 = right_array[right_section - 1]; + + int height = v2->y - v1->y; + right_section_height = height; + right_x = v1->x; + if (height == 0) { + return 0; + } + delta_right_x = (v2->x - v1->x) / height; + + return height; +} + +//////////////////////////////////////////////////////////////////////// + +inline int LeftSection_F4(void) { + soft_vertex * v1 = left_array[left_section]; + soft_vertex * v2 = left_array[left_section - 1]; + + int height = v2->y - v1->y; + left_section_height = height; + left_x = v1->x; + if (height == 0) { + return 0; + } + delta_left_x = (v2->x - v1->x) / height; + + return height; +} + +//////////////////////////////////////////////////////////////////////// + +inline char NextRow_F4(void) { + if (--left_section_height <= 0) { + if (--left_section > 0) + while (LeftSection_F4() <= 0) { + if (--left_section <= 0) + break; + } + } else { + left_x += delta_left_x; + } + + if (--right_section_height <= 0) { + if (--right_section > 0) + while (RightSection_F4() <= 0) { + if (--right_section <= 0) + break; + } + } else { + right_x += delta_right_x; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////// + +inline char SetupSections_F4(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4) { + soft_vertex * v1, *v2, *v3, *v4; + int height, width, longest1, longest2; + + v1 = vtx; + v1->x = x1 << 16; + v1->y = y1; + v2 = vtx + 1; + v2->x = x2 << 16; + v2->y = y2; + v3 = vtx + 2; + v3->x = x3 << 16; + v3->y = y3; + v4 = vtx + 3; + v4->x = x4 << 16; + v4->y = y4; + + if (v1->y > v2->y) { + soft_vertex * v = v1; + v1 = v2; + v2 = v; + } + if (v1->y > v3->y) { + soft_vertex * v = v1; + v1 = v3; + v3 = v; + } + if (v1->y > v4->y) { + soft_vertex * v = v1; + v1 = v4; + v4 = v; + } + if (v2->y > v3->y) { + soft_vertex * v = v2; + v2 = v3; + v3 = v; + } + if (v2->y > v4->y) { + soft_vertex * v = v2; + v2 = v4; + v4 = v; + } + if (v3->y > v4->y) { + soft_vertex * v = v3; + v3 = v4; + v4 = v; + } + + height = v4->y - v1->y; + if (height == 0) + height = 1; + width = (v4->x - v1->x) >> 16; + longest1 = (((v2->y - v1->y) << 16) / height) * width + (v1->x - v2->x); + longest2 = (((v3->y - v1->y) << 16) / height) * width + (v1->x - v3->x); + + if (longest1 < 0) // 2 is right + { + if (longest2 < 0) // 3 is right + { + left_array[0] = v4; + left_array[1] = v1; + left_section = 1; + + height = v3->y - v1->y; + if (height == 0) + height = 1; + longest1 = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x) + >> 16) + (v1->x - v2->x); + if (longest1 >= 0) { + right_array[0] = v4; // 1 + right_array[1] = v3; // 3 + right_array[2] = v1; // 4 + right_section = 2; + } else { + height = v4->y - v2->y; + if (height == 0) + height = 1; + longest1 = (((v3->y - v2->y) << 16) / height) + * ((v4->x - v2->x) >> 16) + (v2->x - v3->x); + if (longest1 >= 0) { + right_array[0] = v4; // 1 + right_array[1] = v2; // 2 + right_array[2] = v1; // 4 + right_section = 2; + } else { + right_array[0] = v4; // 1 + right_array[1] = v3; // 2 + right_array[2] = v2; // 3 + right_array[3] = v1; // 4 + right_section = 3; + } + } + } else { + left_array[0] = v4; + left_array[1] = v3; // 1 + left_array[2] = v1; // 2 + left_section = 2; // 3 + right_array[0] = v4; // 4 + right_array[1] = v2; + right_array[2] = v1; + right_section = 2; + } + } else { + if (longest2 < 0) { + left_array[0] = v4; // 1 + left_array[1] = v2; // 2 + left_array[2] = v1; // 3 + left_section = 2; // 4 + right_array[0] = v4; + right_array[1] = v3; + right_array[2] = v1; + right_section = 2; + } else { + right_array[0] = v4; + right_array[1] = v1; + right_section = 1; + + height = v3->y - v1->y; + if (height == 0) + height = 1; + longest1 = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x) + >> 16) + (v1->x - v2->x); + if (longest1 < 0) { + left_array[0] = v4; // 1 + left_array[1] = v3; // 3 + left_array[2] = v1; // 4 + left_section = 2; + } else { + height = v4->y - v2->y; + if (height == 0) + height = 1; + longest1 = (((v3->y - v2->y) << 16) / height) + * ((v4->x - v2->x) >> 16) + (v2->x - v3->x); + if (longest1 < 0) { + left_array[0] = v4; // 1 + left_array[1] = v2; // 2 + left_array[2] = v1; // 4 + left_section = 2; + } else { + left_array[0] = v4; // 1 + left_array[1] = v3; // 2 + left_array[2] = v2; // 3 + left_array[3] = v1; // 4 + left_section = 3; + } + } + } + } + + while (LeftSection_F4() <= 0) { + if (--left_section <= 0) + break; + } + + while (RightSection_F4() <= 0) { + if (--right_section <= 0) + break; + } + + g_soft.Ymin = v1->y; + g_soft.Ymax = MIN(v4->y - 1, g_prim.drawH); + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +inline int RightSection_FT4(void) { + soft_vertex * v1 = right_array[right_section]; + soft_vertex * v2 = right_array[right_section - 1]; + + int height = v2->y - v1->y; + right_section_height = height; + right_x = v1->x; + right_u = v1->u; + right_v = v1->v; + if (height == 0) { + return 0; + } + delta_right_x = (v2->x - v1->x) / height; + delta_right_u = (v2->u - v1->u) / height; + delta_right_v = (v2->v - v1->v) / height; + + return height; +} + +//////////////////////////////////////////////////////////////////////// + +inline int LeftSection_FT4(void) { + soft_vertex * v1 = left_array[left_section]; + soft_vertex * v2 = left_array[left_section - 1]; + + int height = v2->y - v1->y; + left_section_height = height; + left_x = v1->x; + left_u = v1->u; + left_v = v1->v; + if (height == 0) { + return 0; + } + delta_left_x = (v2->x - v1->x) / height; + delta_left_u = (v2->u - v1->u) / height; + delta_left_v = (v2->v - v1->v) / height; + + return height; +} + +//////////////////////////////////////////////////////////////////////// + +inline char NextRow_FT4(void) { + if (--left_section_height <= 0) { + if (--left_section > 0) + while (LeftSection_FT4() <= 0) { + if (--left_section <= 0) + break; + } + } else { + left_x += delta_left_x; + left_u += delta_left_u; + left_v += delta_left_v; + } + + if (--right_section_height <= 0) { + if (--right_section > 0) + while (RightSection_FT4() <= 0) { + if (--right_section <= 0) + break; + } + } else { + right_x += delta_right_x; + right_u += delta_right_u; + right_v += delta_right_v; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////// + +inline char SetupSections_FT4(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4) { + soft_vertex * v1, *v2, *v3, *v4; + int height, width, longest1, longest2; + + v1 = vtx; + v1->x = x1 << 16; + v1->y = y1; + v1->u = tx1 << 16; + v1->v = ty1 << 16; + + v2 = vtx + 1; + v2->x = x2 << 16; + v2->y = y2; + v2->u = tx2 << 16; + v2->v = ty2 << 16; + + v3 = vtx + 2; + v3->x = x3 << 16; + v3->y = y3; + v3->u = tx3 << 16; + v3->v = ty3 << 16; + + v4 = vtx + 3; + v4->x = x4 << 16; + v4->y = y4; + v4->u = tx4 << 16; + v4->v = ty4 << 16; + + if (v1->y > v2->y) { + soft_vertex * v = v1; + v1 = v2; + v2 = v; + } + if (v1->y > v3->y) { + soft_vertex * v = v1; + v1 = v3; + v3 = v; + } + if (v1->y > v4->y) { + soft_vertex * v = v1; + v1 = v4; + v4 = v; + } + if (v2->y > v3->y) { + soft_vertex * v = v2; + v2 = v3; + v3 = v; + } + if (v2->y > v4->y) { + soft_vertex * v = v2; + v2 = v4; + v4 = v; + } + if (v3->y > v4->y) { + soft_vertex * v = v3; + v3 = v4; + v4 = v; + } + + height = v4->y - v1->y; + if (height == 0) + height = 1; + width = (v4->x - v1->x) >> 16; + longest1 = (((v2->y - v1->y) << 16) / height) * width + (v1->x - v2->x); + longest2 = (((v3->y - v1->y) << 16) / height) * width + (v1->x - v3->x); + + if (longest1 < 0) // 2 is right + { + if (longest2 < 0) // 3 is right + { + left_array[0] = v4; + left_array[1] = v1; + left_section = 1; + + height = v3->y - v1->y; + if (height == 0) + height = 1; + longest1 = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x) + >> 16) + (v1->x - v2->x); + if (longest1 >= 0) { + right_array[0] = v4; // 1 + right_array[1] = v3; // 3 + right_array[2] = v1; // 4 + right_section = 2; + } else { + height = v4->y - v2->y; + if (height == 0) + height = 1; + longest1 = (((v3->y - v2->y) << 16) / height) + * ((v4->x - v2->x) >> 16) + (v2->x - v3->x); + if (longest1 >= 0) { + right_array[0] = v4; // 1 + right_array[1] = v2; // 2 + right_array[2] = v1; // 4 + right_section = 2; + } else { + right_array[0] = v4; // 1 + right_array[1] = v3; // 2 + right_array[2] = v2; // 3 + right_array[3] = v1; // 4 + right_section = 3; + } + } + } else { + left_array[0] = v4; + left_array[1] = v3; // 1 + left_array[2] = v1; // 2 + left_section = 2; // 3 + right_array[0] = v4; // 4 + right_array[1] = v2; + right_array[2] = v1; + right_section = 2; + } + } else { + if (longest2 < 0) { + left_array[0] = v4; // 1 + left_array[1] = v2; // 2 + left_array[2] = v1; // 3 + left_section = 2; // 4 + right_array[0] = v4; + right_array[1] = v3; + right_array[2] = v1; + right_section = 2; + } else { + right_array[0] = v4; + right_array[1] = v1; + right_section = 1; + + height = v3->y - v1->y; + if (height == 0) + height = 1; + longest1 = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x) + >> 16) + (v1->x - v2->x); + if (longest1 < 0) { + left_array[0] = v4; // 1 + left_array[1] = v3; // 3 + left_array[2] = v1; // 4 + left_section = 2; + } else { + height = v4->y - v2->y; + if (height == 0) + height = 1; + longest1 = (((v3->y - v2->y) << 16) / height) + * ((v4->x - v2->x) >> 16) + (v2->x - v3->x); + if (longest1 < 0) { + left_array[0] = v4; // 1 + left_array[1] = v2; // 2 + left_array[2] = v1; // 4 + left_section = 2; + } else { + left_array[0] = v4; // 1 + left_array[1] = v3; // 2 + left_array[2] = v2; // 3 + left_array[3] = v1; // 4 + left_section = 3; + } + } + } + } + + while (LeftSection_FT4() <= 0) { + if (--left_section <= 0) + break; + } + + while (RightSection_FT4() <= 0) { + if (--right_section <= 0) + break; + } + + g_soft.Ymin = v1->y; + g_soft.Ymax = MIN(v4->y - 1, g_prim.drawH); + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +inline int RightSection_GT4(void) { + soft_vertex * v1 = right_array[right_section]; + soft_vertex * v2 = right_array[right_section - 1]; + + int height = v2->y - v1->y; + right_section_height = height; + right_x = v1->x; + right_u = v1->u; + right_v = v1->v; + right_R = v1->R; + right_G = v1->G; + right_B = v1->B; + + if (height == 0) { + return 0; + } + delta_right_x = (v2->x - v1->x) / height; + delta_right_u = (v2->u - v1->u) / height; + delta_right_v = (v2->v - v1->v) / height; + delta_right_R = (v2->R - v1->R) / height; + delta_right_G = (v2->G - v1->G) / height; + delta_right_B = (v2->B - v1->B) / height; + + return height; +} + +//////////////////////////////////////////////////////////////////////// + +inline int LeftSection_GT4(void) { + soft_vertex * v1 = left_array[left_section]; + soft_vertex * v2 = left_array[left_section - 1]; + + int height = v2->y - v1->y; + left_section_height = height; + left_x = v1->x; + left_u = v1->u; + left_v = v1->v; + left_R = v1->R; + left_G = v1->G; + left_B = v1->B; + + if (height == 0) { + return 0; + } + delta_left_x = (v2->x - v1->x) / height; + delta_left_u = (v2->u - v1->u) / height; + delta_left_v = (v2->v - v1->v) / height; + delta_left_R = (v2->R - v1->R) / height; + delta_left_G = (v2->G - v1->G) / height; + delta_left_B = (v2->B - v1->B) / height; + + return height; +} + +//////////////////////////////////////////////////////////////////////// + +inline char NextRow_GT4(void) { + if (--left_section_height <= 0) { + if (--left_section > 0) + while (LeftSection_GT4() <= 0) { + if (--left_section <= 0) + break; + } + } else { + left_x += delta_left_x; + left_u += delta_left_u; + left_v += delta_left_v; + left_R += delta_left_R; + left_G += delta_left_G; + left_B += delta_left_B; + } + + if (--right_section_height <= 0) { + if (--right_section > 0) + while (RightSection_GT4() <= 0) { + if (--right_section <= 0) + break; + } + } else { + right_x += delta_right_x; + right_u += delta_right_u; + right_v += delta_right_v; + right_R += delta_right_R; + right_G += delta_right_G; + right_B += delta_right_B; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////// + +inline char SetupSections_GT4(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, int32_t rgb1, + int32_t rgb2, int32_t rgb3, int32_t rgb4) { + soft_vertex * v1, *v2, *v3, *v4; + int height, width, longest1, longest2; + + v1 = vtx; + v1->x = x1 << 16; + v1->y = y1; + v1->u = tx1 << 16; + v1->v = ty1 << 16; + v1->R = (rgb1) & 0x00ff0000; + v1->G = (rgb1 << 8) & 0x00ff0000; + v1->B = (rgb1 << 16) & 0x00ff0000; + + v2 = vtx + 1; + v2->x = x2 << 16; + v2->y = y2; + v2->u = tx2 << 16; + v2->v = ty2 << 16; + v2->R = (rgb2) & 0x00ff0000; + v2->G = (rgb2 << 8) & 0x00ff0000; + v2->B = (rgb2 << 16) & 0x00ff0000; + + v3 = vtx + 2; + v3->x = x3 << 16; + v3->y = y3; + v3->u = tx3 << 16; + v3->v = ty3 << 16; + v3->R = (rgb3) & 0x00ff0000; + v3->G = (rgb3 << 8) & 0x00ff0000; + v3->B = (rgb3 << 16) & 0x00ff0000; + + v4 = vtx + 3; + v4->x = x4 << 16; + v4->y = y4; + v4->u = tx4 << 16; + v4->v = ty4 << 16; + v4->R = (rgb4) & 0x00ff0000; + v4->G = (rgb4 << 8) & 0x00ff0000; + v4->B = (rgb4 << 16) & 0x00ff0000; + + if (v1->y > v2->y) { + soft_vertex * v = v1; + v1 = v2; + v2 = v; + } + if (v1->y > v3->y) { + soft_vertex * v = v1; + v1 = v3; + v3 = v; + } + if (v1->y > v4->y) { + soft_vertex * v = v1; + v1 = v4; + v4 = v; + } + if (v2->y > v3->y) { + soft_vertex * v = v2; + v2 = v3; + v3 = v; + } + if (v2->y > v4->y) { + soft_vertex * v = v2; + v2 = v4; + v4 = v; + } + if (v3->y > v4->y) { + soft_vertex * v = v3; + v3 = v4; + v4 = v; + } + + height = v4->y - v1->y; + if (height == 0) + height = 1; + width = (v4->x - v1->x) >> 16; + longest1 = (((v2->y - v1->y) << 16) / height) * width + (v1->x - v2->x); + longest2 = (((v3->y - v1->y) << 16) / height) * width + (v1->x - v3->x); + + if (longest1 < 0) // 2 is right + { + if (longest2 < 0) // 3 is right + { + left_array[0] = v4; + left_array[1] = v1; + left_section = 1; + + height = v3->y - v1->y; + if (height == 0) + height = 1; + longest1 = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x) + >> 16) + (v1->x - v2->x); + if (longest1 >= 0) { + right_array[0] = v4; // 1 + right_array[1] = v3; // 3 + right_array[2] = v1; // 4 + right_section = 2; + } else { + height = v4->y - v2->y; + if (height == 0) + height = 1; + longest1 = (((v3->y - v2->y) << 16) / height) + * ((v4->x - v2->x) >> 16) + (v2->x - v3->x); + if (longest1 >= 0) { + right_array[0] = v4; // 1 + right_array[1] = v2; // 2 + right_array[2] = v1; // 4 + right_section = 2; + } else { + right_array[0] = v4; // 1 + right_array[1] = v3; // 2 + right_array[2] = v2; // 3 + right_array[3] = v1; // 4 + right_section = 3; + } + } + } else { + left_array[0] = v4; + left_array[1] = v3; // 1 + left_array[2] = v1; // 2 + left_section = 2; // 3 + right_array[0] = v4; // 4 + right_array[1] = v2; + right_array[2] = v1; + right_section = 2; + } + } else { + if (longest2 < 0) { + left_array[0] = v4; // 1 + left_array[1] = v2; // 2 + left_array[2] = v1; // 3 + left_section = 2; // 4 + right_array[0] = v4; + right_array[1] = v3; + right_array[2] = v1; + right_section = 2; + } else { + right_array[0] = v4; + right_array[1] = v1; + right_section = 1; + + height = v3->y - v1->y; + if (height == 0) + height = 1; + longest1 = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x) + >> 16) + (v1->x - v2->x); + if (longest1 < 0) { + left_array[0] = v4; // 1 + left_array[1] = v3; // 3 + left_array[2] = v1; // 4 + left_section = 2; + } else { + height = v4->y - v2->y; + if (height == 0) + height = 1; + longest1 = (((v3->y - v2->y) << 16) / height) + * ((v4->x - v2->x) >> 16) + (v2->x - v3->x); + if (longest1 < 0) { + left_array[0] = v4; // 1 + left_array[1] = v2; // 2 + left_array[2] = v1; // 4 + left_section = 2; + } else { + left_array[0] = v4; // 1 + left_array[1] = v3; // 2 + left_array[2] = v2; // 3 + left_array[3] = v1; // 4 + left_section = 3; + } + } + } + } + + while (LeftSection_GT4() <= 0) { + if (--left_section <= 0) + break; + } + + while (RightSection_GT4() <= 0) { + if (--right_section <= 0) + break; + } + + g_soft.Ymin = v1->y; + g_soft.Ymax = MIN(v4->y - 1, g_prim.drawH); + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// POLY FUNCS +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// POLY 3/4 FLAT SHADED +//////////////////////////////////////////////////////////////////////// + +inline void drawPoly3Fi(short x1, short y1, short x2, short y2, short x3, + short y3, int32_t rgb) { + int i, j, xmin, xmax, ymin, ymax; + unsigned short color; + uint32_t lcolor; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_F(x1, y1, x2, y2, x3, y3)) + return; + + ymax = g_soft.Ymax; + + color = ((rgb & 0x00f80000) >> 9) | ((rgb & 0x0000f800) >> 6) | ((rgb + & 0x000000f8) >> 3); + lcolor = g_draw.lSetMask | (((uint32_t) (color)) << 16) | color; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_F()) + return; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + color |= g_draw.sSetMask; + for (i = ymin; i <= ymax; i++) { + xmin = left_x >> 16; + if (g_prim.drawX > xmin) + xmin = g_prim.drawX; + xmax = (right_x >> 16) - 1; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + PUTLE32(((uint32_t *)&g_gpu.psx_vram.u16[(i<<10)+j]), lcolor); + } + if (j == xmax) + PUTLE16(&g_gpu.psx_vram.u16[(i<<10)+j], color); + + if (NextRow_F()) + return; + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = left_x >> 16; + if (g_prim.drawX > xmin) + xmin = g_prim.drawX; + xmax = (right_x >> 16) - 1; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + GetShadeTransCol32((uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + lcolor); + } + if (j == xmax) + GetShadeTransCol(&g_gpu.psx_vram.u16[(i << 10) + j], color); + + if (NextRow_F()) + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3F(int32_t rgb) { + drawPoly3Fi(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, g_soft.lx2, + g_soft.ly2, rgb); +} + +#ifdef POLYQUAD3FS + +void drawPoly4F_TRI(int32_t rgb) +{ + drawPog_soft.ly3Fi(g_soft.lx1,g_soft.ly1,g_soft.lx3,g_soft.ly3,g_soft.lx2,g_soft.ly2,rgb); + drawPog_soft.ly3Fi(g_soft.lx0,g_soft.ly0,g_soft.lx1,g_soft.ly1,g_soft.lx2,g_soft.ly2,rgb); +} + +#endif + +// more exact: + +void drawPoly4F(int32_t rgb) { + int i, j, xmin, xmax, ymin, ymax; + unsigned short color; + uint32_t lcolor; + + if (g_soft.lx0 > g_prim.drawW && g_soft.lx1 > g_prim.drawW && g_soft.lx2 + > g_prim.drawW && g_soft.lx3 > g_prim.drawW) + return; + if (g_soft.ly0 > g_prim.drawH && g_soft.ly1 > g_prim.drawH && g_soft.ly2 + > g_prim.drawH && g_soft.ly3 > g_prim.drawH) + return; + if (g_soft.lx0 < g_prim.drawX && g_soft.lx1 < g_prim.drawX && g_soft.lx2 + < g_prim.drawX && g_soft.lx3 < g_prim.drawX) + return; + if (g_soft.ly0 < g_prim.drawY && g_soft.ly1 < g_prim.drawY && g_soft.ly2 + < g_prim.drawY && g_soft.ly3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_F4(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, g_soft.lx3, g_soft.ly3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_F4()) + return; + + color = ((rgb & 0x00f80000) >> 9) | ((rgb & 0x0000f800) >> 6) | ((rgb + & 0x000000f8) >> 3); + lcolor = g_draw.lSetMask | (((uint32_t) (color)) << 16) | color; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + color |= g_draw.sSetMask; + for (i = ymin; i <= ymax; i++) { + xmin = left_x >> 16; + if (g_prim.drawX > xmin) + xmin = g_prim.drawX; + xmax = (right_x >> 16) - 1; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + PUTLE32(((uint32_t *)&g_gpu.psx_vram.u16[(i<<10)+j]), lcolor); + } + if (j == xmax) + PUTLE16(&g_gpu.psx_vram.u16[(i<<10)+j], color); + + if (NextRow_F4()) + return; + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = left_x >> 16; + if (g_prim.drawX > xmin) + xmin = g_prim.drawX; + xmax = (right_x >> 16) - 1; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + GetShadeTransCol32((uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + lcolor); + } + if (j == xmax) + GetShadeTransCol(&g_gpu.psx_vram.u16[(i << 10) + j], color); + + if (NextRow_F4()) + return; + } +} + +//////////////////////////////////////////////////////////////////////// +// POLY 3/4 F-SHADED TEX PAL 4 +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TEx4(short x1, short y1, short x2, short y2, short x3, short y3, + short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, + short clX, short clY) { + int i, j, xmin, xmax, ymin, ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, XAdjust; + int32_t clutP; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16); + tC1 + = g_gpu.psx_vram.u8[((posY >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + XAdjust = ((posX + difX) >> 16); + tC2 = g_gpu.psx_vram.u8[(((posY + difY) >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + (XAdjust >> 1)]; + tC2 = (tC2 >> ((XAdjust & 1) << 2)) & 0xf; + + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + + posX += difX2; + posY += difY2; + } + if (j == xmax) { + XAdjust = (posX >> 16); + tC1 + = g_gpu.psx_vram.u8[((posY >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + GetTextureTransColG_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16); + tC1 = g_gpu.psx_vram.u8[((posY >> 5) & (int32_t) 0xFFFFF800) + + YAdjust + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + XAdjust = ((posX + difX) >> 16); + tC2 = g_gpu.psx_vram.u8[(((posY + difY) >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + (XAdjust >> 1)]; + tC2 = (tC2 >> ((XAdjust & 1) << 2)) & 0xf; + + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + + posX += difX2; + posY += difY2; + } + if (j == xmax) { + XAdjust = (posX >> 16); + tC1 = g_gpu.psx_vram.u8[((posY >> 5) & (int32_t) 0xFFFFF800) + + YAdjust + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + GetTextureTransColG(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TEx4_IL(short x1, short y1, short x2, short y2, short x3, + short y3, short tx1, short ty1, short tx2, short ty2, short tx3, + short ty3, short clX, short clY) { + int i, j, xmin, xmax, ymin, ymax, n_xi, n_yi, TXV; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, XAdjust; + int32_t clutP; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = (g_soft.GlobalTextAddrY << 10) + g_soft.GlobalTextAddrX; + + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16); + + TXV = posY >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC1 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + XAdjust = ((posX + difX) >> 16); + + TXV = (posY + difY) >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC2 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + + posX += difX2; + posY += difY2; + } + if (j == xmax) { + XAdjust = (posX >> 16); + + TXV = posY >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC1 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + GetTextureTransColG_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16); + + TXV = posY >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC1 = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + XAdjust = ((posX + difX) >> 16); + + TXV = (posY + difY) >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC2 = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + + posX += difX2; + posY += difY2; + } + if (j == xmax) { + XAdjust = (posX >> 16); + + TXV = posY >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC1 = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + GetTextureTransColG(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TEx4_TW(short x1, short y1, short x2, short y2, short x3, + short y3, short tx1, short ty1, short tx2, short ty2, short tx3, + short ty3, short clX, short clY) { + int i, j, xmin, xmax, ymin, ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, XAdjust; + int32_t clutP; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + YAdjust += (g_prim.TWin.Position.y0 << 11) + (g_prim.TWin.Position.x0 >> 1); + + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16);//-1; //!!!!!!!!!!!!!!!! + if (xmax > xmin) + xmax--; + + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16) % g_prim.TWin.Position.x1; + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + XAdjust = ((posX + difX) >> 16) % g_prim.TWin.Position.x1; + tC2 = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (XAdjust >> 1)]; + tC2 = (tC2 >> ((XAdjust & 1) << 2)) & 0xf; + + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + + posX += difX2; + posY += difY2; + } + if (j == xmax) { + XAdjust = (posX >> 16) % g_prim.TWin.Position.x1; + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + GetTextureTransColG_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16) % g_prim.TWin.Position.x1; + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + (XAdjust + >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + XAdjust = ((posX + difX) >> 16) % g_prim.TWin.Position.x1; + tC2 = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + (XAdjust + >> 1)]; + tC2 = (tC2 >> ((XAdjust & 1) << 2)) & 0xf; + + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + + posX += difX2; + posY += difY2; + } + if (j == xmax) { + XAdjust = (posX >> 16) % g_prim.TWin.Position.x1; + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + (XAdjust + >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + GetTextureTransColG(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +#ifdef POLYQUAD3 + +void drawPoly4TEx4_TRI(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, short clX, + short clY) { + drawPoly3TEx4(x2, y2, x3, y3, x4, y4, tx2, ty2, tx3, ty3, tx4, ty4, clX, + clY); + drawPoly3TEx4(x1, y1, x2, y2, x4, y4, tx1, ty1, tx2, ty2, tx4, ty4, clX, + clY); +} + +#endif + +// more exact: + +void drawPoly4TEx4(short x1, short y1, short x2, short y2, short x3, short y3, + short x4, short y4, short tx1, short ty1, short tx2, short ty2, + short tx3, short ty3, short tx4, short ty4, short clX, short clY) { + int32_t num; + int32_t i, j, xmin, xmax, ymin, ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP, XAdjust; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW && x4 + > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH && y4 + > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX && x4 + < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY && y4 + < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT4(x1, y1, x2, y2, x3, y3, x4, y4, tx1, ty1, tx2, ty2, + tx3, ty3, tx4, ty4)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT4()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16); + tC1 + = g_gpu.psx_vram.u8[((posY >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + XAdjust = ((posX + difX) >> 16); + tC2 = g_gpu.psx_vram.u8[(((posY + difY) >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + (XAdjust >> 1)]; + tC2 = (tC2 >> ((XAdjust & 1) << 2)) & 0xf; + + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + if (j == xmax) { + XAdjust = (posX >> 16); + tC1 + = g_gpu.psx_vram.u8[((posY >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + GetTextureTransColG_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + + } + if (NextRow_FT4()) + return; + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16); + tC1 = g_gpu.psx_vram.u8[((posY >> 5) & (int32_t) 0xFFFFF800) + + YAdjust + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + XAdjust = ((posX + difX) >> 16); + tC2 = g_gpu.psx_vram.u8[(((posY + difY) >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + (XAdjust >> 1)]; + tC2 = (tC2 >> ((XAdjust & 1) << 2)) & 0xf; + + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + if (j == xmax) { + XAdjust = (posX >> 16); + tC1 = g_gpu.psx_vram.u8[((posY >> 5) & (int32_t) 0xFFFFF800) + + YAdjust + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + GetTextureTransColG(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT4()) + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TEx4_IL(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, short clX, + short clY) { + int32_t num; + int32_t i, j = 0, xmin, xmax, ymin, ymax, n_xi, n_yi, TXV; + int32_t difX, difY, difX2, difY2; + int32_t posX = 0, posY = 0, YAdjust, clutP, XAdjust; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW && x4 + > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH && y4 + > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX && x4 + < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY && y4 + < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT4(x1, y1, x2, y2, x3, y3, x4, y4, tx1, ty1, tx2, ty2, + tx3, ty3, tx4, ty4)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT4()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 10) + g_soft.GlobalTextAddrX; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16); + + TXV = posY >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC1 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + XAdjust = ((posX + difX) >> 16); + + TXV = (posY + difY) >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC2 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + posX += difX2; + posY += difY2; + } + + if (j == xmax) { + XAdjust = (posX >> 16); + TXV = posY >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC1 = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + GetTextureTransColG_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + + } + if (NextRow_FT4()) + return; + } +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16); + + TXV = posY >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC1 = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + XAdjust = ((posX + difX) >> 16); + + TXV = (posY + difY) >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC2 = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + if (j == xmax) { + XAdjust = (posX >> 16); + TXV = posY >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC1 = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + GetTextureTransColG(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT4()) + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TEx4_TW(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, short clX, + short clY) { + int32_t num; + int32_t i, j, xmin, xmax, ymin, ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP, XAdjust; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW && x4 + > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH && y4 + > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX && x4 + < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY && y4 + < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT4(x1, y1, x2, y2, x3, y3, x4, y4, tx1, ty1, tx2, ty2, + tx3, ty3, tx4, ty4)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT4()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + YAdjust += (g_prim.TWin.Position.y0 << 11) + (g_prim.TWin.Position.x0 >> 1); + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16) % g_prim.TWin.Position.x1; + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + XAdjust = ((posX + difX) >> 16) % g_prim.TWin.Position.x1; + tC2 = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (XAdjust >> 1)]; + tC2 = (tC2 >> ((XAdjust & 1) << 2)) & 0xf; + + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + if (j == xmax) { + XAdjust = (posX >> 16) % g_prim.TWin.Position.x1; + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + GetTextureTransColG_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT4()) + return; + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16) % g_prim.TWin.Position.x1; + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + (XAdjust + >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + XAdjust = ((posX + difX) >> 16) % g_prim.TWin.Position.x1; + tC2 = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + (XAdjust + >> 1)]; + tC2 = (tC2 >> ((XAdjust & 1) << 2)) & 0xf; + + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + if (j == xmax) { + XAdjust = (posX >> 16) % g_prim.TWin.Position.x1; + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + (XAdjust + >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + GetTextureTransColG(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT4()) + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TEx4_TW_S(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, short clX, + short clY) { + int32_t num; + int32_t i, j, xmin, xmax, ymin, ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP, XAdjust; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW && x4 + > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH && y4 + > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX && x4 + < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY && y4 + < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT4(x1, y1, x2, y2, x3, y3, x4, y4, tx1, ty1, tx2, ty2, + tx3, ty3, tx4, ty4)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT4()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + YAdjust += (g_prim.TWin.Position.y0 << 11) + (g_prim.TWin.Position.x0 >> 1); + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16) % g_prim.TWin.Position.x1; + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + XAdjust = ((posX + difX) >> 16) % g_prim.TWin.Position.x1; + tC2 = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (XAdjust >> 1)]; + tC2 = (tC2 >> ((XAdjust & 1) << 2)) & 0xf; + + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + if (j == xmax) { + XAdjust = (posX >> 16) % g_prim.TWin.Position.x1; + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + GetTextureTransColG_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT4()) + return; + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16) % g_prim.TWin.Position.x1; + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + (XAdjust + >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + XAdjust = ((posX + difX) >> 16) % g_prim.TWin.Position.x1; + tC2 = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + (XAdjust + >> 1)]; + tC2 = (tC2 >> ((XAdjust & 1) << 2)) & 0xf; + + GetTextureTransColG32_SPR((uint32_t *) &g_gpu.psx_vram.u16[(i + << 10) + j], GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + if (j == xmax) { + XAdjust = (posX >> 16) % g_prim.TWin.Position.x1; + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + (XAdjust + >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + GetTextureTransColG_SPR(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT4()) + return; + } +} +//////////////////////////////////////////////////////////////////////// +// POLY 3 F-SHADED TEX PAL 8 +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TEx8(short x1, short y1, short x2, short y2, short x3, short y3, + short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, + short clX, short clY) { + int i, j, xmin, xmax, ymin, ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + tC1 + = g_gpu.psx_vram.u8[((posY >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + (posX + >> 16)]; + tC2 = g_gpu.psx_vram.u8[(((posY + difY) >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + ((posX + difX) + >> 16)]; + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + + if (j == xmax) { + tC1 + = g_gpu.psx_vram.u8[((posY >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + (posX + >> 16)]; + GetTextureTransColG_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + tC1 = g_gpu.psx_vram.u8[((posY >> 5) & (int32_t) 0xFFFFF800) + + YAdjust + (posX >> 16)]; + tC2 = g_gpu.psx_vram.u8[(((posY + difY) >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + ((posX + difX) + >> 16)]; + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + + if (j == xmax) { + tC1 = g_gpu.psx_vram.u8[((posY >> 5) & (int32_t) 0xFFFFF800) + + YAdjust + (posX >> 16)]; + GetTextureTransColG(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + + } + if (NextRow_FT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TEx8_IL(short x1, short y1, short x2, short y2, short x3, + short y3, short tx1, short ty1, short tx2, short ty2, short tx3, + short ty3, short clX, short clY) { + int i, j, xmin, xmax, ymin, ymax, n_xi, n_yi, TXV, TXU; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = (g_soft.GlobalTextAddrY << 10) + g_soft.GlobalTextAddrX; + + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + TXU = posX >> 16; + TXV = posY >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV + << 3) & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + + tC1 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + + TXU = (posX + difX) >> 16; + TXV = (posY + difY) >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV + << 3) & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + + tC2 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + + if (j == xmax) { + TXU = posX >> 16; + TXV = posY >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV + << 3) & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + + tC1 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + + GetTextureTransColG_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + TXU = posX >> 16; + TXV = posY >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV << 3) + & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + + tC1 = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + + TXU = (posX + difX) >> 16; + TXV = (posY + difY) >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV << 3) + & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + + tC2 = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + + if (j == xmax) { + TXU = posX >> 16; + TXV = posY >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV << 3) + & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + + tC1 = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + + GetTextureTransColG(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + + } + if (NextRow_FT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TEx8_TW(short x1, short y1, short x2, short y2, short x3, + short y3, short tx1, short ty1, short tx2, short ty2, short tx3, + short ty3, short clX, short clY) { + int i, j, xmin, xmax, ymin, ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + YAdjust += (g_prim.TWin.Position.y0 << 11) + (g_prim.TWin.Position.x0); + + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16);//-1; //!!!!!!!!!!!!!!!! + if (xmax > xmin) + xmax--; + + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + ((posX >> 16) % g_prim.TWin.Position.x1)]; + tC2 + = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (((posX + difX) >> 16) + % g_prim.TWin.Position.x1)]; + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + + if (j == xmax) { + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + ((posX >> 16) % g_prim.TWin.Position.x1)]; + GetTextureTransColG_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + ((posX + >> 16) % g_prim.TWin.Position.x1)]; + tC2 = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + (((posX + + difX) >> 16) % g_prim.TWin.Position.x1)]; + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + + if (j == xmax) { + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + ((posX + >> 16) % g_prim.TWin.Position.x1)]; + GetTextureTransColG(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + + } + if (NextRow_FT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +#ifdef POLYQUAD3 + +void drawPoly4TEx8_TRI(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, short clX, + short clY) { + drawPoly3TEx8(x2, y2, x3, y3, x4, y4, tx2, ty2, tx3, ty3, tx4, ty4, clX, + clY); + + drawPoly3TEx8(x1, y1, x2, y2, x4, y4, tx1, ty1, tx2, ty2, tx4, ty4, clX, + clY); +} + +#endif + +// more exact: + +void drawPoly4TEx8(short x1, short y1, short x2, short y2, short x3, short y3, + short x4, short y4, short tx1, short ty1, short tx2, short ty2, + short tx3, short ty3, short tx4, short ty4, short clX, short clY) { + int32_t num; + int32_t i, j, xmin, xmax, ymin, ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW && x4 + > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH && y4 + > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX && x4 + < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY && y4 + < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT4(x1, y1, x2, y2, x3, y3, x4, y4, tx1, ty1, tx2, ty2, + tx3, ty3, tx4, ty4)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT4()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + tC1 + = g_gpu.psx_vram.u8[((posY >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + (posX + >> 16)]; + tC2 = g_gpu.psx_vram.u8[(((posY + difY) >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + ((posX + difX) + >> 16)]; + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + if (j == xmax) { + tC1 + = g_gpu.psx_vram.u8[((posY >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + (posX + >> 16)]; + GetTextureTransColG_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT4()) + return; + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + tC1 = g_gpu.psx_vram.u8[((posY >> 5) & (int32_t) 0xFFFFF800) + + YAdjust + (posX >> 16)]; + tC2 = g_gpu.psx_vram.u8[(((posY + difY) >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + ((posX + difX) + >> 16)]; + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + if (j == xmax) { + tC1 = g_gpu.psx_vram.u8[((posY >> 5) & (int32_t) 0xFFFFF800) + + YAdjust + (posX >> 16)]; + GetTextureTransColG(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT4()) + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TEx8_IL(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, short clX, + short clY) { + int32_t num; + int32_t i, j, xmin, xmax, ymin, ymax, n_xi, n_yi, TXV, TXU; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW && x4 + > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH && y4 + > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX && x4 + < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY && y4 + < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT4(x1, y1, x2, y2, x3, y3, x4, y4, tx1, ty1, tx2, ty2, + tx3, ty3, tx4, ty4)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT4()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = (g_soft.GlobalTextAddrY << 10) + g_soft.GlobalTextAddrX; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + TXU = posX >> 16; + TXV = posY >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV + << 3) & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + + tC1 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + + TXU = (posX + difX) >> 16; + TXV = (posY + difY) >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV + << 3) & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + + tC2 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + if (j == xmax) { + TXU = posX >> 16; + TXV = posY >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV + << 3) & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + + tC1 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + + GetTextureTransColG_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT4()) + return; + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + TXU = posX >> 16; + TXV = posY >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV << 3) + & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + + tC1 = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + + TXU = (posX + difX) >> 16; + TXV = (posY + difY) >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV << 3) + & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + + tC2 = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + if (j == xmax) { + TXU = posX >> 16; + TXV = posY >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV << 3) + & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + tC1 = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + GetTextureTransColG(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT4()) + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TEx8_TW(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, short clX, + short clY) { + int32_t num; + int32_t i, j, xmin, xmax, ymin, ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW && x4 + > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH && y4 + > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX && x4 + < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY && y4 + < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT4(x1, y1, x2, y2, x3, y3, x4, y4, tx1, ty1, tx2, ty2, + tx3, ty3, tx4, ty4)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT4()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + YAdjust += (g_prim.TWin.Position.y0 << 11) + (g_prim.TWin.Position.x0); + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + ((posX >> 16) % g_prim.TWin.Position.x1)]; + tC2 + = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (((posX + difX) >> 16) + % g_prim.TWin.Position.x1)]; + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + if (j == xmax) { + tC1 = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + ((posX >> 16) % g_prim.TWin.Position.x1)]; + GetTextureTransColG_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT4()) + return; + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + ((posX + >> 16) % g_prim.TWin.Position.x1)]; + tC2 = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + (((posX + + difX) >> 16) % g_prim.TWin.Position.x1)]; + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + if (j == xmax) { + tC1 = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + ((posX + >> 16) % g_prim.TWin.Position.x1)]; + GetTextureTransColG(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT4()) + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TEx8_TW_S(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, short clX, + short clY) { + int32_t num; + int32_t i, j, xmin, xmax, ymin, ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW && x4 + > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH && y4 + > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX && x4 + < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY && y4 + < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT4(x1, y1, x2, y2, x3, y3, x4, y4, tx1, ty1, tx2, ty2, + tx3, ty3, tx4, ty4)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT4()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + YAdjust += (g_prim.TWin.Position.y0 << 11) + (g_prim.TWin.Position.x0); + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + ((posX >> 16) % g_prim.TWin.Position.x1)]; + tC2 + = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (((posX + difX) >> 16) + % g_prim.TWin.Position.x1)]; + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + if (j == xmax) { + tC1 = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + ((posX >> 16) % g_prim.TWin.Position.x1)]; + GetTextureTransColG_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT4()) + return; + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + ((posX + >> 16) % g_prim.TWin.Position.x1)]; + tC2 = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + (((posX + + difX) >> 16) % g_prim.TWin.Position.x1)]; + GetTextureTransColG32_SPR((uint32_t *) &g_gpu.psx_vram.u16[(i + << 10) + j], GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16); + posX += difX2; + posY += difY2; + } + if (j == xmax) { + tC1 = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + ((posX + >> 16) % g_prim.TWin.Position.x1)]; + GetTextureTransColG_SPR(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1])); + } + } + if (NextRow_FT4()) + return; + } +} + +//////////////////////////////////////////////////////////////////////// +// POLY 3 F-SHADED TEX 15 BIT +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TD(short x1, short y1, short x2, short y2, short x3, short y3, + short tx1, short ty1, short tx2, short ty2, short tx3, short ty3) { + int i, j, xmin, xmax, ymin, ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT()) + return; + + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[((((posY+difY)>>16)+g_soft.GlobalTextAddrY)<<10)+((posX+difX)>>16)+g_soft.GlobalTextAddrX])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+((posX)>>16)+g_soft.GlobalTextAddrX])); + + posX += difX2; + posY += difY2; + } + if (j == xmax) + GetTextureTransColG_S( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+(posX>>16)+g_soft.GlobalTextAddrX])); + } + if (NextRow_FT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[((((posY+difY)>>16)+g_soft.GlobalTextAddrY)<<10)+((posX+difX)>>16)+g_soft.GlobalTextAddrX])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+((posX)>>16)+g_soft.GlobalTextAddrX])); + + posX += difX2; + posY += difY2; + } + if (j == xmax) + GetTextureTransColG( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+(posX>>16)+g_soft.GlobalTextAddrX])); + } + if (NextRow_FT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TD_TW(short x1, short y1, short x2, short y2, short x3, short y3, + short tx1, short ty1, short tx2, short ty2, short tx3, short ty3) { + int i, j, xmin, xmax, ymin, ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT()) + return; + + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[(((((posY+difY)>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + (((posX)>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])); + + posX += difX2; + posY += difY2; + } + if (j == xmax) + GetTextureTransColG_S( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + ((posX>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])); + } + if (NextRow_FT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + + for (j = xmin; j < xmax; j += 2) { + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[(((((posY+difY)>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + (((posX)>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])); + + posX += difX2; + posY += difY2; + } + if (j == xmax) + GetTextureTransColG( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + ((posX>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])); + } + if (NextRow_FT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +#ifdef POLYQUAD3 + +void drawPoly4TD_TRI(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4) { + drawPoly3TD(x2, y2, x3, y3, x4, y4, tx2, ty2, tx3, ty3, tx4, ty4); + drawPoly3TD(x1, y1, x2, y2, x4, y4, tx1, ty1, tx2, ty2, tx4, ty4); +} + +#endif + +// more exact: + +void drawPoly4TD(short x1, short y1, short x2, short y2, short x3, short y3, + short x4, short y4, short tx1, short ty1, short tx2, short ty2, + short tx3, short ty3, short tx4, short ty4) { + int32_t num; + int32_t i, j, xmin, xmax, ymin, ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW && x4 + > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH && y4 + > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX && x4 + < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY && y4 + < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT4(x1, y1, x2, y2, x3, y3, x4, y4, tx1, ty1, tx2, ty2, + tx3, ty3, tx4, ty4)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT4()) + return; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[((((posY+difY)>>16)+g_soft.GlobalTextAddrY)<<10)+((posX+difX)>>16)+g_soft.GlobalTextAddrX])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+((posX)>>16)+g_soft.GlobalTextAddrX])); + + posX += difX2; + posY += difY2; + } + if (j == xmax) + GetTextureTransColG_S( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+(posX>>16)+g_soft.GlobalTextAddrX])); + } + if (NextRow_FT4()) + return; + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[((((posY+difY)>>16)+g_soft.GlobalTextAddrY)<<10)+((posX+difX)>>16)+g_soft.GlobalTextAddrX])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+((posX)>>16)+g_soft.GlobalTextAddrX])); + + posX += difX2; + posY += difY2; + } + if (j == xmax) + GetTextureTransColG( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+(posX>>16)+g_soft.GlobalTextAddrX])); + } + if (NextRow_FT4()) + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TD_TW(short x1, short y1, short x2, short y2, short x3, short y3, + short x4, short y4, short tx1, short ty1, short tx2, short ty2, + short tx3, short ty3, short tx4, short ty4) { + int32_t num; + int32_t i, j, xmin, xmax, ymin, ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW && x4 + > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH && y4 + > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX && x4 + < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY && y4 + < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT4(x1, y1, x2, y2, x3, y3, x4, y4, tx1, ty1, tx2, ty2, + tx3, ty3, tx4, ty4)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT4()) + return; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[(((((posY+difY)>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY)<<10)+g_prim.TWin.Position.y0+ + ((posX>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])); + + posX += difX2; + posY += difY2; + } + if (j == xmax) + GetTextureTransColG_S( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + ((posX>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])); + } + if (NextRow_FT4()) + return; + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + GetTextureTransColG32( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[(((((posY+difY)>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + ((posX>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])); + + posX += difX2; + posY += difY2; + } + if (j == xmax) + GetTextureTransColG( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + ((posX>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])); + } + if (NextRow_FT4()) + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TD_TW_S(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4) { + int32_t num; + int32_t i, j, xmin, xmax, ymin, ymax; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW && x4 + > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH && y4 + > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX && x4 + < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY && y4 + < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_FT4(x1, y1, x2, y2, x3, y3, x4, y4, tx1, ty1, tx2, ty2, + tx3, ty3, tx4, ty4)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_FT4()) + return; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[(((((posY+difY)>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY)<<10)+g_prim.TWin.Position.y0+ + ((posX>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])); + + posX += difX2; + posY += difY2; + } + if (j == xmax) + GetTextureTransColG_S( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + ((posX>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])); + } + if (NextRow_FT4()) + return; + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + GetTextureTransColG32_SPR( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[(((((posY+difY)>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + ((posX>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])); + + posX += difX2; + posY += difY2; + } + if (j == xmax) + GetTextureTransColG_SPR( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + ((posX>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])); + } + if (NextRow_FT4()) + return; + } +} + +//////////////////////////////////////////////////////////////////////// +// POLY 3/4 G-SHADED +//////////////////////////////////////////////////////////////////////// + +inline void drawPoly3Gi(short x1, short y1, short x2, short y2, short x3, + short y3, int32_t rgb1, int32_t rgb2, int32_t rgb3) { + int i, j, xmin, xmax, ymin, ymax; + int32_t cR1, cG1, cB1; + int32_t difR, difB, difG, difR2, difB2, difG2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_G(x1, y1, x2, y2, x3, y3, rgb1, rgb2, rgb3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_G()) + return; + + difR = delta_right_R; + difG = delta_right_G; + difB = delta_right_B; + difR2 = difR << 1; + difG2 = difG << 1; + difB2 = difB << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans && g_prim.iDither != 2) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j < xmax; j += 2) { + PUTLE32(((uint32_t *)&g_gpu.psx_vram.u16[(i<<10)+j]), + ((((cR1+difR) <<7)&0x7c000000)|(((cG1+difG) << 2)&0x03e00000)|(((cB1+difB)>>3)&0x001f0000)| + (((cR1) >> 9)&0x7c00)|(((cG1) >> 14)&0x03e0)|(((cB1) >> 19)&0x001f))|g_draw.lSetMask); + + cR1 += difR2; + cG1 += difG2; + cB1 += difB2; + } + if (j == xmax) + PUTLE16(&g_gpu.psx_vram.u16[(i<<10)+j], (((cR1 >> 9)&0x7c00)|((cG1 >> 14)&0x03e0)|((cB1 >> 19)&0x001f))|g_draw.sSetMask); + } + if (NextRow_G()) + return; + } + return; + } + +#endif + + if (g_prim.iDither == 2) + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j <= xmax; j++) { + GetShadeTransCol_Dither(&g_gpu.psx_vram.u16[(i << 10) + j], + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + + cR1 += difR; + cG1 += difG; + cB1 += difB; + } + } + if (NextRow_G()) + return; + } + else + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j <= xmax; j++) { + GetShadeTransCol(&g_gpu.psx_vram.u16[(i << 10) + j], ((cR1 + >> 9) & 0x7c00) | ((cG1 >> 14) & 0x03e0) | ((cB1 + >> 19) & 0x001f)); + + cR1 += difR; + cG1 += difG; + cB1 += difB; + } + } + if (NextRow_G()) + return; + } + +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3G(int32_t rgb1, int32_t rgb2, int32_t rgb3) { + drawPoly3Gi(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, g_soft.lx2, + g_soft.ly2, rgb1, rgb2, rgb3); +} + +// draw two g-shaded tris for right psx shading emulation + +void drawPoly4G(int32_t rgb1, int32_t rgb2, int32_t rgb3, int32_t rgb4) { + drawPoly3Gi(g_soft.lx1, g_soft.ly1, g_soft.lx3, g_soft.ly3, g_soft.lx2, + g_soft.ly2, rgb2, rgb4, rgb3); + drawPoly3Gi(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, g_soft.lx2, + g_soft.ly2, rgb1, rgb2, rgb3); +} + +//////////////////////////////////////////////////////////////////////// +// POLY 3/4 G-SHADED TEX PAL4 +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGEx4(short x1, short y1, short x2, short y2, short x3, short y3, + short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, + short clX, short clY, int32_t col1, int32_t col2, int32_t col3) { + int i, j, xmin, xmax, ymin, ymax; + int32_t cR1, cG1, cB1; + int32_t difR, difB, difG, difR2, difB2, difG2; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP, XAdjust; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_GT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3, + col1, col2, col3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_GT()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + + difR = delta_right_R; + difG = delta_right_G; + difB = delta_right_B; + difR2 = difR << 1; + difG2 = difG << 1; + difB2 = difB << 1; + + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans && !g_prim.iDither) { + for (i = ymin; i <= ymax; i++) { + xmin = ((left_x) >> 16); + xmax = ((right_x) >> 16) - 1; //!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16); + tC1 = g_gpu.psx_vram.u8[((posY >> 5) & 0xFFFFF800) + + YAdjust + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + XAdjust = ((posX + difX) >> 16); + tC2 = g_gpu.psx_vram.u8[(((posY + difY) >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + (XAdjust >> 1)]; + tC2 = (tC2 >> ((XAdjust & 1) << 2)) & 0xf; + + GetTextureTransColGX32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16, (cB1 >> 16) | ((cB1 + difB) + & 0xff0000), (cG1 >> 16) | ((cG1 + difG) + & 0xff0000), (cR1 >> 16) | ((cR1 + difR) + & 0xff0000)); + posX += difX2; + posY += difY2; + cR1 += difR2; + cG1 += difG2; + cB1 += difB2; + } + if (j == xmax) { + XAdjust = (posX >> 16); + tC1 + = g_gpu.psx_vram.u8[((posY >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + GetTextureTransColGX_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + } + } + if (NextRow_GT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j <= xmax; j++) { + XAdjust = (posX >> 16); + tC1 = g_gpu.psx_vram.u8[((posY >> 5) & (int32_t) 0xFFFFF800) + + YAdjust + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + if (g_prim.iDither) + GetTextureTransColGX_Dither(&g_gpu.psx_vram.u16[(i << 10) + + j], GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), (cB1 + >> 16), (cG1 >> 16), (cR1 >> 16)); + else + GetTextureTransColGX(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + posX += difX; + posY += difY; + cR1 += difR; + cG1 += difG; + cB1 += difB; + } + } + if (NextRow_GT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGEx4_IL(short x1, short y1, short x2, short y2, short x3, + short y3, short tx1, short ty1, short tx2, short ty2, short tx3, + short ty3, short clX, short clY, int32_t col1, int32_t col2, + int32_t col3) { + int i, j, xmin, xmax, ymin, ymax, n_xi, n_yi, TXV; + int32_t cR1, cG1, cB1; + int32_t difR, difB, difG, difR2, difB2, difG2; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP, XAdjust; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_GT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3, + col1, col2, col3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_GT()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = (g_soft.GlobalTextAddrY << 10) + g_soft.GlobalTextAddrX; + + difR = delta_right_R; + difG = delta_right_G; + difB = delta_right_B; + difR2 = difR << 1; + difG2 = difG << 1; + difB2 = difB << 1; + + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans && !g_prim.iDither) { + for (i = ymin; i <= ymax; i++) { + xmin = ((left_x) >> 16); + xmax = ((right_x) >> 16) - 1; //!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16); + + TXV = posY >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC1 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + XAdjust = ((posX + difX) >> 16); + + TXV = (posY + difY) >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC2 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + GetTextureTransColGX32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16, (cB1 >> 16) | ((cB1 + difB) + & 0xff0000), (cG1 >> 16) | ((cG1 + difG) + & 0xff0000), (cR1 >> 16) | ((cR1 + difR) + & 0xff0000)); + posX += difX2; + posY += difY2; + cR1 += difR2; + cG1 += difG2; + cB1 += difB2; + } + if (j == xmax) { + XAdjust = (posX >> 16); + + TXV = posY >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC1 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + GetTextureTransColGX_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + } + } + if (NextRow_GT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j <= xmax; j++) { + XAdjust = (posX >> 16); + + TXV = posY >> 16; + n_xi = ((XAdjust >> 2) & ~0x3c) + ((TXV << 2) & 0x3c); + n_yi = (TXV & ~0xf) + ((XAdjust >> 4) & 0xf); + + tC1 = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((XAdjust & 0x03) << 2)) & 0x0f; + + if (g_prim.iDither) + GetTextureTransColGX_Dither(&g_gpu.psx_vram.u16[(i << 10) + + j], GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), (cB1 + >> 16), (cG1 >> 16), (cR1 >> 16)); + else + GetTextureTransColGX(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + posX += difX; + posY += difY; + cR1 += difR; + cG1 += difG; + cB1 += difB; + } + } + if (NextRow_GT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGEx4_TW(short x1, short y1, short x2, short y2, short x3, + short y3, short tx1, short ty1, short tx2, short ty2, short tx3, + short ty3, short clX, short clY, int32_t col1, int32_t col2, + int32_t col3) { + int i, j, xmin, xmax, ymin, ymax; + int32_t cR1, cG1, cB1; + int32_t difR, difB, difG, difR2, difB2, difG2; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP, XAdjust; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_GT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3, + col1, col2, col3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_GT()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + YAdjust += (g_prim.TWin.Position.y0 << 11) + (g_prim.TWin.Position.x0 >> 1); + + difR = delta_right_R; + difG = delta_right_G; + difB = delta_right_B; + difR2 = difR << 1; + difG2 = difG << 1; + difB2 = difB << 1; + + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans && !g_prim.iDither) { + for (i = ymin; i <= ymax; i++) { + xmin = ((left_x) >> 16); + xmax = ((right_x) >> 16) - 1; //!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16) % g_prim.TWin.Position.x1; + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + XAdjust = ((posX + difX) >> 16) % g_prim.TWin.Position.x1; + tC2 = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (XAdjust >> 1)]; + tC2 = (tC2 >> ((XAdjust & 1) << 2)) & 0xf; + GetTextureTransColGX32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16, (cB1 >> 16) | ((cB1 + difB) + & 0xff0000), (cG1 >> 16) | ((cG1 + difG) + & 0xff0000), (cR1 >> 16) | ((cR1 + difR) + & 0xff0000)); + posX += difX2; + posY += difY2; + cR1 += difR2; + cG1 += difG2; + cB1 += difB2; + } + if (j == xmax) { + XAdjust = (posX >> 16) % g_prim.TWin.Position.x1; + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + GetTextureTransColGX_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + } + } + if (NextRow_GT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j <= xmax; j++) { + XAdjust = (posX >> 16) % g_prim.TWin.Position.x1; + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + (XAdjust + >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + if (g_prim.iDither) + GetTextureTransColGX_Dither(&g_gpu.psx_vram.u16[(i << 10) + + j], GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), (cB1 + >> 16), (cG1 >> 16), (cR1 >> 16)); + else + GetTextureTransColGX(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + posX += difX; + posY += difY; + cR1 += difR; + cG1 += difG; + cB1 += difB; + } + } + if (NextRow_GT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +// note: the psx is doing g-shaded quads as two g-shaded tris, +// like the following func... sadly texturing is not 100% +// correct that way, so small texture distortions can +// happen... + +void drawPoly4TGEx4_TRI_IL(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, short clX, + short clY, int32_t col1, int32_t col2, int32_t col3, int32_t col4) { + drawPoly3TGEx4_IL(x2, y2, x3, y3, x4, y4, tx2, ty2, tx3, ty3, tx4, ty4, + clX, clY, col2, col4, col3); + drawPoly3TGEx4_IL(x1, y1, x2, y2, x4, y4, tx1, ty1, tx2, ty2, tx4, ty4, + clX, clY, col1, col2, col3); +} + +#ifdef POLYQUAD3GT + +void drawPoly4TGEx4_TRI(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, short clX, + short clY, int32_t col1, int32_t col2, int32_t col3, int32_t col4) { + drawPoly3TGEx4(x2, y2, x3, y3, x4, y4, tx2, ty2, tx3, ty3, tx4, ty4, clX, + clY, col2, col4, col3); + drawPoly3TGEx4(x1, y1, x2, y2, x4, y4, tx1, ty1, tx2, ty2, tx4, ty4, clX, + clY, col1, col2, col3); +} + +#endif + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TGEx4(short x1, short y1, short x2, short y2, short x3, short y3, + short x4, short y4, short tx1, short ty1, short tx2, short ty2, + short tx3, short ty3, short tx4, short ty4, short clX, short clY, + int32_t col1, int32_t col2, int32_t col4, int32_t col3) { + int32_t num; + int32_t i, j, xmin, xmax, ymin, ymax; + int32_t cR1, cG1, cB1; + int32_t difR, difB, difG, difR2, difB2, difG2; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP, XAdjust; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW && x4 + > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH && y4 + > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX && x4 + < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY && y4 + < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_GT4(x1, y1, x2, y2, x3, y3, x4, y4, tx1, ty1, tx2, ty2, + tx3, ty3, tx4, ty4, col1, col2, col3, col4)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_GT4()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans && !g_prim.iDither) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + difR = (right_R - cR1) / num; + difG = (right_G - cG1) / num; + difB = (right_B - cB1) / num; + difR2 = difR << 1; + difG2 = difG << 1; + difB2 = difB << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + XAdjust = (posX >> 16); + tC1 + = g_gpu.psx_vram.u8[((posY >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + XAdjust = ((posX + difX) >> 16); + tC2 = g_gpu.psx_vram.u8[(((posY + difY) >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + (XAdjust >> 1)]; + tC2 = (tC2 >> ((XAdjust & 1) << 2)) & 0xf; + + GetTextureTransColGX32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16, (cB1 >> 16) | ((cB1 + difB) + & 0xff0000), (cG1 >> 16) | ((cG1 + difG) + & 0xff0000), (cR1 >> 16) | ((cR1 + difR) + & 0xff0000)); + posX += difX2; + posY += difY2; + cR1 += difR2; + cG1 += difG2; + cB1 += difB2; + } + if (j == xmax) { + XAdjust = (posX >> 16); + tC1 + = g_gpu.psx_vram.u8[((posY >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + + GetTextureTransColGX_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + } + } + if (NextRow_GT4()) + return; + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + difR = (right_R - cR1) / num; + difG = (right_G - cG1) / num; + difB = (right_B - cB1) / num; + difR2 = difR << 1; + difG2 = difG << 1; + difB2 = difB << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j <= xmax; j++) { + XAdjust = (posX >> 16); + tC1 = g_gpu.psx_vram.u8[((posY >> 5) & (int32_t) 0xFFFFF800) + + YAdjust + (XAdjust >> 1)]; + tC1 = (tC1 >> ((XAdjust & 1) << 2)) & 0xf; + if (g_prim.iDither) + GetTextureTransColGX_Dither(&g_gpu.psx_vram.u16[(i << 10) + + j], GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), (cB1 + >> 16), (cG1 >> 16), (cR1 >> 16)); + else + GetTextureTransColGX(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + posX += difX; + posY += difY; + cR1 += difR; + cG1 += difG; + cB1 += difB; + } + } + if (NextRow_GT4()) + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TGEx4_TW(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, short clX, + short clY, int32_t col1, int32_t col2, int32_t col3, int32_t col4) { + drawPoly3TGEx4_TW(x2, y2, x3, y3, x4, y4, tx2, ty2, tx3, ty3, tx4, ty4, + clX, clY, col2, col4, col3); + + drawPoly3TGEx4_TW(x1, y1, x2, y2, x4, y4, tx1, ty1, tx2, ty2, tx4, ty4, + clX, clY, col1, col2, col3); +} + +//////////////////////////////////////////////////////////////////////// +// POLY 3/4 G-SHADED TEX PAL8 +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGEx8(short x1, short y1, short x2, short y2, short x3, short y3, + short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, + short clX, short clY, int32_t col1, int32_t col2, int32_t col3) { + int i, j, xmin, xmax, ymin, ymax; + int32_t cR1, cG1, cB1; + int32_t difR, difB, difG, difR2, difB2, difG2; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_GT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3, + col1, col2, col3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_GT()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + + difR = delta_right_R; + difG = delta_right_G; + difB = delta_right_B; + difR2 = difR << 1; + difG2 = difG << 1; + difB2 = difB << 1; + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans && !g_prim.iDither) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; // !!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j < xmax; j += 2) { + tC1 + = g_gpu.psx_vram.u8[((posY >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + ((posX + >> 16))]; + tC2 = g_gpu.psx_vram.u8[(((posY + difY) >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + (((posX + difX) + >> 16))]; + GetTextureTransColGX32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16, (cB1 >> 16) | ((cB1 + difB) + & 0xff0000), (cG1 >> 16) | ((cG1 + difG) + & 0xff0000), (cR1 >> 16) | ((cR1 + difR) + & 0xff0000)); + posX += difX2; + posY += difY2; + cR1 += difR2; + cG1 += difG2; + cB1 += difB2; + } + if (j == xmax) { + tC1 + = g_gpu.psx_vram.u8[((posY >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + ((posX + >> 16))]; + GetTextureTransColGX_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + } + } + if (NextRow_GT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j <= xmax; j++) { + tC1 = g_gpu.psx_vram.u8[((posY >> 5) & (int32_t) 0xFFFFF800) + + YAdjust + ((posX >> 16))]; + if (g_prim.iDither) + GetTextureTransColGX_Dither(&g_gpu.psx_vram.u16[(i << 10) + + j], GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), (cB1 + >> 16), (cG1 >> 16), (cR1 >> 16)); + else + GetTextureTransColGX(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + posX += difX; + posY += difY; + cR1 += difR; + cG1 += difG; + cB1 += difB; + } + } + if (NextRow_GT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGEx8_IL(short x1, short y1, short x2, short y2, short x3, + short y3, short tx1, short ty1, short tx2, short ty2, short tx3, + short ty3, short clX, short clY, int32_t col1, int32_t col2, + int32_t col3) { + int i, j, xmin, xmax, ymin, ymax, n_xi, n_yi, TXV, TXU; + int32_t cR1, cG1, cB1; + int32_t difR, difB, difG, difR2, difB2, difG2; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_GT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3, + col1, col2, col3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_GT()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = (g_soft.GlobalTextAddrY << 10) + g_soft.GlobalTextAddrX; + + difR = delta_right_R; + difG = delta_right_G; + difB = delta_right_B; + difR2 = difR << 1; + difG2 = difG << 1; + difB2 = difB << 1; + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans && !g_prim.iDither) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; // !!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j < xmax; j += 2) { + TXU = posX >> 16; + TXV = posY >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV + << 3) & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + + tC1 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + + TXU = (posX + difX) >> 16; + TXV = (posY + difY) >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV + << 3) & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + + tC2 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + + GetTextureTransColGX32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16, (cB1 >> 16) | ((cB1 + difB) + & 0xff0000), (cG1 >> 16) | ((cG1 + difG) + & 0xff0000), (cR1 >> 16) | ((cR1 + difR) + & 0xff0000)); + posX += difX2; + posY += difY2; + cR1 += difR2; + cG1 += difG2; + cB1 += difB2; + } + if (j == xmax) { + TXU = posX >> 16; + TXV = posY >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV + << 3) & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + + tC1 + = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + + GetTextureTransColGX_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + } + } + if (NextRow_GT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j <= xmax; j++) { + TXU = posX >> 16; + TXV = posY >> 16; + n_xi = ((TXU >> 1) & ~0x78) + ((TXU << 2) & 0x40) + ((TXV << 3) + & 0x38); + n_yi = (TXV & ~0x7) + ((TXU >> 5) & 0x7); + + tC1 = (GETLE16(&g_gpu.psx_vram.u16[(n_yi<<10)+YAdjust+n_xi]) + >> ((TXU & 0x01) << 3)) & 0xff; + + if (g_prim.iDither) + GetTextureTransColGX_Dither(&g_gpu.psx_vram.u16[(i << 10) + + j], GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), (cB1 + >> 16), (cG1 >> 16), (cR1 >> 16)); + else + GetTextureTransColGX(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + posX += difX; + posY += difY; + cR1 += difR; + cG1 += difG; + cB1 += difB; + } + } + if (NextRow_GT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGEx8_TW(short x1, short y1, short x2, short y2, short x3, + short y3, short tx1, short ty1, short tx2, short ty2, short tx3, + short ty3, short clX, short clY, int32_t col1, int32_t col2, + int32_t col3) { + int i, j, xmin, xmax, ymin, ymax; + int32_t cR1, cG1, cB1; + int32_t difR, difB, difG, difR2, difB2, difG2; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_GT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3, + col1, col2, col3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_GT()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + YAdjust += (g_prim.TWin.Position.y0 << 11) + (g_prim.TWin.Position.x0); + + difR = delta_right_R; + difG = delta_right_G; + difB = delta_right_B; + difR2 = difR << 1; + difG2 = difG << 1; + difB2 = difB << 1; + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans && !g_prim.iDither) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; // !!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j < xmax; j += 2) { + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + ((posX >> 16) % g_prim.TWin.Position.x1)]; + tC2 + = g_gpu.psx_vram.u8[((((posY + difY) >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + (((posX + difX) >> 16) + % g_prim.TWin.Position.x1)]; + + GetTextureTransColGX32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16, (cB1 >> 16) | ((cB1 + difB) + & 0xff0000), (cG1 >> 16) | ((cG1 + difG) + & 0xff0000), (cR1 >> 16) | ((cR1 + difR) + & 0xff0000)); + posX += difX2; + posY += difY2; + cR1 += difR2; + cG1 += difG2; + cB1 += difB2; + } + if (j == xmax) { + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + + ((posX >> 16) % g_prim.TWin.Position.x1)]; + GetTextureTransColGX_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + } + } + if (NextRow_GT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j <= xmax; j++) { + tC1 = g_gpu.psx_vram.u8[(((posY >> 16) + % g_prim.TWin.Position.y1) << 11) + YAdjust + ((posX + >> 16) % g_prim.TWin.Position.x1)]; + if (g_prim.iDither) + GetTextureTransColGX_Dither(&g_gpu.psx_vram.u16[(i << 10) + + j], GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), (cB1 + >> 16), (cG1 >> 16), (cR1 >> 16)); + else + GetTextureTransColGX(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + posX += difX; + posY += difY; + cR1 += difR; + cG1 += difG; + cB1 += difB; + } + } + if (NextRow_GT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +// note: two g-shaded tris: small texture distortions can happen + +void drawPoly4TGEx8_TRI_IL(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, short clX, + short clY, int32_t col1, int32_t col2, int32_t col3, int32_t col4) { + drawPoly3TGEx8_IL(x2, y2, x3, y3, x4, y4, tx2, ty2, tx3, ty3, tx4, ty4, + clX, clY, col2, col4, col3); + drawPoly3TGEx8_IL(x1, y1, x2, y2, x4, y4, tx1, ty1, tx2, ty2, tx4, ty4, + clX, clY, col1, col2, col3); +} + +#ifdef POLYQUAD3GT + +void drawPoly4TGEx8_TRI(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, short clX, + short clY, int32_t col1, int32_t col2, int32_t col3, int32_t col4) { + drawPoly3TGEx8(x2, y2, x3, y3, x4, y4, tx2, ty2, tx3, ty3, tx4, ty4, clX, + clY, col2, col4, col3); + drawPoly3TGEx8(x1, y1, x2, y2, x4, y4, tx1, ty1, tx2, ty2, tx4, ty4, clX, + clY, col1, col2, col3); +} + +#endif + +void drawPoly4TGEx8(short x1, short y1, short x2, short y2, short x3, short y3, + short x4, short y4, short tx1, short ty1, short tx2, short ty2, + short tx3, short ty3, short tx4, short ty4, short clX, short clY, + int32_t col1, int32_t col2, int32_t col4, int32_t col3) { + int32_t num; + int32_t i, j, xmin, xmax, ymin, ymax; + int32_t cR1, cG1, cB1; + int32_t difR, difB, difG, difR2, difB2, difG2; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY, YAdjust, clutP; + short tC1, tC2; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW && x4 + > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH && y4 + > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX && x4 + < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY && y4 + < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_GT4(x1, y1, x2, y2, x3, y3, x4, y4, tx1, ty1, tx2, ty2, + tx3, ty3, tx4, ty4, col1, col2, col3, col4)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_GT4()) + return; + + clutP = (clY << 10) + clX; + + YAdjust = ((g_soft.GlobalTextAddrY) << 11) + (g_soft.GlobalTextAddrX << 1); + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans && !g_prim.iDither) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + difR = (right_R - cR1) / num; + difG = (right_G - cG1) / num; + difB = (right_B - cB1) / num; + difR2 = difR << 1; + difG2 = difG << 1; + difB2 = difB << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + tC1 + = g_gpu.psx_vram.u8[((posY >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + (posX + >> 16)]; + tC2 = g_gpu.psx_vram.u8[(((posY + difY) >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + ((posX + difX) + >> 16)]; + + GetTextureTransColGX32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]) + | ((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16, (cB1 >> 16) | ((cB1 + difB) + & 0xff0000), (cG1 >> 16) | ((cG1 + difG) + & 0xff0000), (cR1 >> 16) | ((cR1 + difR) + & 0xff0000)); + posX += difX2; + posY += difY2; + cR1 += difR2; + cG1 += difG2; + cB1 += difB2; + } + if (j == xmax) { + tC1 + = g_gpu.psx_vram.u8[((posY >> 5) + & (int32_t) 0xFFFFF800) + YAdjust + (posX + >> 16)]; + GetTextureTransColGX_S(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + } + } + if (NextRow_GT4()) + return; + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + difR = (right_R - cR1) / num; + difG = (right_G - cG1) / num; + difB = (right_B - cB1) / num; + difR2 = difR << 1; + difG2 = difG << 1; + difB2 = difB << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j <= xmax; j++) { + tC1 = g_gpu.psx_vram.u8[((posY >> 5) & (int32_t) 0xFFFFF800) + + YAdjust + (posX >> 16)]; + if (g_prim.iDither) + GetTextureTransColGX_Dither(&g_gpu.psx_vram.u16[(i << 10) + + j], GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), (cB1 + >> 16), (cG1 >> 16), (cR1 >> 16)); + else + GetTextureTransColGX(&g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[clutP+tC1]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + posX += difX; + posY += difY; + cR1 += difR; + cG1 += difG; + cB1 += difB; + } + } + if (NextRow_GT4()) + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TGEx8_TW(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, short clX, + short clY, int32_t col1, int32_t col2, int32_t col3, int32_t col4) { + drawPoly3TGEx8_TW(x2, y2, x3, y3, x4, y4, tx2, ty2, tx3, ty3, tx4, ty4, + clX, clY, col2, col4, col3); + drawPoly3TGEx8_TW(x1, y1, x2, y2, x4, y4, tx1, ty1, tx2, ty2, tx4, ty4, + clX, clY, col1, col2, col3); +} + +//////////////////////////////////////////////////////////////////////// +// POLY 3 G-SHADED TEX 15 BIT +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGD(short x1, short y1, short x2, short y2, short x3, short y3, + short tx1, short ty1, short tx2, short ty2, short tx3, short ty3, + int32_t col1, int32_t col2, int32_t col3) { + int i, j, xmin, xmax, ymin, ymax; + int32_t cR1, cG1, cB1; + int32_t difR, difB, difG, difR2, difB2, difG2; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_GT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3, + col1, col2, col3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_GT()) + return; + + difR = delta_right_R; + difG = delta_right_G; + difB = delta_right_B; + difR2 = difR << 1; + difG2 = difG << 1; + difB2 = difB << 1; + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans && !g_prim.iDither) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j < xmax; j += 2) { + GetTextureTransColGX32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[((((posY+difY)>>16)+g_soft.GlobalTextAddrY)<<10)+((posX+difX)>>16)+g_soft.GlobalTextAddrX])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+((posX)>>16)+g_soft.GlobalTextAddrX]), + (cB1 >> 16) | ((cB1 + difB) & 0xff0000), + (cG1 >> 16) | ((cG1 + difG) & 0xff0000), + (cR1 >> 16) | ((cR1 + difR) & 0xff0000)); + posX += difX2; + posY += difY2; + cR1 += difR2; + cG1 += difG2; + cB1 += difB2; + } + if (j == xmax) + GetTextureTransColGX_S( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+(posX>>16)+g_soft.GlobalTextAddrX]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + } + if (NextRow_GT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j <= xmax; j++) { + if (g_prim.iDither) + GetTextureTransColGX_Dither( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+(posX>>16)+g_soft.GlobalTextAddrX]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + else + GetTextureTransColGX( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+(posX>>16)+g_soft.GlobalTextAddrX]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + posX += difX; + posY += difY; + cR1 += difR; + cG1 += difG; + cB1 += difB; + } + } + if (NextRow_GT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3TGD_TW(short x1, short y1, short x2, short y2, short x3, + short y3, short tx1, short ty1, short tx2, short ty2, short tx3, + short ty3, int32_t col1, int32_t col2, int32_t col3) { + int i, j, xmin, xmax, ymin, ymax; + int32_t cR1, cG1, cB1; + int32_t difR, difB, difG, difR2, difB2, difG2; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_GT(x1, y1, x2, y2, x3, y3, tx1, ty1, tx2, ty2, tx3, ty3, + col1, col2, col3)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_GT()) + return; + + difR = delta_right_R; + difG = delta_right_G; + difB = delta_right_B; + difR2 = difR << 1; + difG2 = difG << 1; + difB2 = difB << 1; + difX = delta_right_u; + difX2 = difX << 1; + difY = delta_right_v; + difY2 = difY << 1; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans && !g_prim.iDither) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j < xmax; j += 2) { + GetTextureTransColGX32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[(((((posY+difY)>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + (((posX)>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0]), + (cB1 >> 16) | ((cB1 + difB) & 0xff0000), + (cG1 >> 16) | ((cG1 + difG) & 0xff0000), + (cR1 >> 16) | ((cR1 + difR) & 0xff0000)); + posX += difX2; + posY += difY2; + cR1 += difR2; + cG1 += difG2; + cB1 += difB2; + } + if (j == xmax) + GetTextureTransColGX_S( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + ((posX>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + } + if (NextRow_GT()) { + return; + } + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!!!! + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + + for (j = xmin; j <= xmax; j++) { + if (g_prim.iDither) + GetTextureTransColGX_Dither( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + ((posX>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + else + GetTextureTransColGX( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[((((posY>>16)%g_prim.TWin.Position.y1)+g_soft.GlobalTextAddrY+g_prim.TWin.Position.y0)<<10)+ + ((posX>>16)%g_prim.TWin.Position.x1)+g_soft.GlobalTextAddrX+g_prim.TWin.Position.x0]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + posX += difX; + posY += difY; + cR1 += difR; + cG1 += difG; + cB1 += difB; + } + } + if (NextRow_GT()) { + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +// note: two g-shaded tris: small texture distortions can happen + +#ifdef POLYQUAD3GT + +void drawPoly4TGD_TRI(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, int32_t col1, + int32_t col2, int32_t col3, int32_t col4) { + drawPoly3TGD(x2, y2, x3, y3, x4, y4, tx2, ty2, tx3, ty3, tx4, ty4, col2, + col4, col3); + drawPoly3TGD(x1, y1, x2, y2, x4, y4, tx1, ty1, tx2, ty2, tx4, ty4, col1, + col2, col3); +} + +#endif + +void drawPoly4TGD(short x1, short y1, short x2, short y2, short x3, short y3, + short x4, short y4, short tx1, short ty1, short tx2, short ty2, + short tx3, short ty3, short tx4, short ty4, int32_t col1, int32_t col2, + int32_t col4, int32_t col3) { + int32_t num; + int32_t i, j, xmin, xmax, ymin, ymax; + int32_t cR1, cG1, cB1; + int32_t difR, difB, difG, difR2, difB2, difG2; + int32_t difX, difY, difX2, difY2; + int32_t posX, posY; + + if (x1 > g_prim.drawW && x2 > g_prim.drawW && x3 > g_prim.drawW && x4 + > g_prim.drawW) + return; + if (y1 > g_prim.drawH && y2 > g_prim.drawH && y3 > g_prim.drawH && y4 + > g_prim.drawH) + return; + if (x1 < g_prim.drawX && x2 < g_prim.drawX && x3 < g_prim.drawX && x4 + < g_prim.drawX) + return; + if (y1 < g_prim.drawY && y2 < g_prim.drawY && y3 < g_prim.drawY && y4 + < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + if (!SetupSections_GT4(x1, y1, x2, y2, x3, y3, x4, y4, tx1, ty1, tx2, ty2, + tx3, ty3, tx4, ty4, col1, col2, col3, col4)) + return; + + ymax = g_soft.Ymax; + + for (ymin = g_soft.Ymin; ymin < g_prim.drawY; ymin++) + if (NextRow_GT4()) + return; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans && !g_prim.iDither) { + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + difR = (right_R - cR1) / num; + difG = (right_G - cG1) / num; + difB = (right_B - cB1) / num; + difR2 = difR << 1; + difG2 = difG << 1; + difB2 = difB << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j < xmax; j += 2) { + GetTextureTransColGX32_S( + (uint32_t *) &g_gpu.psx_vram.u16[(i << 10) + j], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[((((posY+difY)>>16)+g_soft.GlobalTextAddrY)<<10)+((posX+difX)>>16)+g_soft.GlobalTextAddrX])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+((posX)>>16)+g_soft.GlobalTextAddrX]), + (cB1 >> 16) | ((cB1 + difB) & 0xff0000), + (cG1 >> 16) | ((cG1 + difG) & 0xff0000), + (cR1 >> 16) | ((cR1 + difR) & 0xff0000)); + posX += difX2; + posY += difY2; + cR1 += difR2; + cG1 += difG2; + cB1 += difB2; + } + if (j == xmax) + GetTextureTransColGX_S( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+(posX>>16)+g_soft.GlobalTextAddrX]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + } + if (NextRow_GT4()) + return; + } + return; + } + +#endif + + for (i = ymin; i <= ymax; i++) { + xmin = (left_x >> 16); + xmax = (right_x >> 16); + + if (xmax >= xmin) { + posX = left_u; + posY = left_v; + + num = (xmax - xmin); + if (num == 0) + num = 1; + difX = (right_u - posX) / num; + difY = (right_v - posY) / num; + difX2 = difX << 1; + difY2 = difY << 1; + + cR1 = left_R; + cG1 = left_G; + cB1 = left_B; + difR = (right_R - cR1) / num; + difG = (right_G - cG1) / num; + difB = (right_B - cB1) / num; + difR2 = difR << 1; + difG2 = difG << 1; + difB2 = difB << 1; + + if (xmin < g_prim.drawX) { + j = g_prim.drawX - xmin; + xmin = g_prim.drawX; + posX += j * difX; + posY += j * difY; + cR1 += j * difR; + cG1 += j * difG; + cB1 += j * difB; + } + xmax--; + if (g_prim.drawW < xmax) + xmax = g_prim.drawW; + + for (j = xmin; j <= xmax; j++) { + if (g_prim.iDither) + GetTextureTransColGX( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+(posX>>16)+g_soft.GlobalTextAddrX]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + else + GetTextureTransColGX( + &g_gpu.psx_vram.u16[(i << 10) + j], + GETLE16(&g_gpu.psx_vram.u16[(((posY>>16)+g_soft.GlobalTextAddrY)<<10)+(posX>>16)+g_soft.GlobalTextAddrX]), + (cB1 >> 16), (cG1 >> 16), (cR1 >> 16)); + posX += difX; + posY += difY; + cR1 += difR; + cG1 += difG; + cB1 += difB; + } + } + if (NextRow_GT4()) + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4TGD_TW(short x1, short y1, short x2, short y2, short x3, + short y3, short x4, short y4, short tx1, short ty1, short tx2, + short ty2, short tx3, short ty3, short tx4, short ty4, int32_t col1, + int32_t col2, int32_t col3, int32_t col4) { + drawPoly3TGD_TW(x2, y2, x3, y3, x4, y4, tx2, ty2, tx3, ty3, tx4, ty4, col2, + col4, col3); + drawPoly3TGD_TW(x1, y1, x2, y2, x4, y4, tx1, ty1, tx2, ty2, tx4, ty4, col1, + col2, col3); +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + + +/* + // no real rect test, but it does its job the way I need it + inline char IsNoRect(void) + { + if(g_soft.lx0==g_soft.lx1 && g_soft.lx2==g_soft.lx3) return 0; + if(g_soft.lx0==g_soft.lx2 && g_soft.lx1==g_soft.lx3) return 0; + if(g_soft.lx0==g_soft.lx3 && g_soft.lx1==g_soft.lx2) return 0; + return 1; + } + */ + +// real rect test +inline char IsNoRect(void) { + if (!(g_prim.dwActFixes & 0x200)) + return 0; + + if (g_soft.ly0 == g_soft.ly1) { + if (g_soft.lx1 == g_soft.lx3 && g_soft.ly3 == g_soft.ly2 && g_soft.lx2 + == g_soft.lx0) + return 0; + if (g_soft.lx1 == g_soft.lx2 && g_soft.ly2 == g_soft.ly3 && g_soft.lx3 + == g_soft.lx0) + return 0; + return 1; + } + + if (g_soft.ly0 == g_soft.ly2) { + if (g_soft.lx2 == g_soft.lx3 && g_soft.ly3 == g_soft.ly1 && g_soft.lx1 + == g_soft.lx0) + return 0; + if (g_soft.lx2 == g_soft.lx1 && g_soft.ly1 == g_soft.ly3 && g_soft.lx3 + == g_soft.lx0) + return 0; + return 1; + } + + if (g_soft.ly0 == g_soft.ly3) { + if (g_soft.lx3 == g_soft.lx2 && g_soft.ly2 == g_soft.ly1 && g_soft.lx1 + == g_soft.lx0) + return 0; + if (g_soft.lx3 == g_soft.lx1 && g_soft.ly1 == g_soft.ly2 && g_soft.lx2 + == g_soft.lx0) + return 0; + return 1; + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3FT(unsigned char * baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + + if (0 && g_soft.GlobalTextTP < 2) { + if (g_soft.GlobalTextTP == 0) + drawPoly3TEx4_IL(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[4]) + & 0x000000ff), ((GETLE32(&gpuData[4]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[6]) & 0x000000ff), + ((GETLE32(&gpuData[6]) >> 8) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 12) & 0x3f0), + ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + else + drawPoly3TEx8_IL(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[4]) + & 0x000000ff), ((GETLE32(&gpuData[4]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[6]) & 0x000000ff), + ((GETLE32(&gpuData[6]) >> 8) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 12) & 0x3f0), + ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + return; + } + + if (!g_prim.bUsingTWin && !(g_prim.dwActFixes & 0x100)) { + switch (g_soft.GlobalTextTP) // depending on texture mode + { + case 0: + drawPoly3TEx4(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[4]) + & 0x000000ff), ((GETLE32(&gpuData[4]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[6]) & 0x000000ff), + ((GETLE32(&gpuData[6]) >> 8) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 12) & 0x3f0), + ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + return; + case 1: + drawPoly3TEx8(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[4]) + & 0x000000ff), ((GETLE32(&gpuData[4]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[6]) & 0x000000ff), + ((GETLE32(&gpuData[6]) >> 8) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 12) & 0x3f0), + ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + return; + case 2: + drawPoly3TD(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[4]) + & 0x000000ff), ((GETLE32(&gpuData[4]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[6]) & 0x000000ff), + ((GETLE32(&gpuData[6]) >> 8) & 0x000000ff)); + return; + } + return; + } + + switch (g_soft.GlobalTextTP) // depending on texture mode + { + case 0: + drawPoly3TEx4_TW(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, (GETLE32(&gpuData[2]) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6]) + >> 8) & 0x000000ff), ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + return; + case 1: + drawPoly3TEx8_TW(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, (GETLE32(&gpuData[2]) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6]) + >> 8) & 0x000000ff), ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + return; + case 2: + drawPoly3TD_TW(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, (GETLE32(&gpuData[2]) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6]) + >> 8) & 0x000000ff)); + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4FT(unsigned char * baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + + if (0 && g_soft.GlobalTextTP < 2) { + if (g_soft.GlobalTextTP == 0) + drawPoly4TEx4_IL(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[4]) + & 0x000000ff), ((GETLE32(&gpuData[4]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6]) + >> 8) & 0x000000ff), ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + else + drawPoly4TEx8_IL(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[4]) + & 0x000000ff), ((GETLE32(&gpuData[4]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6]) + >> 8) & 0x000000ff), ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + return; + } + + if (!g_prim.bUsingTWin) { +#ifdef POLYQUAD3GT + if (IsNoRect()) { + switch (g_soft.GlobalTextTP) { + case 0: + drawPoly4TEx4_TRI(g_soft.lx0, g_soft.ly0, g_soft.lx1, + g_soft.ly1, g_soft.lx3, g_soft.ly3, g_soft.lx2, + g_soft.ly2, (GETLE32(&gpuData[2]) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[4]) & 0x000000ff), + ((GETLE32(&gpuData[4]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[6]) & 0x000000ff), + ((GETLE32(&gpuData[6]) >> 8) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 12) & 0x3f0), + ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + return; + case 1: + drawPoly4TEx8_TRI(g_soft.lx0, g_soft.ly0, g_soft.lx1, + g_soft.ly1, g_soft.lx3, g_soft.ly3, g_soft.lx2, + g_soft.ly2, (GETLE32(&gpuData[2]) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[4]) & 0x000000ff), + ((GETLE32(&gpuData[4]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[6]) & 0x000000ff), + ((GETLE32(&gpuData[6]) >> 8) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 12) & 0x3f0), + ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + return; + case 2: + drawPoly4TD_TRI(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[4]) & 0x000000ff), + ((GETLE32(&gpuData[4]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[6]) & 0x000000ff), + ((GETLE32(&gpuData[6]) >> 8) & 0x000000ff)); + return; + } + return; + } +#endif + + switch (g_soft.GlobalTextTP) { + case 0: // grandia investigations needed + drawPoly4TEx4(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[4]) + & 0x000000ff), ((GETLE32(&gpuData[4]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6]) + >> 8) & 0x000000ff), ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + return; + case 1: + drawPoly4TEx8(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[4]) + & 0x000000ff), ((GETLE32(&gpuData[4]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6]) + >> 8) & 0x000000ff), ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + return; + case 2: + drawPoly4TD(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[4]) + & 0x000000ff), ((GETLE32(&gpuData[4]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6]) + >> 8) & 0x000000ff)); + return; + } + return; + } + + switch (g_soft.GlobalTextTP) { + case 0: + drawPoly4TEx4_TW(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6]) + >> 8) & 0x000000ff), ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + return; + case 1: + drawPoly4TEx8_TW(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6]) + >> 8) & 0x000000ff), ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + return; + case 2: + drawPoly4TD_TW(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[4]) & 0x000000ff), ((GETLE32(&gpuData[4]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[6]) & 0x000000ff), ((GETLE32(&gpuData[6]) + >> 8) & 0x000000ff)); + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3GT(unsigned char * baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + + if (0 && g_soft.GlobalTextTP < 2) { + if (g_soft.GlobalTextTP == 0) + drawPoly3TGEx4_IL(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[5]) + & 0x000000ff), ((GETLE32(&gpuData[5]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 12) & 0x3f0), + ((GETLE32(&gpuData[2]) >> 22) & 0x01ff), + GETLE32(&gpuData[0]), GETLE32(&gpuData[3]), + GETLE32(&gpuData[6])); + else + drawPoly3TGEx8_IL(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[5]) + & 0x000000ff), ((GETLE32(&gpuData[5]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 12) & 0x3f0), + ((GETLE32(&gpuData[2]) >> 22) & 0x01ff), + GETLE32(&gpuData[0]), GETLE32(&gpuData[3]), + GETLE32(&gpuData[6])); + return; + } + + if (!g_prim.bUsingTWin) { + switch (g_soft.GlobalTextTP) { + case 0: + drawPoly3TGEx4(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[5]) + & 0x000000ff), ((GETLE32(&gpuData[5]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 12) & 0x3f0), + ((GETLE32(&gpuData[2]) >> 22) & 0x01ff), + GETLE32(&gpuData[0]), GETLE32(&gpuData[3]), + GETLE32(&gpuData[6])); + return; + case 1: + drawPoly3TGEx8(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[5]) + & 0x000000ff), ((GETLE32(&gpuData[5]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 12) & 0x3f0), + ((GETLE32(&gpuData[2]) >> 22) & 0x01ff), + GETLE32(&gpuData[0]), GETLE32(&gpuData[3]), + GETLE32(&gpuData[6])); + return; + case 2: + drawPoly3TGD(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[5]) + & 0x000000ff), ((GETLE32(&gpuData[5]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + GETLE32(&gpuData[0]), GETLE32(&gpuData[3]), + GETLE32(&gpuData[6])); + return; + } + return; + } + + switch (g_soft.GlobalTextTP) { + case 0: + drawPoly3TGEx4_TW(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, (GETLE32(&gpuData[2]) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8]) + >> 8) & 0x000000ff), ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff), + GETLE32(&gpuData[0]), GETLE32(&gpuData[3]), + GETLE32(&gpuData[6])); + return; + case 1: + drawPoly3TGEx8_TW(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, (GETLE32(&gpuData[2]) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8]) + >> 8) & 0x000000ff), ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff), + GETLE32(&gpuData[0]), GETLE32(&gpuData[3]), + GETLE32(&gpuData[6])); + return; + case 2: + drawPoly3TGD_TW(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx2, g_soft.ly2, (GETLE32(&gpuData[2]) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8]) + >> 8) & 0x000000ff), GETLE32(&gpuData[0]), + GETLE32(&gpuData[3]), GETLE32(&gpuData[6])); + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4GT(unsigned char *baseAddr) { + uint32_t *gpuData = ((uint32_t *) baseAddr); + + if (0 && g_soft.GlobalTextTP < 2) { + if (g_soft.GlobalTextTP == 0) + drawPoly4TGEx4_TRI_IL(g_soft.lx0, g_soft.ly0, g_soft.lx1, + g_soft.ly1, g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[5]) + & 0x000000ff), ((GETLE32(&gpuData[5]) >> 8) + & 0x000000ff), + (GETLE32(&gpuData[11]) & 0x000000ff), + ((GETLE32(&gpuData[11]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8]) + >> 8) & 0x000000ff), ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff), + GETLE32(&gpuData[0]), GETLE32(&gpuData[3]), + GETLE32(&gpuData[6]), GETLE32(&gpuData[9])); + else + drawPoly4TGEx8_TRI_IL(g_soft.lx0, g_soft.ly0, g_soft.lx1, + g_soft.ly1, g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[5]) + & 0x000000ff), ((GETLE32(&gpuData[5]) >> 8) + & 0x000000ff), + (GETLE32(&gpuData[11]) & 0x000000ff), + ((GETLE32(&gpuData[11]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8]) + >> 8) & 0x000000ff), ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff), + GETLE32(&gpuData[0]), GETLE32(&gpuData[3]), + GETLE32(&gpuData[6]), GETLE32(&gpuData[9])); + return; + } + + if (!g_prim.bUsingTWin) { +#ifdef POLYQUAD3GT + if (IsNoRect()) { + switch (g_soft.GlobalTextTP) { + case 0: + drawPoly4TGEx4_TRI(g_soft.lx0, g_soft.ly0, g_soft.lx1, + g_soft.ly1, g_soft.lx3, g_soft.ly3, g_soft.lx2, + g_soft.ly2, (GETLE32(&gpuData[2]) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[5]) & 0x000000ff), + ((GETLE32(&gpuData[5]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[11]) & 0x000000ff), + ((GETLE32(&gpuData[11]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 12) & 0x3f0), + ((GETLE32(&gpuData[2]) >> 22) & 0x01ff), + GETLE32(&gpuData[0]), GETLE32(&gpuData[3]), + GETLE32(&gpuData[6]), GETLE32(&gpuData[9])); + + return; + case 1: + drawPoly4TGEx8_TRI(g_soft.lx0, g_soft.ly0, g_soft.lx1, + g_soft.ly1, g_soft.lx3, g_soft.ly3, g_soft.lx2, + g_soft.ly2, (GETLE32(&gpuData[2]) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[5]) & 0x000000ff), + ((GETLE32(&gpuData[5]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[11]) & 0x000000ff), + ((GETLE32(&gpuData[11]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 12) & 0x3f0), + ((GETLE32(&gpuData[2]) >> 22) & 0x01ff), + GETLE32(&gpuData[0]), GETLE32(&gpuData[3]), + GETLE32(&gpuData[6]), GETLE32(&gpuData[9])); + return; + case 2: + drawPoly4TGD_TRI(g_soft.lx0, g_soft.ly0, g_soft.lx1, + g_soft.ly1, g_soft.lx3, g_soft.ly3, g_soft.lx2, + g_soft.ly2, (GETLE32(&gpuData[2]) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[5]) & 0x000000ff), + ((GETLE32(&gpuData[5]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[11]) & 0x000000ff), + ((GETLE32(&gpuData[11]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + GETLE32(&gpuData[0]), GETLE32(&gpuData[3]), + GETLE32(&gpuData[6]), GETLE32(&gpuData[9])); + return; + } + return; + } +#endif + + switch (g_soft.GlobalTextTP) { + case 0: + drawPoly4TGEx4(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[5]) + & 0x000000ff), ((GETLE32(&gpuData[5]) >> 8) + & 0x000000ff), + (GETLE32(&gpuData[11]) & 0x000000ff), + ((GETLE32(&gpuData[11]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8]) + >> 8) & 0x000000ff), ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff), + GETLE32(&gpuData[0]), GETLE32(&gpuData[3]), + GETLE32(&gpuData[6]), GETLE32(&gpuData[9])); + + return; + case 1: + drawPoly4TGEx8(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[5]) + & 0x000000ff), ((GETLE32(&gpuData[5]) >> 8) + & 0x000000ff), + (GETLE32(&gpuData[11]) & 0x000000ff), + ((GETLE32(&gpuData[11]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8]) + >> 8) & 0x000000ff), ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff), + GETLE32(&gpuData[0]), GETLE32(&gpuData[3]), + GETLE32(&gpuData[6]), GETLE32(&gpuData[9])); + return; + case 2: + drawPoly4TGD(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[5]) + & 0x000000ff), ((GETLE32(&gpuData[5]) >> 8) + & 0x000000ff), + (GETLE32(&gpuData[11]) & 0x000000ff), + ((GETLE32(&gpuData[11]) >> 8) & 0x000000ff), + (GETLE32(&gpuData[8]) & 0x000000ff), ((GETLE32(&gpuData[8]) + >> 8) & 0x000000ff), GETLE32(&gpuData[0]), + GETLE32(&gpuData[3]), GETLE32(&gpuData[6]), + GETLE32(&gpuData[9])); + return; + } + return; + } + + switch (g_soft.GlobalTextTP) { + case 0: + drawPoly4TGEx4_TW(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[11]) + & 0x000000ff), ((GETLE32(&gpuData[11]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 12) & 0x3f0), ((GETLE32(&gpuData[2]) + >> 22) & 0x01ff), GETLE32(&gpuData[0]), + GETLE32(&gpuData[3]), GETLE32(&gpuData[6]), + GETLE32(&gpuData[9])); + return; + case 1: + drawPoly4TGEx8_TW(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[11]) + & 0x000000ff), ((GETLE32(&gpuData[11]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + ((GETLE32(&gpuData[2]) >> 12) & 0x3f0), ((GETLE32(&gpuData[2]) + >> 22) & 0x01ff), GETLE32(&gpuData[0]), + GETLE32(&gpuData[3]), GETLE32(&gpuData[6]), + GETLE32(&gpuData[9])); + return; + case 2: + drawPoly4TGD_TW(g_soft.lx0, g_soft.ly0, g_soft.lx1, g_soft.ly1, + g_soft.lx3, g_soft.ly3, g_soft.lx2, g_soft.ly2, + (GETLE32(&gpuData[2]) & 0x000000ff), ((GETLE32(&gpuData[2]) + >> 8) & 0x000000ff), + (GETLE32(&gpuData[5]) & 0x000000ff), ((GETLE32(&gpuData[5]) + >> 8) & 0x000000ff), (GETLE32(&gpuData[11]) + & 0x000000ff), ((GETLE32(&gpuData[11]) >> 8) + & 0x000000ff), (GETLE32(&gpuData[8]) & 0x000000ff), + ((GETLE32(&gpuData[8]) >> 8) & 0x000000ff), + GETLE32(&gpuData[0]), GETLE32(&gpuData[3]), + GETLE32(&gpuData[6]), GETLE32(&gpuData[9])); + return; + } +} + +//////////////////////////////////////////////////////////////////////// +// SPRITE FUNCS +//////////////////////////////////////////////////////////////////////// + +void DrawSoftwareSpriteTWin(unsigned char * baseAddr, int32_t w, int32_t h) { + uint32_t *gpuData = (uint32_t *) baseAddr; + short sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3; + short tx0, ty0, tx1, ty1, tx2, ty2, tx3, ty3; + + sx0 = g_soft.lx0; + sy0 = g_soft.ly0; + + sx0 = sx3 = sx0 + g_gpu.dsp.DrawOffset.x; + sx1 = sx2 = sx0 + w; + sy0 = sy1 = sy0 + g_gpu.dsp.DrawOffset.y; + sy2 = sy3 = sy0 + h; + + tx0 = tx3 = GETLE32(&gpuData[2]) & 0xff; + tx1 = tx2 = tx0 + w; + ty0 = ty1 = (GETLE32(&gpuData[2]) >> 8) & 0xff; + ty2 = ty3 = ty0 + h; + + switch (g_soft.GlobalTextTP) { + case 0: + drawPoly4TEx4_TW_S(sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3, tx0, ty0, + tx1, ty1, tx2, ty2, tx3, ty3, ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + return; + case 1: + drawPoly4TEx8_TW_S(sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3, tx0, ty0, + tx1, ty1, tx2, ty2, tx3, ty3, ((GETLE32(&gpuData[2]) >> 12) + & 0x3f0), ((GETLE32(&gpuData[2]) >> 22) & 0x01ff)); + return; + case 2: + drawPoly4TD_TW_S(sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3, tx0, ty0, tx1, + ty1, tx2, ty2, tx3, ty3); + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void DrawSoftwareSpriteMirror(unsigned char * baseAddr, int32_t w, int32_t h) { + int32_t sprtY, sprtX, sprtW, sprtH, lXDir, lYDir; + int32_t clutY0, clutX0, clutP, textX0, textY0, sprtYa, sprCY, sprCX, sprA; + short tC; + uint32_t *gpuData = (uint32_t *) baseAddr; + sprtY = g_soft.ly0; + sprtX = g_soft.lx0; + sprtH = h; + sprtW = w; + clutY0 = (GETLE32(&gpuData[2]) >> 22) & 0x01ff; + clutX0 = (GETLE32(&gpuData[2]) >> 12) & 0x3f0; + clutP = (clutY0 << 11) + (clutX0 << 1); + textY0 = ((GETLE32(&gpuData[2]) >> 8) & 0x000000ff) + + g_soft.GlobalTextAddrY; + textX0 = (GETLE32(&gpuData[2]) & 0x000000ff); + + sprtX += g_gpu.dsp.DrawOffset.x; + sprtY += g_gpu.dsp.DrawOffset.y; + + // while (sprtX>1023) sprtX-=1024; + // while (sprtY>MAXYLINESMIN1) sprtY-=MAXYLINES; + + if (sprtX > g_prim.drawW) { + // if((sprtX+sprtW)>1023) sprtX-=1024; + // else return; + return; + } + + if (sprtY > g_prim.drawH) { + // if ((sprtY+sprtH)>MAXYLINESMIN1) sprtY-=MAXYLINES; + // else return; + return; + } + + if (sprtY < g_prim.drawY) { + if ((sprtY + sprtH) < g_prim.drawY) + return; + sprtH -= (g_prim.drawY - sprtY); + textY0 += (g_prim.drawY - sprtY); + sprtY = g_prim.drawY; + } + + if (sprtX < g_prim.drawX) { + if ((sprtX + sprtW) < g_prim.drawX) + return; + sprtW -= (g_prim.drawX - sprtX); + textX0 += (g_prim.drawX - sprtX); + sprtX = g_prim.drawX; + } + + if ((sprtY + sprtH) > g_prim.drawH) + sprtH = g_prim.drawH - sprtY + 1; + if ((sprtX + sprtW) > g_prim.drawW) + sprtW = g_prim.drawW - sprtX + 1; + + if (g_prim.usMirror & 0x1000) + lXDir = -1; + else + lXDir = 1; + if (g_prim.usMirror & 0x2000) + lYDir = -1; + else + lYDir = 1; + + switch (g_soft.GlobalTextTP) { + case 0: // texture is 4-bit + + sprtW = sprtW / 2; + textX0 = (g_soft.GlobalTextAddrX << 1) + (textX0 >> 1); + sprtYa = (sprtY << 10); + clutP = (clutY0 << 10) + clutX0; + for (sprCY = 0; sprCY < sprtH; sprCY++) + for (sprCX = 0; sprCX < sprtW; sprCX++) { + tC = g_gpu.psx_vram.u8[((textY0 + (sprCY * lYDir)) << 11) + + textX0 + (sprCX * lXDir)]; + sprA = sprtYa + (sprCY << 10) + sprtX + (sprCX << 1); + GetTextureTransColG_SPR(&g_gpu.psx_vram.u16[sprA], + GETLE16(&g_gpu.psx_vram.u16[clutP+((tC>>4)&0xf)])); + GetTextureTransColG_SPR(&g_gpu.psx_vram.u16[sprA + 1], + GETLE16(&g_gpu.psx_vram.u16[clutP+(tC&0xf)])); + } + return; + + case 1: + + clutP >>= 1; + for (sprCY = 0; sprCY < sprtH; sprCY++) + for (sprCX = 0; sprCX < sprtW; sprCX++) { + tC = g_gpu.psx_vram.u8[((textY0 + (sprCY * lYDir)) << 11) + + (g_soft.GlobalTextAddrX << 1) + textX0 + (sprCX + * lXDir)] & 0xff; + GetTextureTransColG_SPR(&g_gpu.psx_vram.u16[((sprtY + sprCY) + << 10) + sprtX + sprCX], g_gpu.psx_vram.u16[clutP + tC]); + } + return; + + case 2: + + for (sprCY = 0; sprCY < sprtH; sprCY++) + for (sprCX = 0; sprCX < sprtW; sprCX++) { + GetTextureTransColG_SPR( + &g_gpu.psx_vram.u16[((sprtY + sprCY) << 10) + sprtX + + sprCX], + GETLE16(&g_gpu.psx_vram.u16[((textY0+(sprCY*lYDir))<<10)+g_soft.GlobalTextAddrX + textX0 +(sprCX*lXDir)])); + } + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void DrawSoftwareSprite_IL(unsigned char * baseAddr, short w, short h, + int32_t tx, int32_t ty) { + int32_t sprtY, sprtX, sprtW, sprtH, tdx, tdy; + uint32_t *gpuData = (uint32_t *) baseAddr; + + sprtY = g_soft.ly0; + sprtX = g_soft.lx0; + sprtH = h; + sprtW = w; + + sprtX += g_gpu.dsp.DrawOffset.x; + sprtY += g_gpu.dsp.DrawOffset.y; + + if (sprtX > g_prim.drawW) + return; + if (sprtY > g_prim.drawH) + return; + + tdx = tx + sprtW; + tdy = ty + sprtH; + + sprtW += sprtX; + sprtH += sprtY; + + // Pete is too lazy to make a faster version ;) + + if (g_soft.GlobalTextTP == 0) + drawPoly4TEx4_IL(sprtX, sprtY, sprtX, sprtH, sprtW, sprtH, sprtW, + sprtY, tx, ty, tx, tdy, tdx, tdy, tdx, ty, + (GETLE32(&gpuData[2]) >> 12) & 0x3f0, ((GETLE32(&gpuData[2]) + >> 22) & 0x01ff)); + + else + drawPoly4TEx8_IL(sprtX, sprtY, sprtX, sprtH, sprtW, sprtH, sprtW, + sprtY, tx, ty, tx, tdy, tdx, tdy, tdx, ty, + (GETLE32(&gpuData[2]) >> 12) & 0x3f0, ((GETLE32(&gpuData[2]) + >> 22) & 0x01ff)); +} + +//////////////////////////////////////////////////////////////////////// + +void DrawSoftwareSprite(unsigned char * baseAddr, short w, short h, int32_t tx, + int32_t ty) { + int32_t sprtY, sprtX, sprtW, sprtH; + int32_t clutY0, clutX0, clutP, textX0, textY0, sprtYa, sprCY, sprCX, sprA; + short tC, tC2; + uint32_t *gpuData = (uint32_t *) baseAddr; + unsigned char * pV; + char bWT, bWS; + + if (0 && g_soft.GlobalTextTP < 2) { + DrawSoftwareSprite_IL(baseAddr, w, h, tx, ty); + return; + } + + sprtY = g_soft.ly0; + sprtX = g_soft.lx0; + sprtH = h; + sprtW = w; + clutY0 = (GETLE32(&gpuData[2]) >> 22) & 0x01ff; + clutX0 = (GETLE32(&gpuData[2]) >> 12) & 0x3f0; + + clutP = (clutY0 << 11) + (clutX0 << 1); + + textY0 = ty + g_soft.GlobalTextAddrY; + textX0 = tx; + + sprtX += g_gpu.dsp.DrawOffset.x; + sprtY += g_gpu.dsp.DrawOffset.y; + + //while (sprtX>1023) sprtX-=1024; + //while (sprtY>MAXYLINESMIN1) sprtY-=MAXYLINES; + + if (sprtX > g_prim.drawW) { + // if((sprtX+sprtW)>1023) sprtX-=1024; + // else return; + return; + } + + if (sprtY > g_prim.drawH) { + // if ((sprtY+sprtH)>MAXYLINESMIN1) sprtY-=MAXYLINES; + // else return; + return; + } + + if (sprtY < g_prim.drawY) { + if ((sprtY + sprtH) < g_prim.drawY) + return; + sprtH -= (g_prim.drawY - sprtY); + textY0 += (g_prim.drawY - sprtY); + sprtY = g_prim.drawY; + } + + if (sprtX < g_prim.drawX) { + if ((sprtX + sprtW) < g_prim.drawX) + return; + + sprtW -= (g_prim.drawX - sprtX); + textX0 += (g_prim.drawX - sprtX); + sprtX = g_prim.drawX; + } + + if ((sprtY + sprtH) > g_prim.drawH) + sprtH = g_prim.drawH - sprtY + 1; + if ((sprtX + sprtW) > g_prim.drawW) + sprtW = g_prim.drawW - sprtX + 1; + + bWT = 0; + bWS = 0; + + switch (g_soft.GlobalTextTP) { + case 0: + + if (textX0 & 1) { + bWS = 1; + sprtW--; + } + if (sprtW & 1) + bWT = 1; + + sprtW = sprtW >> 1; + textX0 = (g_soft.GlobalTextAddrX << 1) + (textX0 >> 1) + (textY0 << 11); + sprtYa = (sprtY << 10) + sprtX; + clutP = (clutY0 << 10) + clutX0; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (sprCY = 0; sprCY < sprtH; sprCY++) { + sprA = sprtYa + (sprCY << 10); + pV = &g_gpu.psx_vram.u8[(sprCY << 11) + textX0]; + + if (bWS) { + tC = *pV++; + GetTextureTransColG_S(&g_gpu.psx_vram.u16[sprA++], + GETLE16(&g_gpu.psx_vram.u16[clutP+((tC>>4)&0xf)])); + } + + for (sprCX = 0; sprCX < sprtW; sprCX++, sprA += 2) { + tC = *pV++; + + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[sprA], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+((tC>>4)&0xf)])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[clutP+(tC&0x0f)])); + } + + if (bWT) { + tC = *pV; + GetTextureTransColG_S(&g_gpu.psx_vram.u16[sprA], + GETLE16(&g_gpu.psx_vram.u16[clutP+(tC&0x0f)])); + } + } + return; + } + +#endif + + for (sprCY = 0; sprCY < sprtH; sprCY++) { + sprA = sprtYa + (sprCY << 10); + pV = &g_gpu.psx_vram.u8[(sprCY << 11) + textX0]; + + if (bWS) { + tC = *pV++; + GetTextureTransColG_SPR(&g_gpu.psx_vram.u16[sprA++], + GETLE16(&g_gpu.psx_vram.u16[clutP+((tC>>4)&0xf)])); + } + + for (sprCX = 0; sprCX < sprtW; sprCX++, sprA += 2) { + tC = *pV++; + + GetTextureTransColG32_SPR( + (uint32_t *) &g_gpu.psx_vram.u16[sprA], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+((tC>>4)&0xf)]) + << 16)) + | GETLE16(&g_gpu.psx_vram.u16[clutP+(tC&0x0f)])); + } + + if (bWT) { + tC = *pV; + GetTextureTransColG_SPR(&g_gpu.psx_vram.u16[sprA], + GETLE16(&g_gpu.psx_vram.u16[clutP+(tC&0x0f)])); + } + } + return; + + case 1: + clutP >>= 1; + sprtW--; + textX0 += (g_soft.GlobalTextAddrX << 1) + (textY0 << 11); + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (sprCY = 0; sprCY < sprtH; sprCY++) { + sprA = ((sprtY + sprCY) << 10) + sprtX; + pV = &g_gpu.psx_vram.u8[(sprCY << 11) + textX0]; + for (sprCX = 0; sprCX < sprtW; sprCX += 2, sprA += 2) { + tC = *pV++; + tC2 = *pV++; + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[sprA], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[clutP+tC])); + } + if (sprCX == sprtW) + GetTextureTransColG_S(&g_gpu.psx_vram.u16[sprA], + GETLE16(&g_gpu.psx_vram.u16[clutP+(*pV)])); + } + return; + } + +#endif + + for (sprCY = 0; sprCY < sprtH; sprCY++) { + sprA = ((sprtY + sprCY) << 10) + sprtX; + pV = &g_gpu.psx_vram.u8[(sprCY << 11) + textX0]; + for (sprCX = 0; sprCX < sprtW; sprCX += 2, sprA += 2) { + tC = *pV++; + tC2 = *pV++; + GetTextureTransColG32_SPR( + (uint32_t *) &g_gpu.psx_vram.u16[sprA], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[clutP+tC2])) + << 16) | GETLE16(&g_gpu.psx_vram.u16[clutP+tC])); + } + if (sprCX == sprtW) + GetTextureTransColG_SPR(&g_gpu.psx_vram.u16[sprA], + GETLE16(&g_gpu.psx_vram.u16[clutP+(*pV)])); + } + return; + + case 2: + + textX0 += (g_soft.GlobalTextAddrX) + (textY0 << 10); + sprtW--; + +#ifdef FASTSOLID + + if (!g_draw.bCheckMask && !g_soft.DrawSemiTrans) { + for (sprCY = 0; sprCY < sprtH; sprCY++) { + sprA = ((sprtY + sprCY) << 10) + sprtX; + + for (sprCX = 0; sprCX < sprtW; sprCX += 2, sprA += 2) { + GetTextureTransColG32_S( + (uint32_t *) &g_gpu.psx_vram.u16[sprA], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[(sprCY<<10) + textX0 + sprCX +1])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[(sprCY<<10) + textX0 + sprCX])); + } + if (sprCX == sprtW) + GetTextureTransColG_S( + &g_gpu.psx_vram.u16[sprA], + GETLE16(&g_gpu.psx_vram.u16[(sprCY<<10) + textX0 + sprCX])); + + } + return; + } + +#endif + + for (sprCY = 0; sprCY < sprtH; sprCY++) { + sprA = ((sprtY + sprCY) << 10) + sprtX; + + for (sprCX = 0; sprCX < sprtW; sprCX += 2, sprA += 2) { + GetTextureTransColG32_SPR( + (uint32_t *) &g_gpu.psx_vram.u16[sprA], + (((int32_t) GETLE16(&g_gpu.psx_vram.u16[(sprCY<<10) + textX0 + sprCX +1])) + << 16) + | GETLE16(&g_gpu.psx_vram.u16[(sprCY<<10) + textX0 + sprCX])); + } + if (sprCX == sprtW) + GetTextureTransColG_SPR( + &g_gpu.psx_vram.u16[sprA], + GETLE16(&g_gpu.psx_vram.u16[(sprCY<<10) + textX0 + sprCX])); + + } + return; + } +} + +/////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +// LINE FUNCS +//////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////// + +void Line_E_SE_Shade(int x0, int y0, int x1, int y1, uint32_t rgb0, + uint32_t rgb1) { + int dx, dy, incrE, incrSE, d; + uint32_t r0, g0, b0, r1, g1, b1; + int32_t dr, dg, db; + + r0 = (rgb0 & 0x00ff0000); + g0 = (rgb0 & 0x0000ff00) << 8; + b0 = (rgb0 & 0x000000ff) << 16; + r1 = (rgb1 & 0x00ff0000); + g1 = (rgb1 & 0x0000ff00) << 8; + b1 = (rgb1 & 0x000000ff) << 16; + + dx = x1 - x0; + dy = y1 - y0; + + if (dx > 0) { + dr = ((int32_t) r1 - (int32_t) r0) / dx; + dg = ((int32_t) g1 - (int32_t) g0) / dx; + db = ((int32_t) b1 - (int32_t) b0) / dx; + } else { + dr = ((int32_t) r1 - (int32_t) r0); + dg = ((int32_t) g1 - (int32_t) g0); + db = ((int32_t) b1 - (int32_t) b0); + } + + d = 2 * dy - dx; /* Initial value of d */ + incrE = 2 * dy; /* incr. used for move to E */ + incrSE = 2 * (dy - dx); /* incr. used for move to SE */ + + if ((x0 >= g_prim.drawX) && (x0 < g_prim.drawW) && (y0 >= g_prim.drawY) + && (y0 < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y0 << 10) + x0], + (unsigned short) (((r0 >> 9) & 0x7c00) | ((g0 >> 14) & 0x03e0) + | ((b0 >> 19) & 0x001f))); + while (x0 < x1) { + if (d <= 0) { + d = d + incrE; /* Choose E */ + } else { + d = d + incrSE; /* Choose SE */ + y0++; + } + x0++; + + r0 += dr; + g0 += dg; + b0 += db; + + if ((x0 >= g_prim.drawX) && (x0 < g_prim.drawW) && (y0 >= g_prim.drawY) + && (y0 < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y0 << 10) + x0], + (unsigned short) (((r0 >> 9) & 0x7c00) | ((g0 >> 14) + & 0x03e0) | ((b0 >> 19) & 0x001f))); + } +} + +/////////////////////////////////////////////////////////////////////// + +void Line_S_SE_Shade(int x0, int y0, int x1, int y1, uint32_t rgb0, + uint32_t rgb1) { + int dx, dy, incrS, incrSE, d; + uint32_t r0, g0, b0, r1, g1, b1; + int32_t dr, dg, db; + + r0 = (rgb0 & 0x00ff0000); + g0 = (rgb0 & 0x0000ff00) << 8; + b0 = (rgb0 & 0x000000ff) << 16; + r1 = (rgb1 & 0x00ff0000); + g1 = (rgb1 & 0x0000ff00) << 8; + b1 = (rgb1 & 0x000000ff) << 16; + + dx = x1 - x0; + dy = y1 - y0; + + if (dy > 0) { + dr = ((int32_t) r1 - (int32_t) r0) / dy; + dg = ((int32_t) g1 - (int32_t) g0) / dy; + db = ((int32_t) b1 - (int32_t) b0) / dy; + } else { + dr = ((int32_t) r1 - (int32_t) r0); + dg = ((int32_t) g1 - (int32_t) g0); + db = ((int32_t) b1 - (int32_t) b0); + } + + d = 2 * dx - dy; /* Initial value of d */ + incrS = 2 * dx; /* incr. used for move to S */ + incrSE = 2 * (dx - dy); /* incr. used for move to SE */ + + if ((x0 >= g_prim.drawX) && (x0 < g_prim.drawW) && (y0 >= g_prim.drawY) + && (y0 < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y0 << 10) + x0], + (unsigned short) (((r0 >> 9) & 0x7c00) | ((g0 >> 14) & 0x03e0) + | ((b0 >> 19) & 0x001f))); + while (y0 < y1) { + if (d <= 0) { + d = d + incrS; /* Choose S */ + } else { + d = d + incrSE; /* Choose SE */ + x0++; + } + y0++; + + r0 += dr; + g0 += dg; + b0 += db; + + if ((x0 >= g_prim.drawX) && (x0 < g_prim.drawW) && (y0 >= g_prim.drawY) + && (y0 < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y0 << 10) + x0], + (unsigned short) (((r0 >> 9) & 0x7c00) | ((g0 >> 14) + & 0x03e0) | ((b0 >> 19) & 0x001f))); + } +} + +/////////////////////////////////////////////////////////////////////// + +void Line_N_NE_Shade(int x0, int y0, int x1, int y1, uint32_t rgb0, + uint32_t rgb1) { + int dx, dy, incrN, incrNE, d; + uint32_t r0, g0, b0, r1, g1, b1; + int32_t dr, dg, db; + + r0 = (rgb0 & 0x00ff0000); + g0 = (rgb0 & 0x0000ff00) << 8; + b0 = (rgb0 & 0x000000ff) << 16; + r1 = (rgb1 & 0x00ff0000); + g1 = (rgb1 & 0x0000ff00) << 8; + b1 = (rgb1 & 0x000000ff) << 16; + + dx = x1 - x0; + dy = -(y1 - y0); + + if (dy > 0) { + dr = ((int32_t) r1 - (int32_t) r0) / dy; + dg = ((int32_t) g1 - (int32_t) g0) / dy; + db = ((int32_t) b1 - (int32_t) b0) / dy; + } else { + dr = ((int32_t) r1 - (int32_t) r0); + dg = ((int32_t) g1 - (int32_t) g0); + db = ((int32_t) b1 - (int32_t) b0); + } + + d = 2 * dx - dy; /* Initial value of d */ + incrN = 2 * dx; /* incr. used for move to N */ + incrNE = 2 * (dx - dy); /* incr. used for move to NE */ + + if ((x0 >= g_prim.drawX) && (x0 < g_prim.drawW) && (y0 >= g_prim.drawY) + && (y0 < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y0 << 10) + x0], + (unsigned short) (((r0 >> 9) & 0x7c00) | ((g0 >> 14) & 0x03e0) + | ((b0 >> 19) & 0x001f))); + while (y0 > y1) { + if (d <= 0) { + d = d + incrN; /* Choose N */ + } else { + d = d + incrNE; /* Choose NE */ + x0++; + } + y0--; + + r0 += dr; + g0 += dg; + b0 += db; + + if ((x0 >= g_prim.drawX) && (x0 < g_prim.drawW) && (y0 >= g_prim.drawY) + && (y0 < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y0 << 10) + x0], + (unsigned short) (((r0 >> 9) & 0x7c00) | ((g0 >> 14) + & 0x03e0) | ((b0 >> 19) & 0x001f))); + } +} + +/////////////////////////////////////////////////////////////////////// + +void Line_E_NE_Shade(int x0, int y0, int x1, int y1, uint32_t rgb0, + uint32_t rgb1) { + int dx, dy, incrE, incrNE, d; + uint32_t r0, g0, b0, r1, g1, b1; + int32_t dr, dg, db; + + r0 = (rgb0 & 0x00ff0000); + g0 = (rgb0 & 0x0000ff00) << 8; + b0 = (rgb0 & 0x000000ff) << 16; + r1 = (rgb1 & 0x00ff0000); + g1 = (rgb1 & 0x0000ff00) << 8; + b1 = (rgb1 & 0x000000ff) << 16; + + dx = x1 - x0; + dy = -(y1 - y0); + + if (dx > 0) { + dr = ((int32_t) r1 - (int32_t) r0) / dx; + dg = ((int32_t) g1 - (int32_t) g0) / dx; + db = ((int32_t) b1 - (int32_t) b0) / dx; + } else { + dr = ((int32_t) r1 - (int32_t) r0); + dg = ((int32_t) g1 - (int32_t) g0); + db = ((int32_t) b1 - (int32_t) b0); + } + + d = 2 * dy - dx; /* Initial value of d */ + incrE = 2 * dy; /* incr. used for move to E */ + incrNE = 2 * (dy - dx); /* incr. used for move to NE */ + + if ((x0 >= g_prim.drawX) && (x0 < g_prim.drawW) && (y0 >= g_prim.drawY) + && (y0 < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y0 << 10) + x0], + (unsigned short) (((r0 >> 9) & 0x7c00) | ((g0 >> 14) & 0x03e0) + | ((b0 >> 19) & 0x001f))); + while (x0 < x1) { + if (d <= 0) { + d = d + incrE; /* Choose E */ + } else { + d = d + incrNE; /* Choose NE */ + y0--; + } + x0++; + + r0 += dr; + g0 += dg; + b0 += db; + + if ((x0 >= g_prim.drawX) && (x0 < g_prim.drawW) && (y0 >= g_prim.drawY) + && (y0 < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y0 << 10) + x0], + (unsigned short) (((r0 >> 9) & 0x7c00) | ((g0 >> 14) + & 0x03e0) | ((b0 >> 19) & 0x001f))); + } +} + +/////////////////////////////////////////////////////////////////////// + +void VertLineShade(int x, int y0, int y1, uint32_t rgb0, uint32_t rgb1) { + int y, dy; + uint32_t r0, g0, b0, r1, g1, b1; + int32_t dr, dg, db; + + r0 = (rgb0 & 0x00ff0000); + g0 = (rgb0 & 0x0000ff00) << 8; + b0 = (rgb0 & 0x000000ff) << 16; + r1 = (rgb1 & 0x00ff0000); + g1 = (rgb1 & 0x0000ff00) << 8; + b1 = (rgb1 & 0x000000ff) << 16; + + dy = (y1 - y0); + + if (dy > 0) { + dr = ((int32_t) r1 - (int32_t) r0) / dy; + dg = ((int32_t) g1 - (int32_t) g0) / dy; + db = ((int32_t) b1 - (int32_t) b0) / dy; + } else { + dr = ((int32_t) r1 - (int32_t) r0); + dg = ((int32_t) g1 - (int32_t) g0); + db = ((int32_t) b1 - (int32_t) b0); + } + + if (y0 < g_prim.drawY) { + r0 += dr * (g_prim.drawY - y0); + g0 += dg * (g_prim.drawY - y0); + b0 += db * (g_prim.drawY - y0); + y0 = g_prim.drawY; + } + + if (y1 > g_prim.drawH) + y1 = g_prim.drawH; + + for (y = y0; y <= y1; y++) { + GetShadeTransCol(&g_gpu.psx_vram.u16[(y << 10) + x], + (unsigned short) (((r0 >> 9) & 0x7c00) | ((g0 >> 14) & 0x03e0) + | ((b0 >> 19) & 0x001f))); + r0 += dr; + g0 += dg; + b0 += db; + } +} + +/////////////////////////////////////////////////////////////////////// + +void HorzLineShade(int y, int x0, int x1, uint32_t rgb0, uint32_t rgb1) { + int x, dx; + uint32_t r0, g0, b0, r1, g1, b1; + int32_t dr, dg, db; + + r0 = (rgb0 & 0x00ff0000); + g0 = (rgb0 & 0x0000ff00) << 8; + b0 = (rgb0 & 0x000000ff) << 16; + r1 = (rgb1 & 0x00ff0000); + g1 = (rgb1 & 0x0000ff00) << 8; + b1 = (rgb1 & 0x000000ff) << 16; + + dx = (x1 - x0); + + if (dx > 0) { + dr = ((int32_t) r1 - (int32_t) r0) / dx; + dg = ((int32_t) g1 - (int32_t) g0) / dx; + db = ((int32_t) b1 - (int32_t) b0) / dx; + } else { + dr = ((int32_t) r1 - (int32_t) r0); + dg = ((int32_t) g1 - (int32_t) g0); + db = ((int32_t) b1 - (int32_t) b0); + } + + if (x0 < g_prim.drawX) { + r0 += dr * (g_prim.drawX - x0); + g0 += dg * (g_prim.drawX - x0); + b0 += db * (g_prim.drawX - x0); + x0 = g_prim.drawX; + } + + if (x1 > g_prim.drawW) + x1 = g_prim.drawW; + + for (x = x0; x <= x1; x++) { + GetShadeTransCol(&g_gpu.psx_vram.u16[(y << 10) + x], + (unsigned short) (((r0 >> 9) & 0x7c00) | ((g0 >> 14) & 0x03e0) + | ((b0 >> 19) & 0x001f))); + r0 += dr; + g0 += dg; + b0 += db; + } +} + +/////////////////////////////////////////////////////////////////////// + +void Line_E_SE_Flat(int x0, int y0, int x1, int y1, unsigned short colour) { + int dx, dy, incrE, incrSE, d, x, y; + + dx = x1 - x0; + dy = y1 - y0; + d = 2 * dy - dx; /* Initial value of d */ + incrE = 2 * dy; /* incr. used for move to E */ + incrSE = 2 * (dy - dx); /* incr. used for move to SE */ + x = x0; + y = y0; + if ((x >= g_prim.drawX) && (x < g_prim.drawW) && (y >= g_prim.drawY) && (y + < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y << 10) + x], colour); + while (x < x1) { + if (d <= 0) { + d = d + incrE; /* Choose E */ + x++; + } else { + d = d + incrSE; /* Choose SE */ + x++; + y++; + } + if ((x >= g_prim.drawX) && (x < g_prim.drawW) && (y >= g_prim.drawY) + && (y < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y << 10) + x], colour); + } +} + +/////////////////////////////////////////////////////////////////////// + +void Line_S_SE_Flat(int x0, int y0, int x1, int y1, unsigned short colour) { + int dx, dy, incrS, incrSE, d, x, y; + + dx = x1 - x0; + dy = y1 - y0; + d = 2 * dx - dy; /* Initial value of d */ + incrS = 2 * dx; /* incr. used for move to S */ + incrSE = 2 * (dx - dy); /* incr. used for move to SE */ + x = x0; + y = y0; + if ((x >= g_prim.drawX) && (x < g_prim.drawW) && (y >= g_prim.drawY) && (y + < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y << 10) + x], colour); + while (y < y1) { + if (d <= 0) { + d = d + incrS; /* Choose S */ + y++; + } else { + d = d + incrSE; /* Choose SE */ + x++; + y++; + } + if ((x >= g_prim.drawX) && (x < g_prim.drawW) && (y >= g_prim.drawY) + && (y < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y << 10) + x], colour); + } +} + +/////////////////////////////////////////////////////////////////////// + +void Line_N_NE_Flat(int x0, int y0, int x1, int y1, unsigned short colour) { + int dx, dy, incrN, incrNE, d, x, y; + + dx = x1 - x0; + dy = -(y1 - y0); + d = 2 * dx - dy; /* Initial value of d */ + incrN = 2 * dx; /* incr. used for move to N */ + incrNE = 2 * (dx - dy); /* incr. used for move to NE */ + x = x0; + y = y0; + if ((x >= g_prim.drawX) && (x < g_prim.drawW) && (y >= g_prim.drawY) && (y + < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y << 10) + x], colour); + while (y > y1) { + if (d <= 0) { + d = d + incrN; /* Choose N */ + y--; + } else { + d = d + incrNE; /* Choose NE */ + x++; + y--; + } + if ((x >= g_prim.drawX) && (x < g_prim.drawW) && (y >= g_prim.drawY) + && (y < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y << 10) + x], colour); + } +} + +/////////////////////////////////////////////////////////////////////// + +void Line_E_NE_Flat(int x0, int y0, int x1, int y1, unsigned short colour) { + int dx, dy, incrE, incrNE, d, x, y; + + dx = x1 - x0; + dy = -(y1 - y0); + d = 2 * dy - dx; /* Initial value of d */ + incrE = 2 * dy; /* incr. used for move to E */ + incrNE = 2 * (dy - dx); /* incr. used for move to NE */ + x = x0; + y = y0; + if ((x >= g_prim.drawX) && (x < g_prim.drawW) && (y >= g_prim.drawY) && (y + < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y << 10) + x], colour); + while (x < x1) { + if (d <= 0) { + d = d + incrE; /* Choose E */ + x++; + } else { + d = d + incrNE; /* Choose NE */ + x++; + y--; + } + if ((x >= g_prim.drawX) && (x < g_prim.drawW) && (y >= g_prim.drawY) + && (y < g_prim.drawH)) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y << 10) + x], colour); + } +} + +/////////////////////////////////////////////////////////////////////// + +void VertLineFlat(int x, int y0, int y1, unsigned short colour) { + int y; + + if (y0 < g_prim.drawY) + y0 = g_prim.drawY; + + if (y1 > g_prim.drawH) + y1 = g_prim.drawH; + + for (y = y0; y <= y1; y++) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y << 10) + x], colour); +} + +/////////////////////////////////////////////////////////////////////// + +void HorzLineFlat(int y, int x0, int x1, unsigned short colour) { + int x; + + if (x0 < g_prim.drawX) + x0 = g_prim.drawX; + + if (x1 > g_prim.drawW) + x1 = g_prim.drawW; + + for (x = x0; x <= x1; x++) + GetShadeTransCol(&g_gpu.psx_vram.u16[(y << 10) + x], colour); +} + +/////////////////////////////////////////////////////////////////////// + +/* Bresenham Line drawing function */ +void DrawSoftwareLineShade(int32_t rgb0, int32_t rgb1) { + short x0, y0, x1, y1, xt, yt; + int32_t rgbt; + double m, dy, dx; + + if (g_soft.lx0 > g_prim.drawW && g_soft.lx1 > g_prim.drawW) + return; + if (g_soft.ly0 > g_prim.drawH && g_soft.ly1 > g_prim.drawH) + return; + if (g_soft.lx0 < g_prim.drawX && g_soft.lx1 < g_prim.drawX) + return; + if (g_soft.ly0 < g_prim.drawY && g_soft.ly1 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + x0 = g_soft.lx0; + y0 = g_soft.ly0; + x1 = g_soft.lx1; + y1 = g_soft.ly1; + + dx = x1 - x0; + dy = y1 - y0; + + if (dx == 0) { + if (dy > 0) + VertLineShade(x0, y0, y1, rgb0, rgb1); + else + VertLineShade(x0, y1, y0, rgb1, rgb0); + } else if (dy == 0) { + if (dx > 0) + HorzLineShade(y0, x0, x1, rgb0, rgb1); + else + HorzLineShade(y0, x1, x0, rgb1, rgb0); + } else { + if (dx < 0) { + xt = x0; + yt = y0; + rgbt = rgb0; + x0 = x1; + y0 = y1; + rgb0 = rgb1; + x1 = xt; + y1 = yt; + rgb1 = rgbt; + + dx = x1 - x0; + dy = y1 - y0; + } + + m = dy / dx; + + if (m >= 0) { + if (m > 1) + Line_S_SE_Shade(x0, y0, x1, y1, rgb0, rgb1); + else + Line_E_SE_Shade(x0, y0, x1, y1, rgb0, rgb1); + } else if (m < -1) + Line_N_NE_Shade(x0, y0, x1, y1, rgb0, rgb1); + else + Line_E_NE_Shade(x0, y0, x1, y1, rgb0, rgb1); + } +} + +/////////////////////////////////////////////////////////////////////// + +void DrawSoftwareLineFlat(int32_t rgb) { + short x0, y0, x1, y1, xt, yt; + double m, dy, dx; + unsigned short colour = 0; + + if (g_soft.lx0 > g_prim.drawW && g_soft.lx1 > g_prim.drawW) + return; + if (g_soft.ly0 > g_prim.drawH && g_soft.ly1 > g_prim.drawH) + return; + if (g_soft.lx0 < g_prim.drawX && g_soft.lx1 < g_prim.drawX) + return; + if (g_soft.ly0 < g_prim.drawY && g_soft.ly1 < g_prim.drawY) + return; + if (g_prim.drawY >= g_prim.drawH) + return; + if (g_prim.drawX >= g_prim.drawW) + return; + + colour = ((rgb & 0x00f80000) >> 9) | ((rgb & 0x0000f800) >> 6) | ((rgb + & 0x000000f8) >> 3); + + x0 = g_soft.lx0; + y0 = g_soft.ly0; + x1 = g_soft.lx1; + y1 = g_soft.ly1; + + dx = x1 - x0; + dy = y1 - y0; + + if (dx == 0) { + if (dy == 0) + return; // Nothing to draw + else if (dy > 0) + VertLineFlat(x0, y0, y1, colour); + else + VertLineFlat(x0, y1, y0, colour); + } else if (dy == 0) { + if (dx > 0) + HorzLineFlat(y0, x0, x1, colour); + else + HorzLineFlat(y0, x1, x0, colour); + } else { + if (dx < 0) { + xt = x0; + yt = y0; + x0 = x1; + y0 = y1; + x1 = xt; + y1 = yt; + + dx = x1 - x0; + dy = y1 - y0; + } + + m = dy / dx; + + if (m >= 0) { + if (m > 1) + Line_S_SE_Flat(x0, y0, x1, y1, colour); + else + Line_E_SE_Flat(x0, y0, x1, y1, colour); + } else if (m < -1) + Line_N_NE_Flat(x0, y0, x1, y1, colour); + else + Line_E_NE_Flat(x0, y0, x1, y1, colour); + } +} + +/////////////////////////////////////////////////////////////////////// diff --git a/plugins/gxvideo/soft.h b/plugins/gxvideo/soft.h new file mode 100644 index 00000000..113ab22e --- /dev/null +++ b/plugins/gxvideo/soft.h @@ -0,0 +1,60 @@ +/***************************************************************************
+ soft.h - description
+ -------------------
+ begin : Sun Oct 28 2001
+ copyright : (C) 2001 by Pete Bernert
+ email : BlackDove@addcom.de
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. See also the license.txt file for *
+ * additional informations. *
+ * *
+ ***************************************************************************/
+
+#ifndef _GPU_SOFT_H_
+#define _GPU_SOFT_H_
+
+#include <stdint.h>
+
+typedef struct {
+ short g_m1;
+ short g_m2;
+ short g_m3;
+ short DrawSemiTrans;
+ short Ymin;
+ short Ymax;
+
+ short ly0, lx0, ly1, lx1, ly2, lx2, ly3, lx3; // global psx vertex coords
+ int32_t GlobalTextAddrX, GlobalTextAddrY, GlobalTextTP;
+ int32_t GlobalTextREST, GlobalTextABR, GlobalTextPAGE;
+} gxv_soft_t;
+
+void offsetPSXLine(void);
+void offsetPSX2(void);
+void offsetPSX3(void);
+void offsetPSX4(void);
+
+void FillSoftwareAreaTrans(short x0, short y0, short x1, short y1,
+ unsigned short col);
+void FillSoftwareArea(short x0, short y0, short x1, short y1,
+ unsigned short col);
+void drawPoly3G(int32_t rgb1, int32_t rgb2, int32_t rgb3);
+void drawPoly4G(int32_t rgb1, int32_t rgb2, int32_t rgb3, int32_t rgb4);
+void drawPoly3F(int32_t rgb);
+void drawPoly4F(int32_t rgb);
+void drawPoly4FT(unsigned char * baseAddr);
+void drawPoly4GT(unsigned char * baseAddr);
+void drawPoly3FT(unsigned char * baseAddr);
+void drawPoly3GT(unsigned char * baseAddr);
+void DrawSoftwareSprite(unsigned char * baseAddr, short w, short h, int32_t tx,
+ int32_t ty);
+void DrawSoftwareSpriteTWin(unsigned char * baseAddr, int32_t w, int32_t h);
+void DrawSoftwareSpriteMirror(unsigned char * baseAddr, int32_t w, int32_t h);
+void DrawSoftwareLineShade(int32_t rgb0, int32_t rgb1);
+void DrawSoftwareLineFlat(int32_t rgb);
+
+#endif // _GPU_SOFT_H_
diff --git a/plugins/gxvideo/swap.h b/plugins/gxvideo/swap.h new file mode 100644 index 00000000..06d23d39 --- /dev/null +++ b/plugins/gxvideo/swap.h @@ -0,0 +1,26 @@ +#include <stdint.h> + +// byteswappings + +#define SWAP16(x) ({ uint16_t y=(x); (((y)>>8 & 0xff) | ((y)<<8 & 0xff00)); }) +#define SWAP32(x) ({ uint32_t y=(x); (((y)>>24 & 0xfful) | ((y)>>8 & 0xff00ul) | ((y)<<8 & 0xff0000ul) | ((y)<<24 & 0xff000000ul)); }) + +// little endian config +#define HOST2LE32(x) (x) +#define HOST2BE32(x) SWAP32(x) +#define LE2HOST32(x) (x) +#define BE2HOST32(x) SWAP32(x) + +#define HOST2LE16(x) (x) +#define HOST2BE16(x) SWAP16(x) +#define LE2HOST16(x) (x) +#define BE2HOST16(x) SWAP16(x) + +#define GETLEs16(X) ((int16_t)GETLE16((uint16_t *)X)) +#define GETLEs32(X) ((int16_t)GETLE32((uint16_t *)X)) + +#define GETLE16(X) LE2HOST16(*(uint16_t *)X) +#define GETLE32(X) LE2HOST32(*(uint32_t *)X) +#define GETLE16D(X) ({uint32_t val = GETLE32(X); (val<<16 | val >> 16);}) +#define PUTLE16(X, Y) do{*((uint16_t *)X)=HOST2LE16((uint16_t)Y);}while(0) +#define PUTLE32(X, Y) do{*((uint32_t *)X)=HOST2LE16((uint32_t)Y);}while(0) |
