From 379a8879f7dae1a9074317c0270e12dd203b32c0 Mon Sep 17 00:00:00 2001 From: "SND\\weimingzhi_cp" Date: Sun, 13 Mar 2011 08:26:16 +0000 Subject: Temporarily reverted r64524 until I (or someone else) find the time to sort out the stuff. git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@64536 e17a0e51-4ae3-4d35-97c3-1a29b211df97 --- plugins/bladesio1/settings.c | 130 +- plugins/bladesio1/sio1.h | 76 +- plugins/dfcdrom/cdr.c | 1056 +- plugins/dfcdrom/cdr.h | 405 +- plugins/dfcdrom/cdrcfg-0.1df/main.c | 580 +- plugins/dfcdrom/cfg.c | 200 +- plugins/dfinput/cfg-gtk2.c | 1446 +-- plugins/dfinput/pad.c | 914 +- plugins/dfinput/pad.h | 370 +- plugins/dfnet/cfg.c | 78 +- plugins/dfnet/dfnet.c | 548 +- plugins/dfnet/dfnet.h | 146 +- plugins/dfnet/gui.c | 467 +- plugins/dfnet/unix.c | 251 +- plugins/dfsound/Makefile.am | 102 +- plugins/dfsound/adsr.c | 1527 ++- plugins/dfsound/adsr.h | 39 +- plugins/dfsound/cfg.c | 350 +- plugins/dfsound/externals.h | 720 +- plugins/dfsound/freeze.c | 458 +- plugins/dfsound/nullsnd.c | 50 +- plugins/dfsound/oss.c | 319 +- plugins/dfsound/pulseaudio.c | 710 +- plugins/dfsound/reverb.c | 925 +- plugins/dfsound/sdl.c | 272 +- plugins/dfsound/spu.c | 2762 ++--- plugins/dfsound/spu.h | 43 +- plugins/dfsound/spucfg-0.1df/main.c | 548 +- plugins/dfsound/stdafx.h | 134 +- plugins/dfsound/xa.c | 820 +- plugins/dfxvideo/cfg.c | 636 +- plugins/dfxvideo/draw.c | 4302 +++---- plugins/dfxvideo/draw.h | 104 +- plugins/dfxvideo/fps.c | 714 +- plugins/dfxvideo/gpu.c | 4607 ++++---- plugins/dfxvideo/gpucfg-0.1df/main.c | 929 +- plugins/dfxvideo/key.c | 185 +- plugins/dfxvideo/menu.c | 487 +- plugins/dfxvideo/prim.c | 3324 +++--- plugins/dfxvideo/soft.c | 16976 ++++++++++++++-------------- plugins/dfxvideo/zn.c | 500 +- plugins/gxvideo/cfg.c | 522 +- plugins/gxvideo/draw.c | 1518 ++- plugins/gxvideo/fps.c | 138 +- plugins/gxvideo/gpu.c | 3104 +++--- plugins/gxvideo/gpucfg/main.c | 714 +- plugins/gxvideo/key.c | 87 +- plugins/gxvideo/menu.c | 113 +- plugins/gxvideo/prim.c | 3234 +++--- plugins/gxvideo/soft.c | 19862 ++++++++++++++++----------------- plugins/peopsxgl/draw.c | 3316 +++--- plugins/peopsxgl/fps.c | 795 +- plugins/peopsxgl/gpu.c | 7056 ++++++------ plugins/peopsxgl/gpu.h | 83 +- plugins/peopsxgl/gpucfg/main.c | 1470 +-- plugins/peopsxgl/key.c | 356 +- plugins/peopsxgl/prim.c | 9323 ++++++++-------- plugins/peopsxgl/soft.c | 16816 ++++++++++++++-------------- plugins/peopsxgl/texture.c | 9842 ++++++++-------- plugins/peopsxgl/texture.h | 137 +- 60 files changed, 63881 insertions(+), 63815 deletions(-) (limited to 'plugins') diff --git a/plugins/bladesio1/settings.c b/plugins/bladesio1/settings.c index f7628440..40e5e43b 100644 --- a/plugins/bladesio1/settings.c +++ b/plugins/bladesio1/settings.c @@ -1,66 +1,64 @@ -/*************************************************************************** - * Copyright (C) 2010 by Blade_Arma * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. * - ***************************************************************************/ - -#include -#include -#include -#include - -#include "settings.h" -#include "sio1.h" - -/******************************************************************************/ - -static const char configName[] = "bladesio1.cfg"; - -/******************************************************************************/ - -void settingsRead() -{ - FILE *file; - - file = fopen( configName, "rb" ); - if( file ) - { - if(fread( &settings, sizeof(settings), 1, file ) != 1) - perror(configName); - fclose( file ); - } - else - { - settings.player = 1; - strcpy( settings.ip, "127.0.0.1" ); - settings.port = 33307; - } -} - -void settingsWrite() -{ - FILE *file; - - file = fopen( configName, "wb" ); - if( file ) - { - if(fwrite( &settings, sizeof(settings), 1, file ) != 1) - perror(configName); - fclose( file ); - } -} - -/******************************************************************************/ +/*************************************************************************** + * Copyright (C) 2010 by Blade_Arma * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "settings.h" +#include "sio1.h" + +/******************************************************************************/ + +static const char configName[] = "bladesio1.cfg"; + +/******************************************************************************/ + +void settingsRead() +{ + FILE *file; + + file = fopen( configName, "rb" ); + if( file ) + { + fread( &settings, 1, sizeof(settings), file ); + fclose( file ); + } + else + { + settings.player = 1; + strcpy( settings.ip, "127.0.0.1" ); + settings.port = 33307; + } +} + +void settingsWrite() +{ + FILE *file; + + file = fopen( configName, "wb" ); + if( file ) + { + fwrite( &settings, 1, sizeof(settings), file ); + fclose( file ); + } +} + +/******************************************************************************/ diff --git a/plugins/bladesio1/sio1.h b/plugins/bladesio1/sio1.h index 727e48ea..f4c8a0ef 100644 --- a/plugins/bladesio1/sio1.h +++ b/plugins/bladesio1/sio1.h @@ -1,33 +1,43 @@ -/*************************************************************************** - * Copyright (C) 2010 by Blade_Arma * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. * - ***************************************************************************/ - -#ifndef _SIO1_H_ -#define _SIO1_H_ - -#include "config.h" - -/******************************************************************************/ - -#include "psemu_plugin_defs.h" - -extern Settings settings; - -/******************************************************************************/ - -#endif // _SIO1_H_ +/*************************************************************************** + * Copyright (C) 2010 by Blade_Arma * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef _SIO1_H_ +#define _SIO1_H_ + +#include "config.h" + +/******************************************************************************/ + +#ifdef ENABLE_NLS +#include +#include +#define _(x) gettext(x) +#define N_(x) (x) +#else +#define _(x) (x) +#define N_(x) (x) +#endif + +#define CALLBACK + +extern Settings settings; + +/******************************************************************************/ + +#endif // _SIO1_H_ diff --git a/plugins/dfcdrom/cdr.c b/plugins/dfcdrom/cdr.c index cf0a539c..ab61886e 100644 --- a/plugins/dfcdrom/cdr.c +++ b/plugins/dfcdrom/cdr.c @@ -1,528 +1,528 @@ -/* - * Copyright (c) 2010, Wei Mingzhi . - * All Rights Reserved. - * - * Based on: Cdrom for Psemu Pro like Emulators - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include "cdr.h" - -#ifndef USE_NULL -static char *LibName = N_("CD-ROM Drive Reader"); -#else -static char *LibName = N_("CDR NULL Plugin"); -#endif - -int initial_time = 0; - -pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t cond = PTHREAD_COND_INITIALIZER; - -volatile CacheData *cdcache; -volatile int cacheaddr; - -volatile unsigned char *cdbuffer; - -crdata cr; - -unsigned char lastTime[3]; -pthread_t thread; -int subqread; -volatile int stopth, found, locked, playing; - -long (*ReadTrackT[])() = { - ReadNormal, - ReadThreaded, -}; - -unsigned char* (*GetBufferT[])() = { - GetBNormal, - GetBThreaded, -}; - -long (*fReadTrack)(); -unsigned char* (*fGetBuffer)(); - -void *CdrThread(void *arg); - -long CDRinit(void) { - thread = (pthread_t)-1; - return 0; -} - -long CDRshutdown(void) { - return 0; -} - -long CDRopen(void) { - LoadConf(); - -#ifndef _MACOSX - if (IsCdHandleOpen()) - return 0; // it's already open -#endif - - if (OpenCdHandle(CdromDev) == -1) { // if we can't open the cdrom we'll works as a null plugin - fprintf(stderr, "CDR: Could not open %s\n", CdromDev); - } - - fReadTrack = ReadTrackT[ReadMode]; - fGetBuffer = GetBufferT[ReadMode]; - - if (ReadMode == THREADED) { - cdcache = (CacheData *)malloc(CacheSize * sizeof(CacheData)); - if (cdcache == NULL) return -1; - memset((void *)cdcache, 0, CacheSize * sizeof(CacheData)); - - found = 0; - } else { - cdbuffer = cr.buf + 12; /* skip sync data */ - } - - if (ReadMode == THREADED) { - pthread_attr_t attr; - - pthread_mutex_init(&mut, NULL); - pthread_cond_init(&cond, NULL); - locked = 0; - - pthread_attr_init(&attr); - pthread_create(&thread, &attr, CdrThread, NULL); - - cacheaddr = -1; - } else thread = (pthread_t)-1; - - playing = 0; - stopth = 0; - initial_time = 0; - - return 0; -} - -long CDRclose(void) { - if (!IsCdHandleOpen()) return 0; - - if (playing) CDRstop(); - - CloseCdHandle(); - - if (thread != (pthread_t)-1) { - if (locked == 0) { - stopth = 1; - while (locked == 0) usleep(5000); - } - - stopth = 2; - pthread_mutex_lock(&mut); - pthread_cond_signal(&cond); - pthread_mutex_unlock(&mut); - - pthread_join(thread, NULL); - pthread_mutex_destroy(&mut); - pthread_cond_destroy(&cond); - } - - if (ReadMode == THREADED) { - free((void *)cdcache); - } - - return 0; -} - -// return Starting and Ending Track -// buffer: -// byte 0 - start track -// byte 1 - end track -long CDRgetTN(unsigned char *buffer) { - long ret; - - if (!IsCdHandleOpen()) { - buffer[0] = 1; - buffer[1] = 1; - return 0; - } - - if (ReadMode == THREADED) pthread_mutex_lock(&mut); - ret = GetTN(buffer); - if (ReadMode == THREADED) pthread_mutex_unlock(&mut); - - return ret; -} - -// return Track Time -// buffer: -// byte 0 - frame -// byte 1 - second -// byte 2 - minute -long CDRgetTD(unsigned char track, unsigned char *buffer) { - long ret; - - if (!IsCdHandleOpen()) { - memset(buffer + 1, 0, 3); - return 0; - } - - if (ReadMode == THREADED) pthread_mutex_lock(&mut); - ret = GetTD(track, buffer); - if (ReadMode == THREADED) pthread_mutex_unlock(&mut); - - return ret; -} - -// normal reading -long ReadNormal() { - if (ReadSector(&cr) == -1) - return -1; - - return 0; -} - -unsigned char *GetBNormal() { - return (unsigned char *)cdbuffer; -} - -// threaded reading (with cache) -long ReadThreaded() { - int addr = msf_to_lba(cr.msf.cdmsf_min0, cr.msf.cdmsf_sec0, cr.msf.cdmsf_frame0); - int i; - - if (addr >= cacheaddr && addr < (cacheaddr + CacheSize) && cacheaddr != -1) { - i = addr - cacheaddr; - PRINTF("found %d\n", (addr - cacheaddr)); - cdbuffer = cdcache[i].cr.buf + 12; - while (cdcache[i].msf[0] != cr.msf.cdmsf_min0 || - cdcache[i].msf[1] != cr.msf.cdmsf_sec0 || - cdcache[i].msf[2] != cr.msf.cdmsf_frame0) { - if (locked == 1) { - if (cdcache[i].ret == 0) break; - return -1; - } - usleep(5000); - } - PRINTF("%d:%d:%d, %p, %p\n", cdcache[i].msf[0], cdcache[i].msf[1], cdcache[i].msf[2], cdbuffer, cdcache); - found = 1; - - return 0; - } else found = 0; - - if (locked == 0) { - stopth = 1; - while (locked == 0) { usleep(5000); } - stopth = 0; - } - - // not found in cache - locked = 0; - - pthread_mutex_lock(&mut); - pthread_cond_signal(&cond); - pthread_mutex_unlock(&mut); - - return 0; -} - -unsigned char *GetBThreaded() { - PRINTF("threadc %d\n", found); - - if (found == 1) return (unsigned char *)cdbuffer; - - cdbuffer = cdcache[0].cr.buf + 12; - - while (cdcache[0].msf[0] != cr.msf.cdmsf_min0 || - cdcache[0].msf[1] != cr.msf.cdmsf_sec0 || - cdcache[0].msf[2] != cr.msf.cdmsf_frame0) { - if (locked == 1) return NULL; - usleep(5000); - } - if (cdcache[0].ret == -1) return NULL; - - return (unsigned char *)cdbuffer; -} - -void *CdrThread(void *arg) { - unsigned char curTime[3]; - int i; - - for (;;) { - pthread_mutex_lock(&mut); - locked = 1; - - pthread_cond_wait(&cond, &mut); - - if (stopth == 2) pthread_exit(NULL); - // refill the buffer - cacheaddr = msf_to_lba(cr.msf.cdmsf_min0, cr.msf.cdmsf_sec0, cr.msf.cdmsf_frame0); - - memcpy(curTime, &cr.msf, 3); - - PRINTF("start thc %d:%d:%d\n", curTime[0], curTime[1], curTime[2]); - - for (i = 0; i < CacheSize; i++) { - cdcache[i].cr.msf.cdmsf_min0 = curTime[0]; - cdcache[i].cr.msf.cdmsf_sec0 = curTime[1]; - cdcache[i].cr.msf.cdmsf_frame0 = curTime[2]; - - PRINTF("reading %d:%d:%d\n", curTime[0], curTime[1], curTime[2]); - - cdcache[i].ret = ReadSector((crdata *)&cdcache[i].cr); - if (cdcache[i].ret == -1) break; - - PRINTF("readed %x:%x:%x\n", cdcache[i].cr.buf[12], cdcache[i].cr.buf[13], cdcache[i].cr.buf[14]); - - cdcache[i].msf[0] = curTime[0]; - cdcache[i].msf[1] = curTime[1]; - cdcache[i].msf[2] = curTime[2]; - - curTime[2]++; - if (curTime[2] == 75) { - curTime[2] = 0; - curTime[1]++; - if (curTime[1] == 60) { - curTime[1] = 0; - curTime[0]++; - } - } - - if (stopth) break; - } - - pthread_mutex_unlock(&mut); - } - - return NULL; -} - -// read track -// time: -// byte 0 - minute -// byte 1 - second -// byte 2 - frame -// uses bcd format -long CDRreadTrack(unsigned char *time) { - if (!IsCdHandleOpen()) { - memset(cr.buf, 0, DATA_SIZE); - return 0; - } - - PRINTF("CDRreadTrack %d:%d:%d\n", btoi(time[0]), btoi(time[1]), btoi(time[2])); - - if (UseSubQ) memcpy(lastTime, time, 3); - subqread = 0; - - cr.msf.cdmsf_min0 = btoi(time[0]); - cr.msf.cdmsf_sec0 = btoi(time[1]); - cr.msf.cdmsf_frame0 = btoi(time[2]); - - return fReadTrack(); -} - -// return readed track -unsigned char *CDRgetBuffer(void) { - return fGetBuffer(); -} - -// plays cdda audio -// sector: -// byte 0 - minute -// byte 1 - second -// byte 2 - frame -// does NOT uses bcd format -long CDRplay(unsigned char *sector) { - long ret; - - if (!IsCdHandleOpen()) - return 0; - - // If play was called with the same time as the previous call, - // don't restart it. Of course, if play is called with a different - // track, stop playing the current stream. - if (playing) { - if (msf_to_lba(sector[0], sector[1], sector[2]) == initial_time) - return 0; - else - CDRstop(); - } - - initial_time = msf_to_lba(sector[0], sector[1], sector[2]); - - if (ReadMode == THREADED) pthread_mutex_lock(&mut); - ret = PlayCDDA(sector); - if (ReadMode == THREADED) pthread_mutex_unlock(&mut); - - if (ret == 0) { - playing = 1; - return 0; - } - - return -1; -} - -// stops cdda audio -long CDRstop(void) { - long ret; - - if (!IsCdHandleOpen()) - return 0; - - if (ReadMode == THREADED) pthread_mutex_lock(&mut); - ret = StopCDDA(); - if (ReadMode == THREADED) pthread_mutex_unlock(&mut); - - if (ret == 0) { - playing = 0; - initial_time = 0; - - return 0; - } - - return -1; -} - -// reads cdr status -// type: -// 0x00 - unknown -// 0x01 - data -// 0x02 - audio -// 0xff - no cdrom -// status: (only shell open supported) -// 0x00 - unknown -// 0x01 - error -// 0x04 - seek error -// 0x10 - shell open -// 0x20 - reading -// 0x40 - seeking -// 0x80 - playing -// time: -// byte 0 - minute -// byte 1 - second -// byte 2 - frame - -long CDRgetStatus(struct CdrStat *stat) { - long ret; - - if (!IsCdHandleOpen()) - return -1; - - if (ReadMode == THREADED) pthread_mutex_lock(&mut); - ret = GetStatus(playing, stat); - if (ReadMode == THREADED) pthread_mutex_unlock(&mut); - - return ret; -} - -unsigned char *CDRgetBufferSub(void) { - static unsigned char *p = NULL; - - if (!UseSubQ) return NULL; - if (subqread) return p; - - if (ReadMode == THREADED) pthread_mutex_lock(&mut); - p = ReadSub(lastTime); - if (ReadMode == THREADED) pthread_mutex_unlock(&mut); - - if (p != NULL) subqread = 1; - - return p; -} - -// read CDDA sector into buffer -long CDRreadCDDA(unsigned char m, unsigned char s, unsigned char f, unsigned char *buffer) { - unsigned char msf[3] = {m, s, f}; - unsigned char *p; - - if (CDRreadTrack(msf) != 0) return -1; - - p = CDRgetBuffer(); - if (p == NULL) return -1; - - memcpy(buffer, p - 12, CD_FRAMESIZE_RAW); // copy from the beginning of the sector - return 0; -} - -// get Track End Time -long CDRgetTE(unsigned char track, unsigned char *m, unsigned char *s, unsigned char *f) { - long ret; - - if (!IsCdHandleOpen()) return -1; - - if (ReadMode == THREADED) pthread_mutex_lock(&mut); - ret = GetTE(track, m, s, f); - if (ReadMode == THREADED) pthread_mutex_unlock(&mut); - - return ret; -} - -#ifndef _MACOSX - -static void ExecCfg(char *arg) { - char cfg[256]; - struct stat buf; - - strcpy(cfg, "./cfgDFCdrom"); - if (stat(cfg, &buf) != -1) { - if (fork() == 0) { - execl(cfg, "cfgDFCdrom", arg, NULL); - exit(0); - } - return; - } - - strcpy(cfg, "./cfg/DFCdrom"); - if (stat(cfg, &buf) != -1) { - if (fork() == 0) { - execl(cfg, "cfgDFCdrom", arg, NULL); - exit(0); - } - return; - } - - fprintf(stderr, "cfgDFCdrom file not found!\n"); -} - -long CDRconfigure() { -#ifndef USE_NULL - ExecCfg("configure"); -#endif - return 0; -} - -void CDRabout() { - ExecCfg("about"); -} - -#endif - -long CDRtest(void) { -#ifndef USE_NULL - if (OpenCdHandle(CdromDev) == -1) - return -1; - CloseCdHandle(); -#endif - return 0; -} - -char *PSEgetLibName(void) { - return _(LibName); -} - -unsigned long PSEgetLibType(void) { - return PSE_LT_CDR; -} - -unsigned long PSEgetLibVersion(void) { - return 1 << 16; -} +/* + * Copyright (c) 2010, Wei Mingzhi . + * All Rights Reserved. + * + * Based on: Cdrom for Psemu Pro like Emulators + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "cdr.h" + +#ifndef USE_NULL +static char *LibName = N_("CD-ROM Drive Reader"); +#else +static char *LibName = N_("CDR NULL Plugin"); +#endif + +int initial_time = 0; + +pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + +volatile CacheData *cdcache; +volatile int cacheaddr; + +volatile unsigned char *cdbuffer; + +crdata cr; + +unsigned char lastTime[3]; +pthread_t thread; +int subqread; +volatile int stopth, found, locked, playing; + +long (*ReadTrackT[])() = { + ReadNormal, + ReadThreaded, +}; + +unsigned char* (*GetBufferT[])() = { + GetBNormal, + GetBThreaded, +}; + +long (*fReadTrack)(); +unsigned char* (*fGetBuffer)(); + +void *CdrThread(void *arg); + +long CDRinit(void) { + thread = (pthread_t)-1; + return 0; +} + +long CDRshutdown(void) { + return 0; +} + +long CDRopen(void) { + LoadConf(); + +#ifndef _MACOSX + if (IsCdHandleOpen()) + return 0; // it's already open +#endif + + if (OpenCdHandle(CdromDev) == -1) { // if we can't open the cdrom we'll works as a null plugin + fprintf(stderr, "CDR: Could not open %s\n", CdromDev); + } + + fReadTrack = ReadTrackT[ReadMode]; + fGetBuffer = GetBufferT[ReadMode]; + + if (ReadMode == THREADED) { + cdcache = (CacheData *)malloc(CacheSize * sizeof(CacheData)); + if (cdcache == NULL) return -1; + memset((void *)cdcache, 0, CacheSize * sizeof(CacheData)); + + found = 0; + } else { + cdbuffer = cr.buf + 12; /* skip sync data */ + } + + if (ReadMode == THREADED) { + pthread_attr_t attr; + + pthread_mutex_init(&mut, NULL); + pthread_cond_init(&cond, NULL); + locked = 0; + + pthread_attr_init(&attr); + pthread_create(&thread, &attr, CdrThread, NULL); + + cacheaddr = -1; + } else thread = (pthread_t)-1; + + playing = 0; + stopth = 0; + initial_time = 0; + + return 0; +} + +long CDRclose(void) { + if (!IsCdHandleOpen()) return 0; + + if (playing) CDRstop(); + + CloseCdHandle(); + + if (thread != (pthread_t)-1) { + if (locked == 0) { + stopth = 1; + while (locked == 0) usleep(5000); + } + + stopth = 2; + pthread_mutex_lock(&mut); + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mut); + + pthread_join(thread, NULL); + pthread_mutex_destroy(&mut); + pthread_cond_destroy(&cond); + } + + if (ReadMode == THREADED) { + free((void *)cdcache); + } + + return 0; +} + +// return Starting and Ending Track +// buffer: +// byte 0 - start track +// byte 1 - end track +long CDRgetTN(unsigned char *buffer) { + long ret; + + if (!IsCdHandleOpen()) { + buffer[0] = 1; + buffer[1] = 1; + return 0; + } + + if (ReadMode == THREADED) pthread_mutex_lock(&mut); + ret = GetTN(buffer); + if (ReadMode == THREADED) pthread_mutex_unlock(&mut); + + return ret; +} + +// return Track Time +// buffer: +// byte 0 - frame +// byte 1 - second +// byte 2 - minute +long CDRgetTD(unsigned char track, unsigned char *buffer) { + long ret; + + if (!IsCdHandleOpen()) { + memset(buffer + 1, 0, 3); + return 0; + } + + if (ReadMode == THREADED) pthread_mutex_lock(&mut); + ret = GetTD(track, buffer); + if (ReadMode == THREADED) pthread_mutex_unlock(&mut); + + return ret; +} + +// normal reading +long ReadNormal() { + if (ReadSector(&cr) == -1) + return -1; + + return 0; +} + +unsigned char *GetBNormal() { + return (unsigned char *)cdbuffer; +} + +// threaded reading (with cache) +long ReadThreaded() { + int addr = msf_to_lba(cr.msf.cdmsf_min0, cr.msf.cdmsf_sec0, cr.msf.cdmsf_frame0); + int i; + + if (addr >= cacheaddr && addr < (cacheaddr + CacheSize) && cacheaddr != -1) { + i = addr - cacheaddr; + PRINTF("found %d\n", (addr - cacheaddr)); + cdbuffer = cdcache[i].cr.buf + 12; + while (cdcache[i].msf[0] != cr.msf.cdmsf_min0 || + cdcache[i].msf[1] != cr.msf.cdmsf_sec0 || + cdcache[i].msf[2] != cr.msf.cdmsf_frame0) { + if (locked == 1) { + if (cdcache[i].ret == 0) break; + return -1; + } + usleep(5000); + } + PRINTF("%d:%d:%d, %p, %p\n", cdcache[i].msf[0], cdcache[i].msf[1], cdcache[i].msf[2], cdbuffer, cdcache); + found = 1; + + return 0; + } else found = 0; + + if (locked == 0) { + stopth = 1; + while (locked == 0) { usleep(5000); } + stopth = 0; + } + + // not found in cache + locked = 0; + + pthread_mutex_lock(&mut); + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mut); + + return 0; +} + +unsigned char *GetBThreaded() { + PRINTF("threadc %d\n", found); + + if (found == 1) return (unsigned char *)cdbuffer; + + cdbuffer = cdcache[0].cr.buf + 12; + + while (cdcache[0].msf[0] != cr.msf.cdmsf_min0 || + cdcache[0].msf[1] != cr.msf.cdmsf_sec0 || + cdcache[0].msf[2] != cr.msf.cdmsf_frame0) { + if (locked == 1) return NULL; + usleep(5000); + } + if (cdcache[0].ret == -1) return NULL; + + return (unsigned char *)cdbuffer; +} + +void *CdrThread(void *arg) { + unsigned char curTime[3]; + int i; + + for (;;) { + pthread_mutex_lock(&mut); + locked = 1; + + pthread_cond_wait(&cond, &mut); + + if (stopth == 2) pthread_exit(NULL); + // refill the buffer + cacheaddr = msf_to_lba(cr.msf.cdmsf_min0, cr.msf.cdmsf_sec0, cr.msf.cdmsf_frame0); + + memcpy(curTime, &cr.msf, 3); + + PRINTF("start thc %d:%d:%d\n", curTime[0], curTime[1], curTime[2]); + + for (i = 0; i < CacheSize; i++) { + cdcache[i].cr.msf.cdmsf_min0 = curTime[0]; + cdcache[i].cr.msf.cdmsf_sec0 = curTime[1]; + cdcache[i].cr.msf.cdmsf_frame0 = curTime[2]; + + PRINTF("reading %d:%d:%d\n", curTime[0], curTime[1], curTime[2]); + + cdcache[i].ret = ReadSector((crdata *)&cdcache[i].cr); + if (cdcache[i].ret == -1) break; + + PRINTF("readed %x:%x:%x\n", cdcache[i].cr.buf[12], cdcache[i].cr.buf[13], cdcache[i].cr.buf[14]); + + cdcache[i].msf[0] = curTime[0]; + cdcache[i].msf[1] = curTime[1]; + cdcache[i].msf[2] = curTime[2]; + + curTime[2]++; + if (curTime[2] == 75) { + curTime[2] = 0; + curTime[1]++; + if (curTime[1] == 60) { + curTime[1] = 0; + curTime[0]++; + } + } + + if (stopth) break; + } + + pthread_mutex_unlock(&mut); + } + + return NULL; +} + +// read track +// time: +// byte 0 - minute +// byte 1 - second +// byte 2 - frame +// uses bcd format +long CDRreadTrack(unsigned char *time) { + if (!IsCdHandleOpen()) { + memset(cr.buf, 0, DATA_SIZE); + return 0; + } + + PRINTF("CDRreadTrack %d:%d:%d\n", btoi(time[0]), btoi(time[1]), btoi(time[2])); + + if (UseSubQ) memcpy(lastTime, time, 3); + subqread = 0; + + cr.msf.cdmsf_min0 = btoi(time[0]); + cr.msf.cdmsf_sec0 = btoi(time[1]); + cr.msf.cdmsf_frame0 = btoi(time[2]); + + return fReadTrack(); +} + +// return readed track +unsigned char *CDRgetBuffer(void) { + return fGetBuffer(); +} + +// plays cdda audio +// sector: +// byte 0 - minute +// byte 1 - second +// byte 2 - frame +// does NOT uses bcd format +long CDRplay(unsigned char *sector) { + long ret; + + if (!IsCdHandleOpen()) + return 0; + + // If play was called with the same time as the previous call, + // don't restart it. Of course, if play is called with a different + // track, stop playing the current stream. + if (playing) { + if (msf_to_lba(sector[0], sector[1], sector[2]) == initial_time) + return 0; + else + CDRstop(); + } + + initial_time = msf_to_lba(sector[0], sector[1], sector[2]); + + if (ReadMode == THREADED) pthread_mutex_lock(&mut); + ret = PlayCDDA(sector); + if (ReadMode == THREADED) pthread_mutex_unlock(&mut); + + if (ret == 0) { + playing = 1; + return 0; + } + + return -1; +} + +// stops cdda audio +long CDRstop(void) { + long ret; + + if (!IsCdHandleOpen()) + return 0; + + if (ReadMode == THREADED) pthread_mutex_lock(&mut); + ret = StopCDDA(); + if (ReadMode == THREADED) pthread_mutex_unlock(&mut); + + if (ret == 0) { + playing = 0; + initial_time = 0; + + return 0; + } + + return -1; +} + +// reads cdr status +// type: +// 0x00 - unknown +// 0x01 - data +// 0x02 - audio +// 0xff - no cdrom +// status: (only shell open supported) +// 0x00 - unknown +// 0x01 - error +// 0x04 - seek error +// 0x10 - shell open +// 0x20 - reading +// 0x40 - seeking +// 0x80 - playing +// time: +// byte 0 - minute +// byte 1 - second +// byte 2 - frame + +long CDRgetStatus(struct CdrStat *stat) { + long ret; + + if (!IsCdHandleOpen()) + return -1; + + if (ReadMode == THREADED) pthread_mutex_lock(&mut); + ret = GetStatus(playing, stat); + if (ReadMode == THREADED) pthread_mutex_unlock(&mut); + + return ret; +} + +unsigned char *CDRgetBufferSub(void) { + static unsigned char *p = NULL; + + if (!UseSubQ) return NULL; + if (subqread) return p; + + if (ReadMode == THREADED) pthread_mutex_lock(&mut); + p = ReadSub(lastTime); + if (ReadMode == THREADED) pthread_mutex_unlock(&mut); + + if (p != NULL) subqread = 1; + + return p; +} + +// read CDDA sector into buffer +long CDRreadCDDA(unsigned char m, unsigned char s, unsigned char f, unsigned char *buffer) { + unsigned char msf[3] = {m, s, f}; + unsigned char *p; + + if (CDRreadTrack(msf) != 0) return -1; + + p = CDRgetBuffer(); + if (p == NULL) return -1; + + memcpy(buffer, p - 12, CD_FRAMESIZE_RAW); // copy from the beginning of the sector + return 0; +} + +// get Track End Time +long CDRgetTE(unsigned char track, unsigned char *m, unsigned char *s, unsigned char *f) { + long ret; + + if (!IsCdHandleOpen()) return -1; + + if (ReadMode == THREADED) pthread_mutex_lock(&mut); + ret = GetTE(track, m, s, f); + if (ReadMode == THREADED) pthread_mutex_unlock(&mut); + + return ret; +} + +#ifndef _MACOSX + +void ExecCfg(char *arg) { + char cfg[256]; + struct stat buf; + + strcpy(cfg, "./cfgDFCdrom"); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgDFCdrom", arg, NULL); + exit(0); + } + return; + } + + strcpy(cfg, "./cfg/DFCdrom"); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgDFCdrom", arg, NULL); + exit(0); + } + return; + } + + fprintf(stderr, "cfgDFCdrom file not found!\n"); +} + +long CDRconfigure() { +#ifndef USE_NULL + ExecCfg("configure"); +#endif + return 0; +} + +void CDRabout() { + ExecCfg("about"); +} + +#endif + +long CDRtest(void) { +#ifndef USE_NULL + if (OpenCdHandle(CdromDev) == -1) + return -1; + CloseCdHandle(); +#endif + return 0; +} + +char *PSEgetLibName(void) { + return _(LibName); +} + +unsigned long PSEgetLibType(void) { + return PSE_LT_CDR; +} + +unsigned long PSEgetLibVersion(void) { + return 1 << 16; +} diff --git a/plugins/dfcdrom/cdr.h b/plugins/dfcdrom/cdr.h index 928683d3..771faa77 100644 --- a/plugins/dfcdrom/cdr.h +++ b/plugins/dfcdrom/cdr.h @@ -1,189 +1,216 @@ -/* - * Copyright (c) 2010, Wei Mingzhi . - * All Rights Reserved. - * - * Based on: Cdrom for Psemu Pro like Emulators - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#ifndef __CDR_H__ -#define __CDR_H__ - -//#define DEBUG 1 - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "psemu_plugin_defs.h" - -#if defined (__linux__) - -#include -#include -#include - -#ifndef CDROMSETSPINDOWN -#define CDROMSETSPINDOWN 0x531e -#endif - -#define DEV_DEF "/dev/cdrom" - -#else - -struct cdrom_msf { - unsigned char cdmsf_min0; /* start minute */ - unsigned char cdmsf_sec0; /* start second */ - unsigned char cdmsf_frame0; /* start frame */ - unsigned char cdmsf_min1; /* end minute */ - unsigned char cdmsf_sec1; /* end second */ - unsigned char cdmsf_frame1; /* end frame */ -}; - -#define CD_SECS 60 -#define CD_FRAMES 75 -#define CD_MSF_OFFSET 150 -#define CD_FRAMESIZE_SUB 96 - -#if defined (__FreeBSD__) -#define DEV_DEF "/dev/cd0" -#else -#define DEV_DEF "" -#endif - -#if !defined (USE_LIBCDIO) && !defined (_MACOSX) -#define USE_NULL 1 -#endif - -#endif - -extern char CdromDev[256]; -extern long ReadMode; -extern long UseSubQ; -extern long CacheSize; -extern long CdrSpeed; -extern long SpinDown; - -#define NORMAL 0 -#define THREADED 1 -#define READ_MODES 2 - -#ifndef CD_FRAMESIZE_RAW -#define CD_FRAMESIZE_RAW 2352 -#endif - -#define DATA_SIZE (CD_FRAMESIZE_RAW - 12) - -// spindown codes -#define SPINDOWN_VENDOR_SPECIFIC 0x00 -#define SPINDOWN_125MS 0x01 -#define SPINDOWN_250MS 0x02 -#define SPINDOWN_500MS 0x03 -#define SPINDOWN_1S 0x04 -#define SPINDOWN_2S 0x05 -#define SPINDOWN_4S 0x06 -#define SPINDOWN_8S 0x07 -#define SPINDOWN_16S 0x08 -#define SPINDOWN_32S 0x09 -#define SPINDOWN_1MIN 0x0A -#define SPINDOWN_2MIN 0x0B -#define SPINDOWN_4MIN 0x0C -#define SPINDOWN_8MIN 0x0D -#define SPINDOWN_16MIN 0x0E -#define SPINDOWN_32MIN 0x0F - -typedef struct _MMC_READ_CD { - unsigned char Code; // 0xBE - - unsigned char RelativeAddress : 1; - unsigned char : 1; - unsigned char ExpectedSectorType : 3; - unsigned char Lun : 3; - - unsigned char StartingLBA[4]; - unsigned char TransferBlocks[3]; - - unsigned char : 1; - unsigned char ErrorFlags : 2; - unsigned char IncludeEDC : 1; - unsigned char IncludeUserData : 1; - unsigned char HeaderCode : 2; - unsigned char IncludeSyncData : 1; - - unsigned char SubChannelSelection : 3; - unsigned char : 5; - - unsigned char Ctrl; -} MMC_READ_CD; - -#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ -#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ - -typedef union { - struct cdrom_msf msf; - unsigned char buf[CD_FRAMESIZE_RAW]; -} crdata; - -typedef struct { - unsigned char msf[3]; - crdata cr; - int ret; -} CacheData; - -long ReadNormal(); -long ReadThreaded(); -unsigned char* GetBNormal(); -unsigned char* GetBThreaded(); - -long CDRstop(void); - -void LoadConf(); -void SaveConf(); - -#ifdef DEBUG -#define PRINTF printf -#else -#define PRINTF(...) /* */ -#endif - -unsigned int msf_to_lba(char m, char s, char f); -void lba_to_msf(unsigned int s, unsigned char *msf); -void DecodeRawSubData(unsigned char *subbuffer); -unsigned short calcCrc(unsigned char *d, int len); - -int OpenCdHandle(); -void CloseCdHandle(); -int IsCdHandleOpen(); -long GetTN(unsigned char *buffer); -long GetTD(unsigned char track, unsigned char *buffer); -long GetTE(unsigned char track, unsigned char *m, unsigned char *s, unsigned char *f); -long ReadSector(crdata *cr); -long PlayCDDA(unsigned char *sector); -long StopCDDA(); -#include "psemu_plugin_defs.h" -long GetStatus(int playing, struct CdrStat *stat); -unsigned char *ReadSub(const unsigned char *time); - -#endif +/* + * Copyright (c) 2010, Wei Mingzhi . + * All Rights Reserved. + * + * Based on: Cdrom for Psemu Pro like Emulators + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef __CDR_H__ +#define __CDR_H__ + +//#define DEBUG 1 + +#include "config.h" + +#ifdef ENABLE_NLS +#include +#include +#define _(x) gettext(x) +#define N_(x) (x) +#else +#define _(x) (x) +#define N_(x) (x) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "psemu_plugin_defs.h" + +#if defined (__linux__) + +#include +#include +#include + +#ifndef CDROMSETSPINDOWN +#define CDROMSETSPINDOWN 0x531e +#endif + +#define DEV_DEF "/dev/cdrom" + +#else + +struct cdrom_msf { + unsigned char cdmsf_min0; /* start minute */ + unsigned char cdmsf_sec0; /* start second */ + unsigned char cdmsf_frame0; /* start frame */ + unsigned char cdmsf_min1; /* end minute */ + unsigned char cdmsf_sec1; /* end second */ + unsigned char cdmsf_frame1; /* end frame */ +}; + +#define CD_SECS 60 +#define CD_FRAMES 75 +#define CD_MSF_OFFSET 150 +#define CD_FRAMESIZE_SUB 96 + +#if defined (__FreeBSD__) +#define DEV_DEF "/dev/cd0" +#else +#define DEV_DEF "" +#endif + +#if !defined (USE_LIBCDIO) && !defined (_MACOSX) +#define USE_NULL 1 +#endif + +#endif + +extern char CdromDev[256]; +extern long ReadMode; +extern long UseSubQ; +extern long CacheSize; +extern long CdrSpeed; +extern long SpinDown; + +#define NORMAL 0 +#define THREADED 1 +#define READ_MODES 2 + +#ifndef CD_FRAMESIZE_RAW +#define CD_FRAMESIZE_RAW 2352 +#endif + +#define DATA_SIZE (CD_FRAMESIZE_RAW - 12) + +// spindown codes +#define SPINDOWN_VENDOR_SPECIFIC 0x00 +#define SPINDOWN_125MS 0x01 +#define SPINDOWN_250MS 0x02 +#define SPINDOWN_500MS 0x03 +#define SPINDOWN_1S 0x04 +#define SPINDOWN_2S 0x05 +#define SPINDOWN_4S 0x06 +#define SPINDOWN_8S 0x07 +#define SPINDOWN_16S 0x08 +#define SPINDOWN_32S 0x09 +#define SPINDOWN_1MIN 0x0A +#define SPINDOWN_2MIN 0x0B +#define SPINDOWN_4MIN 0x0C +#define SPINDOWN_8MIN 0x0D +#define SPINDOWN_16MIN 0x0E +#define SPINDOWN_32MIN 0x0F + +typedef struct _MMC_READ_CD { + unsigned char Code; // 0xBE + + unsigned char RelativeAddress : 1; + unsigned char : 1; + unsigned char ExpectedSectorType : 3; + unsigned char Lun : 3; + + unsigned char StartingLBA[4]; + unsigned char TransferBlocks[3]; + + unsigned char : 1; + unsigned char ErrorFlags : 2; + unsigned char IncludeEDC : 1; + unsigned char IncludeUserData : 1; + unsigned char HeaderCode : 2; + unsigned char IncludeSyncData : 1; + + unsigned char SubChannelSelection : 3; + unsigned char : 5; + + unsigned char Ctrl; +} MMC_READ_CD; + +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ + +struct CdrStat { + unsigned long Type; + unsigned long Status; + unsigned char Time[3]; // current playing time +}; + +struct SubQ { + char res0[12]; + unsigned char ControlAndADR; + unsigned char TrackNumber; + unsigned char IndexNumber; + unsigned char TrackRelativeAddress[3]; + unsigned char Filler; + unsigned char AbsoluteAddress[3]; + unsigned char CRC[2]; + char res1[72]; +}; + +typedef union { + struct cdrom_msf msf; + unsigned char buf[CD_FRAMESIZE_RAW]; +} crdata; + +typedef struct { + unsigned char msf[3]; + crdata cr; + int ret; +} CacheData; + +long ReadNormal(); +long ReadThreaded(); +unsigned char* GetBNormal(); +unsigned char* GetBThreaded(); + +long CDRstop(void); + +void LoadConf(); +void SaveConf(); + +#ifdef DEBUG +#define PRINTF printf +#else +#define PRINTF(...) /* */ +#endif + +unsigned int msf_to_lba(char m, char s, char f); +void lba_to_msf(unsigned int s, unsigned char *msf); +void DecodeRawSubData(unsigned char *subbuffer); +unsigned short calcCrc(unsigned char *d, int len); + +int OpenCdHandle(); +void CloseCdHandle(); +int IsCdHandleOpen(); +long GetTN(unsigned char *buffer); +long GetTD(unsigned char track, unsigned char *buffer); +long GetTE(unsigned char track, unsigned char *m, unsigned char *s, unsigned char *f); +long ReadSector(crdata *cr); +long PlayCDDA(unsigned char *sector); +long StopCDDA(); +long GetStatus(int playing, struct CdrStat *stat); +unsigned char *ReadSub(const unsigned char *time); + +#endif diff --git a/plugins/dfcdrom/cdrcfg-0.1df/main.c b/plugins/dfcdrom/cdrcfg-0.1df/main.c index 454a4e2d..fbbe29d5 100644 --- a/plugins/dfcdrom/cdrcfg-0.1df/main.c +++ b/plugins/dfcdrom/cdrcfg-0.1df/main.c @@ -1,290 +1,290 @@ -/* - * Copyright (c) 2010, Wei Mingzhi . - * All Rights Reserved. - * - * Based on: Cdrom for Psemu Pro like Emulators - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include "../cfg.c" - -#include -#include - -GtkWidget *MainWindow; - -// function to check if the device is a cdrom -static int is_cdrom(const char *device) { - struct stat st; - int fd = -1; - - // check if the file exist - if (stat(device, &st) < 0) return 0; - - // check if is a block or char device - if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) return 0; - - // try to open the device file descriptor - if ((fd = open(device, O_RDONLY | O_NONBLOCK)) < 0) return 0; - -#ifdef __linux__ - // I need a method to check is a device is really a CD-ROM. - // some problems/ideas are: - // - different protocls (ide, scsi, old proprietary...) - // - maybe we can use major number (see linux/major.h) to do some check. - // major number can be retrieved with (st.st_rdev>>8) - // scsi has SCSI_CDROM_MAJOR but does this cover all scsi drives? - // beside IDE major is the same for hard disks and cdroms... - // and DVDs? - // - another idea is to parse /proc, but again IDE, scsi etc have - // different files... I've not found a way to query "which CD drives - // are available?" - // - // Now I use this ioctl which works also if the drive is empty, - // I hope that is implemented for all the drives... here works - // fine: at least doesn't let me to select my HD as CDs ;) - - // try a ioctl to see if it's a CD-ROM device - if (ioctl(fd, CDROM_GET_CAPABILITY, NULL) < 0) { - close(fd); - return 0; - } -#endif - - close(fd); - - // yes, it seems a CD drive! - return 1; -} - -// fill_drives_list: retrieves available cd drives. At the moment it use a quite -// ugly "brute force" method: we check for the most common location for cdrom -// in /dev and chech if they are cdrom devices. -// If your cdrom path is not listed here you'll have to type it in the dialog -// entry yourself (or add it here and recompile). -// Are there any other common entry to add to the list? (especially scsi, I -// deliberately ignored old non standard cdroms... ) -// If you come up with a better method let me know!! -static void fill_drives_list(GtkWidget *widget) { - int i; - GtkListStore *store; - GtkTreeIter iter; - -#if defined (__linux__) - static const char *cdrom_devices[] = { - "/dev/cdrom", - "/dev/cdrom0", - "/dev/cdrom1", - "/dev/cdrom2", - "/dev/cdrom3", - "/dev/cdroms/cdrom0", - "/dev/cdroms/cdrom1", - "/dev/cdroms/cdrom2", - "/dev/cdroms/cdrom3", - "/dev/hda", - "/dev/hdb", - "/dev/hdc", - "/dev/hdd", - "/dev/sda", - "/dev/sdb", - "/dev/sdc", - "/dev/sdd", - "/dev/scd0", - "/dev/scd1", - "/dev/scd2", - "/dev/scd3", - "/dev/optcd", - ""}; -#elif defined (__FreeBSD__) - static const char *cdrom_devices[] = { - "/dev/cd0", - "/dev/cd1", - "/dev/cd2", - "/dev/cd3", - ""}; -#elif defined (__sun) - char cdrom_devices[256][256]; - FILE *fp; - char buf[256], *devname, *nick; - - memset(cdrom_devices, 0, sizeof(cdrom_devices)); - - i = 0; - - fp = popen("eject -l", "r"); - - if (fp != NULL) { - while (!feof(fp) && i < 256) { - fgets(buf, 256, fp); - - devname = strtok(buf, " "); - nick = strtok(NULL, " "); - - if (devname == NULL || nick == NULL) continue; - - if (strstr(nick, "cdrom") != NULL) { - strcpy(cdrom_devices[i++], devname); - } - } - - pclose(fp); - } -#else - static const char *cdrom_devices[] = { "" }; -#endif - - store = gtk_list_store_new(1, G_TYPE_STRING); - - // first we put our current drive - if (CdromDev[0] != '\0') { - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, CdromDev, -1); - } - - i = 0; - - // scan cdrom_devices for real cdrom and add them to list - while (cdrom_devices[i][0] != '\0') { - // check that is not our current dev (already in list) - if (strcmp(cdrom_devices[i], CdromDev) != 0) { - // check that is a cdrom device - if (is_cdrom(cdrom_devices[i])) { - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, cdrom_devices[i], -1); - } - } - ++i; - } - - gtk_combo_box_set_model(GTK_COMBO_BOX(widget), GTK_TREE_MODEL(store)); - gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(widget), 0); -} - -static void OnConfigExit(GtkWidget *widget, gpointer user_data) { - GladeXML *xml; - - xml = glade_get_widget_tree(MainWindow); - - widget = glade_xml_get_widget(xml, "cddev_comboboxentry"); - strncpy(CdromDev, gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(widget)))), 255); - CdromDev[255] = '\0'; - - widget = glade_xml_get_widget(xml, "readmode_combobox"); - ReadMode = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); - - widget = glade_xml_get_widget(xml, "subQ_button"); - UseSubQ = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - - widget = glade_xml_get_widget(xml, "spinCacheSize"); - CacheSize = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); - - widget = glade_xml_get_widget(xml, "spinCdrSpeed"); - CdrSpeed = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); - - widget = glade_xml_get_widget(xml, "comboSpinDown"); - SpinDown = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); - - SaveConf(); - - gtk_widget_destroy(widget); - gtk_exit(0); -} - -long CDRconfigure() { - GladeXML *xml; - GtkWidget *widget; - - LoadConf(); - - xml = glade_xml_new(DATADIR "dfcdrom.glade2", "CfgWnd", NULL); - if (xml == NULL) { - g_warning("We could not load the interface!"); - return -1; - } - - MainWindow = glade_xml_get_widget(xml, "CfgWnd"); - gtk_window_set_title(GTK_WINDOW(MainWindow), _("CDR configuration")); - - widget = glade_xml_get_widget(xml, "CfgWnd"); - g_signal_connect_data(GTK_OBJECT(widget), "delete_event", - G_CALLBACK(OnConfigExit), NULL, NULL, G_CONNECT_AFTER); - - widget = glade_xml_get_widget(xml, "cfg_closebutton"); - g_signal_connect_data(GTK_OBJECT(widget), "clicked", - G_CALLBACK(OnConfigExit), NULL, NULL, G_CONNECT_AFTER); - - widget = glade_xml_get_widget(xml, "cddev_comboboxentry"); - fill_drives_list(widget); - gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(widget))), CdromDev); - - widget = glade_xml_get_widget(xml, "readmode_combobox"); - gtk_combo_box_set_active(GTK_COMBO_BOX(widget), ReadMode); - - widget = glade_xml_get_widget(xml, "subQ_button"); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), UseSubQ); - - widget = glade_xml_get_widget(xml, "spinCacheSize"); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), (float)CacheSize); - - widget = glade_xml_get_widget(xml, "spinCdrSpeed"); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), (float)CdrSpeed); - - widget = glade_xml_get_widget(xml, "comboSpinDown"); - gtk_combo_box_set_active(GTK_COMBO_BOX(widget), SpinDown); - - gtk_widget_show(MainWindow); - gtk_main(); - - return 0; -} - -void CDRabout() { - GtkWidget *widget; - const char *authors[]= {"linuzappz ", - "xobro <_xobro_@tin.it>", - "Wei Mingzhi ", NULL}; - - widget = gtk_about_dialog_new(); - gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(widget), "CD-ROM Device Reader"); - gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(widget), "1.0"); - gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(widget), authors); - gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(widget), "http://pcsxr.codeplex.com/"); - - gtk_dialog_run(GTK_DIALOG(widget)); - gtk_widget_destroy(widget); -} - -int main(int argc, char *argv[]) { -#ifdef ENABLE_NLS - setlocale(LC_ALL, ""); - bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR); - bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); - textdomain(GETTEXT_PACKAGE); -#endif - - gtk_set_locale(); - gtk_init(&argc, &argv); - - if (argc != 2) return 0; - - if (strcmp(argv[1], "configure") == 0) { - CDRconfigure(); - } else { - CDRabout(); - } - - return 0; -} +/* + * Copyright (c) 2010, Wei Mingzhi . + * All Rights Reserved. + * + * Based on: Cdrom for Psemu Pro like Emulators + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "../cfg.c" + +#include +#include + +GtkWidget *MainWindow; + +// function to check if the device is a cdrom +int is_cdrom(const char *device) { + struct stat st; + int fd = -1; + + // check if the file exist + if (stat(device, &st) < 0) return 0; + + // check if is a block or char device + if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) return 0; + + // try to open the device file descriptor + if ((fd = open(device, O_RDONLY | O_NONBLOCK)) < 0) return 0; + +#ifdef __linux__ + // I need a method to check is a device is really a CD-ROM. + // some problems/ideas are: + // - different protocls (ide, scsi, old proprietary...) + // - maybe we can use major number (see linux/major.h) to do some check. + // major number can be retrieved with (st.st_rdev>>8) + // scsi has SCSI_CDROM_MAJOR but does this cover all scsi drives? + // beside IDE major is the same for hard disks and cdroms... + // and DVDs? + // - another idea is to parse /proc, but again IDE, scsi etc have + // different files... I've not found a way to query "which CD drives + // are available?" + // + // Now I use this ioctl which works also if the drive is empty, + // I hope that is implemented for all the drives... here works + // fine: at least doesn't let me to select my HD as CDs ;) + + // try a ioctl to see if it's a CD-ROM device + if (ioctl(fd, CDROM_GET_CAPABILITY, NULL) < 0) { + close(fd); + return 0; + } +#endif + + close(fd); + + // yes, it seems a CD drive! + return 1; +} + +// fill_drives_list: retrieves available cd drives. At the moment it use a quite +// ugly "brute force" method: we check for the most common location for cdrom +// in /dev and chech if they are cdrom devices. +// If your cdrom path is not listed here you'll have to type it in the dialog +// entry yourself (or add it here and recompile). +// Are there any other common entry to add to the list? (especially scsi, I +// deliberately ignored old non standard cdroms... ) +// If you come up with a better method let me know!! +void fill_drives_list(GtkWidget *widget) { + int i; + GtkListStore *store; + GtkTreeIter iter; + +#if defined (__linux__) + static const char *cdrom_devices[] = { + "/dev/cdrom", + "/dev/cdrom0", + "/dev/cdrom1", + "/dev/cdrom2", + "/dev/cdrom3", + "/dev/cdroms/cdrom0", + "/dev/cdroms/cdrom1", + "/dev/cdroms/cdrom2", + "/dev/cdroms/cdrom3", + "/dev/hda", + "/dev/hdb", + "/dev/hdc", + "/dev/hdd", + "/dev/sda", + "/dev/sdb", + "/dev/sdc", + "/dev/sdd", + "/dev/scd0", + "/dev/scd1", + "/dev/scd2", + "/dev/scd3", + "/dev/optcd", + ""}; +#elif defined (__FreeBSD__) + static const char *cdrom_devices[] = { + "/dev/cd0", + "/dev/cd1", + "/dev/cd2", + "/dev/cd3", + ""}; +#elif defined (__sun) + char cdrom_devices[256][256]; + FILE *fp; + char buf[256], *devname, *nick; + + memset(cdrom_devices, 0, sizeof(cdrom_devices)); + + i = 0; + + fp = popen("eject -l", "r"); + + if (fp != NULL) { + while (!feof(fp) && i < 256) { + fgets(buf, 256, fp); + + devname = strtok(buf, " "); + nick = strtok(NULL, " "); + + if (devname == NULL || nick == NULL) continue; + + if (strstr(nick, "cdrom") != NULL) { + strcpy(cdrom_devices[i++], devname); + } + } + + pclose(fp); + } +#else + static const char *cdrom_devices[] = { "" }; +#endif + + store = gtk_list_store_new(1, G_TYPE_STRING); + + // first we put our current drive + if (CdromDev[0] != '\0') { + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, CdromDev, -1); + } + + i = 0; + + // scan cdrom_devices for real cdrom and add them to list + while (cdrom_devices[i][0] != '\0') { + // check that is not our current dev (already in list) + if (strcmp(cdrom_devices[i], CdromDev) != 0) { + // check that is a cdrom device + if (is_cdrom(cdrom_devices[i])) { + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, cdrom_devices[i], -1); + } + } + ++i; + } + + gtk_combo_box_set_model(GTK_COMBO_BOX(widget), GTK_TREE_MODEL(store)); + gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(widget), 0); +} + +static void OnConfigExit(GtkWidget *widget, gpointer user_data) { + GladeXML *xml; + + xml = glade_get_widget_tree(MainWindow); + + widget = glade_xml_get_widget(xml, "cddev_comboboxentry"); + strncpy(CdromDev, gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(widget)))), 255); + CdromDev[255] = '\0'; + + widget = glade_xml_get_widget(xml, "readmode_combobox"); + ReadMode = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); + + widget = glade_xml_get_widget(xml, "subQ_button"); + UseSubQ = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + + widget = glade_xml_get_widget(xml, "spinCacheSize"); + CacheSize = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); + + widget = glade_xml_get_widget(xml, "spinCdrSpeed"); + CdrSpeed = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); + + widget = glade_xml_get_widget(xml, "comboSpinDown"); + SpinDown = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); + + SaveConf(); + + gtk_widget_destroy(widget); + gtk_exit(0); +} + +long CDRconfigure() { + GladeXML *xml; + GtkWidget *widget; + + LoadConf(); + + xml = glade_xml_new(DATADIR "dfcdrom.glade2", "CfgWnd", NULL); + if (xml == NULL) { + g_warning("We could not load the interface!"); + return -1; + } + + MainWindow = glade_xml_get_widget(xml, "CfgWnd"); + gtk_window_set_title(GTK_WINDOW(MainWindow), _("CDR configuration")); + + widget = glade_xml_get_widget(xml, "CfgWnd"); + g_signal_connect_data(GTK_OBJECT(widget), "delete_event", + G_CALLBACK(OnConfigExit), NULL, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "cfg_closebutton"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + G_CALLBACK(OnConfigExit), NULL, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "cddev_comboboxentry"); + fill_drives_list(widget); + gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(widget))), CdromDev); + + widget = glade_xml_get_widget(xml, "readmode_combobox"); + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), ReadMode); + + widget = glade_xml_get_widget(xml, "subQ_button"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), UseSubQ); + + widget = glade_xml_get_widget(xml, "spinCacheSize"); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), (float)CacheSize); + + widget = glade_xml_get_widget(xml, "spinCdrSpeed"); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), (float)CdrSpeed); + + widget = glade_xml_get_widget(xml, "comboSpinDown"); + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), SpinDown); + + gtk_widget_show(MainWindow); + gtk_main(); + + return 0; +} + +void CDRabout() { + GtkWidget *widget; + const char *authors[]= {"linuzappz ", + "xobro <_xobro_@tin.it>", + "Wei Mingzhi ", NULL}; + + widget = gtk_about_dialog_new(); + gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(widget), "CD-ROM Device Reader"); + gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(widget), "1.0"); + gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(widget), authors); + gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(widget), "http://pcsxr.codeplex.com/"); + + gtk_dialog_run(GTK_DIALOG(widget)); + gtk_widget_destroy(widget); +} + +int main(int argc, char *argv[]) { +#ifdef ENABLE_NLS + setlocale(LC_ALL, ""); + bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + textdomain(GETTEXT_PACKAGE); +#endif + + gtk_set_locale(); + gtk_init(&argc, &argv); + + if (argc != 2) return 0; + + if (strcmp(argv[1], "configure") == 0) { + CDRconfigure(); + } else { + CDRabout(); + } + + return 0; +} diff --git a/plugins/dfcdrom/cfg.c b/plugins/dfcdrom/cfg.c index 6985eda6..1ded04c8 100644 --- a/plugins/dfcdrom/cfg.c +++ b/plugins/dfcdrom/cfg.c @@ -1,101 +1,99 @@ -/* - * Copyright (c) 2010, Wei Mingzhi . - * All Rights Reserved. - * - * Based on: Cdrom for Psemu Pro like Emulators - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include "cdr.h" - -char CdromDev[256]; -long ReadMode; -long UseSubQ; -long CacheSize; -long CdrSpeed; -long SpinDown; - -void LoadConf() { - FILE *f; - -#if defined (__sun) - char buf[256], *devname, *nick; - - CdromDev[0] = '\0'; - f = popen("eject -l", "r"); - - if (f != NULL) { - while (!feof(f)) { - fgets(buf, 256, f); - - devname = strtok(buf, " "); - nick = strtok(NULL, " "); - - if (devname == NULL || nick == NULL) continue; - - if (strstr(nick, "cdrom") != NULL) { - strcpy(CdromDev, devname); - break; - } - } - - pclose(f); - } -#else - strcpy(CdromDev, DEV_DEF); -#endif - - ReadMode = THREADED; - UseSubQ = 0; - CacheSize = 64; - CdrSpeed = 0; - SpinDown = SPINDOWN_VENDOR_SPECIFIC; - - f = fopen("dfcdrom.cfg", "r"); - if (f == NULL) return; - - if(fscanf(f, "CdromDev = %s\n", CdromDev) != 1 || - fscanf(f, "ReadMode = %ld\n", &ReadMode) != 1 || - fscanf(f, "UseSubQ = %ld\n", &UseSubQ) != 1 || - fscanf(f, "CacheSize = %ld\n", &CacheSize) != 1 || - fscanf(f, "CdrSpeed = %ld\n", &CdrSpeed) != 1 || - fscanf(f, "SpinDown = %ld\n", &SpinDown) != 1) { - perror("syntax error in dfcdrom.cfg"); - } - fclose(f); - - if (ReadMode >= READ_MODES) ReadMode = THREADED; - if (CacheSize <= 0) CacheSize = 32; - if (CacheSize > 2048) CacheSize = 2048; - if (SpinDown <= 0) SpinDown = SPINDOWN_VENDOR_SPECIFIC; - if (SpinDown > SPINDOWN_32MIN) SpinDown = SPINDOWN_32MIN; -} - -void SaveConf() { - FILE *f; - - f = fopen("dfcdrom.cfg", "w"); - if (f == NULL) - return; - - fprintf(f, "CdromDev = %s\n", CdromDev); - fprintf(f, "ReadMode = %ld\n", ReadMode); - fprintf(f, "UseSubQ = %ld\n", UseSubQ); - fprintf(f, "CacheSize = %ld\n", CacheSize); - fprintf(f, "CdrSpeed = %ld\n", CdrSpeed); - fprintf(f, "SpinDown = %ld\n", SpinDown); - fclose(f); -} +/* + * Copyright (c) 2010, Wei Mingzhi . + * All Rights Reserved. + * + * Based on: Cdrom for Psemu Pro like Emulators + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "cdr.h" + +char CdromDev[256]; +long ReadMode; +long UseSubQ; +long CacheSize; +long CdrSpeed; +long SpinDown; + +void LoadConf() { + FILE *f; + +#if defined (__sun) + char buf[256], *devname, *nick; + + CdromDev[0] = '\0'; + f = popen("eject -l", "r"); + + if (f != NULL) { + while (!feof(f)) { + fgets(buf, 256, f); + + devname = strtok(buf, " "); + nick = strtok(NULL, " "); + + if (devname == NULL || nick == NULL) continue; + + if (strstr(nick, "cdrom") != NULL) { + strcpy(CdromDev, devname); + break; + } + } + + pclose(f); + } +#else + strcpy(CdromDev, DEV_DEF); +#endif + + ReadMode = THREADED; + UseSubQ = 0; + CacheSize = 64; + CdrSpeed = 0; + SpinDown = SPINDOWN_VENDOR_SPECIFIC; + + f = fopen("dfcdrom.cfg", "r"); + if (f == NULL) return; + + fscanf(f, "CdromDev = %s\n", CdromDev); + fscanf(f, "ReadMode = %ld\n", &ReadMode); + fscanf(f, "UseSubQ = %ld\n", &UseSubQ); + fscanf(f, "CacheSize = %ld\n", &CacheSize); + fscanf(f, "CdrSpeed = %ld\n", &CdrSpeed); + fscanf(f, "SpinDown = %ld\n", &SpinDown); + fclose(f); + + if (ReadMode >= READ_MODES) ReadMode = THREADED; + if (CacheSize <= 0) CacheSize = 32; + if (CacheSize > 2048) CacheSize = 2048; + if (SpinDown <= 0) SpinDown = SPINDOWN_VENDOR_SPECIFIC; + if (SpinDown > SPINDOWN_32MIN) SpinDown = SPINDOWN_32MIN; +} + +void SaveConf() { + FILE *f; + + f = fopen("dfcdrom.cfg", "w"); + if (f == NULL) + return; + + fprintf(f, "CdromDev = %s\n", CdromDev); + fprintf(f, "ReadMode = %ld\n", ReadMode); + fprintf(f, "UseSubQ = %ld\n", UseSubQ); + fprintf(f, "CacheSize = %ld\n", CacheSize); + fprintf(f, "CdrSpeed = %ld\n", CdrSpeed); + fprintf(f, "SpinDown = %ld\n", SpinDown); + fclose(f); +} diff --git a/plugins/dfinput/cfg-gtk2.c b/plugins/dfinput/cfg-gtk2.c index f56ed5ac..a3626873 100644 --- a/plugins/dfinput/cfg-gtk2.c +++ b/plugins/dfinput/cfg-gtk2.c @@ -1,723 +1,723 @@ -/* - * Copyright (c) 2009, Wei Mingzhi . - * All Rights Reserved. - * - * 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, see . - */ - -#include "cfg.c" - -#include -#include -#include - -GtkWidget *MainWindow; -GtkBuilder *xml; - -const int DPad[DKEY_TOTAL] = { - DKEY_UP, - DKEY_DOWN, - DKEY_LEFT, - DKEY_RIGHT, - DKEY_CROSS, - DKEY_CIRCLE, - DKEY_SQUARE, - DKEY_TRIANGLE, - DKEY_L1, - DKEY_R1, - DKEY_L2, - DKEY_R2, - DKEY_SELECT, - DKEY_START, - DKEY_L3, - DKEY_R3, - DKEY_ANALOG -}; - -const char *DPadText[DKEY_TOTAL] = { - N_("D-Pad Up"), - N_("D-Pad Down"), - N_("D-Pad Left"), - N_("D-Pad Right"), - N_("Cross"), - N_("Circle"), - N_("Square"), - N_("Triangle"), - N_("L1"), - N_("R1"), - N_("L2"), - N_("R2"), - N_("Select"), - N_("Start"), - N_("L3"), - N_("R3"), - N_("Analog") -}; - -const char *AnalogText[] = { - N_("L-Stick Right"), - N_("L-Stick Left"), - N_("L-Stick Down"), - N_("L-Stick Up"), - N_("R-Stick Right"), - N_("R-Stick Left"), - N_("R-Stick Down"), - N_("R-Stick Up") -}; - -static int GetSelectedKeyIndex(int padnum) { - GtkTreeSelection *selection; - GtkTreeIter iter; - GtkTreeModel *model; - GtkTreePath *path; - gboolean selected; - int i; - - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtk_builder_get_object(xml, padnum == 0 ? "treeview1" : "treeview2"))); - selected = gtk_tree_selection_get_selected(selection, &model, &iter); - - if (!selected) { - return -1; - } - - path = gtk_tree_model_get_path(model, &iter); - i = *gtk_tree_path_get_indices(path); - gtk_tree_path_free(path); - - return i; -} - -static void GetKeyDescription(char *buf, int joynum, int key) { - const char *hatname[16] = {_("Centered"), _("Up"), _("Right"), _("Rightup"), - _("Down"), "", _("Rightdown"), "", _("Left"), _("Leftup"), "", "", - _("Leftdown"), "", "", ""}; - - switch (g.cfg.PadDef[joynum].KeyDef[key].JoyEvType) { - case BUTTON: - sprintf(buf, _("Joystick: Button %d"), g.cfg.PadDef[joynum].KeyDef[key].J.Button); - break; - - case AXIS: - sprintf(buf, _("Joystick: Axis %d%c"), abs(g.cfg.PadDef[joynum].KeyDef[key].J.Axis) - 1, - g.cfg.PadDef[joynum].KeyDef[key].J.Axis > 0 ? '+' : '-'); - break; - - case HAT: - sprintf(buf, _("Joystick: Hat %d %s"), (g.cfg.PadDef[joynum].KeyDef[key].J.Hat >> 8), - hatname[g.cfg.PadDef[joynum].KeyDef[key].J.Hat & 0x0F]); - break; - - case NONE: - default: - buf[0] = '\0'; - break; - } - - if (g.cfg.PadDef[joynum].KeyDef[key].Key != 0) { - if (buf[0] != '\0') { - strcat(buf, " / "); - } - - strcat(buf, _("Keyboard:")); - strcat(buf, " "); - strcat(buf, XKeysymToString(g.cfg.PadDef[joynum].KeyDef[key].Key)); - } else if (buf[0] == '\0') { - strcpy(buf, _("(Not Set)")); - } -} - -static void GetAnalogDescription(char *buf, int joynum, int analognum, int dir) { - const char *hatname[16] = {_("Centered"), _("Up"), _("Right"), _("Rightup"), - _("Down"), "", _("Rightdown"), "", _("Left"), _("Leftup"), "", "", - _("Leftdown"), "", "", ""}; - - switch (g.cfg.PadDef[joynum].AnalogDef[analognum][dir].JoyEvType) { - case BUTTON: - sprintf(buf, _("Joystick: Button %d"), g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Button); - break; - - case AXIS: - sprintf(buf, _("Joystick: Axis %d%c"), abs(g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Axis) - 1, - g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Axis > 0 ? '+' : '-'); - break; - - case HAT: - sprintf(buf, _("Joystick: Hat %d %s"), (g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Hat >> 8), - hatname[g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Hat & 0x0F]); - break; - - case NONE: - default: - buf[0] = '\0'; - break; - } - - if (g.cfg.PadDef[joynum].AnalogDef[analognum][dir].Key != 0) { - if (buf[0] != '\0') { - strcat(buf, " / "); - } - - strcat(buf, _("Keyboard:")); - strcat(buf, " "); - strcat(buf, XKeysymToString(g.cfg.PadDef[joynum].AnalogDef[analognum][dir].Key)); - } else if (buf[0] == '\0') { - strcpy(buf, _("(Not Set)")); - } -} - -static void UpdateKeyList() { - const char *widgetname[2] = {"treeview1", "treeview2"}; - - GtkWidget *widget; - GtkListStore *store; - GtkTreeIter iter; - int i, j; - char buf[256]; - - for (i = 0; i < 2; i++) { - int total; - - if (g.cfg.PadDef[i].Type == PSE_PAD_TYPE_ANALOGPAD) { - total = DKEY_TOTAL; - } else { - total = DKEY_TOTAL - 3; - } - - widget = GTK_WIDGET(gtk_builder_get_object(xml, widgetname[i])); - - store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); - - for (j = 0; j < total; j++) { - gtk_list_store_append(store, &iter); - GetKeyDescription(buf, i, DPad[j]); - gtk_list_store_set(store, &iter, 0, _(DPadText[j]), 1, buf, -1); - } - - if (g.cfg.PadDef[i].Type == PSE_PAD_TYPE_ANALOGPAD) { - for (j = 0; j < 8; j++) { - gtk_list_store_append(store, &iter); - GetAnalogDescription(buf, i, j / 4, j % 4); - gtk_list_store_set(store, &iter, 0, _(AnalogText[j]), 1, buf, -1); - } - } - - gtk_tree_view_set_model(GTK_TREE_VIEW(widget), GTK_TREE_MODEL(store)); - g_object_unref(G_OBJECT(store)); - gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(widget), TRUE); - gtk_widget_show(widget); - } -} - -static void UpdateKey() { - const char *widgetname[2] = {"treeview1", "treeview2"}; - int i, index; - GtkWidget *widget; - GtkTreeModel *model; - GtkTreeIter iter; - GValue value = {0, }; - char buf[256]; - - for (i = 0; i < 2; i++) { - index = GetSelectedKeyIndex(i); - if (index == -1) continue; - - widget = GTK_WIDGET(gtk_builder_get_object(xml, widgetname[i])); - gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)), &model, &iter); - - if (index < DKEY_TOTAL) { - GetKeyDescription(buf, i, DPad[index]); - } else { - GetAnalogDescription(buf, i, (index - DKEY_TOTAL) / 4, (index - DKEY_TOTAL) % 4); - } - - g_value_init(&value, G_TYPE_STRING); - g_value_set_string(&value, buf); - gtk_list_store_set_value(GTK_LIST_STORE(model), &iter, 1, &value); - } -} - -static void OnConfigExit(GtkWidget *widget, gpointer user_data) { - SavePADConfig(); - - gtk_widget_destroy(widget); - SDL_Quit(); - - gtk_exit(0); -} - -static void TreeSelectionChanged(GtkTreeSelection *selection, gpointer user_data) { - GtkTreeIter iter; - GtkTreeModel *model; - GtkTreePath *path; - - gboolean selected; - int i; - - selected = gtk_tree_selection_get_selected(selection, &model, &iter); - - if (selected) { - path = gtk_tree_model_get_path(model, &iter); - i = *gtk_tree_path_get_indices(path); - gtk_tree_path_free(path); - - // If a row was selected, and the row is not blank, we can now enable - // some of the disabled widgets - if ((int)(long)user_data == 0) { - gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnchange1")), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnreset1")), TRUE); - } else { - gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnchange2")), TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnreset2")), TRUE); - } - } else { - if ((int)(long)user_data == 0) { - gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnchange1")), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnreset1")), FALSE); - } else { - gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnchange2")), FALSE); - gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnreset2")), FALSE); - } - } -} - -static void OnDeviceChanged(GtkWidget *widget, gpointer user_data) { - int n = (int)(long)user_data, current = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); - current--; - g.cfg.PadDef[n].DevNum = current; -} - -static void OnTypeChanged(GtkWidget *widget, gpointer user_data) { - int n = (int)(long)user_data, current = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); - g.cfg.PadDef[n].Type = (current == 0 ? PSE_PAD_TYPE_STANDARD : PSE_PAD_TYPE_ANALOGPAD); - - UpdateKeyList(); -} - -static void OnThreadedToggled(GtkWidget *widget, gpointer user_data) { - g.cfg.Threaded = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); -} - -static void ReadDKeyEvent(int padnum, int key) { - SDL_Joystick *js; - time_t t; - GdkEvent *ge; - int i; - Sint16 axis, numAxes = 0, InitAxisPos[256], PrevAxisPos[256]; - - if (g.cfg.PadDef[padnum].DevNum >= 0) { - js = SDL_JoystickOpen(g.cfg.PadDef[padnum].DevNum); - SDL_JoystickEventState(SDL_IGNORE); - - SDL_JoystickUpdate(); - - numAxes = SDL_JoystickNumAxes(js); - if (numAxes > 256) numAxes = 256; - - for (i = 0; i < numAxes; i++) { - InitAxisPos[i] = PrevAxisPos[i] = SDL_JoystickGetAxis(js, i); - } - } else { - js = NULL; - } - - t = time(NULL); - - while (time(NULL) < t + 10) { - // check joystick events - if (js != NULL) { - SDL_JoystickUpdate(); - - for (i = 0; i < SDL_JoystickNumButtons(js); i++) { - if (SDL_JoystickGetButton(js, i)) { - g.cfg.PadDef[padnum].KeyDef[key].JoyEvType = BUTTON; - g.cfg.PadDef[padnum].KeyDef[key].J.Button = i; - goto end; - } - } - - for (i = 0; i < numAxes; i++) { - axis = SDL_JoystickGetAxis(js, i); - if (abs(axis) > 16383 && (abs(axis - InitAxisPos[i]) > 4096 || abs(axis - PrevAxisPos[i]) > 4096)) { - g.cfg.PadDef[padnum].KeyDef[key].JoyEvType = AXIS; - g.cfg.PadDef[padnum].KeyDef[key].J.Axis = (i + 1) * (axis > 0 ? 1 : -1); - goto end; - } - PrevAxisPos[i] = axis; - } - - for (i = 0; i < SDL_JoystickNumHats(js); i++) { - axis = SDL_JoystickGetHat(js, i); - if (axis != SDL_HAT_CENTERED) { - g.cfg.PadDef[padnum].KeyDef[key].JoyEvType = HAT; - - if (axis & SDL_HAT_UP) { - g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_UP); - } else if (axis & SDL_HAT_DOWN) { - g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_DOWN); - } else if (axis & SDL_HAT_LEFT) { - g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_LEFT); - } else if (axis & SDL_HAT_RIGHT) { - g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_RIGHT); - } - - goto end; - } - } - } - - // check keyboard events - while ((ge = gdk_event_get()) != NULL) { - if (ge->type == GDK_KEY_PRESS) { - if (ge->key.keyval != XK_Escape) { - g.cfg.PadDef[padnum].KeyDef[key].Key = ge->key.keyval; - } - gdk_event_free(ge); - goto end; - } - gdk_event_free(ge); - } - - usleep(5000); - } - -end: - if (js != NULL) { - SDL_JoystickClose(js); - } -} - -static void ReadAnalogEvent(int padnum, int analognum, int analogdir) { - SDL_Joystick *js; - time_t t; - GdkEvent *ge; - int i; - Sint16 axis, numAxes = 0, InitAxisPos[256], PrevAxisPos[256]; - - if (g.cfg.PadDef[padnum].DevNum >= 0) { - js = SDL_JoystickOpen(g.cfg.PadDef[padnum].DevNum); - SDL_JoystickEventState(SDL_IGNORE); - - SDL_JoystickUpdate(); - - numAxes = SDL_JoystickNumAxes(js); - if (numAxes > 256) numAxes = 256; - - for (i = 0; i < SDL_JoystickNumAxes(js); i++) { - InitAxisPos[i] = PrevAxisPos[i] = SDL_JoystickGetAxis(js, i); - } - } else { - js = NULL; - } - - t = time(NULL); - - while (time(NULL) < t + 10) { - // check joystick events - if (js != NULL) { - SDL_JoystickUpdate(); - - for (i = 0; i < SDL_JoystickNumButtons(js); i++) { - if (SDL_JoystickGetButton(js, i)) { - g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].JoyEvType = BUTTON; - g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Button = i; - goto end; - } - } - - for (i = 0; i < numAxes; i++) { - axis = SDL_JoystickGetAxis(js, i); - if (abs(axis) > 16383 && (abs(axis - InitAxisPos[i]) > 4096 || abs(axis - PrevAxisPos[i]) > 4096)) { - g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].JoyEvType = AXIS; - g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Axis = (i + 1) * (axis > 0 ? 1 : -1); - goto end; - } - PrevAxisPos[i] = axis; - } - - for (i = 0; i < SDL_JoystickNumHats(js); i++) { - axis = SDL_JoystickGetHat(js, i); - if (axis != SDL_HAT_CENTERED) { - g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].JoyEvType = HAT; - - if (axis & SDL_HAT_UP) { - g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_UP); - } else if (axis & SDL_HAT_DOWN) { - g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_DOWN); - } else if (axis & SDL_HAT_LEFT) { - g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_LEFT); - } else if (axis & SDL_HAT_RIGHT) { - g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_RIGHT); - } - - goto end; - } - } - } - - // check keyboard events - while ((ge = gdk_event_get()) != NULL) { - if (ge->type == GDK_KEY_PRESS) { - if (ge->key.keyval != XK_Escape) { - g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].Key = ge->key.keyval; - } - gdk_event_free(ge); - goto end; - } - gdk_event_free(ge); - } - - usleep(5000); - } - -end: - if (js != NULL) { - SDL_JoystickClose(js); - } -} - -static void OnChangeClicked(GtkWidget *widget, gpointer user_data) { - int pad = (int)(long)user_data; - int index = GetSelectedKeyIndex(pad); - - if (index == -1) return; - - if (index < DKEY_TOTAL) { - ReadDKeyEvent(pad, DPad[index]); - } else { - index -= DKEY_TOTAL; - ReadAnalogEvent(pad, index / 4, index % 4); - } - - UpdateKey(); -} - -static void OnResetClicked(GtkWidget *widget, gpointer user_data) { - int pad = (int)(long)user_data; - int index = GetSelectedKeyIndex(pad); - - if (index == -1) return; - - if (index < DKEY_TOTAL) { - g.cfg.PadDef[pad].KeyDef[DPad[index]].Key = 0; - g.cfg.PadDef[pad].KeyDef[DPad[index]].JoyEvType = NONE; - g.cfg.PadDef[pad].KeyDef[DPad[index]].J.Button = 0; - } else { - index -= DKEY_TOTAL; - g.cfg.PadDef[pad].AnalogDef[index / 4][index % 4].Key = 0; - g.cfg.PadDef[pad].AnalogDef[index / 4][index % 4].JoyEvType = NONE; - g.cfg.PadDef[pad].AnalogDef[index / 4][index % 4].J.Button = 0; - } - - UpdateKey(); -} - -static void PopulateDevList() { - const char *widgetname[2] = {"combodev1", "combodev2"}; - int i, j, n; - GtkWidget *widget; - GtkTreeIter iter; - GtkListStore *store; - GtkCellRenderer *renderer; - char buf[256]; - - for (i = 0; i < 2; i++) { - widget = GTK_WIDGET(gtk_builder_get_object(xml, widgetname[i])); - - renderer = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, FALSE); - gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 0); - - store = gtk_list_store_new(1, G_TYPE_STRING); - - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, _("None"), -1); - - n = SDL_NumJoysticks(); - for (j = 0; j < n; j++) { - sprintf(buf, "%d: %s", j + 1, SDL_JoystickName(j)); - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, buf, -1); - } - - gtk_combo_box_set_model(GTK_COMBO_BOX(widget), GTK_TREE_MODEL(store)); - - n = g.cfg.PadDef[i].DevNum + 1; - if (n > SDL_NumJoysticks()) { - n = 0; - g.cfg.PadDef[i].DevNum = -1; - } - - gtk_combo_box_set_active(GTK_COMBO_BOX(widget), n); - } -} - -long PADconfigure() { - GtkWidget *widget; - GtkTreeSelection *treesel; - GtkTreeViewColumn *column; - GtkCellRenderer *renderer; - - if (SDL_Init(SDL_INIT_JOYSTICK) == -1) { - fprintf(stderr, "Failed to initialize SDL!\n"); - return -1; - } - - LoadPADConfig(); - - xml = gtk_builder_new(); - - if (!gtk_builder_add_from_file(xml, DATADIR "dfinput.ui", NULL)) { - g_warning("We could not load the interface!"); - return -1; - } - - MainWindow = GTK_WIDGET(gtk_builder_get_object(xml, "CfgWnd")); - gtk_window_set_title(GTK_WINDOW(MainWindow), _("Gamepad/Keyboard Input Configuration")); - - widget = GTK_WIDGET(gtk_builder_get_object(xml, "treeview1")); - - // column for key - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes(_("Key"), - renderer, "text", 0, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); - - // column for button - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes(_("Button"), - renderer, "text", 1, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); - - treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); - gtk_tree_selection_set_mode(treesel, GTK_SELECTION_SINGLE); - - g_signal_connect_data(G_OBJECT(treesel), "changed", - G_CALLBACK(TreeSelectionChanged), (gpointer)0, NULL, G_CONNECT_AFTER); - - widget = GTK_WIDGET(gtk_builder_get_object(xml, "treeview2")); - - // column for key - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes(_("Key"), - renderer, "text", 0, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); - - // column for button - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes(_("Button"), - renderer, "text", 1, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); - - treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); - gtk_tree_selection_set_mode(treesel, GTK_SELECTION_SINGLE); - - g_signal_connect_data(G_OBJECT(treesel), "changed", - G_CALLBACK(TreeSelectionChanged), (gpointer)1, NULL, G_CONNECT_AFTER); - - widget = GTK_WIDGET(gtk_builder_get_object(xml, "CfgWnd")); - g_signal_connect_data(GTK_OBJECT(widget), "delete_event", - G_CALLBACK(OnConfigExit), NULL, NULL, G_CONNECT_AFTER); - - widget = GTK_WIDGET(gtk_builder_get_object(xml, "btnclose")); - g_signal_connect_data(GTK_OBJECT(widget), "clicked", - G_CALLBACK(OnConfigExit), NULL, NULL, G_CONNECT_AFTER); - - PopulateDevList(); - UpdateKeyList(); - - widget = GTK_WIDGET(gtk_builder_get_object(xml, "checkmt")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), g.cfg.Threaded); - g_signal_connect_data(GTK_OBJECT(widget), "toggled", - G_CALLBACK(OnThreadedToggled), NULL, NULL, G_CONNECT_AFTER); - - widget = GTK_WIDGET(gtk_builder_get_object(xml, "combodev1")); - g_signal_connect_data(GTK_OBJECT(widget), "changed", - G_CALLBACK(OnDeviceChanged), (gpointer)0, NULL, G_CONNECT_AFTER); - - widget = GTK_WIDGET(gtk_builder_get_object(xml, "combodev2")); - g_signal_connect_data(GTK_OBJECT(widget), "changed", - G_CALLBACK(OnDeviceChanged), (gpointer)1, NULL, G_CONNECT_AFTER); - - widget = GTK_WIDGET(gtk_builder_get_object(xml, "combotype1")); - gtk_combo_box_set_active(GTK_COMBO_BOX(widget), - g.cfg.PadDef[0].Type == PSE_PAD_TYPE_ANALOGPAD ? 1 : 0); - g_signal_connect_data(GTK_OBJECT(widget), "changed", - G_CALLBACK(OnTypeChanged), (gpointer)0, NULL, G_CONNECT_AFTER); - - widget = GTK_WIDGET(gtk_builder_get_object(xml, "combotype2")); - gtk_combo_box_set_active(GTK_COMBO_BOX(widget), - g.cfg.PadDef[1].Type == PSE_PAD_TYPE_ANALOGPAD ? 1 : 0); - g_signal_connect_data(GTK_OBJECT(widget), "changed", - G_CALLBACK(OnTypeChanged), (gpointer)1, NULL, G_CONNECT_AFTER); - - widget = GTK_WIDGET(gtk_builder_get_object(xml, "btnchange1")); - gtk_widget_set_sensitive(widget, FALSE); - g_signal_connect_data(GTK_OBJECT(widget), "clicked", - G_CALLBACK(OnChangeClicked), (gpointer)0, NULL, G_CONNECT_AFTER); - - widget = GTK_WIDGET(gtk_builder_get_object(xml, "btnreset1")); - gtk_widget_set_sensitive(widget, FALSE); - g_signal_connect_data(GTK_OBJECT(widget), "clicked", - G_CALLBACK(OnResetClicked), (gpointer)0, NULL, G_CONNECT_AFTER); - - widget = GTK_WIDGET(gtk_builder_get_object(xml, "btnchange2")); - gtk_widget_set_sensitive(widget, FALSE); - g_signal_connect_data(GTK_OBJECT(widget), "clicked", - G_CALLBACK(OnChangeClicked), (gpointer)1, NULL, G_CONNECT_AFTER); - - widget = GTK_WIDGET(gtk_builder_get_object(xml, "btnreset2")); - gtk_widget_set_sensitive(widget, FALSE); - g_signal_connect_data(GTK_OBJECT(widget), "clicked", - G_CALLBACK(OnResetClicked), (gpointer)1, NULL, G_CONNECT_AFTER); - - gtk_widget_show(MainWindow); - gtk_main(); - - return 0; -} - -void PADabout() { - const char *authors[]= {"Wei Mingzhi ", NULL}; - GtkWidget *widget; - - widget = gtk_about_dialog_new(); - gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(widget), "Gamepad/Keyboard Input"); - gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(widget), "1.1"); - gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(widget), authors); - gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(widget), "http://www.codeplex.com/pcsxr/"); - - gtk_dialog_run(GTK_DIALOG(widget)); - gtk_widget_destroy(widget); -} - -int main(int argc, char *argv[]) { -#ifdef ENABLE_NLS - setlocale(LC_ALL, ""); - bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR); - bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); - textdomain(GETTEXT_PACKAGE); -#endif - - gtk_set_locale(); - gtk_init(&argc, &argv); - - if (argc > 1 && !strcmp(argv[1], "-about")) { - PADabout(); - } else { - PADconfigure(); - } - - gtk_exit(0); - return 0; -} +/* + * Copyright (c) 2009, Wei Mingzhi . + * All Rights Reserved. + * + * 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, see . + */ + +#include "cfg.c" + +#include +#include +#include + +GtkWidget *MainWindow; +GtkBuilder *xml; + +const int DPad[DKEY_TOTAL] = { + DKEY_UP, + DKEY_DOWN, + DKEY_LEFT, + DKEY_RIGHT, + DKEY_CROSS, + DKEY_CIRCLE, + DKEY_SQUARE, + DKEY_TRIANGLE, + DKEY_L1, + DKEY_R1, + DKEY_L2, + DKEY_R2, + DKEY_SELECT, + DKEY_START, + DKEY_L3, + DKEY_R3, + DKEY_ANALOG +}; + +const char *DPadText[DKEY_TOTAL] = { + N_("D-Pad Up"), + N_("D-Pad Down"), + N_("D-Pad Left"), + N_("D-Pad Right"), + N_("Cross"), + N_("Circle"), + N_("Square"), + N_("Triangle"), + N_("L1"), + N_("R1"), + N_("L2"), + N_("R2"), + N_("Select"), + N_("Start"), + N_("L3"), + N_("R3"), + N_("Analog") +}; + +const char *AnalogText[] = { + N_("L-Stick Right"), + N_("L-Stick Left"), + N_("L-Stick Down"), + N_("L-Stick Up"), + N_("R-Stick Right"), + N_("R-Stick Left"), + N_("R-Stick Down"), + N_("R-Stick Up") +}; + +static int GetSelectedKeyIndex(int padnum) { + GtkTreeSelection *selection; + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreePath *path; + gboolean selected; + int i; + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtk_builder_get_object(xml, padnum == 0 ? "treeview1" : "treeview2"))); + selected = gtk_tree_selection_get_selected(selection, &model, &iter); + + if (!selected) { + return -1; + } + + path = gtk_tree_model_get_path(model, &iter); + i = *gtk_tree_path_get_indices(path); + gtk_tree_path_free(path); + + return i; +} + +static void GetKeyDescription(char *buf, int joynum, int key) { + const char *hatname[16] = {_("Centered"), _("Up"), _("Right"), _("Rightup"), + _("Down"), "", _("Rightdown"), "", _("Left"), _("Leftup"), "", "", + _("Leftdown"), "", "", ""}; + + switch (g.cfg.PadDef[joynum].KeyDef[key].JoyEvType) { + case BUTTON: + sprintf(buf, _("Joystick: Button %d"), g.cfg.PadDef[joynum].KeyDef[key].J.Button); + break; + + case AXIS: + sprintf(buf, _("Joystick: Axis %d%c"), abs(g.cfg.PadDef[joynum].KeyDef[key].J.Axis) - 1, + g.cfg.PadDef[joynum].KeyDef[key].J.Axis > 0 ? '+' : '-'); + break; + + case HAT: + sprintf(buf, _("Joystick: Hat %d %s"), (g.cfg.PadDef[joynum].KeyDef[key].J.Hat >> 8), + hatname[g.cfg.PadDef[joynum].KeyDef[key].J.Hat & 0x0F]); + break; + + case NONE: + default: + buf[0] = '\0'; + break; + } + + if (g.cfg.PadDef[joynum].KeyDef[key].Key != 0) { + if (buf[0] != '\0') { + strcat(buf, " / "); + } + + strcat(buf, _("Keyboard:")); + strcat(buf, " "); + strcat(buf, XKeysymToString(g.cfg.PadDef[joynum].KeyDef[key].Key)); + } else if (buf[0] == '\0') { + strcpy(buf, _("(Not Set)")); + } +} + +static void GetAnalogDescription(char *buf, int joynum, int analognum, int dir) { + const char *hatname[16] = {_("Centered"), _("Up"), _("Right"), _("Rightup"), + _("Down"), "", _("Rightdown"), "", _("Left"), _("Leftup"), "", "", + _("Leftdown"), "", "", ""}; + + switch (g.cfg.PadDef[joynum].AnalogDef[analognum][dir].JoyEvType) { + case BUTTON: + sprintf(buf, _("Joystick: Button %d"), g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Button); + break; + + case AXIS: + sprintf(buf, _("Joystick: Axis %d%c"), abs(g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Axis) - 1, + g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Axis > 0 ? '+' : '-'); + break; + + case HAT: + sprintf(buf, _("Joystick: Hat %d %s"), (g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Hat >> 8), + hatname[g.cfg.PadDef[joynum].AnalogDef[analognum][dir].J.Hat & 0x0F]); + break; + + case NONE: + default: + buf[0] = '\0'; + break; + } + + if (g.cfg.PadDef[joynum].AnalogDef[analognum][dir].Key != 0) { + if (buf[0] != '\0') { + strcat(buf, " / "); + } + + strcat(buf, _("Keyboard:")); + strcat(buf, " "); + strcat(buf, XKeysymToString(g.cfg.PadDef[joynum].AnalogDef[analognum][dir].Key)); + } else if (buf[0] == '\0') { + strcpy(buf, _("(Not Set)")); + } +} + +static void UpdateKeyList() { + const char *widgetname[2] = {"treeview1", "treeview2"}; + + GtkWidget *widget; + GtkListStore *store; + GtkTreeIter iter; + int i, j; + char buf[256]; + + for (i = 0; i < 2; i++) { + int total; + + if (g.cfg.PadDef[i].Type == PSE_PAD_TYPE_ANALOGPAD) { + total = DKEY_TOTAL; + } else { + total = DKEY_TOTAL - 3; + } + + widget = gtk_builder_get_object(xml, widgetname[i]); + + store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); + + for (j = 0; j < total; j++) { + gtk_list_store_append(store, &iter); + GetKeyDescription(buf, i, DPad[j]); + gtk_list_store_set(store, &iter, 0, _(DPadText[j]), 1, buf, -1); + } + + if (g.cfg.PadDef[i].Type == PSE_PAD_TYPE_ANALOGPAD) { + for (j = 0; j < 8; j++) { + gtk_list_store_append(store, &iter); + GetAnalogDescription(buf, i, j / 4, j % 4); + gtk_list_store_set(store, &iter, 0, _(AnalogText[j]), 1, buf, -1); + } + } + + gtk_tree_view_set_model(GTK_TREE_VIEW(widget), GTK_TREE_MODEL(store)); + g_object_unref(G_OBJECT(store)); + gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(widget), TRUE); + gtk_widget_show(widget); + } +} + +static void UpdateKey() { + const char *widgetname[2] = {"treeview1", "treeview2"}; + int i, index; + GtkWidget *widget; + GtkTreeModel *model; + GtkTreeIter iter; + GValue value = {0, }; + char buf[256]; + + for (i = 0; i < 2; i++) { + index = GetSelectedKeyIndex(i); + if (index == -1) continue; + + widget = gtk_builder_get_object(xml, widgetname[i]); + gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)), &model, &iter); + + if (index < DKEY_TOTAL) { + GetKeyDescription(buf, i, DPad[index]); + } else { + GetAnalogDescription(buf, i, (index - DKEY_TOTAL) / 4, (index - DKEY_TOTAL) % 4); + } + + g_value_init(&value, G_TYPE_STRING); + g_value_set_string(&value, buf); + gtk_list_store_set_value(GTK_LIST_STORE(model), &iter, 1, &value); + } +} + +static void OnConfigExit(GtkWidget *widget, gpointer user_data) { + SavePADConfig(); + + gtk_widget_destroy(widget); + SDL_Quit(); + + gtk_exit(0); +} + +static void TreeSelectionChanged(GtkTreeSelection *selection, gpointer user_data) { + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreePath *path; + + gboolean selected; + int i; + + selected = gtk_tree_selection_get_selected(selection, &model, &iter); + + if (selected) { + path = gtk_tree_model_get_path(model, &iter); + i = *gtk_tree_path_get_indices(path); + gtk_tree_path_free(path); + + // If a row was selected, and the row is not blank, we can now enable + // some of the disabled widgets + if ((int)user_data == 0) { + gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnchange1")), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnreset1")), TRUE); + } else { + gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnchange2")), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnreset2")), TRUE); + } + } else { + if ((int)user_data == 0) { + gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnchange1")), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnreset1")), FALSE); + } else { + gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnchange2")), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(xml, "btnreset2")), FALSE); + } + } +} + +static void OnDeviceChanged(GtkWidget *widget, gpointer user_data) { + int n = (int)user_data, current = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); + current--; + g.cfg.PadDef[n].DevNum = current; +} + +static void OnTypeChanged(GtkWidget *widget, gpointer user_data) { + int n = (int)user_data, current = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); + g.cfg.PadDef[n].Type = (current == 0 ? PSE_PAD_TYPE_STANDARD : PSE_PAD_TYPE_ANALOGPAD); + + UpdateKeyList(); +} + +static void OnThreadedToggled(GtkWidget *widget, gpointer user_data) { + g.cfg.Threaded = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); +} + +static void ReadDKeyEvent(int padnum, int key) { + SDL_Joystick *js; + time_t t; + GdkEvent *ge; + int i; + Sint16 axis, numAxes = 0, InitAxisPos[256], PrevAxisPos[256]; + + if (g.cfg.PadDef[padnum].DevNum >= 0) { + js = SDL_JoystickOpen(g.cfg.PadDef[padnum].DevNum); + SDL_JoystickEventState(SDL_IGNORE); + + SDL_JoystickUpdate(); + + numAxes = SDL_JoystickNumAxes(js); + if (numAxes > 256) numAxes = 256; + + for (i = 0; i < numAxes; i++) { + InitAxisPos[i] = PrevAxisPos[i] = SDL_JoystickGetAxis(js, i); + } + } else { + js = NULL; + } + + t = time(NULL); + + while (time(NULL) < t + 10) { + // check joystick events + if (js != NULL) { + SDL_JoystickUpdate(); + + for (i = 0; i < SDL_JoystickNumButtons(js); i++) { + if (SDL_JoystickGetButton(js, i)) { + g.cfg.PadDef[padnum].KeyDef[key].JoyEvType = BUTTON; + g.cfg.PadDef[padnum].KeyDef[key].J.Button = i; + goto end; + } + } + + for (i = 0; i < numAxes; i++) { + axis = SDL_JoystickGetAxis(js, i); + if (abs(axis) > 16383 && (abs(axis - InitAxisPos[i]) > 4096 || abs(axis - PrevAxisPos[i]) > 4096)) { + g.cfg.PadDef[padnum].KeyDef[key].JoyEvType = AXIS; + g.cfg.PadDef[padnum].KeyDef[key].J.Axis = (i + 1) * (axis > 0 ? 1 : -1); + goto end; + } + PrevAxisPos[i] = axis; + } + + for (i = 0; i < SDL_JoystickNumHats(js); i++) { + axis = SDL_JoystickGetHat(js, i); + if (axis != SDL_HAT_CENTERED) { + g.cfg.PadDef[padnum].KeyDef[key].JoyEvType = HAT; + + if (axis & SDL_HAT_UP) { + g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_UP); + } else if (axis & SDL_HAT_DOWN) { + g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_DOWN); + } else if (axis & SDL_HAT_LEFT) { + g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_LEFT); + } else if (axis & SDL_HAT_RIGHT) { + g.cfg.PadDef[padnum].KeyDef[key].J.Hat = ((i << 8) | SDL_HAT_RIGHT); + } + + goto end; + } + } + } + + // check keyboard events + while ((ge = gdk_event_get()) != NULL) { + if (ge->type == GDK_KEY_PRESS) { + if (ge->key.keyval != XK_Escape) { + g.cfg.PadDef[padnum].KeyDef[key].Key = ge->key.keyval; + } + gdk_event_free(ge); + goto end; + } + gdk_event_free(ge); + } + + usleep(5000); + } + +end: + if (js != NULL) { + SDL_JoystickClose(js); + } +} + +static void ReadAnalogEvent(int padnum, int analognum, int analogdir) { + SDL_Joystick *js; + time_t t; + GdkEvent *ge; + int i; + Sint16 axis, numAxes = 0, InitAxisPos[256], PrevAxisPos[256]; + + if (g.cfg.PadDef[padnum].DevNum >= 0) { + js = SDL_JoystickOpen(g.cfg.PadDef[padnum].DevNum); + SDL_JoystickEventState(SDL_IGNORE); + + SDL_JoystickUpdate(); + + numAxes = SDL_JoystickNumAxes(js); + if (numAxes > 256) numAxes = 256; + + for (i = 0; i < SDL_JoystickNumAxes(js); i++) { + InitAxisPos[i] = PrevAxisPos[i] = SDL_JoystickGetAxis(js, i); + } + } else { + js = NULL; + } + + t = time(NULL); + + while (time(NULL) < t + 10) { + // check joystick events + if (js != NULL) { + SDL_JoystickUpdate(); + + for (i = 0; i < SDL_JoystickNumButtons(js); i++) { + if (SDL_JoystickGetButton(js, i)) { + g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].JoyEvType = BUTTON; + g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Button = i; + goto end; + } + } + + for (i = 0; i < numAxes; i++) { + axis = SDL_JoystickGetAxis(js, i); + if (abs(axis) > 16383 && (abs(axis - InitAxisPos[i]) > 4096 || abs(axis - PrevAxisPos[i]) > 4096)) { + g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].JoyEvType = AXIS; + g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Axis = (i + 1) * (axis > 0 ? 1 : -1); + goto end; + } + PrevAxisPos[i] = axis; + } + + for (i = 0; i < SDL_JoystickNumHats(js); i++) { + axis = SDL_JoystickGetHat(js, i); + if (axis != SDL_HAT_CENTERED) { + g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].JoyEvType = HAT; + + if (axis & SDL_HAT_UP) { + g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_UP); + } else if (axis & SDL_HAT_DOWN) { + g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_DOWN); + } else if (axis & SDL_HAT_LEFT) { + g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_LEFT); + } else if (axis & SDL_HAT_RIGHT) { + g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].J.Hat = ((i << 8) | SDL_HAT_RIGHT); + } + + goto end; + } + } + } + + // check keyboard events + while ((ge = gdk_event_get()) != NULL) { + if (ge->type == GDK_KEY_PRESS) { + if (ge->key.keyval != XK_Escape) { + g.cfg.PadDef[padnum].AnalogDef[analognum][analogdir].Key = ge->key.keyval; + } + gdk_event_free(ge); + goto end; + } + gdk_event_free(ge); + } + + usleep(5000); + } + +end: + if (js != NULL) { + SDL_JoystickClose(js); + } +} + +static void OnChangeClicked(GtkWidget *widget, gpointer user_data) { + int pad = (int)user_data; + int index = GetSelectedKeyIndex(pad); + + if (index == -1) return; + + if (index < DKEY_TOTAL) { + ReadDKeyEvent(pad, DPad[index]); + } else { + index -= DKEY_TOTAL; + ReadAnalogEvent(pad, index / 4, index % 4); + } + + UpdateKey(); +} + +static void OnResetClicked(GtkWidget *widget, gpointer user_data) { + int pad = (int)user_data; + int index = GetSelectedKeyIndex(pad); + + if (index == -1) return; + + if (index < DKEY_TOTAL) { + g.cfg.PadDef[pad].KeyDef[DPad[index]].Key = 0; + g.cfg.PadDef[pad].KeyDef[DPad[index]].JoyEvType = NONE; + g.cfg.PadDef[pad].KeyDef[DPad[index]].J.Button = 0; + } else { + index -= DKEY_TOTAL; + g.cfg.PadDef[pad].AnalogDef[index / 4][index % 4].Key = 0; + g.cfg.PadDef[pad].AnalogDef[index / 4][index % 4].JoyEvType = NONE; + g.cfg.PadDef[pad].AnalogDef[index / 4][index % 4].J.Button = 0; + } + + UpdateKey(); +} + +static void PopulateDevList() { + const char *widgetname[2] = {"combodev1", "combodev2"}; + int i, j, n; + GtkWidget *widget; + GtkTreeIter iter; + GtkListStore *store; + GtkCellRenderer *renderer; + char buf[256]; + + for (i = 0; i < 2; i++) { + widget = gtk_builder_get_object(xml, widgetname[i]); + + renderer = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, FALSE); + gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 0); + + store = gtk_list_store_new(1, G_TYPE_STRING); + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, _("None"), -1); + + n = SDL_NumJoysticks(); + for (j = 0; j < n; j++) { + sprintf(buf, "%d: %s", j + 1, SDL_JoystickName(j)); + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, buf, -1); + } + + gtk_combo_box_set_model(GTK_COMBO_BOX(widget), GTK_TREE_MODEL(store)); + + n = g.cfg.PadDef[i].DevNum + 1; + if (n > SDL_NumJoysticks()) { + n = 0; + g.cfg.PadDef[i].DevNum = -1; + } + + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), n); + } +} + +long PADconfigure() { + GtkWidget *widget; + GtkTreeSelection *treesel; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + + if (SDL_Init(SDL_INIT_JOYSTICK) == -1) { + fprintf(stderr, "Failed to initialize SDL!\n"); + return -1; + } + + LoadPADConfig(); + + xml = gtk_builder_new(); + + if (!gtk_builder_add_from_file(xml, DATADIR "dfinput.ui", NULL)) { + g_warning("We could not load the interface!"); + return -1; + } + + MainWindow = gtk_builder_get_object(xml, "CfgWnd"); + gtk_window_set_title(GTK_WINDOW(MainWindow), _("Gamepad/Keyboard Input Configuration")); + + widget = gtk_builder_get_object(xml, "treeview1"); + + // column for key + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Key"), + renderer, "text", 0, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); + + // column for button + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Button"), + renderer, "text", 1, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); + + treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + gtk_tree_selection_set_mode(treesel, GTK_SELECTION_SINGLE); + + g_signal_connect_data(G_OBJECT(treesel), "changed", + G_CALLBACK(TreeSelectionChanged), (gpointer)0, NULL, G_CONNECT_AFTER); + + widget = gtk_builder_get_object(xml, "treeview2"); + + // column for key + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Key"), + renderer, "text", 0, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); + + // column for button + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Button"), + renderer, "text", 1, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); + + treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + gtk_tree_selection_set_mode(treesel, GTK_SELECTION_SINGLE); + + g_signal_connect_data(G_OBJECT(treesel), "changed", + G_CALLBACK(TreeSelectionChanged), (gpointer)1, NULL, G_CONNECT_AFTER); + + widget = gtk_builder_get_object(xml, "CfgWnd"); + g_signal_connect_data(GTK_OBJECT(widget), "delete_event", + G_CALLBACK(OnConfigExit), NULL, NULL, G_CONNECT_AFTER); + + widget = gtk_builder_get_object(xml, "btnclose"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + G_CALLBACK(OnConfigExit), NULL, NULL, G_CONNECT_AFTER); + + PopulateDevList(); + UpdateKeyList(); + + widget = gtk_builder_get_object(xml, "checkmt"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), g.cfg.Threaded); + g_signal_connect_data(GTK_OBJECT(widget), "toggled", + G_CALLBACK(OnThreadedToggled), NULL, NULL, G_CONNECT_AFTER); + + widget = gtk_builder_get_object(xml, "combodev1"); + g_signal_connect_data(GTK_OBJECT(widget), "changed", + G_CALLBACK(OnDeviceChanged), (gpointer)0, NULL, G_CONNECT_AFTER); + + widget = gtk_builder_get_object(xml, "combodev2"); + g_signal_connect_data(GTK_OBJECT(widget), "changed", + G_CALLBACK(OnDeviceChanged), (gpointer)1, NULL, G_CONNECT_AFTER); + + widget = gtk_builder_get_object(xml, "combotype1"); + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), + g.cfg.PadDef[0].Type == PSE_PAD_TYPE_ANALOGPAD ? 1 : 0); + g_signal_connect_data(GTK_OBJECT(widget), "changed", + G_CALLBACK(OnTypeChanged), (gpointer)0, NULL, G_CONNECT_AFTER); + + widget = gtk_builder_get_object(xml, "combotype2"); + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), + g.cfg.PadDef[1].Type == PSE_PAD_TYPE_ANALOGPAD ? 1 : 0); + g_signal_connect_data(GTK_OBJECT(widget), "changed", + G_CALLBACK(OnTypeChanged), (gpointer)1, NULL, G_CONNECT_AFTER); + + widget = gtk_builder_get_object(xml, "btnchange1"); + gtk_widget_set_sensitive(widget, FALSE); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + G_CALLBACK(OnChangeClicked), (gpointer)0, NULL, G_CONNECT_AFTER); + + widget = gtk_builder_get_object(xml, "btnreset1"); + gtk_widget_set_sensitive(widget, FALSE); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + G_CALLBACK(OnResetClicked), (gpointer)0, NULL, G_CONNECT_AFTER); + + widget = gtk_builder_get_object(xml, "btnchange2"); + gtk_widget_set_sensitive(widget, FALSE); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + G_CALLBACK(OnChangeClicked), (gpointer)1, NULL, G_CONNECT_AFTER); + + widget = gtk_builder_get_object(xml, "btnreset2"); + gtk_widget_set_sensitive(widget, FALSE); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + G_CALLBACK(OnResetClicked), (gpointer)1, NULL, G_CONNECT_AFTER); + + gtk_widget_show(MainWindow); + gtk_main(); + + return 0; +} + +void PADabout() { + const char *authors[]= {"Wei Mingzhi ", NULL}; + GtkWidget *widget; + + widget = gtk_about_dialog_new(); + gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(widget), "Gamepad/Keyboard Input"); + gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(widget), "1.1"); + gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(widget), authors); + gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(widget), "http://www.codeplex.com/pcsxr/"); + + gtk_dialog_run(GTK_DIALOG(widget)); + gtk_widget_destroy(widget); +} + +int main(int argc, char *argv[]) { +#ifdef ENABLE_NLS + setlocale(LC_ALL, ""); + bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + textdomain(GETTEXT_PACKAGE); +#endif + + gtk_set_locale(); + gtk_init(&argc, &argv); + + if (argc > 1 && !strcmp(argv[1], "-about")) { + PADabout(); + } else { + PADconfigure(); + } + + gtk_exit(0); + return 0; +} diff --git a/plugins/dfinput/pad.c b/plugins/dfinput/pad.c index c6089f12..302560e8 100644 --- a/plugins/dfinput/pad.c +++ b/plugins/dfinput/pad.c @@ -1,457 +1,457 @@ -/* - * Copyright (c) 2009, Wei Mingzhi . - * All Rights Reserved. - * - * 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, see . - */ - -#include "pad.h" - -static void (*gpuVisualVibration)(uint32_t, uint32_t) = NULL; - -char *PSEgetLibName(void) { - return _("Gamepad/Keyboard Input"); -} - -unsigned long CALLBACK PSEgetLibType(void) { - return PSE_LT_PAD; -} - -unsigned long CALLBACK PSEgetLibVersion(void) { - return (1 << 16) | (1 << 8); -} - -static void PADsetMode(const int pad, const int mode) { - g.PadState[pad].PadMode = mode; - g.PadState[pad].PadID = mode ? 0x73 : 0x41; - - g.PadState[pad].Vib0 = 0; - g.PadState[pad].Vib1 = 0; - g.PadState[pad].VibF[0] = 0; - g.PadState[pad].VibF[1] = 0; -} - -long PADinit(long flags) { - LoadPADConfig(); - - PADsetMode(0, 0); - PADsetMode(1, 0); - - gpuVisualVibration = NULL; - - return PSE_PAD_ERR_SUCCESS; -} - -long PADshutdown(void) { - PADclose(); - return PSE_PAD_ERR_SUCCESS; -} - -static pthread_t ThreadID; -static volatile uint8_t TerminateThread = 0; - -static void *JoyThread(void *param) { - while (!TerminateThread) { - CheckJoy(); - usleep(1000); - } - pthread_exit(0); - return NULL; -} - -long PADopen(unsigned long *Disp) { - g.Disp = (Display *)*Disp; - - if (!g.Opened) { - if (SDL_WasInit(SDL_INIT_EVERYTHING)) { - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) { - return PSE_PAD_ERR_FAILURE; - } - } else if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) == -1) { - return PSE_PAD_ERR_FAILURE; - } - - InitSDLJoy(); - InitKeyboard(); - - g.KeyLeftOver = 0; - - if (g.cfg.Threaded) { - TerminateThread = 0; - - if (pthread_create(&ThreadID, NULL, JoyThread, NULL) != 0) { - // thread creation failed, fallback to polling - g.cfg.Threaded = 0; - } - } - } - - g.Opened = 1; - - return PSE_PAD_ERR_SUCCESS; -} - -long PADclose(void) { - if (g.Opened) { - if (g.cfg.Threaded) { - TerminateThread = 1; - pthread_join(ThreadID, NULL); - } - - DestroySDLJoy(); - DestroyKeyboard(); - - if (SDL_WasInit(SDL_INIT_EVERYTHING & ~SDL_INIT_JOYSTICK)) { - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - } else { - SDL_Quit(); - } - } - - g.Opened = 0; - - return PSE_PAD_ERR_SUCCESS; -} - -long PADquery(void) { - return PSE_PAD_USE_PORT1 | PSE_PAD_USE_PORT2; -} - -static void UpdateInput(void) { - int pad; - if (!g.cfg.Threaded) CheckJoy(); - for(pad = 0; pad < 2; pad++) { - if(g.PadState[pad].PadModeSwitch) { - g.PadState[pad].PadModeSwitch = 0; - PADsetMode(pad, 1 - g.PadState[pad].PadMode); - } - } - CheckKeyboard(); -} - -static uint8_t stdpar[2][8] = { - {0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80}, - {0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80} -}; - -static uint8_t unk46[2][8] = { - {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A}, - {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A} -}; - -static uint8_t unk47[2][8] = { - {0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}, - {0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00} -}; - -static uint8_t unk4c[2][8] = { - {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} -}; - -static uint8_t unk4d[2][8] = { - {0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - {0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} -}; - -static uint8_t stdcfg[2][8] = { - {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} -}; - -static uint8_t stdmode[2][8] = { - {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} -}; - -static uint8_t stdmodel[2][8] = { - {0xFF, - 0x5A, - 0x01, // 03 - dualshock2, 01 - dualshock - 0x02, // number of modes - 0x01, // current mode: 01 - analog, 00 - digital - 0x02, - 0x01, - 0x00}, - {0xFF, - 0x5A, - 0x01, // 03 - dualshock2, 01 - dualshock - 0x02, // number of modes - 0x01, // current mode: 01 - analog, 00 - digital - 0x02, - 0x01, - 0x00} -}; - -static uint8_t CurPad = 0, CurByte = 0, CurCmd = 0, CmdLen = 0; - -unsigned char PADstartPoll(int pad) { - CurPad = pad - 1; - CurByte = 0; - - return 0xFF; -} - -unsigned char PADpoll(unsigned char value) { - static uint8_t *buf = NULL; - uint16_t n; - - if (CurByte == 0) { - CurByte++; - - // Don't enable Analog/Vibration for a standard pad - if (g.cfg.PadDef[CurPad].Type != PSE_PAD_TYPE_ANALOGPAD) { - CurCmd = CMD_READ_DATA_AND_VIBRATE; - } else { - CurCmd = value; - } - - switch (CurCmd) { - case CMD_CONFIG_MODE: - CmdLen = 8; - buf = stdcfg[CurPad]; - if (stdcfg[CurPad][3] == 0xFF) return 0xF3; - else return g.PadState[CurPad].PadID; - - case CMD_SET_MODE_AND_LOCK: - CmdLen = 8; - buf = stdmode[CurPad]; - return 0xF3; - - case CMD_QUERY_MODEL_AND_MODE: - CmdLen = 8; - buf = stdmodel[CurPad]; - buf[4] = g.PadState[CurPad].PadMode; - return 0xF3; - - case CMD_QUERY_ACT: - CmdLen = 8; - buf = unk46[CurPad]; - return 0xF3; - - case CMD_QUERY_COMB: - CmdLen = 8; - buf = unk47[CurPad]; - return 0xF3; - - case CMD_QUERY_MODE: - CmdLen = 8; - buf = unk4c[CurPad]; - return 0xF3; - - case CMD_VIBRATION_TOGGLE: - CmdLen = 8; - buf = unk4d[CurPad]; - return 0xF3; - - case CMD_READ_DATA_AND_VIBRATE: - default: - UpdateInput(); - - n = g.PadState[CurPad].KeyStatus; - n &= g.PadState[CurPad].JoyKeyStatus; - - stdpar[CurPad][2] = n & 0xFF; - stdpar[CurPad][3] = n >> 8; - - if (g.PadState[CurPad].PadMode == 1) { - CmdLen = 8; - - stdpar[CurPad][4] = g.PadState[CurPad].AnalogStatus[ANALOG_RIGHT][0]; - stdpar[CurPad][5] = g.PadState[CurPad].AnalogStatus[ANALOG_RIGHT][1]; - stdpar[CurPad][6] = g.PadState[CurPad].AnalogStatus[ANALOG_LEFT][0]; - stdpar[CurPad][7] = g.PadState[CurPad].AnalogStatus[ANALOG_LEFT][1]; - } else { - CmdLen = 4; - } - - buf = stdpar[CurPad]; - return g.PadState[CurPad].PadID; - } - } - - switch (CurCmd) { - case CMD_READ_DATA_AND_VIBRATE: - if (g.cfg.PadDef[CurPad].Type == PSE_PAD_TYPE_ANALOGPAD) { - if (CurByte == g.PadState[CurPad].Vib0) { - g.PadState[CurPad].VibF[0] = value; - - if (gpuVisualVibration != NULL && (g.PadState[CurPad].VibF[0] != 0 || g.PadState[CurPad].VibF[1] != 0)) { - gpuVisualVibration(g.PadState[CurPad].VibF[0], g.PadState[CurPad].VibF[1]); - } - } - - if (CurByte == g.PadState[CurPad].Vib1) { - g.PadState[CurPad].VibF[1] = value; - - if (gpuVisualVibration != NULL && (g.PadState[CurPad].VibF[0] != 0 || g.PadState[CurPad].VibF[1] != 0)) { - gpuVisualVibration(g.PadState[CurPad].VibF[0], g.PadState[CurPad].VibF[1]); - } - } - } - break; - - case CMD_CONFIG_MODE: - if (CurByte == 2) { - switch (value) { - case 0: - buf[2] = 0; - buf[3] = 0; - break; - - case 1: - buf[2] = 0xFF; - buf[3] = 0xFF; - break; - } - } - break; - - case CMD_SET_MODE_AND_LOCK: - if (CurByte == 2) { - PADsetMode(CurPad, value); - } - break; - - case CMD_QUERY_ACT: - if (CurByte == 2) { - switch (value) { - case 0: // default - buf[5] = 0x02; - buf[6] = 0x00; - buf[7] = 0x0A; - break; - - case 1: // Param std conf change - buf[5] = 0x01; - buf[6] = 0x01; - buf[7] = 0x14; - break; - } - } - break; - - case CMD_QUERY_MODE: - if (CurByte == 2) { - switch (value) { - case 0: // mode 0 - digital mode - buf[5] = PSE_PAD_TYPE_STANDARD; - break; - - case 1: // mode 1 - analog mode - buf[5] = PSE_PAD_TYPE_ANALOGPAD; - break; - } - } - break; - - case CMD_VIBRATION_TOGGLE: - if (CurByte >= 2 && CurByte < CmdLen) { - if (CurByte == g.PadState[CurPad].Vib0) { - buf[CurByte] = 0; - } - if (CurByte == g.PadState[CurPad].Vib1) { - buf[CurByte] = 1; - } - - if (value == 0) { - g.PadState[CurPad].Vib0 = CurByte; - if ((g.PadState[CurPad].PadID & 0x0f) < (CurByte - 1) / 2) { - g.PadState[CurPad].PadID = (g.PadState[CurPad].PadID & 0xf0) + (CurByte - 1) / 2; - } - } else if (value == 1) { - g.PadState[CurPad].Vib1 = CurByte; - if ((g.PadState[CurPad].PadID & 0x0f) < (CurByte - 1) / 2) { - g.PadState[CurPad].PadID = (g.PadState[CurPad].PadID & 0xf0) + (CurByte - 1) / 2; - } - } - } - break; - } - - if (CurByte >= CmdLen) return 0; - return buf[CurByte++]; -} - -static long PADreadPort(int num, PadDataS *pad) { - UpdateInput(); - - pad->buttonStatus = (g.PadState[num].KeyStatus & g.PadState[num].JoyKeyStatus); - - // ePSXe different from pcsx, swap bytes - pad->buttonStatus = (pad->buttonStatus >> 8) | (pad->buttonStatus << 8); - - switch (g.cfg.PadDef[num].Type) { - case PSE_PAD_TYPE_ANALOGPAD: // Analog Controller SCPH-1150 - pad->controllerType = PSE_PAD_TYPE_ANALOGPAD; - pad->rightJoyX = g.PadState[num].AnalogStatus[ANALOG_RIGHT][0]; - pad->rightJoyY = g.PadState[num].AnalogStatus[ANALOG_RIGHT][1]; - pad->leftJoyX = g.PadState[num].AnalogStatus[ANALOG_LEFT][0]; - pad->leftJoyY = g.PadState[num].AnalogStatus[ANALOG_LEFT][1]; - break; - - case PSE_PAD_TYPE_STANDARD: // Standard Pad SCPH-1080, SCPH-1150 - default: - pad->controllerType = PSE_PAD_TYPE_STANDARD; - break; - } - - return PSE_PAD_ERR_SUCCESS; -} - -long PADreadPort1(PadDataS *pad) { - return PADreadPort(0, pad); -} - -long PADreadPort2(PadDataS *pad) { - return PADreadPort(1, pad); -} - -long PADkeypressed(void) { - long s; - - CheckKeyboard(); - - s = g.KeyLeftOver; - g.KeyLeftOver = 0; - - return s; -} - -void PADregisterVibration(void (*callback)(uint32_t, uint32_t)) { - gpuVisualVibration = callback; -} - -#ifndef _MACOSX - -long PADconfigure(void) { - if (fork() == 0) { - execl("cfg/cfgDFInput", "cfgDFInput", NULL); - exit(0); - } - return PSE_PAD_ERR_SUCCESS; -} - -void PADabout(void) { - if (fork() == 0) { - execl("cfg/cfgDFInput", "cfgDFInput", "-about", NULL); - exit(0); - } -} - -#endif - -long PADtest(void) { - return PSE_PAD_ERR_SUCCESS; -} +/* + * Copyright (c) 2009, Wei Mingzhi . + * All Rights Reserved. + * + * 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, see . + */ + +#include "pad.h" + +static void (*gpuVisualVibration)(uint32_t, uint32_t) = NULL; + +char *PSEgetLibName(void) { + return _("Gamepad/Keyboard Input"); +} + +uint32_t PSEgetLibType(void) { + return PSE_LT_PAD; +} + +uint32_t PSEgetLibVersion(void) { + return (1 << 16) | (1 << 8); +} + +void PADsetMode(const int pad, const int mode) { + g.PadState[pad].PadMode = mode; + g.PadState[pad].PadID = mode ? 0x73 : 0x41; + + g.PadState[pad].Vib0 = 0; + g.PadState[pad].Vib1 = 0; + g.PadState[pad].VibF[0] = 0; + g.PadState[pad].VibF[1] = 0; +} + +long PADinit(long flags) { + LoadPADConfig(); + + PADsetMode(0, 0); + PADsetMode(1, 0); + + gpuVisualVibration = NULL; + + return PSE_PAD_ERR_SUCCESS; +} + +long PADshutdown(void) { + PADclose(); + return PSE_PAD_ERR_SUCCESS; +} + +static pthread_t ThreadID; +static volatile uint8_t TerminateThread = 0; + +static void *JoyThread(void *param) { + while (!TerminateThread) { + CheckJoy(); + usleep(1000); + } + pthread_exit(0); + return NULL; +} + +long PADopen(unsigned long *Disp) { + g.Disp = (Display *)*Disp; + + if (!g.Opened) { + if (SDL_WasInit(SDL_INIT_EVERYTHING)) { + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) { + return PSE_PAD_ERR_FAILURE; + } + } else if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) == -1) { + return PSE_PAD_ERR_FAILURE; + } + + InitSDLJoy(); + InitKeyboard(); + + g.KeyLeftOver = 0; + + if (g.cfg.Threaded) { + TerminateThread = 0; + + if (pthread_create(&ThreadID, NULL, JoyThread, NULL) != 0) { + // thread creation failed, fallback to polling + g.cfg.Threaded = 0; + } + } + } + + g.Opened = 1; + + return PSE_PAD_ERR_SUCCESS; +} + +long PADclose(void) { + if (g.Opened) { + if (g.cfg.Threaded) { + TerminateThread = 1; + pthread_join(ThreadID, NULL); + } + + DestroySDLJoy(); + DestroyKeyboard(); + + if (SDL_WasInit(SDL_INIT_EVERYTHING & ~SDL_INIT_JOYSTICK)) { + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + } else { + SDL_Quit(); + } + } + + g.Opened = 0; + + return PSE_PAD_ERR_SUCCESS; +} + +long PADquery(void) { + return PSE_PAD_USE_PORT1 | PSE_PAD_USE_PORT2; +} + +static void UpdateInput(void) { + int pad; + if (!g.cfg.Threaded) CheckJoy(); + for(pad = 0; pad < 2; pad++) { + if(g.PadState[pad].PadModeSwitch) { + g.PadState[pad].PadModeSwitch = 0; + PADsetMode(pad, 1 - g.PadState[pad].PadMode); + } + } + CheckKeyboard(); +} + +static uint8_t stdpar[2][8] = { + {0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80}, + {0xFF, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80} +}; + +static uint8_t unk46[2][8] = { + {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A}, + {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A} +}; + +static uint8_t unk47[2][8] = { + {0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}, + {0xFF, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00} +}; + +static uint8_t unk4c[2][8] = { + {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +}; + +static uint8_t unk4d[2][8] = { + {0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} +}; + +static uint8_t stdcfg[2][8] = { + {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +}; + +static uint8_t stdmode[2][8] = { + {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +}; + +static uint8_t stdmodel[2][8] = { + {0xFF, + 0x5A, + 0x01, // 03 - dualshock2, 01 - dualshock + 0x02, // number of modes + 0x01, // current mode: 01 - analog, 00 - digital + 0x02, + 0x01, + 0x00}, + {0xFF, + 0x5A, + 0x01, // 03 - dualshock2, 01 - dualshock + 0x02, // number of modes + 0x01, // current mode: 01 - analog, 00 - digital + 0x02, + 0x01, + 0x00} +}; + +static uint8_t CurPad = 0, CurByte = 0, CurCmd = 0, CmdLen = 0; + +unsigned char PADstartPoll(int pad) { + CurPad = pad - 1; + CurByte = 0; + + return 0xFF; +} + +unsigned char PADpoll(unsigned char value) { + static uint8_t *buf = NULL; + uint16_t n; + + if (CurByte == 0) { + CurByte++; + + // Don't enable Analog/Vibration for a standard pad + if (g.cfg.PadDef[CurPad].Type != PSE_PAD_TYPE_ANALOGPAD) { + CurCmd = CMD_READ_DATA_AND_VIBRATE; + } else { + CurCmd = value; + } + + switch (CurCmd) { + case CMD_CONFIG_MODE: + CmdLen = 8; + buf = stdcfg[CurPad]; + if (stdcfg[CurPad][3] == 0xFF) return 0xF3; + else return g.PadState[CurPad].PadID; + + case CMD_SET_MODE_AND_LOCK: + CmdLen = 8; + buf = stdmode[CurPad]; + return 0xF3; + + case CMD_QUERY_MODEL_AND_MODE: + CmdLen = 8; + buf = stdmodel[CurPad]; + buf[4] = g.PadState[CurPad].PadMode; + return 0xF3; + + case CMD_QUERY_ACT: + CmdLen = 8; + buf = unk46[CurPad]; + return 0xF3; + + case CMD_QUERY_COMB: + CmdLen = 8; + buf = unk47[CurPad]; + return 0xF3; + + case CMD_QUERY_MODE: + CmdLen = 8; + buf = unk4c[CurPad]; + return 0xF3; + + case CMD_VIBRATION_TOGGLE: + CmdLen = 8; + buf = unk4d[CurPad]; + return 0xF3; + + case CMD_READ_DATA_AND_VIBRATE: + default: + UpdateInput(); + + n = g.PadState[CurPad].KeyStatus; + n &= g.PadState[CurPad].JoyKeyStatus; + + stdpar[CurPad][2] = n & 0xFF; + stdpar[CurPad][3] = n >> 8; + + if (g.PadState[CurPad].PadMode == 1) { + CmdLen = 8; + + stdpar[CurPad][4] = g.PadState[CurPad].AnalogStatus[ANALOG_RIGHT][0]; + stdpar[CurPad][5] = g.PadState[CurPad].AnalogStatus[ANALOG_RIGHT][1]; + stdpar[CurPad][6] = g.PadState[CurPad].AnalogStatus[ANALOG_LEFT][0]; + stdpar[CurPad][7] = g.PadState[CurPad].AnalogStatus[ANALOG_LEFT][1]; + } else { + CmdLen = 4; + } + + buf = stdpar[CurPad]; + return g.PadState[CurPad].PadID; + } + } + + switch (CurCmd) { + case CMD_READ_DATA_AND_VIBRATE: + if (g.cfg.PadDef[CurPad].Type == PSE_PAD_TYPE_ANALOGPAD) { + if (CurByte == g.PadState[CurPad].Vib0) { + g.PadState[CurPad].VibF[0] = value; + + if (gpuVisualVibration != NULL && (g.PadState[CurPad].VibF[0] != 0 || g.PadState[CurPad].VibF[1] != 0)) { + gpuVisualVibration(g.PadState[CurPad].VibF[0], g.PadState[CurPad].VibF[1]); + } + } + + if (CurByte == g.PadState[CurPad].Vib1) { + g.PadState[CurPad].VibF[1] = value; + + if (gpuVisualVibration != NULL && (g.PadState[CurPad].VibF[0] != 0 || g.PadState[CurPad].VibF[1] != 0)) { + gpuVisualVibration(g.PadState[CurPad].VibF[0], g.PadState[CurPad].VibF[1]); + } + } + } + break; + + case CMD_CONFIG_MODE: + if (CurByte == 2) { + switch (value) { + case 0: + buf[2] = 0; + buf[3] = 0; + break; + + case 1: + buf[2] = 0xFF; + buf[3] = 0xFF; + break; + } + } + break; + + case CMD_SET_MODE_AND_LOCK: + if (CurByte == 2) { + PADsetMode(CurPad, value); + } + break; + + case CMD_QUERY_ACT: + if (CurByte == 2) { + switch (value) { + case 0: // default + buf[5] = 0x02; + buf[6] = 0x00; + buf[7] = 0x0A; + break; + + case 1: // Param std conf change + buf[5] = 0x01; + buf[6] = 0x01; + buf[7] = 0x14; + break; + } + } + break; + + case CMD_QUERY_MODE: + if (CurByte == 2) { + switch (value) { + case 0: // mode 0 - digital mode + buf[5] = PSE_PAD_TYPE_STANDARD; + break; + + case 1: // mode 1 - analog mode + buf[5] = PSE_PAD_TYPE_ANALOGPAD; + break; + } + } + break; + + case CMD_VIBRATION_TOGGLE: + if (CurByte >= 2 && CurByte < CmdLen) { + if (CurByte == g.PadState[CurPad].Vib0) { + buf[CurByte] = 0; + } + if (CurByte == g.PadState[CurPad].Vib1) { + buf[CurByte] = 1; + } + + if (value == 0) { + g.PadState[CurPad].Vib0 = CurByte; + if ((g.PadState[CurPad].PadID & 0x0f) < (CurByte - 1) / 2) { + g.PadState[CurPad].PadID = (g.PadState[CurPad].PadID & 0xf0) + (CurByte - 1) / 2; + } + } else if (value == 1) { + g.PadState[CurPad].Vib1 = CurByte; + if ((g.PadState[CurPad].PadID & 0x0f) < (CurByte - 1) / 2) { + g.PadState[CurPad].PadID = (g.PadState[CurPad].PadID & 0xf0) + (CurByte - 1) / 2; + } + } + } + break; + } + + if (CurByte >= CmdLen) return 0; + return buf[CurByte++]; +} + +static long PADreadPort(int num, PadDataS *pad) { + UpdateInput(); + + pad->buttonStatus = (g.PadState[num].KeyStatus & g.PadState[num].JoyKeyStatus); + + // ePSXe different from pcsx, swap bytes + pad->buttonStatus = (pad->buttonStatus >> 8) | (pad->buttonStatus << 8); + + switch (g.cfg.PadDef[num].Type) { + case PSE_PAD_TYPE_ANALOGPAD: // Analog Controller SCPH-1150 + pad->controllerType = PSE_PAD_TYPE_ANALOGPAD; + pad->rightJoyX = g.PadState[num].AnalogStatus[ANALOG_RIGHT][0]; + pad->rightJoyY = g.PadState[num].AnalogStatus[ANALOG_RIGHT][1]; + pad->leftJoyX = g.PadState[num].AnalogStatus[ANALOG_LEFT][0]; + pad->leftJoyY = g.PadState[num].AnalogStatus[ANALOG_LEFT][1]; + break; + + case PSE_PAD_TYPE_STANDARD: // Standard Pad SCPH-1080, SCPH-1150 + default: + pad->controllerType = PSE_PAD_TYPE_STANDARD; + break; + } + + return PSE_PAD_ERR_SUCCESS; +} + +long PADreadPort1(PadDataS *pad) { + return PADreadPort(0, pad); +} + +long PADreadPort2(PadDataS *pad) { + return PADreadPort(1, pad); +} + +long PADkeypressed(void) { + long s; + + CheckKeyboard(); + + s = g.KeyLeftOver; + g.KeyLeftOver = 0; + + return s; +} + +void PADregisterVibration(void (*callback)(uint32_t, uint32_t)) { + gpuVisualVibration = callback; +} + +#ifndef _MACOSX + +long PADconfigure(void) { + if (fork() == 0) { + execl("cfg/cfgDFInput", "cfgDFInput", NULL); + exit(0); + } + return PSE_PAD_ERR_SUCCESS; +} + +void PADabout(void) { + if (fork() == 0) { + execl("cfg/cfgDFInput", "cfgDFInput", "-about", NULL); + exit(0); + } +} + +#endif + +long PADtest(void) { + return PSE_PAD_ERR_SUCCESS; +} diff --git a/plugins/dfinput/pad.h b/plugins/dfinput/pad.h index ae30c391..7c1b0e64 100644 --- a/plugins/dfinput/pad.h +++ b/plugins/dfinput/pad.h @@ -1,172 +1,198 @@ -/* - * Copyright (c) 2009, Wei Mingzhi . - * All Rights Reserved. - * - * 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, see . - */ - -#ifndef PAD_H_ -#define PAD_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _MACOSX -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef _MACOSX -#include -typedef void *Display; -#define ThreadID ThreadID_MACOSX -#else -#include -#include -#include -#include -#endif - -#include "psemu_plugin_defs.h" - -enum { - DKEY_SELECT = 0, - DKEY_L3, - DKEY_R3, - DKEY_START, - DKEY_UP, - DKEY_RIGHT, - DKEY_DOWN, - DKEY_LEFT, - DKEY_L2, - DKEY_R2, - DKEY_L1, - DKEY_R1, - DKEY_TRIANGLE, - DKEY_CIRCLE, - DKEY_CROSS, - DKEY_SQUARE, - DKEY_ANALOG, - - DKEY_TOTAL -}; - -enum { - ANALOG_LEFT = 0, - ANALOG_RIGHT, - - ANALOG_TOTAL -}; - -enum { NONE = 0, AXIS, HAT, BUTTON }; - -typedef struct tagKeyDef { - uint8_t JoyEvType; - union { - int16_t d; - int16_t Axis; // positive=axis+, negative=axis-, abs(Axis)-1=axis index - uint16_t Hat; // 8-bit for hat number, 8-bit for direction - uint16_t Button; // button number - } J; - uint16_t Key; -} KEYDEF; - -enum { ANALOG_XP = 0, ANALOG_XM, ANALOG_YP, ANALOG_YM }; - -typedef struct tagPadDef { - int8_t DevNum; - uint16_t Type; - KEYDEF KeyDef[DKEY_TOTAL]; - KEYDEF AnalogDef[ANALOG_TOTAL][4]; -} PADDEF; - -typedef struct tagConfig { - uint8_t Threaded; - PADDEF PadDef[2]; -} CONFIG; - -typedef struct tagPadState { - SDL_Joystick *JoyDev; - uint8_t PadMode; - uint8_t PadID; - uint8_t PadModeKey; - volatile uint8_t PadModeSwitch; - volatile uint16_t KeyStatus; - volatile uint16_t JoyKeyStatus; - volatile uint8_t AnalogStatus[ANALOG_TOTAL][2]; // 0-255 where 127 is center position - volatile uint8_t AnalogKeyStatus[ANALOG_TOTAL][4]; - uint8_t Vib0, Vib1; - volatile uint8_t VibF[2]; -} PADSTATE; - -typedef struct tagGlobalData { - CONFIG cfg; - - uint8_t Opened; - Display *Disp; - - PADSTATE PadState[2]; - volatile long KeyLeftOver; -} GLOBALDATA; - -extern GLOBALDATA g; - -enum { - CMD_READ_DATA_AND_VIBRATE = 0x42, - CMD_CONFIG_MODE = 0x43, - CMD_SET_MODE_AND_LOCK = 0x44, - CMD_QUERY_MODEL_AND_MODE = 0x45, - CMD_QUERY_ACT = 0x46, // ?? - CMD_QUERY_COMB = 0x47, // ?? - CMD_QUERY_MODE = 0x4C, // QUERY_MODE ?? - CMD_VIBRATION_TOGGLE = 0x4D, -}; - -// cfg.c functions... -void LoadPADConfig(); -void SavePADConfig(); - -// sdljoy.c functions... -void InitSDLJoy(); -void DestroySDLJoy(); -void CheckJoy(); - -// xkb.c functions... -void InitKeyboard(); -void DestroyKeyboard(); -void CheckKeyboard(); - -// analog.c functions... -void InitAnalog(); -void CheckAnalog(); -int AnalogKeyPressed(uint16_t Key); -int AnalogKeyReleased(uint16_t Key); - -#include "psemu_plugin_defs.h" - -#ifdef __cplusplus -} -#endif - -#endif +/* + * Copyright (c) 2009, Wei Mingzhi . + * All Rights Reserved. + * + * 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, see . + */ + +#ifndef PAD_H_ +#define PAD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _MACOSX +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef _MACOSX +#include +typedef void *Display; +#define ThreadID ThreadID_MACOSX +#else +#include +#include +#include +#include +#endif + +#include "psemu_plugin_defs.h" + +#ifdef ENABLE_NLS +#include +#include +#define _(x) gettext(x) +#define N_(x) (x) +#else +#define _(x) (x) +#define N_(x) (x) +#endif + +enum { + DKEY_SELECT = 0, + DKEY_L3, + DKEY_R3, + DKEY_START, + DKEY_UP, + DKEY_RIGHT, + DKEY_DOWN, + DKEY_LEFT, + DKEY_L2, + DKEY_R2, + DKEY_L1, + DKEY_R1, + DKEY_TRIANGLE, + DKEY_CIRCLE, + DKEY_CROSS, + DKEY_SQUARE, + DKEY_ANALOG, + + DKEY_TOTAL +}; + +enum { + ANALOG_LEFT = 0, + ANALOG_RIGHT, + + ANALOG_TOTAL +}; + +enum { NONE = 0, AXIS, HAT, BUTTON }; + +typedef struct tagKeyDef { + uint8_t JoyEvType; + union { + int16_t d; + int16_t Axis; // positive=axis+, negative=axis-, abs(Axis)-1=axis index + uint16_t Hat; // 8-bit for hat number, 8-bit for direction + uint16_t Button; // button number + } J; + uint16_t Key; +} KEYDEF; + +enum { ANALOG_XP = 0, ANALOG_XM, ANALOG_YP, ANALOG_YM }; + +typedef struct tagPadDef { + int8_t DevNum; + uint16_t Type; + KEYDEF KeyDef[DKEY_TOTAL]; + KEYDEF AnalogDef[ANALOG_TOTAL][4]; +} PADDEF; + +typedef struct tagConfig { + uint8_t Threaded; + PADDEF PadDef[2]; +} CONFIG; + +typedef struct tagPadState { + SDL_Joystick *JoyDev; + uint8_t PadMode; + uint8_t PadID; + uint8_t PadModeKey; + volatile uint8_t PadModeSwitch; + volatile uint16_t KeyStatus; + volatile uint16_t JoyKeyStatus; + volatile uint8_t AnalogStatus[ANALOG_TOTAL][2]; // 0-255 where 127 is center position + volatile uint8_t AnalogKeyStatus[ANALOG_TOTAL][4]; + uint8_t Vib0, Vib1; + volatile uint8_t VibF[2]; +} PADSTATE; + +typedef struct tagGlobalData { + CONFIG cfg; + + uint8_t Opened; + Display *Disp; + + PADSTATE PadState[2]; + volatile long KeyLeftOver; +} GLOBALDATA; + +extern GLOBALDATA g; + +enum { + CMD_READ_DATA_AND_VIBRATE = 0x42, + CMD_CONFIG_MODE = 0x43, + CMD_SET_MODE_AND_LOCK = 0x44, + CMD_QUERY_MODEL_AND_MODE = 0x45, + CMD_QUERY_ACT = 0x46, // ?? + CMD_QUERY_COMB = 0x47, // ?? + CMD_QUERY_MODE = 0x4C, // QUERY_MODE ?? + CMD_VIBRATION_TOGGLE = 0x4D, +}; + +// cfg.c functions... +void LoadPADConfig(); +void SavePADConfig(); + +// sdljoy.c functions... +void InitSDLJoy(); +void DestroySDLJoy(); +void CheckJoy(); + +// xkb.c functions... +void InitKeyboard(); +void DestroyKeyboard(); +void CheckKeyboard(); + +// analog.c functions... +void InitAnalog(); +void CheckAnalog(); +int AnalogKeyPressed(uint16_t Key); +int AnalogKeyReleased(uint16_t Key); + +// pad.c functions... +char *PSEgetLibName(void); +uint32_t PSEgetLibType(void); +uint32_t PSEgetLibVersion(void); +long PADinit(long flags); +long PADshutdown(void); +long PADopen(unsigned long *Disp); +long PADclose(void); +long PADquery(void); +unsigned char PADstartPoll(int pad); +unsigned char PADpoll(unsigned char value); +long PADreadPort1(PadDataS *pad); +long PADreadPort2(PadDataS *pad); +long PADkeypressed(void); +long PADconfigure(void); +void PADabout(void); +long PADtest(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/dfnet/cfg.c b/plugins/dfnet/cfg.c index 69d25b12..12fc7d6d 100644 --- a/plugins/dfnet/cfg.c +++ b/plugins/dfnet/cfg.c @@ -1,40 +1,38 @@ -// -// DF Netplay Plugin -// -// Based on netSock 0.2 by linuzappz. -// The Plugin is free source code. -// - -#include -#include -#include - -#include "dfnet.h" - -#define CFG_FILENAME "dfnet.cfg" - -void SaveConf() { - FILE *f; - - f = fopen(CFG_FILENAME, "w"); - if (f == NULL) return; - if(fwrite(&conf, sizeof(conf), 1, f) != 1) - perror(CFG_FILENAME); - fclose(f); -} - -void LoadConf() { - FILE *f; - - f = fopen(CFG_FILENAME, "r"); - if (f == NULL) { - conf.PlayerNum = 1; - conf.PortNum = 33306; - strcpy(conf.ipAddress, "127.0.0.1"); - return; - } - - if(fread(&conf, sizeof(conf), 1, f) != 1) - perror(CFG_FILENAME); - fclose(f); -} +// +// DF Netplay Plugin +// +// Based on netSock 0.2 by linuzappz. +// The Plugin is free source code. +// + +#include +#include +#include + +#include "dfnet.h" + +#define CFG_FILENAME "dfnet.cfg" + +void SaveConf() { + FILE *f; + + f = fopen(CFG_FILENAME, "w"); + if (f == NULL) return; + fwrite(&conf, 1, sizeof(conf), f); + fclose(f); +} + +void LoadConf() { + FILE *f; + + f = fopen(CFG_FILENAME, "r"); + if (f == NULL) { + conf.PlayerNum = 1; + conf.PortNum = 33306; + strcpy(conf.ipAddress, "127.0.0.1"); + return; + } + + fread(&conf, 1, sizeof(conf), f); + fclose(f); +} diff --git a/plugins/dfnet/dfnet.c b/plugins/dfnet/dfnet.c index 22fbbe4e..0162f652 100644 --- a/plugins/dfnet/dfnet.c +++ b/plugins/dfnet/dfnet.c @@ -1,274 +1,274 @@ -// -// DF Netplay Plugin -// -// Based on netSock 0.2 by linuzappz. -// The Plugin is free source code. -// - -#include -#include -#include -#include -#include -#include -#include - -#include "dfnet.h" -#include "psemu_plugin_defs.h" - -const unsigned char version = 2; // NET library v2 -const unsigned char revision = 0; -const unsigned char build = 3; // increase that with each version - -static char *libraryName = N_("Socket Driver"); - -unsigned long CALLBACK PSEgetLibType() { - return PSE_LT_NET; -} - -char* CALLBACK PSEgetLibName() { - return _(libraryName); -} - -unsigned long CALLBACK PSEgetLibVersion() { - return version << 16 | revision << 8 | build; -} - -long CALLBACK NETinit() { - return sockInit(); -} - -int SEND(const void *buf, int Size, int Mode) { - int bytes; - int count = 0; - const char *pData = (const char *)buf; - - if (Mode & PSE_NET_NONBLOCKING) { // NONBLOCKING - int ret; - - FD_ZERO(&wset); - FD_SET(sock, &wset); - - ret = select(sock + 1, NULL, &wset, NULL, &tm); - if (ret == -1) return -1; - - if (FD_ISSET(sock, &wset)) { - return send(sock, pData, Size, 0); - } else { - return 0; - } - } else { // BLOCKING - while (Size > 0) { - bytes = send(sock, pData, Size, 0); - if (bytes < 0) return -1; - pData += bytes; Size -= bytes; - count += bytes; - } - } - - return count; -} - -int RECV(void *buf, int Size, int Mode) { - int bytes; - int count = 0; - char *pData = (char *)buf; - - if (Mode & PSE_NET_NONBLOCKING) { // NONBLOCKING - int ret; - - FD_ZERO(&rset); - FD_SET(sock, &rset); - - ret = select(sock, &rset, NULL, NULL, &tm); - - if (FD_ISSET(sock, &rset)) { - return recv(sock, pData, Size, 0); - } else { - return 0; - } - } else { // BLOCKING - while (Size > 0) { - bytes = recv(sock, pData, Size, 0); - if (bytes == -1) return -1; - pData+= bytes; Size-= bytes; - count+= bytes; - } - } - - return count; -} - -long CALLBACK NETopen(unsigned long *gpuDisp) { - int ret = sockOpen(); - - struct sockaddr_in address; - - if (ret == -1) return -1; - - if (conf.PlayerNum == 1) { - int listen_sock, reuse_addr = 1; - int ret; - - memset((char *)&address, 0, sizeof (address)); - - address.sin_family = AF_INET; - address.sin_port = htons(conf.PortNum); - address.sin_addr.s_addr = INADDR_ANY; - - listen_sock = socket(AF_INET, SOCK_STREAM, 0); - if (listen_sock == -1) - return -1; - - setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse_addr, sizeof(reuse_addr)); - - if (bind(listen_sock,(struct sockaddr *) &address, sizeof(address)) == -1) - return -1; - - if (listen(listen_sock, 1) != 0) - return -1; - - sock = -1; - - WaitCancel = 0; - sockCreateWaitDlg(); - - while (sock < 0) { - FD_ZERO(&rset); - FD_SET(listen_sock, &rset); - - ret = select(listen_sock + 1, &rset, NULL, NULL, &tm); - if (FD_ISSET(listen_sock, &rset)) { - sock = accept(listen_sock, NULL, NULL); - } - - if (WaitCancel) break; - sockDlgUpdate(); - } - close(listen_sock); - - sockDestroyWaitDlg(); - if (WaitCancel == 1) return -1; - } else { - memset((char *)&address, 0, sizeof(address)); - address.sin_family = AF_INET; - address.sin_port = htons(conf.PortNum); - address.sin_addr.s_addr = inet_addr(conf.ipAddress); - - sock = socket(AF_INET, SOCK_STREAM, 0); - - if (connect(sock, (struct sockaddr *)&address, sizeof(address))!=0) { - SysMessage(_("error connecting to %s: %s\n"), conf.ipAddress, strerror(errno)); - return -1; - } - } - - PadInit = 0; - PadCount = 0; - PadSize[0] = -1; - PadSize[1] = -1; - PadRecvSize = -1; - PadSendSize = -1; - Ping = sockPing(); - Ping = (sockPing() + Ping) / 2; - Ping = (sockPing() + Ping) / 2; - - if (conf.PlayerNum == 1) { - PadCountMax = (int)(((double)Ping / 1000.0) * 60.0); - if (PadCountMax <= 0) PadCountMax = 1; - SEND(&PadCountMax, 4, PSE_NET_BLOCKING); - } else { - RECV(&PadCountMax, 4, PSE_NET_BLOCKING); - } - - PadSendData = (char *)malloc(PadCountMax * 128); - if (PadSendData == NULL) { - SysMessage(_("Error allocating memory!\n")); return -1; - } - memset(PadSendData, 0xff, PadCountMax); - - return ret; -} - -long CALLBACK NETclose() { - close(sock); - - return 0; -} - -long CALLBACK NETshutdown() { - return sockShutdown(); -} - -void CALLBACK NETpause() { -/* unsigned char Code = 0x80; - - SEND(&Code, 1, PSE_NET_BLOCKING);*/ -} - -void CALLBACK NETresume() { -/* unsigned char Code = 0x80; - - SEND(&Code, 1, PSE_NET_BLOCKING);*/ -} - -long CALLBACK NETsendData(void *pData, int Size, int Mode) { - return SEND(pData, Size, Mode); -} - -long CALLBACK NETrecvData(void *pData, int Size, int Mode) { - return RECV(pData, Size, Mode); -} - -long CALLBACK NETsendPadData(void *pData, int Size) { - if (PadSendSize == -1) { - PadSendSize = Size; - - if (SEND(&PadSendSize, 1, PSE_NET_BLOCKING) == -1) - return -1; - - if (RECV(&PadRecvSize, 1, PSE_NET_BLOCKING) == -1) - return -1; - } - - memcpy(&PadSendData[PadCount], pData, Size); - if (SEND(pData, PadSendSize, PSE_NET_BLOCKING) == -1) - return -1; - - return 0; -} - -long CALLBACK NETrecvPadData(void *pData, int Pad) { - if (PadInit == 0) { - if (conf.PlayerNum == Pad) { - memset(pData, 0xff, PadSendSize); - } else { - memset(pData, 0xff, PadRecvSize); - } - } else { - if (conf.PlayerNum == Pad) { - memcpy(pData, &PadSendData[PadCount == 0 ? PadCountMax-1 : PadCount-1], PadSendSize); - } else { - if (RECV(pData, PadRecvSize, PSE_NET_BLOCKING) == -1) - return -1; - } - } - - if (Pad == 2) { - PadCount++; - if (PadCount == PadCountMax) { - PadCount = 0; - PadInit = 1; - } - } - - return 0; -} - -long CALLBACK NETqueryPlayer() { - return conf.PlayerNum; -} - -long CALLBACK NETtest() { - return 0; -} +// +// DF Netplay Plugin +// +// Based on netSock 0.2 by linuzappz. +// The Plugin is free source code. +// + +#include +#include +#include +#include +#include +#include +#include +extern int errno; + +#include "dfnet.h" + +const unsigned char version = 2; // NET library v2 +const unsigned char revision = 0; +const unsigned char build = 3; // increase that with each version + +static char *libraryName = N_("Socket Driver"); + +unsigned long CALLBACK PSEgetLibType() { + return PSE_LT_NET; +} + +char* CALLBACK PSEgetLibName() { + return _(libraryName); +} + +unsigned long CALLBACK PSEgetLibVersion() { + return version << 16 | revision << 8 | build; +} + +long CALLBACK NETinit() { + return sockInit(); +} + +int SEND(const void *buf, int Size, int Mode) { + int bytes; + int count = 0; + const char *pData = (const char *)buf; + + if (Mode & PSE_NET_NONBLOCKING) { // NONBLOCKING + int ret; + + FD_ZERO(&wset); + FD_SET(sock, &wset); + + ret = select(sock + 1, NULL, &wset, NULL, &tm); + if (ret == -1) return -1; + + if (FD_ISSET(sock, &wset)) { + return send(sock, pData, Size, 0); + } else { + return 0; + } + } else { // BLOCKING + while (Size > 0) { + bytes = send(sock, pData, Size, 0); + if (bytes < 0) return -1; + pData += bytes; Size -= bytes; + count += bytes; + } + } + + return count; +} + +int RECV(void *buf, int Size, int Mode) { + int bytes; + int count = 0; + char *pData = (char *)buf; + + if (Mode & PSE_NET_NONBLOCKING) { // NONBLOCKING + int ret; + + FD_ZERO(&rset); + FD_SET(sock, &rset); + + ret = select(sock, &rset, NULL, NULL, &tm); + + if (FD_ISSET(sock, &rset)) { + return recv(sock, pData, Size, 0); + } else { + return 0; + } + } else { // BLOCKING + while (Size > 0) { + bytes = recv(sock, pData, Size, 0); + if (bytes == -1) return -1; + pData+= bytes; Size-= bytes; + count+= bytes; + } + } + + return count; +} + +long CALLBACK NETopen(unsigned long *gpuDisp) { + int ret = sockOpen(); + + struct sockaddr_in address; + + if (ret == -1) return -1; + + if (conf.PlayerNum == 1) { + int listen_sock, reuse_addr = 1; + int ret; + + memset((char *)&address, 0, sizeof (address)); + + address.sin_family = AF_INET; + address.sin_port = htons(conf.PortNum); + address.sin_addr.s_addr = INADDR_ANY; + + listen_sock = socket(AF_INET, SOCK_STREAM, 0); + if (listen_sock == -1) + return -1; + + setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse_addr, sizeof(reuse_addr)); + + if (bind(listen_sock,(struct sockaddr *) &address, sizeof(address)) == -1) + return -1; + + if (listen(listen_sock, 1) != 0) + return -1; + + sock = -1; + + WaitCancel = 0; + sockCreateWaitDlg(); + + while (sock < 0) { + FD_ZERO(&rset); + FD_SET(listen_sock, &rset); + + ret = select(listen_sock + 1, &rset, NULL, NULL, &tm); + if (FD_ISSET(listen_sock, &rset)) { + sock = accept(listen_sock, NULL, NULL); + } + + if (WaitCancel) break; + sockDlgUpdate(); + } + close(listen_sock); + + sockDestroyWaitDlg(); + if (WaitCancel == 1) return -1; + } else { + memset((char *)&address, 0, sizeof(address)); + address.sin_family = AF_INET; + address.sin_port = htons(conf.PortNum); + address.sin_addr.s_addr = inet_addr(conf.ipAddress); + + sock = socket(AF_INET, SOCK_STREAM, 0); + + if (connect(sock, (struct sockaddr *)&address, sizeof(address))!=0) { + SysMessage(_("error connecting to %s: %s\n"), conf.ipAddress, strerror(errno)); + return -1; + } + } + + PadInit = 0; + PadCount = 0; + PadSize[0] = -1; + PadSize[1] = -1; + PadRecvSize = -1; + PadSendSize = -1; + Ping = sockPing(); + Ping = (sockPing() + Ping) / 2; + Ping = (sockPing() + Ping) / 2; + + if (conf.PlayerNum == 1) { + PadCountMax = (int)(((double)Ping / 1000.0) * 60.0); + if (PadCountMax <= 0) PadCountMax = 1; + SEND(&PadCountMax, 4, PSE_NET_BLOCKING); + } else { + RECV(&PadCountMax, 4, PSE_NET_BLOCKING); + } + + PadSendData = (char *)malloc(PadCountMax * 128); + if (PadSendData == NULL) { + SysMessage(_("Error allocating memory!\n")); return -1; + } + memset(PadSendData, 0xff, PadCountMax); + + return ret; +} + +long CALLBACK NETclose() { + close(sock); + + return 0; +} + +long CALLBACK NETshutdown() { + return sockShutdown(); +} + +void CALLBACK NETpause() { +/* unsigned char Code = 0x80; + + SEND(&Code, 1, PSE_NET_BLOCKING);*/ +} + +void CALLBACK NETresume() { +/* unsigned char Code = 0x80; + + SEND(&Code, 1, PSE_NET_BLOCKING);*/ +} + +long CALLBACK NETsendData(void *pData, int Size, int Mode) { + return SEND(pData, Size, Mode); +} + +long CALLBACK NETrecvData(void *pData, int Size, int Mode) { + return RECV(pData, Size, Mode); +} + +long CALLBACK NETsendPadData(void *pData, int Size) { + if (PadSendSize == -1) { + PadSendSize = Size; + + if (SEND(&PadSendSize, 1, PSE_NET_BLOCKING) == -1) + return -1; + + if (RECV(&PadRecvSize, 1, PSE_NET_BLOCKING) == -1) + return -1; + } + + memcpy(&PadSendData[PadCount], pData, Size); + if (SEND(pData, PadSendSize, PSE_NET_BLOCKING) == -1) + return -1; + + return 0; +} + +long CALLBACK NETrecvPadData(void *pData, int Pad) { + if (PadInit == 0) { + if (conf.PlayerNum == Pad) { + memset(pData, 0xff, PadSendSize); + } else { + memset(pData, 0xff, PadRecvSize); + } + } else { + if (conf.PlayerNum == Pad) { + memcpy(pData, &PadSendData[PadCount == 0 ? PadCountMax-1 : PadCount-1], PadSendSize); + } else { + if (RECV(pData, PadRecvSize, PSE_NET_BLOCKING) == -1) + return -1; + } + } + + if (Pad == 2) { + PadCount++; + if (PadCount == PadCountMax) { + PadCount = 0; + PadInit = 1; + } + } + + return 0; +} + +long CALLBACK NETqueryPlayer() { + return conf.PlayerNum; +} + +long CALLBACK NETtest() { + return 0; +} diff --git a/plugins/dfnet/dfnet.h b/plugins/dfnet/dfnet.h index 4d8ae149..d83cb3bb 100644 --- a/plugins/dfnet/dfnet.h +++ b/plugins/dfnet/dfnet.h @@ -1,66 +1,80 @@ -// -// DF Netplay Plugin -// -// Based on netSock 0.2 by linuzappz. -// The Plugin is free source code. -// - -#ifndef __DFNET_H__ -#define __DFNET_H__ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -struct timeval tm; - -long timeGetTime(); - -#include "psemu_plugin_defs.h" - -typedef struct { - int PlayerNum; - unsigned short PortNum; - char ipAddress[32]; -} NetConfig; - -NetConfig conf; - -void LoadConf(); -void SaveConf(); - -long sock; -char *PadSendData; -char *PadRecvData; -char PadSendSize; -char PadRecvSize; -char PadSize[2]; -int PadCount; -int PadCountMax; -int PadInit; -int Ping; -volatile int WaitCancel; -fd_set rset; -fd_set wset; - -long sockInit(); -long sockShutdown(); -long sockOpen(); -void sockCreateWaitDlg(); -void sockDlgUpdate(); -void sockDestroyWaitDlg(); -int sockPing(); - -int ShowPauseDlg(); -void SysMessage(const char *fmt, ...); - -int SEND(const void *pData, int Size, int Mode); -int RECV(void *pData, int Size, int Mode); - -#endif +// +// DF Netplay Plugin +// +// Based on netSock 0.2 by linuzappz. +// The Plugin is free source code. +// + +#ifndef __DFNET_H__ +#define __DFNET_H__ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#ifdef ENABLE_NLS +#include +#include +#define _(x) gettext(x) +#define N_(x) (x) +#else +#define _(x) (x) +#define N_(x) (x) +#endif + +typedef void* HWND; + +struct timeval tm; + +#define CALLBACK + +long timeGetTime(); + +#include "psemu_plugin_defs.h" + +typedef struct { + int PlayerNum; + unsigned short PortNum; + char ipAddress[32]; +} Config; + +Config conf; + +void LoadConf(); +void SaveConf(); + +long sock; +char *PadSendData; +char *PadRecvData; +char PadSendSize; +char PadRecvSize; +char PadSize[2]; +int PadCount; +int PadCountMax; +int PadInit; +int Ping; +volatile int WaitCancel; +fd_set rset; +fd_set wset; + +long sockInit(); +long sockShutdown(); +long sockOpen(); +void sockCreateWaitDlg(); +void sockDlgUpdate(); +void sockDestroyWaitDlg(); +int sockPing(); + +int ShowPauseDlg(); +void SysMessage(const char *fmt, ...); + +int SEND(const void *pData, int Size, int Mode); +int RECV(void *pData, int Size, int Mode); + +#endif diff --git a/plugins/dfnet/gui.c b/plugins/dfnet/gui.c index fed9d70b..6d2ec25e 100644 --- a/plugins/dfnet/gui.c +++ b/plugins/dfnet/gui.c @@ -1,234 +1,233 @@ -// -// DF Netplay Plugin -// -// Based on netSock 0.2 by linuzappz. -// The Plugin is free source code. -// - -#include -#include -#include - -#include -#include -#include - -#include "cfg.c" -#include "psemu_plugin_defs.h" - -static void cfgSysMessage(const char *fmt, ...) { - GtkWidget *MsgDlg; - va_list list; - char msg[512]; - - va_start(list, fmt); - vsprintf(msg, fmt, list); - va_end(list); - - if (msg[strlen(msg) - 1] == '\n') msg[strlen(msg) - 1] = 0; - - MsgDlg = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, - GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("NetPlay")); - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(MsgDlg), "%s", msg); - - gtk_dialog_run(GTK_DIALOG(MsgDlg)); - gtk_widget_destroy(MsgDlg); -} - -static void CFGconfigure() { - cfgSysMessage(_("Nothing to configure")); -} - -#ifdef __linux__ - -#include -#include - -#define MAXINTERFACES 16 - -static void sockGetIP(char *IPAddress) { - int fd, intrface; - struct ifreq buf[MAXINTERFACES]; - struct ifconf ifc; - struct sockaddr_in addr; - - strcpy(IPAddress, "127.0.0.1"); - - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) { - ifc.ifc_len = sizeof(buf); - ifc.ifc_buf = (caddr_t)buf; - if (!ioctl(fd, SIOCGIFCONF, (char *)&ifc)) { - intrface = ifc.ifc_len / sizeof(struct ifreq); - while (intrface-- > 0) { - if (!(ioctl(fd, SIOCGIFADDR, (char *)&buf[intrface]))) { - memcpy(&addr, &(buf[intrface].ifr_addr), sizeof(addr)); - strcpy(IPAddress, inet_ntoa(addr.sin_addr)); - break; - } - } - } - close(fd); - } -} - -#else - -void sockGetIP(char *IPAddress) { - struct hostent *host; - char str[256]; - - gethostname(str, 256); - host = gethostbyname(str); - - if (host != NULL) - strcpy(IPAddress, inet_ntoa(*((struct in_addr *)host->h_addr_list[0]))); - else strcpy(IPAddress, "127.0.0.1"); -} - -#endif - -static void OnCopyIP(GtkWidget *widget, gpointer user_data) { - char str[256]; - - sockGetIP(str); - gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), str, strlen(str)); - cfgSysMessage(_("IP %s"), str); -} - -static long CFGopen() { - GtkBuilder *builder; - GtkWidget *widget, *MainWindow; - char buf[256]; - - LoadConf(); - - builder = gtk_builder_new(); - - if (!gtk_builder_add_from_file(builder, DATADIR "dfnet.ui", NULL)) { - g_warning("We could not load the interface!"); - return 0; - } - - MainWindow = GTK_WIDGET(gtk_builder_get_object(builder, "dlgStart")); - gtk_window_set_title(GTK_WINDOW(MainWindow), _("NetPlay")); - - widget = GTK_WIDGET(gtk_builder_get_object(builder, "btnCopyIP")); - g_signal_connect_data(GTK_OBJECT(widget), "clicked", - G_CALLBACK(OnCopyIP), NULL, NULL, G_CONNECT_AFTER); - - widget = GTK_WIDGET(gtk_builder_get_object(builder, "tbServerIP")); - gtk_entry_set_text(GTK_ENTRY(widget), conf.ipAddress); - - widget = GTK_WIDGET(gtk_builder_get_object(builder, "tbPort")); - sprintf(buf, "%d", conf.PortNum); - gtk_entry_set_text(GTK_ENTRY(widget), buf); - - if (conf.PlayerNum == 1) { - widget = GTK_WIDGET(gtk_builder_get_object(builder, "rbServer")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE); - } else { - widget = GTK_WIDGET(gtk_builder_get_object(builder, "rbClient")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE); - } - - if (gtk_dialog_run(GTK_DIALOG(MainWindow)) == GTK_RESPONSE_OK) { - widget = GTK_WIDGET(gtk_builder_get_object(builder, "tbServerIP")); - strcpy(conf.ipAddress, gtk_entry_get_text(GTK_ENTRY(widget))); - - widget = GTK_WIDGET(gtk_builder_get_object(builder, "tbPort")); - conf.PortNum = atoi(gtk_entry_get_text(GTK_ENTRY(widget))); - - widget = GTK_WIDGET(gtk_builder_get_object(builder, "rbServer")); - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { - conf.PlayerNum = 1; - } else { - conf.PlayerNum = 2; - } - - SaveConf(); - gtk_widget_destroy(MainWindow); - return 1; - } - - gtk_widget_destroy(MainWindow); - - return 0; -} - -static void OnWaitDialog_Abort() { - kill(getppid(), SIGUSR2); -} - -static void CFGwait() { - GtkWidget *WaitDlg; - - WaitDlg = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, - GTK_BUTTONS_CANCEL, _("Waiting for connection...")); - - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(WaitDlg), - _("The Client should now Start a Connection, waiting...")); - - gtk_dialog_run(GTK_DIALOG(WaitDlg)); - gtk_widget_destroy(WaitDlg); - - OnWaitDialog_Abort(); -} - -static long CFGpause() { - return 0; -} - -static void CFGabout() { - const char *authors[]= {"linuzappz ", "Wei Mingzhi ", NULL}; - GtkWidget *widget; - - widget = gtk_about_dialog_new(); - gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(widget), "Socket NetPlay Driver"); - gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(widget), "0.21"); - gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(widget), authors); - gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(widget), "http://www.codeplex.com/pcsxr/"); - - gtk_dialog_run(GTK_DIALOG(widget)); - gtk_widget_destroy(widget); -} - -static long CFGmessage(char *args[], int num) { - char msg[512]; - - memset(msg, 0, sizeof(msg)); - while (num) { - strcat(msg, *args); strcat(msg, " "); - num--; args++; - } - cfgSysMessage(msg); - - return 0; -} - -int main(int argc, char *argv[]) { -#ifdef ENABLE_NLS - setlocale(LC_ALL, ""); - bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR); - bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); - textdomain(GETTEXT_PACKAGE); -#endif - - gtk_set_locale(); - gtk_init(&argc, &argv); - - if (!strcmp(argv[1], "configure")) { - CFGconfigure(); - } else if (!strcmp(argv[1], "open")) { - return CFGopen(); - } else if (!strcmp(argv[1], "wait")) { - CFGwait(); - } else if (!strcmp(argv[1], "pause")) { - return CFGpause(); - } else if (!strcmp(argv[1], "about")) { - CFGabout(); - } else if (!strcmp(argv[1], "message")) { - CFGmessage(&argv[2], argc - 2); - } - - return 0; -} +// +// DF Netplay Plugin +// +// Based on netSock 0.2 by linuzappz. +// The Plugin is free source code. +// + +#include +#include +#include + +#include +#include +#include + +#include "cfg.c" + +void cfgSysMessage(const char *fmt, ...) { + GtkWidget *MsgDlg; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg) - 1] == '\n') msg[strlen(msg) - 1] = 0; + + MsgDlg = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("NetPlay")); + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(MsgDlg), "%s", msg); + + gtk_dialog_run(GTK_DIALOG(MsgDlg)); + gtk_widget_destroy(MsgDlg); +} + +void CFGconfigure() { + cfgSysMessage(_("Nothing to configure")); +} + +#ifdef __linux__ + +#include +#include + +#define MAXINTERFACES 16 + +void sockGetIP(char *IPAddress) { + int fd, intrface; + struct ifreq buf[MAXINTERFACES]; + struct ifconf ifc; + struct sockaddr_in addr; + + strcpy(IPAddress, "127.0.0.1"); + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) { + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = (caddr_t)buf; + if (!ioctl(fd, SIOCGIFCONF, (char *)&ifc)) { + intrface = ifc.ifc_len / sizeof(struct ifreq); + while (intrface-- > 0) { + if (!(ioctl(fd, SIOCGIFADDR, (char *)&buf[intrface]))) { + memcpy(&addr, &(buf[intrface].ifr_addr), sizeof(addr)); + strcpy(IPAddress, inet_ntoa(addr.sin_addr)); + break; + } + } + } + close(fd); + } +} + +#else + +void sockGetIP(char *IPAddress) { + struct hostent *host; + char str[256]; + + gethostname(str, 256); + host = gethostbyname(str); + + if (host != NULL) + strcpy(IPAddress, inet_ntoa(*((struct in_addr *)host->h_addr_list[0]))); + else strcpy(IPAddress, "127.0.0.1"); +} + +#endif + +void OnCopyIP(GtkWidget *widget, gpointer user_data) { + char str[256]; + + sockGetIP(str); + gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), str, strlen(str)); + cfgSysMessage(_("IP %s"), str); +} + +long CFGopen() { + GtkBuilder *builder; + GtkWidget *widget, *MainWindow; + char buf[256]; + + LoadConf(); + + builder = gtk_builder_new(); + + if (!gtk_builder_add_from_file(builder, DATADIR "dfnet.ui", NULL)) { + g_warning("We could not load the interface!"); + return 0; + } + + MainWindow = gtk_builder_get_object(builder, "dlgStart"); + gtk_window_set_title(GTK_WINDOW(MainWindow), _("NetPlay")); + + widget = gtk_builder_get_object(builder, "btnCopyIP"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + G_CALLBACK(OnCopyIP), NULL, NULL, G_CONNECT_AFTER); + + widget = gtk_builder_get_object(builder, "tbServerIP"); + gtk_entry_set_text(GTK_ENTRY(widget), conf.ipAddress); + + widget = gtk_builder_get_object(builder, "tbPort"); + sprintf(buf, "%d", conf.PortNum); + gtk_entry_set_text(GTK_ENTRY(widget), buf); + + if (conf.PlayerNum == 1) { + widget = gtk_builder_get_object(builder, "rbServer"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE); + } else { + widget = gtk_builder_get_object(builder, "rbClient"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE); + } + + if (gtk_dialog_run(GTK_DIALOG(MainWindow)) == GTK_RESPONSE_OK) { + widget = gtk_builder_get_object(builder, "tbServerIP"); + strcpy(conf.ipAddress, gtk_entry_get_text(GTK_ENTRY(widget))); + + widget = gtk_builder_get_object(builder, "tbPort"); + conf.PortNum = atoi(gtk_entry_get_text(GTK_ENTRY(widget))); + + widget = gtk_builder_get_object(builder, "rbServer"); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { + conf.PlayerNum = 1; + } else { + conf.PlayerNum = 2; + } + + SaveConf(); + gtk_widget_destroy(MainWindow); + return 1; + } + + gtk_widget_destroy(MainWindow); + + return 0; +} + +void OnWaitDialog_Abort() { + kill(getppid(), SIGUSR2); +} + +void CFGwait() { + GtkWidget *WaitDlg; + + WaitDlg = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, + GTK_BUTTONS_CANCEL, _("Waiting for connection...")); + + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(WaitDlg), + _("The Client should now Start a Connection, waiting...")); + + gtk_dialog_run(GTK_DIALOG(WaitDlg)); + gtk_widget_destroy(WaitDlg); + + OnWaitDialog_Abort(); +} + +long CFGpause() { + return 0; +} + +void CFGabout() { + const char *authors[]= {"linuzappz ", "Wei Mingzhi ", NULL}; + GtkWidget *widget; + + widget = gtk_about_dialog_new(); + gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(widget), "Socket NetPlay Driver"); + gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(widget), "0.21"); + gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(widget), authors); + gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(widget), "http://www.codeplex.com/pcsxr/"); + + gtk_dialog_run(GTK_DIALOG(widget)); + gtk_widget_destroy(widget); +} + +long CFGmessage(char *args[], int num) { + char msg[512]; + + memset(msg, 0, sizeof(msg)); + while (num) { + strcat(msg, *args); strcat(msg, " "); + num--; args++; + } + cfgSysMessage(msg); + + return 0; +} + +int main(int argc, char *argv[]) { +#ifdef ENABLE_NLS + setlocale(LC_ALL, ""); + bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + textdomain(GETTEXT_PACKAGE); +#endif + + gtk_set_locale(); + gtk_init(&argc, &argv); + + if (!strcmp(argv[1], "configure")) { + CFGconfigure(); + } else if (!strcmp(argv[1], "open")) { + return CFGopen(); + } else if (!strcmp(argv[1], "wait")) { + CFGwait(); + } else if (!strcmp(argv[1], "pause")) { + return CFGpause(); + } else if (!strcmp(argv[1], "about")) { + CFGabout(); + } else if (!strcmp(argv[1], "message")) { + CFGmessage(&argv[2], argc - 2); + } + + return 0; +} diff --git a/plugins/dfnet/unix.c b/plugins/dfnet/unix.c index 6b082899..50c00269 100644 --- a/plugins/dfnet/unix.c +++ b/plugins/dfnet/unix.c @@ -1,126 +1,125 @@ -// -// DF Netplay Plugin -// -// Based on netSock 0.2 by linuzappz. -// The Plugin is free source code. -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dfnet.h" -#include "psemu_plugin_defs.h" - -static int ExecCfg(const char *arg, int f) { - char cfg[512]; - - strcpy(cfg, "cfg/cfgDFNet"); - strcat(cfg, " "); - strcat(cfg, arg); - - if (f) { - if (fork() == 0) { exit(system(cfg)); } - return 0; - } - - return system(cfg); -} - -void SysMessage(const char *fmt, ...) { - va_list list; - char msg[512]; - char cmd[512]; - - va_start(list, fmt); - vsprintf(msg, fmt, list); - va_end(list); - - sprintf(cmd, "message %s\n", msg); - ExecCfg(cmd, 1); -} - -long sockInit() { - conf.PlayerNum = 0; - tm.tv_sec = 0; - tm.tv_usec = 0; - - return 0; -} - -long sockShutdown() { - return 0; -} - -long sockOpen() { - if (ExecCfg("open", 0) == 0) return -1; - - LoadConf(); - - return 0; -} - -int sockPing() { - char data[32]; - struct timeval tv, tvn; - - memset(data, 0, sizeof(data)); - - gettimeofday(&tv, NULL); - SEND(data, 32, PSE_NET_BLOCKING); - RECV(data, 32, PSE_NET_BLOCKING); - gettimeofday(&tvn, NULL); - - return (tvn.tv_sec - tv.tv_sec) * 1000 + - (tvn.tv_usec - tv.tv_usec) / 1000; -} - -long CALLBACK NETconfigure() { - ExecCfg("configure", 1); - return 0; -} - -void CALLBACK NETabout() { - ExecCfg("about", 1); -} - -pid_t cfgpid = 0; - -static void OnWaitDlg_Abort(int num) { - WaitCancel = 1; - cfgpid = 0; -} - -void sockCreateWaitDlg() { - signal(SIGUSR2, OnWaitDlg_Abort); - if ((cfgpid = fork()) == 0) { - execl("cfg/cfgDFNet", "cfgDFNet", "wait", NULL); - exit(0); - } - usleep(100000); -} - -void sockDlgUpdate() { - usleep(100000); -} - -void sockDestroyWaitDlg() { - if (cfgpid > 0) { - kill(cfgpid, SIGKILL); - cfgpid = 0; - } -} - -long timeGetTime() { - struct timeval tv; - - gettimeofday(&tv, NULL); - return (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000; -} +// +// DF Netplay Plugin +// +// Based on netSock 0.2 by linuzappz. +// The Plugin is free source code. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +extern int errno; + +#include "dfnet.h" + +int ExecCfg(const char *arg, int f) { + char cfg[512]; + + strcpy(cfg, "cfg/cfgDFNet"); + strcat(cfg, " "); + strcat(cfg, arg); + + if (f) { + if (fork() == 0) { system(cfg); exit(0); } + return 0; + } + + return system(cfg); +} + +void SysMessage(const char *fmt, ...) { + va_list list; + char msg[512]; + char cmd[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + sprintf(cmd, "message %s\n", msg); + ExecCfg(cmd, 1); +} + +long sockInit() { + conf.PlayerNum = 0; + tm.tv_sec = 0; + tm.tv_usec = 0; + + return 0; +} + +long sockShutdown() { + return 0; +} + +long sockOpen() { + if (ExecCfg("open", 0) == 0) return -1; + + LoadConf(); + + return 0; +} + +int sockPing() { + char data[32]; + struct timeval tv, tvn; + + memset(data, 0, sizeof(data)); + + gettimeofday(&tv, NULL); + SEND(data, 32, PSE_NET_BLOCKING); + RECV(data, 32, PSE_NET_BLOCKING); + gettimeofday(&tvn, NULL); + + return (tvn.tv_sec - tv.tv_sec) * 1000 + + (tvn.tv_usec - tv.tv_usec) / 1000; +} + +void CALLBACK NETconfigure() { + ExecCfg("configure", 1); +} + +void CALLBACK NETabout() { + ExecCfg("about", 1); +} + +pid_t cfgpid = 0; + +void OnWaitDlg_Abort(int num) { + WaitCancel = 1; + cfgpid = 0; +} + +void sockCreateWaitDlg() { + signal(SIGUSR2, OnWaitDlg_Abort); + if ((cfgpid = fork()) == 0) { + execl("cfg/cfgDFNet", "cfgDFNet", "wait", NULL); + exit(0); + } + usleep(100000); +} + +void sockDlgUpdate() { + usleep(100000); +} + +void sockDestroyWaitDlg() { + if (cfgpid > 0) { + kill(cfgpid, SIGKILL); + cfgpid = 0; + } +} + +long timeGetTime() { + struct timeval tv; + + gettimeofday(&tv, NULL); + return (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000; +} diff --git a/plugins/dfsound/Makefile.am b/plugins/dfsound/Makefile.am index ca62b32e..e5e17917 100644 --- a/plugins/dfsound/Makefile.am +++ b/plugins/dfsound/Makefile.am @@ -1,51 +1,51 @@ -AM_CPPFLAGS = -I../../include -I../../libpcsxcore - -bindir = @libdir@/games/psemu/ -libdir = @libdir@/games/psemu/ - -lib_LTLIBRARIES = libDFSound.la - -libDFSound_la_SOURCES = spu.c cfg.c dma.c freeze.c registers.c - -libDFSound_la_CPPFLAGS = $(AM_CPPFLAGS) -libDFSound_la_LDFLAGS = -module -avoid-version -libDFSound_la_LIBADD = -lpthread -lm - -if SOUND_ALSA -libDFSound_la_SOURCES += alsa.c -libDFSound_la_CPPFLAGS += -DUSEALSA=1 -libDFSound_la_LIBADD += $(ALSA_LIBS) -endif - -if SOUND_OSS -libDFSound_la_SOURCES += oss.c -libDFSound_la_CPPFLAGS += -DUSEOSS=1 -endif - -if SOUND_PULSEAUDIO -libDFSound_la_SOURCES += pulseaudio.c -libDFSound_la_CPPFLAGS += -DUSEPULSEAUDIO=1 $(PULSEAUDIO_CFLAGS) -libDFSound_la_LIBADD += $(PULSEAUDIO_LIBS) -endif - -if SOUND_SDL -libDFSound_la_SOURCES += sdl.c -libDFSound_la_CPPFLAGS += -DUSESDL=1 $(SDL_CFLAGS) -libDFSound_la_LIBADD += $(SDL_LIBS) -endif - -if SOUND_NULL -libDFSound_la_SOURCES += nullsnd.c -libDFSound_la_CPPFLAGS += -DUSENULL=1 -endif - -bin_PROGRAMS = cfgDFSound -cfgDFSound_CPPFLAGS = -DLOCALE_DIR=\"${datadir}/locale/\" \ - -DDATADIR=\"${datadir}/psemu/\" \ - $(GTK2_CFLAGS) $(GLADE2_CFLAGS) $(AM_CPPFLAGS) -cfgDFSound_SOURCES = spucfg-0.1df/main.c -cfgDFSound_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) - -glade_DATA = spucfg-0.1df/dfsound.glade2 -gladedir = $(datadir)/psemu/ -EXTRA_DIST = $(glade_DATA) +AM_CPPFLAGS = -I../../include + +bindir = @libdir@/games/psemu/ +libdir = @libdir@/games/psemu/ + +lib_LTLIBRARIES = libDFSound.la + +libDFSound_la_SOURCES = spu.c cfg.c dma.c freeze.c registers.c + +libDFSound_la_CPPFLAGS = $(AM_CPPFLAGS) +libDFSound_la_LDFLAGS = -module -avoid-version +libDFSound_la_LIBADD = -lpthread -lm + +if SOUND_ALSA +libDFSound_la_SOURCES += alsa.c +libDFSound_la_CPPFLAGS += -DUSEALSA=1 +libDFSound_la_LIBADD += $(ALSA_LIBS) +endif + +if SOUND_OSS +libDFSound_la_SOURCES += oss.c +libDFSound_la_CPPFLAGS += -DUSEOSS=1 +endif + +if SOUND_PULSEAUDIO +libDFSound_la_SOURCES += pulseaudio.c +libDFSound_la_CPPFLAGS += -DUSEPULSEAUDIO=1 $(PULSEAUDIO_CFLAGS) +libDFSound_la_LIBADD += $(PULSEAUDIO_LIBS) +endif + +if SOUND_SDL +libDFSound_la_SOURCES += sdl.c +libDFSound_la_CPPFLAGS += -DUSESDL=1 $(SDL_CFLAGS) +libDFSound_la_LIBADD += $(SDL_LIBS) +endif + +if SOUND_NULL +libDFSound_la_SOURCES += nullsnd.c +libDFSound_la_CPPFLAGS += -DUSENULL=1 +endif + +bin_PROGRAMS = cfgDFSound +cfgDFSound_CPPFLAGS = -DLOCALE_DIR=\"${datadir}/locale/\" \ + -DDATADIR=\"${datadir}/psemu/\" \ + $(GTK2_CFLAGS) $(GLADE2_CFLAGS) $(AM_CPPFLAGS) +cfgDFSound_SOURCES = spucfg-0.1df/main.c +cfgDFSound_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) + +glade_DATA = spucfg-0.1df/dfsound.glade2 +gladedir = $(datadir)/psemu/ +EXTRA_DIST = $(glade_DATA) diff --git a/plugins/dfsound/adsr.c b/plugins/dfsound/adsr.c index d0f7808e..f75a5127 100644 --- a/plugins/dfsound/adsr.c +++ b/plugins/dfsound/adsr.c @@ -1,764 +1,763 @@ -/*************************************************************************** - adsr.c - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 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 "stdafx.h" -#include "adsr.h" - -#define _IN_ADSR - -// will be included from spu.c -#ifdef _IN_SPU - -//////////////////////////////////////////////////////////////////////// -// ADSR func -//////////////////////////////////////////////////////////////////////// - -/* -ADSR -- Dr. Hell (Xebra PS1 emu) -- Accurate (!) -- http://drhell.web.fc2.com - - -Envelope increase -0-47: (7 - (RATE & 3)) <<(11 - (RATE>> 2)) -48+: 7 - (RATE & 3) / (1 <<((RATE>> 2) - 11)) - -Envelope decrease -0-47: (-8 + (RATE & 3)) <<(11 - (RATE>> 2)) -48+: -8 + (RATE & 3) / (1 <<((RATE>> 2) - 11)) - - -Exponential increase -0000-5FFF = (rate + 0) -6000+ = (rate + 8) - -Exponential decrease -(molecules (decrease) * level)>> 15 - ------------------------------------ - -Fraction (release rate) -1<<((4*32>>2)-11) = 1<<21 - - -Increase -40 = (7-0)<<(11-10) = 7<<1 = 14 -41 = (7-1)<<(11-10) = 6<<1 = 12 -42 = (7-2)<<(11-10) = 5<<1 = 10 -43 = (7-3)<<(11-10) = 4<<1 = 8 - -44 = (7-0)<<(11-11) = 7<<0 = 7 -45 = (7-1)<<(11-11) = 6<<0 = 6 -46 = (7-2)<<(11-11) = 5<<0 = 5 -47 = (7-3)<<(11-11) = 4<<0 = 4 --- -48 = (7-0) / 1<<(12-11) = 7 / 2 -49 = (7-1) / 1<<(12-11) = 6 / 2 -50 = (7-2) / 1<<(12-11) = 5 / 2 -51 = (7-3) / 1<<(12-11) = 4 / 2 - -52 = (7-0) / 1<<(13-11) = 7 / 4 -56 = (7-0) / 1<<(14-11) = 7 / 8 -60 = (7-0) / 1<<(15-11) = 7 / 16 - - -Decrease -40 = (-8+0)<<(11-10) = -8<<1 = -16 -41 = (-8+1)<<(11-10) = -7<<1 = -14 -42 = (-8+2)<<(11-10) = -6<<1 = -12 -43 = (-8+3)<<(11-10) = -5<<1 = -10 - -44 = (-8+0)<<(11-11) = -8<<0 = -8 -45 = (-8+1)<<(11-11) = -7<<0 = -7 -46 = (-8+2)<<(11-11) = -6<<0 = -6 -47 = (-8+3)<<(11-11) = -5<<0 = -5 --- -48 = (-8+0) / 1<<(12-11) = -8 / 2 -49 = (-8+1) / 1<<(12-11) = -7 / 2 -50 = (-8+2) / 1<<(12-11) = -6 / 2 -51 = (-8+3) / 1<<(12-11) = -5 / 2 -*/ - - -static int RateTableAdd[128]; -static int RateTableAdd_f[128]; -static int RateTableSub[128]; -static int RateTableSub_f[128]; -static const int RateTable_denom = 1 << (( (4*32)>>2) - 11); - -void InitADSR(void) // INIT ADSR -{ - int lcv; - - memset(RateTableAdd,0,sizeof(int)*128); - memset(RateTableAdd_f,0,sizeof(int)*128); - memset(RateTableSub,0,sizeof(int)*128); - memset(RateTableSub_f,0,sizeof(int)*128); - - - // Optimize table - Dr. Hell ADSR math - for( lcv=0; lcv<48; lcv++ ) { - RateTableAdd[lcv] = (7 - (lcv&3)) << (11 - (lcv >> 2)); - RateTableSub[lcv] = (-8 + (lcv&3)) << (11 - (lcv >> 2)); - - RateTableAdd_f[lcv] = 0; - RateTableSub_f[lcv] = 0; - } - - for( lcv=48; lcv<128; lcv++ ) { - int denom; - - denom = 1 << ((lcv>>2) - 11); - - // whole - RateTableAdd[lcv] = (7 - (lcv&3)) / denom; - RateTableSub[lcv] = (-8 + (lcv&3)) / denom; - - // fraction - RateTableAdd_f[lcv] = (7 - (lcv&3)) % denom; - RateTableSub_f[lcv] = (-8 + (lcv&3)) % denom; - - RateTableAdd_f[lcv] *= RateTable_denom / denom; - RateTableSub_f[lcv] *= RateTable_denom / denom; - - // goofy compiler - mod - if( RateTableSub_f[lcv] > 0 ) RateTableSub_f[lcv] = -RateTableSub_f[lcv]; - } -} - -//////////////////////////////////////////////////////////////////////// - -INLINE void StartADSR(int ch) // MIX ADSR -{ - s_chan[ch].ADSRX.lVolume=1; // and init some adsr vars - s_chan[ch].ADSRX.State=0; - s_chan[ch].ADSRX.EnvelopeVol=0; - s_chan[ch].ADSRX.EnvelopeVol_f=0; -} - -//////////////////////////////////////////////////////////////////////// - -INLINE int MixADSR(int ch) // MIX ADSR -{ - int EnvelopeVol = s_chan[ch].ADSRX.EnvelopeVol; - int EnvelopeVol_f = s_chan[ch].ADSRX.EnvelopeVol_f; - - - // dead volume - voice on - if( s_chan[ch].iSilent == 2 ) { - if( s_chan[ch].bStop ) s_chan[ch].bOn = 0; - return 0; - } - - - if(s_chan[ch].bStop) // should be stopped: - { // do release - if(s_chan[ch].ADSRX.ReleaseModeExp) - EnvelopeVol += ( RateTableSub[ s_chan[ch].ADSRX.ReleaseRate * 4 ] * EnvelopeVol ) >> 15; - else - EnvelopeVol += RateTableSub[ s_chan[ch].ADSRX.ReleaseRate * 4 ]; - - EnvelopeVol_f += RateTableSub_f[ s_chan[ch].ADSRX.ReleaseRate * 4 ]; - if( EnvelopeVol_f < 0 ) { - EnvelopeVol_f += RateTable_denom; - EnvelopeVol--; - } - - if(EnvelopeVol<0) - { - EnvelopeVol=0; - EnvelopeVol_f=0; - // don't stop if this chan can still cause irqs - if(!(spuCtrl&0x40) || (s_chan[ch].pCurr > pSpuIrq && s_chan[ch].pLoop > pSpuIrq)) - s_chan[ch].bOn=0; - } - - - s_chan[ch].ADSRX.EnvelopeVol=EnvelopeVol; - s_chan[ch].ADSRX.EnvelopeVol_f=EnvelopeVol_f; - s_chan[ch].ADSRX.lVolume=EnvelopeVol>>5; - return EnvelopeVol>>5; - } - else // not stopped yet? - { - if(s_chan[ch].ADSRX.State==0) // -> attack - { - if(s_chan[ch].ADSRX.AttackModeExp) - { - if(EnvelopeVol>=0x6000) { - EnvelopeVol+=RateTableAdd[s_chan[ch].ADSRX.AttackRate + 8]; - EnvelopeVol_f += RateTableAdd_f[ s_chan[ch].ADSRX.AttackRate + 8]; - } - else { - EnvelopeVol+=RateTableAdd[ s_chan[ch].ADSRX.AttackRate + 0]; - EnvelopeVol_f += RateTableAdd_f[ s_chan[ch].ADSRX.AttackRate + 0]; - } - } - else { - EnvelopeVol+=RateTableAdd[ s_chan[ch].ADSRX.AttackRate + 0]; - EnvelopeVol_f += RateTableAdd_f[ s_chan[ch].ADSRX.AttackRate + 0]; - } - - if( EnvelopeVol_f >= RateTable_denom ) { - EnvelopeVol_f -= RateTable_denom; - EnvelopeVol++; - } - - if(EnvelopeVol>=0x8000) - { - EnvelopeVol=0x7FFF; - EnvelopeVol_f=RateTable_denom; - s_chan[ch].ADSRX.State=1; - } - - s_chan[ch].ADSRX.EnvelopeVol=EnvelopeVol; - s_chan[ch].ADSRX.EnvelopeVol_f=EnvelopeVol_f; - s_chan[ch].ADSRX.lVolume=EnvelopeVol>>5; - return EnvelopeVol>>5; - } - //--------------------------------------------------// - if(s_chan[ch].ADSRX.State==1) // -> decay - { - EnvelopeVol += ( RateTableSub[ s_chan[ch].ADSRX.DecayRate * 4 ] * EnvelopeVol ) >> 15; - - EnvelopeVol_f += RateTableSub_f[ s_chan[ch].ADSRX.DecayRate * 4 ]; - if( EnvelopeVol_f < 0 ) { - EnvelopeVol_f += RateTable_denom; - EnvelopeVol--; - } - - if(EnvelopeVol<0) { - EnvelopeVol=0; - EnvelopeVol_f=0; - } - - // FF7 cursor - use Neill's 4-bit accuracy - if( ((EnvelopeVol>>11)&0xf) <= s_chan[ch].ADSRX.SustainLevel) - { - s_chan[ch].ADSRX.State=2; - } - - - s_chan[ch].ADSRX.EnvelopeVol=EnvelopeVol; - s_chan[ch].ADSRX.EnvelopeVol_f=EnvelopeVol_f; - s_chan[ch].ADSRX.lVolume=EnvelopeVol>>5; - return EnvelopeVol>>5; - } - //--------------------------------------------------// - if(s_chan[ch].ADSRX.State==2) // -> sustain - { - if(s_chan[ch].ADSRX.SustainIncrease) - { - if(s_chan[ch].ADSRX.SustainModeExp) - { - if(EnvelopeVol>=0x6000) { - EnvelopeVol+=RateTableAdd[ s_chan[ch].ADSRX.SustainRate + 8]; - EnvelopeVol_f += RateTableAdd_f[ s_chan[ch].ADSRX.SustainRate + 8]; - } - else { - EnvelopeVol+=RateTableAdd[ s_chan[ch].ADSRX.SustainRate + 0]; - EnvelopeVol_f += RateTableAdd_f[ s_chan[ch].ADSRX.SustainRate + 0]; - } - } - else { - EnvelopeVol+=RateTableAdd[ s_chan[ch].ADSRX.SustainRate + 0]; - EnvelopeVol_f += RateTableAdd_f[ s_chan[ch].ADSRX.SustainRate + 0]; - } - - if( EnvelopeVol_f >= RateTable_denom ) { - EnvelopeVol_f -= RateTable_denom; - EnvelopeVol++; - } - - if(EnvelopeVol >= 0x8000) - { - EnvelopeVol=0x7FFF; - EnvelopeVol_f=RateTable_denom; - } - } - else - { - if(s_chan[ch].ADSRX.SustainModeExp) - EnvelopeVol += ( RateTableSub[ s_chan[ch].ADSRX.SustainRate ] * EnvelopeVol ) >> 15; - else - EnvelopeVol += RateTableSub[ s_chan[ch].ADSRX.SustainRate ]; - - EnvelopeVol_f += RateTableSub_f[ s_chan[ch].ADSRX.SustainRate ]; - if( EnvelopeVol_f < 0 ) { - EnvelopeVol_f += RateTable_denom; - EnvelopeVol--; - } - - - if(EnvelopeVol<0) { - EnvelopeVol=0; - EnvelopeVol_f=0; - } - } - - - s_chan[ch].ADSRX.EnvelopeVol=EnvelopeVol; - s_chan[ch].ADSRX.EnvelopeVol_f=EnvelopeVol_f; - s_chan[ch].ADSRX.lVolume=EnvelopeVol>>5; - return EnvelopeVol>>5; - } - } - return 0; -} - -#endif - -/* -James Higgs ADSR investigations: - -PSX SPU Envelope Timings -~~~~~~~~~~~~~~~~~~~~~~~~ - -First, here is an extract from doomed's SPU doc, which explains the basics -of the SPU "volume envelope": - -*** doomed doc extract start *** - --------------------------------------------------------------------------- -Voices. --------------------------------------------------------------------------- -The SPU has 24 hardware voices. These voices can be used to reproduce sample -data, noise or can be used as frequency modulator on the next voice. -Each voice has it's own programmable ADSR envelope filter. The main volume -can be programmed independently for left and right output. - -The ADSR envelope filter works as follows: -Ar = Attack rate, which specifies the speed at which the volume increases - from zero to it's maximum value, as soon as the note on is given. The - slope can be set to lineair or exponential. -Dr = Decay rate specifies the speed at which the volume decreases to the - sustain level. Decay is always decreasing exponentially. -Sl = Sustain level, base level from which sustain starts. -Sr = Sustain rate is the rate at which the volume of the sustained note - increases or decreases. This can be either lineair or exponential. -Rr = Release rate is the rate at which the volume of the note decreases - as soon as the note off is given. - - lvl | - ^ | /\Dr __ - Sl _| _ / _ \__--- \ - | / ---__ \ Rr - | /Ar Sr \ \ - | / \\ - |/___________________\________ - ->time - -The overal volume can also be set to sweep up or down lineairly or -exponentially from it's current value. This can be done seperately -for left and right. - -Relevant SPU registers: -------------------------------------------------------------- -$1f801xx8 Attack/Decay/Sustain level -bit |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00| -desc.|Am| Ar |Dr |Sl | - -Am 0 Attack mode Linear - 1 Exponential - -Ar 0-7f attack rate -Dr 0-f decay rate -Sl 0-f sustain level -------------------------------------------------------------- -$1f801xxa Sustain rate, Release Rate. -bit |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00| -desc.|Sm|Sd| 0| Sr |Rm|Rr | - -Sm 0 sustain rate mode linear - 1 exponential -Sd 0 sustain rate mode increase - 1 decrease -Sr 0-7f Sustain Rate -Rm 0 Linear decrease - 1 Exponential decrease -Rr 0-1f Release Rate - -Note: decay mode is always Expontial decrease, and thus cannot -be set. -------------------------------------------------------------- -$1f801xxc Current ADSR volume -bit |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00| -desc.|ADSRvol | - -ADSRvol Returns the current envelope volume when - read. --- James' Note: return range: 0 -> 32767 - -*** doomed doc extract end *** - -By using a small PSX proggie to visualise the envelope as it was played, -the following results for envelope timing were obtained: - -1. Attack rate value (linear mode) - - Attack value range: 0 -> 127 - - Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | | 80 | - ----------------------------------------------------------------- - Frames | 11 | 21 | 42 | 84 | 169| 338| 676| |2890| - - Note: frames is no. of PAL frames to reach full volume (100% - amplitude) - - Hmm, noticing that the time taken to reach full volume doubles - every time we add 4 to our attack value, we know the equation is - of form: - frames = k * 2 ^ (value / 4) - - (You may ponder about envelope generator hardware at this point, - or maybe not... :) - - By substituting some stuff and running some checks, we get: - - k = 0.00257 (close enuf) - - therefore, - frames = 0.00257 * 2 ^ (value / 4) - If you just happen to be writing an emulator, then you can probably - use an equation like: - - %volume_increase_per_tick = 1 / frames - - - ------------------------------------ - Pete: - ms=((1<<(value>>2))*514)/10000 - ------------------------------------ - -2. Decay rate value (only has log mode) - - Decay value range: 0 -> 15 - - Value | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | - ------------------------------------------------ - frames | | | | | 6 | 12 | 24 | 47 | - - Note: frames here is no. of PAL frames to decay to 50% volume. - - formula: frames = k * 2 ^ (value) - - Substituting, we get: k = 0.00146 - - Further info on logarithmic nature: - frames to decay to sustain level 3 = 3 * frames to decay to - sustain level 9 - - Also no. of frames to 25% volume = roughly 1.85 * no. of frames to - 50% volume. - - Frag it - just use linear approx. - - ------------------------------------ - Pete: - ms=((1< 127 - - Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | - ------------------------------------------- - frames | 9 | 19 | 37 | 74 | 147| 293| 587| - - Here, frames = no. of PAL frames for volume amplitude to go from 100% - to 0% (or vice-versa). - - Same formula as for attack value, just a different value for k: - - k = 0.00225 - - ie: frames = 0.00225 * 2 ^ (value / 4) - - For emulation purposes: - - %volume_increase_or_decrease_per_tick = 1 / frames - - ------------------------------------ - Pete: - ms=((1<<(value>>2))*450)/10000 - ------------------------------------ - - -4. Release rate (linear mode) - - Release rate range: 0 -> 31 - - Value | 13 | 14 | 15 | 16 | 17 | - --------------------------------------------------------------- - frames | 18 | 36 | 73 | 146| 292| - - Here, frames = no. of PAL frames to decay from 100% vol to 0% vol - after "note-off" is triggered. - - Formula: frames = k * 2 ^ (value) - - And so: k = 0.00223 - - ------------------------------------ - Pete: - ms=((1< release phase - { - if(s_chan[ch].ADSR.ReleaseVal!=0) // -> release not 0: do release (if 0: stop right now) - { - if(!s_chan[ch].ADSR.ReleaseVol) // --> release just started? set up the release stuff - { - s_chan[ch].ADSR.ReleaseStartTime=s_chan[ch].ADSR.lTime; - s_chan[ch].ADSR.ReleaseVol=s_chan[ch].ADSR.lVolume; - s_chan[ch].ADSR.ReleaseTime = // --> calc how long does it take to reach the wanted sus level - (s_chan[ch].ADSR.ReleaseTime* - s_chan[ch].ADSR.ReleaseVol)/1024; - } - // -> NO release exp mode used (yet) - v=s_chan[ch].ADSR.ReleaseVol; // -> get last volume - lT=s_chan[ch].ADSR.lTime- // -> how much time is past? - s_chan[ch].ADSR.ReleaseStartTime; - l1=s_chan[ch].ADSR.ReleaseTime; - - if(lT we still have to release - { - v=v-((v*lT)/l1); // --> calc new volume - } - else // -> release is over: now really stop that sample - {v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;} - } - else // -> release IS 0: release at once - { - v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0; - } - } - else - {//--------------------------------------------------// not in release phase: - v=1024; - lT=s_chan[ch].ADSR.lTime; - l1=s_chan[ch].ADSR.AttackTime; - - if(lT0) - { - if(l3!=0) v2+=((v-v2)*lT)/l3; - else v2=v; - } - else - { - if(l3!=0) v2-=(v2*lT)/l3; - else v2=v; - } - - if(v2>v) v2=v; - if(v2<=0) {v2=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;} - - v=v2; - } - } - } - - //----------------------------------------------------// - // ok, done for this channel, so increase time - - s_chan[ch].ADSR.lTime+=1; // 1 = 1.020408f ms; - - if(v>1024) v=1024; // adjust volume - if(v<0) v=0; - s_chan[ch].ADSR.lVolume=v; // store act volume - - return v; // return the volume factor -*/ - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -/* ------------------------------------------------------------------------------ -Neill Corlett -Playstation SPU envelope timing notes ------------------------------------------------------------------------------ - -This is preliminary. This may be wrong. But the model described herein fits -all of my experimental data, and it's just simple enough to sound right. - -ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally. -The value returned by channel reg 0xC is (envelope_level>>16). - -Each sample, an increment or decrement value will be added to or -subtracted from this envelope level. - -Create the rate log table. The values double every 4 entries. - entry #0 = 4 - - 4, 5, 6, 7, - 8,10,12,14, - 16,20,24,28, ... - - entry #40 = 4096... - entry #44 = 8192... - entry #48 = 16384... - entry #52 = 32768... - entry #56 = 65536... - -increments and decrements are in terms of ratelogtable[n] -n may exceed the table bounds (plan on n being between -32 and 127). -table values are all clipped between 0x00000000 and 0x3FFFFFFF - -when you "voice on", the envelope is always fully reset. -(yes, it may click. the real thing does this too.) - -envelope level begins at zero. - -each state happens for at least 1 cycle -(transitions are not instantaneous) -this may result in some oddness: if the decay rate is uberfast, it will cut -the envelope from full down to half in one sample, potentially skipping over -the sustain level - -ATTACK ------- -- if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and - proceed to DECAY. - -Linear attack mode: -- line extends upward to 0x7FFFFFFF -- increment per sample is ratelogtable[(Ar^0x7F)-0x10] - -Logarithmic attack mode: -if envelope_level < 0x60000000: - - line extends upward to 0x60000000 - - increment per sample is ratelogtable[(Ar^0x7F)-0x10] -else: - - line extends upward to 0x7FFFFFFF - - increment per sample is ratelogtable[(Ar^0x7F)-0x18] - -DECAY ------ -- if ((envelope_level>>27)&0xF) <= Sl, proceed to SUSTAIN. - Do not clip to the sustain level. -- current line ends at (envelope_level & 0x07FFFFFF) -- decrement per sample depends on (envelope_level>>28)&0x7 - 0: ratelogtable[(4*(Dr^0x1F))-0x18+0] - 1: ratelogtable[(4*(Dr^0x1F))-0x18+4] - 2: ratelogtable[(4*(Dr^0x1F))-0x18+6] - 3: ratelogtable[(4*(Dr^0x1F))-0x18+8] - 4: ratelogtable[(4*(Dr^0x1F))-0x18+9] - 5: ratelogtable[(4*(Dr^0x1F))-0x18+10] - 6: ratelogtable[(4*(Dr^0x1F))-0x18+11] - 7: ratelogtable[(4*(Dr^0x1F))-0x18+12] - (note that this is the same as the release rate formula, except that - decay rates 10-1F aren't possible... those would be slower in theory) - -SUSTAIN -------- -- no terminating condition except for voice off -- Sd=0 (increase) behavior is identical to ATTACK for both log and linear. -- Sd=1 (decrease) behavior: -Linear sustain decrease: -- line extends to 0x00000000 -- decrement per sample is ratelogtable[(Sr^0x7F)-0x0F] -Logarithmic sustain decrease: -- current line ends at (envelope_level & 0x07FFFFFF) -- decrement per sample depends on (envelope_level>>28)&0x7 - 0: ratelogtable[(Sr^0x7F)-0x1B+0] - 1: ratelogtable[(Sr^0x7F)-0x1B+4] - 2: ratelogtable[(Sr^0x7F)-0x1B+6] - 3: ratelogtable[(Sr^0x7F)-0x1B+8] - 4: ratelogtable[(Sr^0x7F)-0x1B+9] - 5: ratelogtable[(Sr^0x7F)-0x1B+10] - 6: ratelogtable[(Sr^0x7F)-0x1B+11] - 7: ratelogtable[(Sr^0x7F)-0x1B+12] - -RELEASE -------- -- if the envelope level has overflowed to negative, clip to 0 and QUIT. - -Linear release mode: -- line extends to 0x00000000 -- decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C] - -Logarithmic release mode: -- line extends to (envelope_level & 0x0FFFFFFF) -- decrement per sample depends on (envelope_level>>28)&0x7 - 0: ratelogtable[(4*(Rr^0x1F))-0x18+0] - 1: ratelogtable[(4*(Rr^0x1F))-0x18+4] - 2: ratelogtable[(4*(Rr^0x1F))-0x18+6] - 3: ratelogtable[(4*(Rr^0x1F))-0x18+8] - 4: ratelogtable[(4*(Rr^0x1F))-0x18+9] - 5: ratelogtable[(4*(Rr^0x1F))-0x18+10] - 6: ratelogtable[(4*(Rr^0x1F))-0x18+11] - 7: ratelogtable[(4*(Rr^0x1F))-0x18+12] - ------------------------------------------------------------------------------ -*/ - +/*************************************************************************** + adsr.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 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 "stdafx.h" + +#define _IN_ADSR + +// will be included from spu.c +#ifdef _IN_SPU + +//////////////////////////////////////////////////////////////////////// +// ADSR func +//////////////////////////////////////////////////////////////////////// + +/* +ADSR +- Dr. Hell (Xebra PS1 emu) +- Accurate (!) +- http://drhell.web.fc2.com + + +Envelope increase +0-47: (7 - (RATE & 3)) <<(11 - (RATE>> 2)) +48+: 7 - (RATE & 3) / (1 <<((RATE>> 2) - 11)) + +Envelope decrease +0-47: (-8 + (RATE & 3)) <<(11 - (RATE>> 2)) +48+: -8 + (RATE & 3) / (1 <<((RATE>> 2) - 11)) + + +Exponential increase +0000-5FFF = (rate + 0) +6000+ = (rate + 8) + +Exponential decrease +(molecules (decrease) * level)>> 15 + +----------------------------------- + +Fraction (release rate) +1<<((4*32>>2)-11) = 1<<21 + + +Increase +40 = (7-0)<<(11-10) = 7<<1 = 14 +41 = (7-1)<<(11-10) = 6<<1 = 12 +42 = (7-2)<<(11-10) = 5<<1 = 10 +43 = (7-3)<<(11-10) = 4<<1 = 8 + +44 = (7-0)<<(11-11) = 7<<0 = 7 +45 = (7-1)<<(11-11) = 6<<0 = 6 +46 = (7-2)<<(11-11) = 5<<0 = 5 +47 = (7-3)<<(11-11) = 4<<0 = 4 +-- +48 = (7-0) / 1<<(12-11) = 7 / 2 +49 = (7-1) / 1<<(12-11) = 6 / 2 +50 = (7-2) / 1<<(12-11) = 5 / 2 +51 = (7-3) / 1<<(12-11) = 4 / 2 + +52 = (7-0) / 1<<(13-11) = 7 / 4 +56 = (7-0) / 1<<(14-11) = 7 / 8 +60 = (7-0) / 1<<(15-11) = 7 / 16 + + +Decrease +40 = (-8+0)<<(11-10) = -8<<1 = -16 +41 = (-8+1)<<(11-10) = -7<<1 = -14 +42 = (-8+2)<<(11-10) = -6<<1 = -12 +43 = (-8+3)<<(11-10) = -5<<1 = -10 + +44 = (-8+0)<<(11-11) = -8<<0 = -8 +45 = (-8+1)<<(11-11) = -7<<0 = -7 +46 = (-8+2)<<(11-11) = -6<<0 = -6 +47 = (-8+3)<<(11-11) = -5<<0 = -5 +-- +48 = (-8+0) / 1<<(12-11) = -8 / 2 +49 = (-8+1) / 1<<(12-11) = -7 / 2 +50 = (-8+2) / 1<<(12-11) = -6 / 2 +51 = (-8+3) / 1<<(12-11) = -5 / 2 +*/ + + +static int RateTableAdd[128]; +static int RateTableAdd_f[128]; +static int RateTableSub[128]; +static int RateTableSub_f[128]; +static const int RateTable_denom = 1 << (( (4*32)>>2) - 11); + +void InitADSR(void) // INIT ADSR +{ + int lcv; + + memset(RateTableAdd,0,sizeof(int)*128); + memset(RateTableAdd_f,0,sizeof(int)*128); + memset(RateTableSub,0,sizeof(int)*128); + memset(RateTableSub_f,0,sizeof(int)*128); + + + // Optimize table - Dr. Hell ADSR math + for( lcv=0; lcv<48; lcv++ ) { + RateTableAdd[lcv] = (7 - (lcv&3)) << (11 - (lcv >> 2)); + RateTableSub[lcv] = (-8 + (lcv&3)) << (11 - (lcv >> 2)); + + RateTableAdd_f[lcv] = 0; + RateTableSub_f[lcv] = 0; + } + + for( lcv=48; lcv<128; lcv++ ) { + int denom; + + denom = 1 << ((lcv>>2) - 11); + + // whole + RateTableAdd[lcv] = (7 - (lcv&3)) / denom; + RateTableSub[lcv] = (-8 + (lcv&3)) / denom; + + // fraction + RateTableAdd_f[lcv] = (7 - (lcv&3)) % denom; + RateTableSub_f[lcv] = (-8 + (lcv&3)) % denom; + + RateTableAdd_f[lcv] *= RateTable_denom / denom; + RateTableSub_f[lcv] *= RateTable_denom / denom; + + // goofy compiler - mod + if( RateTableSub_f[lcv] > 0 ) RateTableSub_f[lcv] = -RateTableSub_f[lcv]; + } +} + +//////////////////////////////////////////////////////////////////////// + +INLINE void StartADSR(int ch) // MIX ADSR +{ + s_chan[ch].ADSRX.lVolume=1; // and init some adsr vars + s_chan[ch].ADSRX.State=0; + s_chan[ch].ADSRX.EnvelopeVol=0; + s_chan[ch].ADSRX.EnvelopeVol_f=0; +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int MixADSR(int ch) // MIX ADSR +{ + int EnvelopeVol = s_chan[ch].ADSRX.EnvelopeVol; + int EnvelopeVol_f = s_chan[ch].ADSRX.EnvelopeVol_f; + + + // dead volume - voice on + if( s_chan[ch].iSilent == 2 ) { + if( s_chan[ch].bStop ) s_chan[ch].bOn = 0; + return 0; + } + + + if(s_chan[ch].bStop) // should be stopped: + { // do release + if(s_chan[ch].ADSRX.ReleaseModeExp) + EnvelopeVol += ( RateTableSub[ s_chan[ch].ADSRX.ReleaseRate * 4 ] * EnvelopeVol ) >> 15; + else + EnvelopeVol += RateTableSub[ s_chan[ch].ADSRX.ReleaseRate * 4 ]; + + EnvelopeVol_f += RateTableSub_f[ s_chan[ch].ADSRX.ReleaseRate * 4 ]; + if( EnvelopeVol_f < 0 ) { + EnvelopeVol_f += RateTable_denom; + EnvelopeVol--; + } + + if(EnvelopeVol<0) + { + EnvelopeVol=0; + EnvelopeVol_f=0; + // don't stop if this chan can still cause irqs + if(!(spuCtrl&0x40) || (s_chan[ch].pCurr > pSpuIrq && s_chan[ch].pLoop > pSpuIrq)) + s_chan[ch].bOn=0; + } + + + s_chan[ch].ADSRX.EnvelopeVol=EnvelopeVol; + s_chan[ch].ADSRX.EnvelopeVol_f=EnvelopeVol_f; + s_chan[ch].ADSRX.lVolume=EnvelopeVol>>5; + return EnvelopeVol>>5; + } + else // not stopped yet? + { + if(s_chan[ch].ADSRX.State==0) // -> attack + { + if(s_chan[ch].ADSRX.AttackModeExp) + { + if(EnvelopeVol>=0x6000) { + EnvelopeVol+=RateTableAdd[s_chan[ch].ADSRX.AttackRate + 8]; + EnvelopeVol_f += RateTableAdd_f[ s_chan[ch].ADSRX.AttackRate + 8]; + } + else { + EnvelopeVol+=RateTableAdd[ s_chan[ch].ADSRX.AttackRate + 0]; + EnvelopeVol_f += RateTableAdd_f[ s_chan[ch].ADSRX.AttackRate + 0]; + } + } + else { + EnvelopeVol+=RateTableAdd[ s_chan[ch].ADSRX.AttackRate + 0]; + EnvelopeVol_f += RateTableAdd_f[ s_chan[ch].ADSRX.AttackRate + 0]; + } + + if( EnvelopeVol_f >= RateTable_denom ) { + EnvelopeVol_f -= RateTable_denom; + EnvelopeVol++; + } + + if(EnvelopeVol>=0x8000) + { + EnvelopeVol=0x7FFF; + EnvelopeVol_f=RateTable_denom; + s_chan[ch].ADSRX.State=1; + } + + s_chan[ch].ADSRX.EnvelopeVol=EnvelopeVol; + s_chan[ch].ADSRX.EnvelopeVol_f=EnvelopeVol_f; + s_chan[ch].ADSRX.lVolume=EnvelopeVol>>5; + return EnvelopeVol>>5; + } + //--------------------------------------------------// + if(s_chan[ch].ADSRX.State==1) // -> decay + { + EnvelopeVol += ( RateTableSub[ s_chan[ch].ADSRX.DecayRate * 4 ] * EnvelopeVol ) >> 15; + + EnvelopeVol_f += RateTableSub_f[ s_chan[ch].ADSRX.DecayRate * 4 ]; + if( EnvelopeVol_f < 0 ) { + EnvelopeVol_f += RateTable_denom; + EnvelopeVol--; + } + + if(EnvelopeVol<0) { + EnvelopeVol=0; + EnvelopeVol_f=0; + } + + // FF7 cursor - use Neill's 4-bit accuracy + if( ((EnvelopeVol>>11)&0xf) <= s_chan[ch].ADSRX.SustainLevel) + { + s_chan[ch].ADSRX.State=2; + } + + + s_chan[ch].ADSRX.EnvelopeVol=EnvelopeVol; + s_chan[ch].ADSRX.EnvelopeVol_f=EnvelopeVol_f; + s_chan[ch].ADSRX.lVolume=EnvelopeVol>>5; + return EnvelopeVol>>5; + } + //--------------------------------------------------// + if(s_chan[ch].ADSRX.State==2) // -> sustain + { + if(s_chan[ch].ADSRX.SustainIncrease) + { + if(s_chan[ch].ADSRX.SustainModeExp) + { + if(EnvelopeVol>=0x6000) { + EnvelopeVol+=RateTableAdd[ s_chan[ch].ADSRX.SustainRate + 8]; + EnvelopeVol_f += RateTableAdd_f[ s_chan[ch].ADSRX.SustainRate + 8]; + } + else { + EnvelopeVol+=RateTableAdd[ s_chan[ch].ADSRX.SustainRate + 0]; + EnvelopeVol_f += RateTableAdd_f[ s_chan[ch].ADSRX.SustainRate + 0]; + } + } + else { + EnvelopeVol+=RateTableAdd[ s_chan[ch].ADSRX.SustainRate + 0]; + EnvelopeVol_f += RateTableAdd_f[ s_chan[ch].ADSRX.SustainRate + 0]; + } + + if( EnvelopeVol_f >= RateTable_denom ) { + EnvelopeVol_f -= RateTable_denom; + EnvelopeVol++; + } + + if(EnvelopeVol >= 0x8000) + { + EnvelopeVol=0x7FFF; + EnvelopeVol_f=RateTable_denom; + } + } + else + { + if(s_chan[ch].ADSRX.SustainModeExp) + EnvelopeVol += ( RateTableSub[ s_chan[ch].ADSRX.SustainRate ] * EnvelopeVol ) >> 15; + else + EnvelopeVol += RateTableSub[ s_chan[ch].ADSRX.SustainRate ]; + + EnvelopeVol_f += RateTableSub_f[ s_chan[ch].ADSRX.SustainRate ]; + if( EnvelopeVol_f < 0 ) { + EnvelopeVol_f += RateTable_denom; + EnvelopeVol--; + } + + + if(EnvelopeVol<0) { + EnvelopeVol=0; + EnvelopeVol_f=0; + } + } + + + s_chan[ch].ADSRX.EnvelopeVol=EnvelopeVol; + s_chan[ch].ADSRX.EnvelopeVol_f=EnvelopeVol_f; + s_chan[ch].ADSRX.lVolume=EnvelopeVol>>5; + return EnvelopeVol>>5; + } + } + return 0; +} + +#endif + +/* +James Higgs ADSR investigations: + +PSX SPU Envelope Timings +~~~~~~~~~~~~~~~~~~~~~~~~ + +First, here is an extract from doomed's SPU doc, which explains the basics +of the SPU "volume envelope": + +*** doomed doc extract start *** + +-------------------------------------------------------------------------- +Voices. +-------------------------------------------------------------------------- +The SPU has 24 hardware voices. These voices can be used to reproduce sample +data, noise or can be used as frequency modulator on the next voice. +Each voice has it's own programmable ADSR envelope filter. The main volume +can be programmed independently for left and right output. + +The ADSR envelope filter works as follows: +Ar = Attack rate, which specifies the speed at which the volume increases + from zero to it's maximum value, as soon as the note on is given. The + slope can be set to lineair or exponential. +Dr = Decay rate specifies the speed at which the volume decreases to the + sustain level. Decay is always decreasing exponentially. +Sl = Sustain level, base level from which sustain starts. +Sr = Sustain rate is the rate at which the volume of the sustained note + increases or decreases. This can be either lineair or exponential. +Rr = Release rate is the rate at which the volume of the note decreases + as soon as the note off is given. + + lvl | + ^ | /\Dr __ + Sl _| _ / _ \__--- \ + | / ---__ \ Rr + | /Ar Sr \ \ + | / \\ + |/___________________\________ + ->time + +The overal volume can also be set to sweep up or down lineairly or +exponentially from it's current value. This can be done seperately +for left and right. + +Relevant SPU registers: +------------------------------------------------------------- +$1f801xx8 Attack/Decay/Sustain level +bit |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00| +desc.|Am| Ar |Dr |Sl | + +Am 0 Attack mode Linear + 1 Exponential + +Ar 0-7f attack rate +Dr 0-f decay rate +Sl 0-f sustain level +------------------------------------------------------------- +$1f801xxa Sustain rate, Release Rate. +bit |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00| +desc.|Sm|Sd| 0| Sr |Rm|Rr | + +Sm 0 sustain rate mode linear + 1 exponential +Sd 0 sustain rate mode increase + 1 decrease +Sr 0-7f Sustain Rate +Rm 0 Linear decrease + 1 Exponential decrease +Rr 0-1f Release Rate + +Note: decay mode is always Expontial decrease, and thus cannot +be set. +------------------------------------------------------------- +$1f801xxc Current ADSR volume +bit |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00| +desc.|ADSRvol | + +ADSRvol Returns the current envelope volume when + read. +-- James' Note: return range: 0 -> 32767 + +*** doomed doc extract end *** + +By using a small PSX proggie to visualise the envelope as it was played, +the following results for envelope timing were obtained: + +1. Attack rate value (linear mode) + + Attack value range: 0 -> 127 + + Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | | 80 | + ----------------------------------------------------------------- + Frames | 11 | 21 | 42 | 84 | 169| 338| 676| |2890| + + Note: frames is no. of PAL frames to reach full volume (100% + amplitude) + + Hmm, noticing that the time taken to reach full volume doubles + every time we add 4 to our attack value, we know the equation is + of form: + frames = k * 2 ^ (value / 4) + + (You may ponder about envelope generator hardware at this point, + or maybe not... :) + + By substituting some stuff and running some checks, we get: + + k = 0.00257 (close enuf) + + therefore, + frames = 0.00257 * 2 ^ (value / 4) + If you just happen to be writing an emulator, then you can probably + use an equation like: + + %volume_increase_per_tick = 1 / frames + + + ------------------------------------ + Pete: + ms=((1<<(value>>2))*514)/10000 + ------------------------------------ + +2. Decay rate value (only has log mode) + + Decay value range: 0 -> 15 + + Value | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | + ------------------------------------------------ + frames | | | | | 6 | 12 | 24 | 47 | + + Note: frames here is no. of PAL frames to decay to 50% volume. + + formula: frames = k * 2 ^ (value) + + Substituting, we get: k = 0.00146 + + Further info on logarithmic nature: + frames to decay to sustain level 3 = 3 * frames to decay to + sustain level 9 + + Also no. of frames to 25% volume = roughly 1.85 * no. of frames to + 50% volume. + + Frag it - just use linear approx. + + ------------------------------------ + Pete: + ms=((1< 127 + + Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | + ------------------------------------------- + frames | 9 | 19 | 37 | 74 | 147| 293| 587| + + Here, frames = no. of PAL frames for volume amplitude to go from 100% + to 0% (or vice-versa). + + Same formula as for attack value, just a different value for k: + + k = 0.00225 + + ie: frames = 0.00225 * 2 ^ (value / 4) + + For emulation purposes: + + %volume_increase_or_decrease_per_tick = 1 / frames + + ------------------------------------ + Pete: + ms=((1<<(value>>2))*450)/10000 + ------------------------------------ + + +4. Release rate (linear mode) + + Release rate range: 0 -> 31 + + Value | 13 | 14 | 15 | 16 | 17 | + --------------------------------------------------------------- + frames | 18 | 36 | 73 | 146| 292| + + Here, frames = no. of PAL frames to decay from 100% vol to 0% vol + after "note-off" is triggered. + + Formula: frames = k * 2 ^ (value) + + And so: k = 0.00223 + + ------------------------------------ + Pete: + ms=((1< release phase + { + if(s_chan[ch].ADSR.ReleaseVal!=0) // -> release not 0: do release (if 0: stop right now) + { + if(!s_chan[ch].ADSR.ReleaseVol) // --> release just started? set up the release stuff + { + s_chan[ch].ADSR.ReleaseStartTime=s_chan[ch].ADSR.lTime; + s_chan[ch].ADSR.ReleaseVol=s_chan[ch].ADSR.lVolume; + s_chan[ch].ADSR.ReleaseTime = // --> calc how long does it take to reach the wanted sus level + (s_chan[ch].ADSR.ReleaseTime* + s_chan[ch].ADSR.ReleaseVol)/1024; + } + // -> NO release exp mode used (yet) + v=s_chan[ch].ADSR.ReleaseVol; // -> get last volume + lT=s_chan[ch].ADSR.lTime- // -> how much time is past? + s_chan[ch].ADSR.ReleaseStartTime; + l1=s_chan[ch].ADSR.ReleaseTime; + + if(lT we still have to release + { + v=v-((v*lT)/l1); // --> calc new volume + } + else // -> release is over: now really stop that sample + {v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;} + } + else // -> release IS 0: release at once + { + v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0; + } + } + else + {//--------------------------------------------------// not in release phase: + v=1024; + lT=s_chan[ch].ADSR.lTime; + l1=s_chan[ch].ADSR.AttackTime; + + if(lT0) + { + if(l3!=0) v2+=((v-v2)*lT)/l3; + else v2=v; + } + else + { + if(l3!=0) v2-=(v2*lT)/l3; + else v2=v; + } + + if(v2>v) v2=v; + if(v2<=0) {v2=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;} + + v=v2; + } + } + } + + //----------------------------------------------------// + // ok, done for this channel, so increase time + + s_chan[ch].ADSR.lTime+=1; // 1 = 1.020408f ms; + + if(v>1024) v=1024; // adjust volume + if(v<0) v=0; + s_chan[ch].ADSR.lVolume=v; // store act volume + + return v; // return the volume factor +*/ + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + + +/* +----------------------------------------------------------------------------- +Neill Corlett +Playstation SPU envelope timing notes +----------------------------------------------------------------------------- + +This is preliminary. This may be wrong. But the model described herein fits +all of my experimental data, and it's just simple enough to sound right. + +ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally. +The value returned by channel reg 0xC is (envelope_level>>16). + +Each sample, an increment or decrement value will be added to or +subtracted from this envelope level. + +Create the rate log table. The values double every 4 entries. + entry #0 = 4 + + 4, 5, 6, 7, + 8,10,12,14, + 16,20,24,28, ... + + entry #40 = 4096... + entry #44 = 8192... + entry #48 = 16384... + entry #52 = 32768... + entry #56 = 65536... + +increments and decrements are in terms of ratelogtable[n] +n may exceed the table bounds (plan on n being between -32 and 127). +table values are all clipped between 0x00000000 and 0x3FFFFFFF + +when you "voice on", the envelope is always fully reset. +(yes, it may click. the real thing does this too.) + +envelope level begins at zero. + +each state happens for at least 1 cycle +(transitions are not instantaneous) +this may result in some oddness: if the decay rate is uberfast, it will cut +the envelope from full down to half in one sample, potentially skipping over +the sustain level + +ATTACK +------ +- if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and + proceed to DECAY. + +Linear attack mode: +- line extends upward to 0x7FFFFFFF +- increment per sample is ratelogtable[(Ar^0x7F)-0x10] + +Logarithmic attack mode: +if envelope_level < 0x60000000: + - line extends upward to 0x60000000 + - increment per sample is ratelogtable[(Ar^0x7F)-0x10] +else: + - line extends upward to 0x7FFFFFFF + - increment per sample is ratelogtable[(Ar^0x7F)-0x18] + +DECAY +----- +- if ((envelope_level>>27)&0xF) <= Sl, proceed to SUSTAIN. + Do not clip to the sustain level. +- current line ends at (envelope_level & 0x07FFFFFF) +- decrement per sample depends on (envelope_level>>28)&0x7 + 0: ratelogtable[(4*(Dr^0x1F))-0x18+0] + 1: ratelogtable[(4*(Dr^0x1F))-0x18+4] + 2: ratelogtable[(4*(Dr^0x1F))-0x18+6] + 3: ratelogtable[(4*(Dr^0x1F))-0x18+8] + 4: ratelogtable[(4*(Dr^0x1F))-0x18+9] + 5: ratelogtable[(4*(Dr^0x1F))-0x18+10] + 6: ratelogtable[(4*(Dr^0x1F))-0x18+11] + 7: ratelogtable[(4*(Dr^0x1F))-0x18+12] + (note that this is the same as the release rate formula, except that + decay rates 10-1F aren't possible... those would be slower in theory) + +SUSTAIN +------- +- no terminating condition except for voice off +- Sd=0 (increase) behavior is identical to ATTACK for both log and linear. +- Sd=1 (decrease) behavior: +Linear sustain decrease: +- line extends to 0x00000000 +- decrement per sample is ratelogtable[(Sr^0x7F)-0x0F] +Logarithmic sustain decrease: +- current line ends at (envelope_level & 0x07FFFFFF) +- decrement per sample depends on (envelope_level>>28)&0x7 + 0: ratelogtable[(Sr^0x7F)-0x1B+0] + 1: ratelogtable[(Sr^0x7F)-0x1B+4] + 2: ratelogtable[(Sr^0x7F)-0x1B+6] + 3: ratelogtable[(Sr^0x7F)-0x1B+8] + 4: ratelogtable[(Sr^0x7F)-0x1B+9] + 5: ratelogtable[(Sr^0x7F)-0x1B+10] + 6: ratelogtable[(Sr^0x7F)-0x1B+11] + 7: ratelogtable[(Sr^0x7F)-0x1B+12] + +RELEASE +------- +- if the envelope level has overflowed to negative, clip to 0 and QUIT. + +Linear release mode: +- line extends to 0x00000000 +- decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C] + +Logarithmic release mode: +- line extends to (envelope_level & 0x0FFFFFFF) +- decrement per sample depends on (envelope_level>>28)&0x7 + 0: ratelogtable[(4*(Rr^0x1F))-0x18+0] + 1: ratelogtable[(4*(Rr^0x1F))-0x18+4] + 2: ratelogtable[(4*(Rr^0x1F))-0x18+6] + 3: ratelogtable[(4*(Rr^0x1F))-0x18+8] + 4: ratelogtable[(4*(Rr^0x1F))-0x18+9] + 5: ratelogtable[(4*(Rr^0x1F))-0x18+10] + 6: ratelogtable[(4*(Rr^0x1F))-0x18+11] + 7: ratelogtable[(4*(Rr^0x1F))-0x18+12] + +----------------------------------------------------------------------------- +*/ + diff --git a/plugins/dfsound/adsr.h b/plugins/dfsound/adsr.h index e15031dc..ff2af1ff 100644 --- a/plugins/dfsound/adsr.h +++ b/plugins/dfsound/adsr.h @@ -1,20 +1,19 @@ -/*************************************************************************** - adsr.h - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 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. * - * * - ***************************************************************************/ - -INLINE void StartADSR(int ch); -INLINE int MixADSR(int ch); -void InitADSR(void); +/*************************************************************************** + adsr.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 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. * + * * + ***************************************************************************/ + +INLINE void StartADSR(int ch); +INLINE int MixADSR(int ch); diff --git a/plugins/dfsound/cfg.c b/plugins/dfsound/cfg.c index 2bf42c9c..a98a695f 100644 --- a/plugins/dfsound/cfg.c +++ b/plugins/dfsound/cfg.c @@ -1,177 +1,173 @@ -/*************************************************************************** - cfg.c - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 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 "stdafx.h" - -#define _IN_CFG - -#include "cfg.h" - -#include "externals.h" - -//////////////////////////////////////////////////////////////////////// -// LINUX CONFIG/ABOUT HANDLING -//////////////////////////////////////////////////////////////////////// - -#include - -//////////////////////////////////////////////////////////////////////// -// START EXTERNAL CFG TOOL -//////////////////////////////////////////////////////////////////////// - -void StartCfgTool(char * pCmdLine) -{ - FILE * cf; - char filename[255]; - - strcpy(filename,"cfgDFSound"); - cf=fopen(filename,"rb"); - if(cf!=NULL) - { - fclose(cf); - if(fork()==0) - { - execl("./cfgDFSound","cfgDFSound",pCmdLine,NULL); - exit(0); - } - } - else - { - strcpy(filename,"cfg/cfgDFSound"); - cf=fopen(filename,"rb"); - if(cf!=NULL) - { - fclose(cf); - if(fork()==0) - { - if(chdir("cfg") != 0) - perror("cfg"); - execl("./cfgDFSound","cfgDFSound",pCmdLine,NULL); - exit(0); - } - } - else - { - sprintf(filename,"%s/cfgDFSound",getenv("HOME")); - cf=fopen(filename,"rb"); - if(cf!=NULL) - { - fclose(cf); - if(fork()==0) - { - if(chdir(getenv("HOME")) != 0) - perror("HOME"); - execl("./cfgDFSound","cfgDFSound",pCmdLine,NULL); - exit(0); - } - } - else printf("Sound error: cfgDFSound not found!\n"); - } - } -} - -///////////////////////////////////////////////////////// -// READ LINUX CONFIG FILE -///////////////////////////////////////////////////////// - -static void ReadConfigFile(void) -{ - FILE *in;char t[256];int len; - char * pB, * p; - - strcpy(t,"dfsound.cfg"); - in = fopen(t,"rb"); - if(!in) - { - strcpy(t,"cfg/dfsound.cfg"); - in = fopen(t,"rb"); - if(!in) - { - sprintf(t,"%s/dfsound.cfg",getenv("HOME")); - in = fopen(t,"rb"); - if(!in) return; - } - } - - pB = (char *)malloc(32767); - memset(pB,0,32767); - - len = fread(pB, 1, 32767, in); - fclose(in); - - strcpy(t,"\nVolume");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - if(p) iVolume=4-atoi(p+len); - if(iVolume<1) iVolume=1; - if(iVolume>5) iVolume=5; - - strcpy(t,"\nXAPitch");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - if(p) iXAPitch=atoi(p+len); - if(iXAPitch<0) iXAPitch=0; - if(iXAPitch>1) iXAPitch=1; - - strcpy(t,"\nHighCompMode");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - if(p) iUseTimer=atoi(p+len); - if(iUseTimer<0) iUseTimer=0; - // note: timer mode 1 (win time events) is not supported - // in linux. But timer mode 2 (spuupdate) is safe to use. - if(iUseTimer) iUseTimer=2; - - strcpy(t,"\nSPUIRQWait");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - if(p) iSPUIRQWait=atoi(p+len); - if(iSPUIRQWait<0) iSPUIRQWait=0; - if(iSPUIRQWait>1) iSPUIRQWait=1; - - strcpy(t,"\nUseReverb");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - if(p) iUseReverb=atoi(p+len); - if(iUseReverb<0) iUseReverb=0; - if(iUseReverb>2) iUseReverb=2; - - strcpy(t,"\nUseInterpolation");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - if(p) iUseInterpolation=atoi(p+len); - if(iUseInterpolation<0) iUseInterpolation=0; - if(iUseInterpolation>3) iUseInterpolation=3; - - strcpy(t,"\nDisStereo");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - if(p) iDisStereo=atoi(p+len); - if(iDisStereo<0) iDisStereo=0; - if(iDisStereo>1) iDisStereo=1; - - strcpy(t,"\nFreqResponse");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - if(p) iFreqResponse=atoi(p+len); - if(iFreqResponse<0) iFreqResponse=0; - if(iFreqResponse>1) iFreqResponse=1; - - free(pB); -} - -///////////////////////////////////////////////////////// -// READ CONFIG called by spu funcs -///////////////////////////////////////////////////////// - -void ReadConfig(void) -{ - iVolume=2; - iXAPitch=0; - iSPUIRQWait=1; - iUseTimer=2; - iUseReverb=2; - iUseInterpolation=2; - iDisStereo=0; - iFreqResponse=0; - - ReadConfigFile(); -} +/*************************************************************************** + cfg.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 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 "stdafx.h" + +#define _IN_CFG + +#include "externals.h" + +//////////////////////////////////////////////////////////////////////// +// LINUX CONFIG/ABOUT HANDLING +//////////////////////////////////////////////////////////////////////// + +#include + +//////////////////////////////////////////////////////////////////////// +// START EXTERNAL CFG TOOL +//////////////////////////////////////////////////////////////////////// + +void StartCfgTool(char * pCmdLine) +{ + FILE * cf; + char filename[255]; + + strcpy(filename,"cfgDFSound"); + cf=fopen(filename,"rb"); + if(cf!=NULL) + { + fclose(cf); + if(fork()==0) + { + execl("./cfgDFSound","cfgDFSound",pCmdLine,NULL); + exit(0); + } + } + else + { + strcpy(filename,"cfg/cfgDFSound"); + cf=fopen(filename,"rb"); + if(cf!=NULL) + { + fclose(cf); + if(fork()==0) + { + chdir("cfg"); + execl("./cfgDFSound","cfgDFSound",pCmdLine,NULL); + exit(0); + } + } + else + { + sprintf(filename,"%s/cfgDFSound",getenv("HOME")); + cf=fopen(filename,"rb"); + if(cf!=NULL) + { + fclose(cf); + if(fork()==0) + { + chdir(getenv("HOME")); + execl("./cfgDFSound","cfgDFSound",pCmdLine,NULL); + exit(0); + } + } + else printf("Sound error: cfgDFSound not found!\n"); + } + } +} + +///////////////////////////////////////////////////////// +// READ LINUX CONFIG FILE +///////////////////////////////////////////////////////// + +void ReadConfigFile(void) +{ + FILE *in;char t[256];int len; + char * pB, * p; + + strcpy(t,"dfsound.cfg"); + in = fopen(t,"rb"); + if(!in) + { + strcpy(t,"cfg/dfsound.cfg"); + in = fopen(t,"rb"); + if(!in) + { + sprintf(t,"%s/dfsound.cfg",getenv("HOME")); + in = fopen(t,"rb"); + if(!in) return; + } + } + + pB = (char *)malloc(32767); + memset(pB,0,32767); + + len = fread(pB, 1, 32767, in); + fclose(in); + + strcpy(t,"\nVolume");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) iVolume=4-atoi(p+len); + if(iVolume<1) iVolume=1; + if(iVolume>5) iVolume=5; + + strcpy(t,"\nXAPitch");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) iXAPitch=atoi(p+len); + if(iXAPitch<0) iXAPitch=0; + if(iXAPitch>1) iXAPitch=1; + + strcpy(t,"\nHighCompMode");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) iUseTimer=atoi(p+len); + if(iUseTimer<0) iUseTimer=0; + // note: timer mode 1 (win time events) is not supported + // in linux. But timer mode 2 (spuupdate) is safe to use. + if(iUseTimer) iUseTimer=2; + + strcpy(t,"\nSPUIRQWait");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) iSPUIRQWait=atoi(p+len); + if(iSPUIRQWait<0) iSPUIRQWait=0; + if(iSPUIRQWait>1) iSPUIRQWait=1; + + strcpy(t,"\nUseReverb");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) iUseReverb=atoi(p+len); + if(iUseReverb<0) iUseReverb=0; + if(iUseReverb>2) iUseReverb=2; + + strcpy(t,"\nUseInterpolation");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) iUseInterpolation=atoi(p+len); + if(iUseInterpolation<0) iUseInterpolation=0; + if(iUseInterpolation>3) iUseInterpolation=3; + + strcpy(t,"\nDisStereo");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) iDisStereo=atoi(p+len); + if(iDisStereo<0) iDisStereo=0; + if(iDisStereo>1) iDisStereo=1; + + strcpy(t,"\nFreqResponse");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) iFreqResponse=atoi(p+len); + if(iFreqResponse<0) iFreqResponse=0; + if(iFreqResponse>1) iFreqResponse=1; + + free(pB); +} + +///////////////////////////////////////////////////////// +// READ CONFIG called by spu funcs +///////////////////////////////////////////////////////// + +void ReadConfig(void) +{ + iVolume=2; + iXAPitch=0; + iSPUIRQWait=1; + iUseTimer=2; + iUseReverb=2; + iUseInterpolation=2; + iDisStereo=0; + iFreqResponse=0; + + ReadConfigFile(); +} diff --git a/plugins/dfsound/externals.h b/plugins/dfsound/externals.h index 011205b8..b8a5c43d 100644 --- a/plugins/dfsound/externals.h +++ b/plugins/dfsound/externals.h @@ -1,361 +1,359 @@ -/*************************************************************************** - externals.h - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 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 - -#include "psemu_plugin_defs.h" - -///////////////////////////////////////////////////////// -// generic defines -///////////////////////////////////////////////////////// - -#define PSE_LT_SPU 4 -#define PSE_SPU_ERR_SUCCESS 0 -#define PSE_SPU_ERR -60 -#define PSE_SPU_ERR_NOTCONFIGURED PSE_SPU_ERR - 1 -#define PSE_SPU_ERR_INIT PSE_SPU_ERR - 2 -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -//////////////////////////////////////////////////////////////////////// -// spu defines -//////////////////////////////////////////////////////////////////////// - -// sound buffer sizes -// 400 ms complete sound buffer -#define SOUNDSIZE 70560 -// 137 ms test buffer... if less than that is buffered, a new upload will happen -#define TESTSIZE 24192 - -// num of channels -#define MAXCHAN 24 - - -// ~ 1 ms of data - somewhat slower than Eternal -//#define NSSIZE 45 -//#define INTERVAL_TIME 1000 - -// ~ 0.5 ms of data - roughly Eternal maybe -//#define NSSIZE 23 -//#define INTERVAL_TIME 2000 - -// ~ 0.25 ms of data - seems a little bad..? -//#define NSSIZE 12 -//#define INTERVAL_TIME 4000 - -#define NSSIZE 10 -#define APU_CYCLES_UPDATE NSSIZE - - -// update times -#if 0 -// PEOPS DSound 1.09a - good sound cards -#define LATENCY 10 -#elif defined (_WINDOWS) -// work on most cards -#define LATENCY 25 -#else -// work on most cards -#define LATENCY 25 -#endif - - -// make sure this is bigger than cpu action - no glitchy -#define INTERVAL_TIME 4500 - - -#define CPU_CLOCK 33868800 - -/////////////////////////////////////////////////////////// -// struct defines -/////////////////////////////////////////////////////////// - -// ADSR INFOS PER CHANNEL -typedef struct -{ - int AttackModeExp; - long AttackTime; - long DecayTime; - long SustainLevel; - int SustainModeExp; - long SustainModeDec; - long SustainTime; - int ReleaseModeExp; - unsigned long ReleaseVal; - long ReleaseTime; - long ReleaseStartTime; - long ReleaseVol; - long lTime; - long lVolume; -} ADSRInfo; - -typedef struct -{ - int State; - int AttackModeExp; - int AttackRate; - int DecayRate; - int SustainLevel; - int SustainModeExp; - int SustainIncrease; - int SustainRate; - int ReleaseModeExp; - int ReleaseRate; - int EnvelopeVol; - int EnvelopeVol_f; // fraction - long lVolume; - long lDummy1; - long lDummy2; -} ADSRInfoEx; - -/////////////////////////////////////////////////////////// - -// Tmp Flags - -// used for debug channel muting -#define FLAG_MUTE 1 - -// used for simple interpolation -#define FLAG_IPOL0 2 -#define FLAG_IPOL1 4 - -/////////////////////////////////////////////////////////// - -// MAIN CHANNEL STRUCT -typedef struct -{ - // no mutexes used anymore... don't need them to sync access - //HANDLE hMutex; - - int bNew; // start flag - - int iSBPos; // mixing stuff - int spos; - int sinc; - int SB[32+32]; // Pete added another 32 dwords in 1.6 ... prevents overflow issues with gaussian/cubic interpolation (thanx xodnizel!), and can be used for even better interpolations, eh? :) - int sval; - - unsigned char * pStart; // start ptr into sound mem - unsigned char * pCurr; // current pos in sound mem - unsigned char * pLoop; // loop ptr in sound mem - - int bOn; // is channel active (sample playing?) - int bStop; // is channel stopped (sample _can_ still be playing, ADSR Release phase) - int bReverb; // can we do reverb on this channel? must have ctrl register bit, to get active - int iActFreq; // current psx pitch - int iUsedFreq; // current pc pitch - int iLeftVolume; // left volume - int iLeftVolRaw; // left psx volume value - int bIgnoreLoop; // ignore loop bit, if an external loop address is used - int iMute; // mute mode (debug) - int iSilent; // voice on - sound on/off - int iRightVolume; // right volume - int iRightVolRaw; // right psx volume value - int iRawPitch; // raw pitch (0...3fff) - int iIrqDone; // debug irq done flag - int s_1; // last decoding infos - int s_2; - int bRVBActive; // reverb active flag - int iRVBOffset; // reverb offset - int iRVBRepeat; // reverb repeat - int bNoise; // noise active flag - int bFMod; // freq mod (0=off, 1=sound channel, 2=freq channel) - int iRVBNum; // another reverb helper - int iOldNoise; // old noise val for this channel - ADSRInfo ADSR; // active ADSR settings - ADSRInfoEx ADSRX; // next ADSR settings (will be moved to active on sample start) -} SPUCHAN; - -/////////////////////////////////////////////////////////// - -typedef struct -{ - int StartAddr; // reverb area start addr in samples - int CurrAddr; // reverb area curr addr in samples - - int VolLeft; - int VolRight; - int iLastRVBLeft; - int iLastRVBRight; - int iRVBLeft; - int iRVBRight; - - int FB_SRC_A; // (offset) - int FB_SRC_B; // (offset) - int IIR_ALPHA; // (coef.) - int ACC_COEF_A; // (coef.) - int ACC_COEF_B; // (coef.) - int ACC_COEF_C; // (coef.) - int ACC_COEF_D; // (coef.) - int IIR_COEF; // (coef.) - int FB_ALPHA; // (coef.) - int FB_X; // (coef.) - int IIR_DEST_A0; // (offset) - int IIR_DEST_A1; // (offset) - int ACC_SRC_A0; // (offset) - int ACC_SRC_A1; // (offset) - int ACC_SRC_B0; // (offset) - int ACC_SRC_B1; // (offset) - int IIR_SRC_A0; // (offset) - int IIR_SRC_A1; // (offset) - int IIR_DEST_B0; // (offset) - int IIR_DEST_B1; // (offset) - int ACC_SRC_C0; // (offset) - int ACC_SRC_C1; // (offset) - int ACC_SRC_D0; // (offset) - int ACC_SRC_D1; // (offset) - int IIR_SRC_B1; // (offset) - int IIR_SRC_B0; // (offset) - int MIX_DEST_A0; // (offset) - int MIX_DEST_A1; // (offset) - int MIX_DEST_B0; // (offset) - int MIX_DEST_B1; // (offset) - int IN_COEF_L; // (coef.) - int IN_COEF_R; // (coef.) -} REVERBInfo; - -#ifdef _WINDOWS -extern HINSTANCE hInst; -#define WM_MUTE (WM_USER+543) -#endif - -/////////////////////////////////////////////////////////// -// SPU.C globals -/////////////////////////////////////////////////////////// - -#ifndef _IN_SPU - -// psx buffers / addresses - -extern unsigned short regArea[]; -extern unsigned short spuMem[]; -extern unsigned char * spuMemC; -extern unsigned char * pSpuIrq; -extern unsigned char * pSpuBuffer; - -// user settings - -extern int iVolume; -extern int iXAPitch; -extern int iUseTimer; -extern int iSPUIRQWait; -extern int iDebugMode; -extern int iRecordMode; -extern int iUseReverb; -extern int iUseInterpolation; -extern int iDisStereo; -extern int iFreqResponse; -// MISC - -extern int iSpuAsyncWait; - -extern SPUCHAN s_chan[]; -extern REVERBInfo rvb; - -extern unsigned long dwNoiseVal; -extern unsigned long dwNoiseClock; -extern unsigned long dwNoiseCount; -extern unsigned short spuCtrl; -extern unsigned short spuStat; -extern unsigned short spuIrq; -extern unsigned long spuAddr; -extern int bEndThread; -extern int bThreadEnded; -extern int bSpuInit; -extern uint32_t dwNewChannel; - -extern int SSumR[]; -extern int SSumL[]; -extern int iCycle; -extern short * pS; - -#ifdef _WINDOWS -extern HWND hWMain; // window handle -extern HWND hWDebug; -#endif - -extern void (CALLBACK *cddavCallback)(unsigned short,unsigned short); - -#endif - -/////////////////////////////////////////////////////////// -// DSOUND.C globals -/////////////////////////////////////////////////////////// - -#ifndef _IN_DSOUND - -#ifdef _WINDOWS -extern unsigned long LastWrite; -extern unsigned long LastPlay; -#endif - -#endif - -/////////////////////////////////////////////////////////// -// RECORD.C globals -/////////////////////////////////////////////////////////// - -#ifndef _IN_RECORD - -#ifdef _WINDOWS -extern int iDoRecord; -#endif - -#endif - -/////////////////////////////////////////////////////////// -// XA.C globals -/////////////////////////////////////////////////////////// - -#ifndef _IN_XA - -extern xa_decode_t * xapGlobal; - -extern uint32_t * XAFeed; -extern uint32_t * XAPlay; -extern uint32_t * XAStart; -extern uint32_t * XAEnd; - -extern uint32_t XARepeat; -extern uint32_t XALastVal; - -extern uint32_t * CDDAFeed; -extern uint32_t * CDDAPlay; -extern uint32_t * CDDAStart; -extern uint32_t * CDDAEnd; - -extern int iLeftXAVol; -extern int iRightXAVol; - -#endif - -/////////////////////////////////////////////////////////// -// REVERB.C globals -/////////////////////////////////////////////////////////// - -#ifndef _IN_REVERB - -extern int * sRVBPlay; -extern int * sRVBEnd; -extern int * sRVBStart; -extern int iReverbOff; -extern int iReverbRepeat; -extern int iReverbNum; - -#endif +/*************************************************************************** + externals.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 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 + +///////////////////////////////////////////////////////// +// generic defines +///////////////////////////////////////////////////////// + +#define PSE_LT_SPU 4 +#define PSE_SPU_ERR_SUCCESS 0 +#define PSE_SPU_ERR -60 +#define PSE_SPU_ERR_NOTCONFIGURED PSE_SPU_ERR - 1 +#define PSE_SPU_ERR_INIT PSE_SPU_ERR - 2 +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +//////////////////////////////////////////////////////////////////////// +// spu defines +//////////////////////////////////////////////////////////////////////// + +// sound buffer sizes +// 400 ms complete sound buffer +#define SOUNDSIZE 70560 +// 137 ms test buffer... if less than that is buffered, a new upload will happen +#define TESTSIZE 24192 + +// num of channels +#define MAXCHAN 24 + + +// ~ 1 ms of data - somewhat slower than Eternal +//#define NSSIZE 45 +//#define INTERVAL_TIME 1000 + +// ~ 0.5 ms of data - roughly Eternal maybe +//#define NSSIZE 23 +//#define INTERVAL_TIME 2000 + +// ~ 0.25 ms of data - seems a little bad..? +//#define NSSIZE 12 +//#define INTERVAL_TIME 4000 + +#define NSSIZE 10 +#define APU_CYCLES_UPDATE NSSIZE + + +// update times +#if 0 +// PEOPS DSound 1.09a - good sound cards +#define LATENCY 10 +#elif defined (_WINDOWS) +// work on most cards +#define LATENCY 25 +#else +// work on most cards +#define LATENCY 25 +#endif + + +// make sure this is bigger than cpu action - no glitchy +#define INTERVAL_TIME 4500 + + +#define CPU_CLOCK 33868800 + +/////////////////////////////////////////////////////////// +// struct defines +/////////////////////////////////////////////////////////// + +// ADSR INFOS PER CHANNEL +typedef struct +{ + int AttackModeExp; + long AttackTime; + long DecayTime; + long SustainLevel; + int SustainModeExp; + long SustainModeDec; + long SustainTime; + int ReleaseModeExp; + unsigned long ReleaseVal; + long ReleaseTime; + long ReleaseStartTime; + long ReleaseVol; + long lTime; + long lVolume; +} ADSRInfo; + +typedef struct +{ + int State; + int AttackModeExp; + int AttackRate; + int DecayRate; + int SustainLevel; + int SustainModeExp; + int SustainIncrease; + int SustainRate; + int ReleaseModeExp; + int ReleaseRate; + int EnvelopeVol; + int EnvelopeVol_f; // fraction + long lVolume; + long lDummy1; + long lDummy2; +} ADSRInfoEx; + +/////////////////////////////////////////////////////////// + +// Tmp Flags + +// used for debug channel muting +#define FLAG_MUTE 1 + +// used for simple interpolation +#define FLAG_IPOL0 2 +#define FLAG_IPOL1 4 + +/////////////////////////////////////////////////////////// + +// MAIN CHANNEL STRUCT +typedef struct +{ + // no mutexes used anymore... don't need them to sync access + //HANDLE hMutex; + + int bNew; // start flag + + int iSBPos; // mixing stuff + int spos; + int sinc; + int SB[32+32]; // Pete added another 32 dwords in 1.6 ... prevents overflow issues with gaussian/cubic interpolation (thanx xodnizel!), and can be used for even better interpolations, eh? :) + int sval; + + unsigned char * pStart; // start ptr into sound mem + unsigned char * pCurr; // current pos in sound mem + unsigned char * pLoop; // loop ptr in sound mem + + int bOn; // is channel active (sample playing?) + int bStop; // is channel stopped (sample _can_ still be playing, ADSR Release phase) + int bReverb; // can we do reverb on this channel? must have ctrl register bit, to get active + int iActFreq; // current psx pitch + int iUsedFreq; // current pc pitch + int iLeftVolume; // left volume + int iLeftVolRaw; // left psx volume value + int bIgnoreLoop; // ignore loop bit, if an external loop address is used + int iMute; // mute mode (debug) + int iSilent; // voice on - sound on/off + int iRightVolume; // right volume + int iRightVolRaw; // right psx volume value + int iRawPitch; // raw pitch (0...3fff) + int iIrqDone; // debug irq done flag + int s_1; // last decoding infos + int s_2; + int bRVBActive; // reverb active flag + int iRVBOffset; // reverb offset + int iRVBRepeat; // reverb repeat + int bNoise; // noise active flag + int bFMod; // freq mod (0=off, 1=sound channel, 2=freq channel) + int iRVBNum; // another reverb helper + int iOldNoise; // old noise val for this channel + ADSRInfo ADSR; // active ADSR settings + ADSRInfoEx ADSRX; // next ADSR settings (will be moved to active on sample start) +} SPUCHAN; + +/////////////////////////////////////////////////////////// + +typedef struct +{ + int StartAddr; // reverb area start addr in samples + int CurrAddr; // reverb area curr addr in samples + + int VolLeft; + int VolRight; + int iLastRVBLeft; + int iLastRVBRight; + int iRVBLeft; + int iRVBRight; + + int FB_SRC_A; // (offset) + int FB_SRC_B; // (offset) + int IIR_ALPHA; // (coef.) + int ACC_COEF_A; // (coef.) + int ACC_COEF_B; // (coef.) + int ACC_COEF_C; // (coef.) + int ACC_COEF_D; // (coef.) + int IIR_COEF; // (coef.) + int FB_ALPHA; // (coef.) + int FB_X; // (coef.) + int IIR_DEST_A0; // (offset) + int IIR_DEST_A1; // (offset) + int ACC_SRC_A0; // (offset) + int ACC_SRC_A1; // (offset) + int ACC_SRC_B0; // (offset) + int ACC_SRC_B1; // (offset) + int IIR_SRC_A0; // (offset) + int IIR_SRC_A1; // (offset) + int IIR_DEST_B0; // (offset) + int IIR_DEST_B1; // (offset) + int ACC_SRC_C0; // (offset) + int ACC_SRC_C1; // (offset) + int ACC_SRC_D0; // (offset) + int ACC_SRC_D1; // (offset) + int IIR_SRC_B1; // (offset) + int IIR_SRC_B0; // (offset) + int MIX_DEST_A0; // (offset) + int MIX_DEST_A1; // (offset) + int MIX_DEST_B0; // (offset) + int MIX_DEST_B1; // (offset) + int IN_COEF_L; // (coef.) + int IN_COEF_R; // (coef.) +} REVERBInfo; + +#ifdef _WINDOWS +extern HINSTANCE hInst; +#define WM_MUTE (WM_USER+543) +#endif + +/////////////////////////////////////////////////////////// +// SPU.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_SPU + +// psx buffers / addresses + +extern unsigned short regArea[]; +extern unsigned short spuMem[]; +extern unsigned char * spuMemC; +extern unsigned char * pSpuIrq; +extern unsigned char * pSpuBuffer; + +// user settings + +extern int iVolume; +extern int iXAPitch; +extern int iUseTimer; +extern int iSPUIRQWait; +extern int iDebugMode; +extern int iRecordMode; +extern int iUseReverb; +extern int iUseInterpolation; +extern int iDisStereo; +extern int iFreqResponse; +// MISC + +extern int iSpuAsyncWait; + +extern SPUCHAN s_chan[]; +extern REVERBInfo rvb; + +extern unsigned long dwNoiseVal; +extern unsigned long dwNoiseClock; +extern unsigned long dwNoiseCount; +extern unsigned short spuCtrl; +extern unsigned short spuStat; +extern unsigned short spuIrq; +extern unsigned long spuAddr; +extern int bEndThread; +extern int bThreadEnded; +extern int bSpuInit; +extern uint32_t dwNewChannel; + +extern int SSumR[]; +extern int SSumL[]; +extern int iCycle; +extern short * pS; + +#ifdef _WINDOWS +extern HWND hWMain; // window handle +extern HWND hWDebug; +#endif + +extern void (CALLBACK *cddavCallback)(unsigned short,unsigned short); + +#endif + +/////////////////////////////////////////////////////////// +// DSOUND.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_DSOUND + +#ifdef _WINDOWS +extern unsigned long LastWrite; +extern unsigned long LastPlay; +#endif + +#endif + +/////////////////////////////////////////////////////////// +// RECORD.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_RECORD + +#ifdef _WINDOWS +extern int iDoRecord; +#endif + +#endif + +/////////////////////////////////////////////////////////// +// XA.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_XA + +extern xa_decode_t * xapGlobal; + +extern uint32_t * XAFeed; +extern uint32_t * XAPlay; +extern uint32_t * XAStart; +extern uint32_t * XAEnd; + +extern uint32_t XARepeat; +extern uint32_t XALastVal; + +extern uint32_t * CDDAFeed; +extern uint32_t * CDDAPlay; +extern uint32_t * CDDAStart; +extern uint32_t * CDDAEnd; + +extern int iLeftXAVol; +extern int iRightXAVol; + +#endif + +/////////////////////////////////////////////////////////// +// REVERB.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_REVERB + +extern int * sRVBPlay; +extern int * sRVBEnd; +extern int * sRVBStart; +extern int iReverbOff; +extern int iReverbRepeat; +extern int iReverbNum; + +#endif diff --git a/plugins/dfsound/freeze.c b/plugins/dfsound/freeze.c index f724568f..156fd693 100644 --- a/plugins/dfsound/freeze.c +++ b/plugins/dfsound/freeze.c @@ -1,223 +1,235 @@ -/*************************************************************************** - freeze.c - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 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 "stdafx.h" - -#define _IN_FREEZE - -#include "externals.h" -#include "registers.h" -#include "spu.h" -#include "regs.h" - -//////////////////////////////////////////////////////////////////////// -// freeze structs -//////////////////////////////////////////////////////////////////////// - -typedef struct -{ - unsigned short spuIrq; - uint32_t pSpuIrq; - uint32_t spuAddr; - uint32_t dummy1; - uint32_t dummy2; - uint32_t dummy3; - - SPUCHAN s_chan[MAXCHAN]; - -} SPUOSSFreeze_t; - -//////////////////////////////////////////////////////////////////////// - -void LoadStateV5(SPUFreeze_t * pF); // newest version -void LoadStateUnknown(SPUFreeze_t * pF); // unknown format - -//////////////////////////////////////////////////////////////////////// -// SPUFREEZE: called by main emu on savestate load/save -//////////////////////////////////////////////////////////////////////// - -long CALLBACK SPUfreeze(uint32_t ulFreezeMode,SPUFreeze_t * pF) -{ - int i;SPUOSSFreeze_t * pFO; - - if(!pF) return 0; // first check - - if(!bSpuInit) return 0; - - if(ulFreezeMode) // info or save? - {//--------------------------------------------------// - if(ulFreezeMode==1) - memset(pF,0,sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t)); - - strcpy(pF->PluginName,"PBOSS"); - pF->PluginVersion=5; - pF->Size=sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t); - - if(ulFreezeMode==2) return 1; // info mode? ok, bye - // save mode: - RemoveTimer(); // stop timer - - memcpy(pF->SPURam,spuMem,0x80000); // copy common infos - memcpy(pF->SPUPorts,regArea,0x200); - - if(xapGlobal && XAPlay!=XAFeed) // some xa - { - pF->xa=*xapGlobal; - } - else - memset(&pF->xa,0,sizeof(xa_decode_t)); // or clean xa - - pFO=(SPUOSSFreeze_t *)(pF+1); // store special stuff - - pFO->spuIrq=spuIrq; - if(pSpuIrq) pFO->pSpuIrq = (unsigned long)pSpuIrq-(unsigned long)spuMemC; - - pFO->spuAddr=spuAddr; - if(pFO->spuAddr==0) pFO->spuAddr=0xbaadf00d; - - for(i=0;is_chan[i],(void *)&s_chan[i],sizeof(SPUCHAN)); - if(pFO->s_chan[i].pStart) - pFO->s_chan[i].pStart-=(unsigned long)spuMemC; - if(pFO->s_chan[i].pCurr) - pFO->s_chan[i].pCurr-=(unsigned long)spuMemC; - if(pFO->s_chan[i].pLoop) - pFO->s_chan[i].pLoop-=(unsigned long)spuMemC; - } - - SetupTimer(); // sound processing on again - - return 1; - //--------------------------------------------------// - } - - if(ulFreezeMode!=0) return 0; // bad mode? bye - -#ifdef _WINDOWS - if(iDebugMode && IsWindow(hWDebug)) // clean debug mute infos - SendMessage(hWDebug,WM_MUTE,0,0); - if(IsBadReadPtr(pF,sizeof(SPUFreeze_t))) // check bad emu stuff - return 0; -#endif - - RemoveTimer(); // we stop processing while doing the save! - - memcpy(spuMem,pF->SPURam,0x80000); // get ram - memcpy(regArea,pF->SPUPorts,0x200); - - if(pF->xa.nsamples<=4032) // start xa again - SPUplayADPCMchannel(&pF->xa); - - xapGlobal=0; - - if(!strcmp(pF->PluginName,"PBOSS") && pF->PluginVersion==5) - LoadStateV5(pF); - else LoadStateUnknown(pF); - - lastch = -1; - - // repair some globals - for(i=0;i<=62;i+=2) - SPUwriteRegister(H_Reverb+i,regArea[(H_Reverb+i-0xc00)>>1]); - SPUwriteRegister(H_SPUReverbAddr,regArea[(H_SPUReverbAddr-0xc00)>>1]); - SPUwriteRegister(H_SPUrvolL,regArea[(H_SPUrvolL-0xc00)>>1]); - SPUwriteRegister(H_SPUrvolR,regArea[(H_SPUrvolR-0xc00)>>1]); - - SPUwriteRegister(H_SPUctrl,(unsigned short)(regArea[(H_SPUctrl-0xc00)>>1]|0x4000)); - SPUwriteRegister(H_SPUstat,regArea[(H_SPUstat-0xc00)>>1]); - SPUwriteRegister(H_CDLeft,regArea[(H_CDLeft-0xc00)>>1]); - SPUwriteRegister(H_CDRight,regArea[(H_CDRight-0xc00)>>1]); - - // fix to prevent new interpolations from crashing - for(i=0;ispuIrq; - if(pFO->pSpuIrq) pSpuIrq = pFO->pSpuIrq+spuMemC; else pSpuIrq=NULL; - - if(pFO->spuAddr) - { - spuAddr = pFO->spuAddr; - if (spuAddr == 0xbaadf00d) spuAddr = 0; - } - - for(i=0;is_chan[i],sizeof(SPUCHAN)); - - s_chan[i].pStart+=(unsigned long)spuMemC; - s_chan[i].pCurr+=(unsigned long)spuMemC; - s_chan[i].pLoop+=(unsigned long)spuMemC; - s_chan[i].iMute=0; - s_chan[i].iIrqDone=0; - } -} - -//////////////////////////////////////////////////////////////////////// - -void LoadStateUnknown(SPUFreeze_t * pF) -{ - int i; - - for(i=0;iszSPUName,"PBOSS"); + pF->ulFreezeVersion=5; + pF->ulFreezeSize=sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t); + + if(ulFreezeMode==2) return 1; // info mode? ok, bye + // save mode: + RemoveTimer(); // stop timer + + memcpy(pF->cSPURam,spuMem,0x80000); // copy common infos + memcpy(pF->cSPUPort,regArea,0x200); + + if(xapGlobal && XAPlay!=XAFeed) // some xa + { + pF->xaS=*xapGlobal; + } + else + memset(&pF->xaS,0,sizeof(xa_decode_t)); // or clean xa + + pFO=(SPUOSSFreeze_t *)(pF+1); // store special stuff + + pFO->spuIrq=spuIrq; + if(pSpuIrq) pFO->pSpuIrq = (unsigned long)pSpuIrq-(unsigned long)spuMemC; + + pFO->spuAddr=spuAddr; + if(pFO->spuAddr==0) pFO->spuAddr=0xbaadf00d; + + for(i=0;is_chan[i],(void *)&s_chan[i],sizeof(SPUCHAN)); + if(pFO->s_chan[i].pStart) + pFO->s_chan[i].pStart-=(unsigned long)spuMemC; + if(pFO->s_chan[i].pCurr) + pFO->s_chan[i].pCurr-=(unsigned long)spuMemC; + if(pFO->s_chan[i].pLoop) + pFO->s_chan[i].pLoop-=(unsigned long)spuMemC; + } + + SetupTimer(); // sound processing on again + + return 1; + //--------------------------------------------------// + } + + if(ulFreezeMode!=0) return 0; // bad mode? bye + +#ifdef _WINDOWS + if(iDebugMode && IsWindow(hWDebug)) // clean debug mute infos + SendMessage(hWDebug,WM_MUTE,0,0); + if(IsBadReadPtr(pF,sizeof(SPUFreeze_t))) // check bad emu stuff + return 0; +#endif + + RemoveTimer(); // we stop processing while doing the save! + + memcpy(spuMem,pF->cSPURam,0x80000); // get ram + memcpy(regArea,pF->cSPUPort,0x200); + + if(pF->xaS.nsamples<=4032) // start xa again + SPUplayADPCMchannel(&pF->xaS); + + xapGlobal=0; + + if(!strcmp(pF->szSPUName,"PBOSS") && pF->ulFreezeVersion==5) + LoadStateV5(pF); + else LoadStateUnknown(pF); + + lastch = -1; + + // repair some globals + for(i=0;i<=62;i+=2) + SPUwriteRegister(H_Reverb+i,regArea[(H_Reverb+i-0xc00)>>1]); + SPUwriteRegister(H_SPUReverbAddr,regArea[(H_SPUReverbAddr-0xc00)>>1]); + SPUwriteRegister(H_SPUrvolL,regArea[(H_SPUrvolL-0xc00)>>1]); + SPUwriteRegister(H_SPUrvolR,regArea[(H_SPUrvolR-0xc00)>>1]); + + SPUwriteRegister(H_SPUctrl,(unsigned short)(regArea[(H_SPUctrl-0xc00)>>1]|0x4000)); + SPUwriteRegister(H_SPUstat,regArea[(H_SPUstat-0xc00)>>1]); + SPUwriteRegister(H_CDLeft,regArea[(H_CDLeft-0xc00)>>1]); + SPUwriteRegister(H_CDRight,regArea[(H_CDRight-0xc00)>>1]); + + // fix to prevent new interpolations from crashing + for(i=0;ispuIrq; + if(pFO->pSpuIrq) pSpuIrq = pFO->pSpuIrq+spuMemC; else pSpuIrq=NULL; + + if(pFO->spuAddr) + { + spuAddr = pFO->spuAddr; + if (spuAddr == 0xbaadf00d) spuAddr = 0; + } + + for(i=0;is_chan[i],sizeof(SPUCHAN)); + + s_chan[i].pStart+=(unsigned long)spuMemC; + s_chan[i].pCurr+=(unsigned long)spuMemC; + s_chan[i].pLoop+=(unsigned long)spuMemC; + s_chan[i].iMute=0; + s_chan[i].iIrqDone=0; + } +} + +//////////////////////////////////////////////////////////////////////// + +void LoadStateUnknown(SPUFreeze_t * pF) +{ + int i; + + for(i=0;i - -//////////////////////////////////////////////////////////////////////// -// oss globals -//////////////////////////////////////////////////////////////////////// - -#define OSS_MODE_STEREO 1 -#define OSS_MODE_MONO 0 - -#define OSS_SPEED_44100 44100 - -static int oss_audio_fd = -1; - -//////////////////////////////////////////////////////////////////////// -// SETUP SOUND -//////////////////////////////////////////////////////////////////////// - -void SetupSound(void) -{ - int pspeed=44100; - int pstereo; - int format; - int fragsize = 0; - int myfrag; - int oss_speed, oss_stereo; - - if(iDisStereo) pstereo=OSS_MODE_MONO; - else pstereo=OSS_MODE_STEREO; - - oss_speed = pspeed; - oss_stereo = pstereo; - - if((oss_audio_fd=open("/dev/dsp",O_WRONLY,0))==-1) - { - printf("Sound device not available!\n"); - return; - } - - if(ioctl(oss_audio_fd,SNDCTL_DSP_RESET,0)==-1) - { - printf("Sound reset failed\n"); - return; - } - - // we use 64 fragments with 1024 bytes each - - fragsize=10; - myfrag=(63<<16)|fragsize; - - if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFRAGMENT,&myfrag)==-1) - { - printf("Sound set fragment failed!\n"); - return; - } - - format = AFMT_S16_NE; - - if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFMT,&format) == -1) - { - printf("Sound format not supported!\n"); - return; - } - - if(format!=AFMT_S16_NE) - { - printf("Sound format not supported!\n"); - return; - } - - if(ioctl(oss_audio_fd,SNDCTL_DSP_STEREO,&oss_stereo)==-1) - { - printf("Stereo mode not supported!\n"); - return; - } - - if(oss_stereo!=1) - { - iDisStereo=1; - } - - if(ioctl(oss_audio_fd,SNDCTL_DSP_SPEED,&oss_speed)==-1) - { - printf("Sound frequency not supported\n"); - return; - } - - if(oss_speed!=pspeed) - { - printf("Sound frequency not supported\n"); - return; - } -} - -//////////////////////////////////////////////////////////////////////// -// REMOVE SOUND -//////////////////////////////////////////////////////////////////////// - -void RemoveSound(void) -{ - if(oss_audio_fd != -1 ) - { - close(oss_audio_fd); - oss_audio_fd = -1; - } -} - -//////////////////////////////////////////////////////////////////////// -// GET BYTES BUFFERED -//////////////////////////////////////////////////////////////////////// - -unsigned long SoundGetBytesBuffered(void) -{ - audio_buf_info info; - unsigned long l; - - if(oss_audio_fd == -1) return SOUNDSIZE; - if(ioctl(oss_audio_fd,SNDCTL_DSP_GETOSPACE,&info)==-1) - l=0; - else - { - if(info.fragments<(info.fragstotal>>1)) // can we write in at least the half of fragments? - l=SOUNDSIZE; // -> no? wait - else l=0; // -> else go on - } - - return l; -} - -//////////////////////////////////////////////////////////////////////// -// FEED SOUND DATA -//////////////////////////////////////////////////////////////////////// - -void SoundFeedStreamData(unsigned char* pSound,long lBytes) -{ - if(oss_audio_fd == -1) return; - write(oss_audio_fd,pSound,lBytes); -} +/*************************************************************************** + oss.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 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 "stdafx.h" + +#define _IN_OSS + +#include "externals.h" + +//////////////////////////////////////////////////////////////////////// +// oss globals +//////////////////////////////////////////////////////////////////////// + +#define OSS_MODE_STEREO 1 +#define OSS_MODE_MONO 0 + +#define OSS_SPEED_44100 44100 + +static int oss_audio_fd = -1; +extern int errno; + +//////////////////////////////////////////////////////////////////////// +// SETUP SOUND +//////////////////////////////////////////////////////////////////////// + +void SetupSound(void) +{ + int pspeed=44100; + int pstereo; + int format; + int fragsize = 0; + int myfrag; + int oss_speed, oss_stereo; + + if(iDisStereo) pstereo=OSS_MODE_MONO; + else pstereo=OSS_MODE_STEREO; + + oss_speed = pspeed; + oss_stereo = pstereo; + + if((oss_audio_fd=open("/dev/dsp",O_WRONLY,0))==-1) + { + printf("Sound device not available!\n"); + return; + } + + if(ioctl(oss_audio_fd,SNDCTL_DSP_RESET,0)==-1) + { + printf("Sound reset failed\n"); + return; + } + + // we use 64 fragments with 1024 bytes each + + fragsize=10; + myfrag=(63<<16)|fragsize; + + if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFRAGMENT,&myfrag)==-1) + { + printf("Sound set fragment failed!\n"); + return; + } + + format = AFMT_S16_NE; + + if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFMT,&format) == -1) + { + printf("Sound format not supported!\n"); + return; + } + + if(format!=AFMT_S16_NE) + { + printf("Sound format not supported!\n"); + return; + } + + if(ioctl(oss_audio_fd,SNDCTL_DSP_STEREO,&oss_stereo)==-1) + { + printf("Stereo mode not supported!\n"); + return; + } + + if(oss_stereo!=1) + { + iDisStereo=1; + } + + if(ioctl(oss_audio_fd,SNDCTL_DSP_SPEED,&oss_speed)==-1) + { + printf("Sound frequency not supported\n"); + return; + } + + if(oss_speed!=pspeed) + { + printf("Sound frequency not supported\n"); + return; + } +} + +//////////////////////////////////////////////////////////////////////// +// REMOVE SOUND +//////////////////////////////////////////////////////////////////////// + +void RemoveSound(void) +{ + if(oss_audio_fd != -1 ) + { + close(oss_audio_fd); + oss_audio_fd = -1; + } +} + +//////////////////////////////////////////////////////////////////////// +// GET BYTES BUFFERED +//////////////////////////////////////////////////////////////////////// + +unsigned long SoundGetBytesBuffered(void) +{ + audio_buf_info info; + unsigned long l; + + if(oss_audio_fd == -1) return SOUNDSIZE; + if(ioctl(oss_audio_fd,SNDCTL_DSP_GETOSPACE,&info)==-1) + l=0; + else + { + if(info.fragments<(info.fragstotal>>1)) // can we write in at least the half of fragments? + l=SOUNDSIZE; // -> no? wait + else l=0; // -> else go on + } + + return l; +} + +//////////////////////////////////////////////////////////////////////// +// FEED SOUND DATA +//////////////////////////////////////////////////////////////////////// + +void SoundFeedStreamData(unsigned char* pSound,long lBytes) +{ + if(oss_audio_fd == -1) return; + write(oss_audio_fd,pSound,lBytes); +} diff --git a/plugins/dfsound/pulseaudio.c b/plugins/dfsound/pulseaudio.c index 2185d149..19b1e0b8 100644 --- a/plugins/dfsound/pulseaudio.c +++ b/plugins/dfsound/pulseaudio.c @@ -1,356 +1,354 @@ -/*************************************************************************** - pulseaudio.c - description - ------------------- -begin : Thu Feb 04 2010 -copyright : (C) 2010 by Tristin Celestin -email : cetris1@umbc.edu -comment : Much of this was taken from simple.c, in the pulseaudio - library -***************************************************************************/ -/*************************************************************************** - * * - * 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 "stdafx.h" - -#ifdef USEPULSEAUDIO - -#define _IN_OSS - -#include "externals.h" -#include - -#include "dsoundoss.h" - -//////////////////////////////////////////////////////////////////////// -// pulseaudio structs -//////////////////////////////////////////////////////////////////////// - -typedef struct { - pa_threaded_mainloop *mainloop; - pa_context *context; - pa_mainloop_api *api; - pa_stream *stream; - pa_sample_spec spec; - int first; -} Device; - -typedef struct { - unsigned int frequency; - unsigned int latency_in_msec; -} Settings; - -//////////////////////////////////////////////////////////////////////// -// pulseaudio globals -//////////////////////////////////////////////////////////////////////// - -static Device device = { - .mainloop = NULL, - .api = NULL, - .context = NULL, - .stream = NULL -}; - -static Settings settings = { - .frequency = 44100, - .latency_in_msec = 20, -}; - -// the number of bytes written in SoundFeedStreamData -const int mixlen = 3240; - -// used to calculate how much space is used in the buffer, for debugging purposes -//int maxlength = 0; - -//////////////////////////////////////////////////////////////////////// -// CALLBACKS FOR THREADED MAINLOOP -//////////////////////////////////////////////////////////////////////// -static void context_state_cb (pa_context *context, void *userdata) -{ - Device *dev = userdata; - - if ((context == NULL) || (dev == NULL)) - return; - - switch (pa_context_get_state (context)) - { - case PA_CONTEXT_READY: - case PA_CONTEXT_TERMINATED: - case PA_CONTEXT_FAILED: - pa_threaded_mainloop_signal (dev->mainloop, 0); - break; - - case PA_CONTEXT_UNCONNECTED: - case PA_CONTEXT_CONNECTING: - case PA_CONTEXT_AUTHORIZING: - case PA_CONTEXT_SETTING_NAME: - break; - } -} - -static void stream_state_cb (pa_stream *stream, void * userdata) -{ - Device *dev = userdata; - - if ((stream == NULL) || (dev == NULL)) - return; - - switch (pa_stream_get_state (stream)) - { - case PA_STREAM_READY: - case PA_STREAM_FAILED: - case PA_STREAM_TERMINATED: - pa_threaded_mainloop_signal (dev->mainloop, 0); - break; - - case PA_STREAM_UNCONNECTED: - case PA_STREAM_CREATING: - break; - } -} - -static void stream_latency_update_cb (pa_stream *stream, void *userdata) -{ - Device *dev = userdata; - - if ((stream == NULL) || (dev == NULL)) - return; - - pa_threaded_mainloop_signal (dev->mainloop, 0); -} - -static void stream_request_cb (pa_stream *stream, size_t length, void *userdata) -{ - Device *dev = userdata; - - if ((stream == NULL) || (dev == NULL)) - return; - pa_threaded_mainloop_signal (dev->mainloop, 0); -} - -//////////////////////////////////////////////////////////////////////// -// SETUP SOUND -//////////////////////////////////////////////////////////////////////// - -void SetupSound (void) -{ - int error_number; - - // Acquire mainloop /////////////////////////////////////////////////////// - device.mainloop = pa_threaded_mainloop_new (); - if (device.mainloop == NULL) - { - fprintf (stderr, "Could not acquire PulseAudio main loop\n"); - return; - } - - // Acquire context //////////////////////////////////////////////////////// - device.api = pa_threaded_mainloop_get_api (device.mainloop); - device.context = pa_context_new (device.api, "PCSX"); - pa_context_set_state_callback (device.context, context_state_cb, &device); - - if (device.context == NULL) - { - fprintf (stderr, "Could not acquire PulseAudio device context\n"); - return; - } - - // Connect to PulseAudio server /////////////////////////////////////////// - if (pa_context_connect (device.context, NULL, 0, NULL) < 0) - { - error_number = pa_context_errno (device.context); - fprintf (stderr, "Could not connect to PulseAudio server: %s\n", pa_strerror(error_number)); - return; - } - - // Run mainloop until sever context is ready ////////////////////////////// - pa_threaded_mainloop_lock (device.mainloop); - if (pa_threaded_mainloop_start (device.mainloop) < 0) - { - fprintf (stderr, "Could not start mainloop\n"); - return; - } - - pa_context_state_t context_state; - context_state = pa_context_get_state (device.context); - while (context_state != PA_CONTEXT_READY) - { - context_state = pa_context_get_state (device.context); - if (! PA_CONTEXT_IS_GOOD (context_state)) - { - error_number = pa_context_errno (device.context); - fprintf (stderr, "Context state is not good: %s\n", pa_strerror (error_number)); - return; - } - else if (context_state == PA_CONTEXT_READY) - break; - else - fprintf (stderr, "PulseAudio context state is %d\n", context_state); - pa_threaded_mainloop_wait (device.mainloop); - } - - // Set sample spec //////////////////////////////////////////////////////// - device.spec.format = PA_SAMPLE_S16NE; - if (iDisStereo) - device.spec.channels = 1; - else - device.spec.channels = 2; - device.spec.rate = settings.frequency; - - pa_buffer_attr buffer_attributes; - buffer_attributes.tlength = pa_bytes_per_second (& device.spec) / 5; - buffer_attributes.maxlength = buffer_attributes.tlength * 3; - buffer_attributes.minreq = buffer_attributes.tlength / 3; - buffer_attributes.prebuf = buffer_attributes.tlength; - - //maxlength = buffer_attributes.maxlength; - //fprintf (stderr, "Total space: %u\n", buffer_attributes.maxlength); - //fprintf (stderr, "Minimum request size: %u\n", buffer_attributes.minreq); - //fprintf (stderr, "Bytes needed before playback: %u\n", buffer_attributes.prebuf); - //fprintf (stderr, "Target buffer size: %lu\n", buffer_attributes.tlength); - - // Acquire new stream using spec ////////////////////////////////////////// - device.stream = pa_stream_new (device.context, "PCSX", &device.spec, NULL); - if (device.stream == NULL) - { - error_number = pa_context_errno (device.context); - fprintf (stderr, "Could not acquire new PulseAudio stream: %s\n", pa_strerror (error_number)); - return; - } - - // Set callbacks for server events //////////////////////////////////////// - pa_stream_set_state_callback (device.stream, stream_state_cb, &device); - pa_stream_set_write_callback (device.stream, stream_request_cb, &device); - pa_stream_set_latency_update_callback (device.stream, stream_latency_update_cb, &device); - - // Ready stream for playback ////////////////////////////////////////////// - pa_stream_flags_t flags = (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE); - //pa_stream_flags_t flags = (pa_stream_flags_t) (PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_EARLY_REQUESTS); - if (pa_stream_connect_playback (device.stream, NULL, &buffer_attributes, flags, NULL, NULL) < 0) - { - pa_context_errno (device.context); - fprintf (stderr, "Could not connect for playback: %s\n", pa_strerror (error_number)); - return; - } - - // Run mainloop until stream is ready ///////////////////////////////////// - pa_stream_state_t stream_state; - stream_state = pa_stream_get_state (device.stream); - while (stream_state != PA_STREAM_READY) - { - stream_state = pa_stream_get_state (device.stream); - - if (stream_state == PA_STREAM_READY) - break; - - else if (! PA_STREAM_IS_GOOD (stream_state)) - { - error_number = pa_context_errno (device.context); - fprintf (stderr, "Stream state is not good: %s\n", pa_strerror (error_number)); - return; - } - else - fprintf (stderr, "PulseAudio stream state is %d\n", stream_state); - pa_threaded_mainloop_wait (device.mainloop); - } - - pa_threaded_mainloop_unlock (device.mainloop); - - fprintf (stderr, "PulseAudio should be connected\n"); - return; -} - -//////////////////////////////////////////////////////////////////////// -// REMOVE SOUND -//////////////////////////////////////////////////////////////////////// -void RemoveSound (void) -{ - if (device.mainloop != NULL) - pa_threaded_mainloop_stop (device.mainloop); - - // Release in reverse order of acquisition - if (device.stream != NULL) - { - pa_stream_unref (device.stream); - device.stream = NULL; - - } - if (device.context != NULL) - { - pa_context_disconnect (device.context); - pa_context_unref (device.context); - device.context = NULL; - } - - if (device.mainloop != NULL) - { - pa_threaded_mainloop_free (device.mainloop); - device.mainloop = NULL; - } - -} - -//////////////////////////////////////////////////////////////////////// -// GET BYTES BUFFERED -//////////////////////////////////////////////////////////////////////// - -unsigned long SoundGetBytesBuffered (void) -{ - int free_space; - int error_code; - long latency; - int playing = 0; - - if ((device.mainloop == NULL) || (device.api == NULL) || ( device.context == NULL) || (device.stream == NULL)) - return SOUNDSIZE; - - pa_threaded_mainloop_lock (device.mainloop); - free_space = pa_stream_writable_size (device.stream); - pa_threaded_mainloop_unlock (device.mainloop); - - //fprintf (stderr, "Free space: %d\n", free_space); - //fprintf (stderr, "Used space: %d\n", maxlength - free_space); - if (free_space < mixlen * 3) - { - // Don't buffer anymore, just play - //fprintf (stderr, "Not buffering.\n"); - return SOUNDSIZE; - } - else - { - // Buffer some sound - //fprintf (stderr, "Buffering.\n"); - return 0; - } -} - -//////////////////////////////////////////////////////////////////////// -// FEED SOUND DATA -//////////////////////////////////////////////////////////////////////// - -void SoundFeedStreamData (unsigned char *pSound, long lBytes) -{ - int error_code; - int size; - - if (device.mainloop != NULL) - { - pa_threaded_mainloop_lock (device.mainloop); - if (pa_stream_write (device.stream, pSound, lBytes, NULL, 0LL, PA_SEEK_RELATIVE) < 0) - { - fprintf (stderr, "Could not perform write\n"); - } - else - { - //fprintf (stderr, "Wrote %d bytes\n", lBytes); - pa_threaded_mainloop_unlock (device.mainloop); - } - } -} -#endif +/*************************************************************************** + pulseaudio.c - description + ------------------- +begin : Thu Feb 04 2010 +copyright : (C) 2010 by Tristin Celestin +email : cetris1@umbc.edu +comment : Much of this was taken from simple.c, in the pulseaudio + library +***************************************************************************/ +/*************************************************************************** + * * + * 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 "stdafx.h" + +#ifdef USEPULSEAUDIO + +#define _IN_OSS + +#include "externals.h" +#include + +//////////////////////////////////////////////////////////////////////// +// pulseaudio structs +//////////////////////////////////////////////////////////////////////// + +typedef struct { + pa_threaded_mainloop *mainloop; + pa_context *context; + pa_mainloop_api *api; + pa_stream *stream; + pa_sample_spec spec; + int first; +} Device; + +typedef struct { + unsigned int frequency; + unsigned int latency_in_msec; +} Settings; + +//////////////////////////////////////////////////////////////////////// +// pulseaudio globals +//////////////////////////////////////////////////////////////////////// + +static Device device = { + .mainloop = NULL, + .api = NULL, + .context = NULL, + .stream = NULL +}; + +static Settings settings = { + .frequency = 44100, + .latency_in_msec = 20, +}; + +// the number of bytes written in SoundFeedStreamData +const int mixlen = 3240; + +// used to calculate how much space is used in the buffer, for debugging purposes +//int maxlength = 0; + +//////////////////////////////////////////////////////////////////////// +// CALLBACKS FOR THREADED MAINLOOP +//////////////////////////////////////////////////////////////////////// +static void context_state_cb (pa_context *context, void *userdata) +{ + Device *dev = userdata; + + if ((context == NULL) || (dev == NULL)) + return; + + switch (pa_context_get_state (context)) + { + case PA_CONTEXT_READY: + case PA_CONTEXT_TERMINATED: + case PA_CONTEXT_FAILED: + pa_threaded_mainloop_signal (dev->mainloop, 0); + break; + + case PA_CONTEXT_UNCONNECTED: + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + } +} + +static void stream_state_cb (pa_stream *stream, void * userdata) +{ + Device *dev = userdata; + + if ((stream == NULL) || (dev == NULL)) + return; + + switch (pa_stream_get_state (stream)) + { + case PA_STREAM_READY: + case PA_STREAM_FAILED: + case PA_STREAM_TERMINATED: + pa_threaded_mainloop_signal (dev->mainloop, 0); + break; + + case PA_STREAM_UNCONNECTED: + case PA_STREAM_CREATING: + break; + } +} + +static void stream_latency_update_cb (pa_stream *stream, void *userdata) +{ + Device *dev = userdata; + + if ((stream == NULL) || (dev == NULL)) + return; + + pa_threaded_mainloop_signal (dev->mainloop, 0); +} + +static void stream_request_cb (pa_stream *stream, size_t length, void *userdata) +{ + Device *dev = userdata; + + if ((stream == NULL) || (dev == NULL)) + return; + pa_threaded_mainloop_signal (dev->mainloop, 0); +} + +//////////////////////////////////////////////////////////////////////// +// SETUP SOUND +//////////////////////////////////////////////////////////////////////// + +void SetupSound (void) +{ + int error_number; + + // Acquire mainloop /////////////////////////////////////////////////////// + device.mainloop = pa_threaded_mainloop_new (); + if (device.mainloop == NULL) + { + fprintf (stderr, "Could not acquire PulseAudio main loop\n"); + return; + } + + // Acquire context //////////////////////////////////////////////////////// + device.api = pa_threaded_mainloop_get_api (device.mainloop); + device.context = pa_context_new (device.api, "PCSX"); + pa_context_set_state_callback (device.context, context_state_cb, &device); + + if (device.context == NULL) + { + fprintf (stderr, "Could not acquire PulseAudio device context\n"); + return; + } + + // Connect to PulseAudio server /////////////////////////////////////////// + if (pa_context_connect (device.context, NULL, 0, NULL) < 0) + { + error_number = pa_context_errno (device.context); + fprintf (stderr, "Could not connect to PulseAudio server: %s\n", pa_strerror(error_number)); + return; + } + + // Run mainloop until sever context is ready ////////////////////////////// + pa_threaded_mainloop_lock (device.mainloop); + if (pa_threaded_mainloop_start (device.mainloop) < 0) + { + fprintf (stderr, "Could not start mainloop\n"); + return; + } + + pa_context_state_t context_state; + context_state = pa_context_get_state (device.context); + while (context_state != PA_CONTEXT_READY) + { + context_state = pa_context_get_state (device.context); + if (! PA_CONTEXT_IS_GOOD (context_state)) + { + error_number = pa_context_errno (device.context); + fprintf (stderr, "Context state is not good: %s\n", pa_strerror (error_number)); + return; + } + else if (context_state == PA_CONTEXT_READY) + break; + else + fprintf (stderr, "PulseAudio context state is %d\n", context_state); + pa_threaded_mainloop_wait (device.mainloop); + } + + // Set sample spec //////////////////////////////////////////////////////// + device.spec.format = PA_SAMPLE_S16NE; + if (iDisStereo) + device.spec.channels = 1; + else + device.spec.channels = 2; + device.spec.rate = settings.frequency; + + pa_buffer_attr buffer_attributes; + buffer_attributes.tlength = pa_bytes_per_second (& device.spec) / 5; + buffer_attributes.maxlength = buffer_attributes.tlength * 3; + buffer_attributes.minreq = buffer_attributes.tlength / 3; + buffer_attributes.prebuf = buffer_attributes.tlength; + + //maxlength = buffer_attributes.maxlength; + //fprintf (stderr, "Total space: %u\n", buffer_attributes.maxlength); + //fprintf (stderr, "Minimum request size: %u\n", buffer_attributes.minreq); + //fprintf (stderr, "Bytes needed before playback: %u\n", buffer_attributes.prebuf); + //fprintf (stderr, "Target buffer size: %lu\n", buffer_attributes.tlength); + + // Acquire new stream using spec ////////////////////////////////////////// + device.stream = pa_stream_new (device.context, "PCSX", &device.spec, NULL); + if (device.stream == NULL) + { + error_number = pa_context_errno (device.context); + fprintf (stderr, "Could not acquire new PulseAudio stream: %s\n", pa_strerror (error_number)); + return; + } + + // Set callbacks for server events //////////////////////////////////////// + pa_stream_set_state_callback (device.stream, stream_state_cb, &device); + pa_stream_set_write_callback (device.stream, stream_request_cb, &device); + pa_stream_set_latency_update_callback (device.stream, stream_latency_update_cb, &device); + + // Ready stream for playback ////////////////////////////////////////////// + pa_stream_flags_t flags = (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE); + //pa_stream_flags_t flags = (pa_stream_flags_t) (PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_EARLY_REQUESTS); + if (pa_stream_connect_playback (device.stream, NULL, &buffer_attributes, flags, NULL, NULL) < 0) + { + pa_context_errno (device.context); + fprintf (stderr, "Could not connect for playback: %s\n", pa_strerror (error_number)); + return; + } + + // Run mainloop until stream is ready ///////////////////////////////////// + pa_stream_state_t stream_state; + stream_state = pa_stream_get_state (device.stream); + while (stream_state != PA_STREAM_READY) + { + stream_state = pa_stream_get_state (device.stream); + + if (stream_state == PA_STREAM_READY) + break; + + else if (! PA_STREAM_IS_GOOD (stream_state)) + { + error_number = pa_context_errno (device.context); + fprintf (stderr, "Stream state is not good: %s\n", pa_strerror (error_number)); + return; + } + else + fprintf (stderr, "PulseAudio stream state is %d\n", stream_state); + pa_threaded_mainloop_wait (device.mainloop); + } + + pa_threaded_mainloop_unlock (device.mainloop); + + fprintf (stderr, "PulseAudio should be connected\n"); + return; +} + +//////////////////////////////////////////////////////////////////////// +// REMOVE SOUND +//////////////////////////////////////////////////////////////////////// +void RemoveSound (void) +{ + if (device.mainloop != NULL) + pa_threaded_mainloop_stop (device.mainloop); + + // Release in reverse order of acquisition + if (device.stream != NULL) + { + pa_stream_unref (device.stream); + device.stream = NULL; + + } + if (device.context != NULL) + { + pa_context_disconnect (device.context); + pa_context_unref (device.context); + device.context = NULL; + } + + if (device.mainloop != NULL) + { + pa_threaded_mainloop_free (device.mainloop); + device.mainloop = NULL; + } + +} + +//////////////////////////////////////////////////////////////////////// +// GET BYTES BUFFERED +//////////////////////////////////////////////////////////////////////// + +unsigned long SoundGetBytesBuffered (void) +{ + int free_space; + int error_code; + long latency; + int playing = 0; + + if ((device.mainloop == NULL) || (device.api == NULL) || ( device.context == NULL) || (device.stream == NULL)) + return SOUNDSIZE; + + pa_threaded_mainloop_lock (device.mainloop); + free_space = pa_stream_writable_size (device.stream); + pa_threaded_mainloop_unlock (device.mainloop); + + //fprintf (stderr, "Free space: %d\n", free_space); + //fprintf (stderr, "Used space: %d\n", maxlength - free_space); + if (free_space < mixlen * 3) + { + // Don't buffer anymore, just play + //fprintf (stderr, "Not buffering.\n"); + return SOUNDSIZE; + } + else + { + // Buffer some sound + //fprintf (stderr, "Buffering.\n"); + return 0; + } +} + +//////////////////////////////////////////////////////////////////////// +// FEED SOUND DATA +//////////////////////////////////////////////////////////////////////// + +void SoundFeedStreamData (unsigned char *pSound, long lBytes) +{ + int error_code; + int size; + + if (device.mainloop != NULL) + { + pa_threaded_mainloop_lock (device.mainloop); + if (pa_stream_write (device.stream, pSound, lBytes, NULL, 0LL, PA_SEEK_RELATIVE) < 0) + { + fprintf (stderr, "Could not perform write\n"); + } + else + { + //fprintf (stderr, "Wrote %d bytes\n", lBytes); + pa_threaded_mainloop_unlock (device.mainloop); + } + } +} +#endif diff --git a/plugins/dfsound/reverb.c b/plugins/dfsound/reverb.c index dfab03a4..92e31fcb 100644 --- a/plugins/dfsound/reverb.c +++ b/plugins/dfsound/reverb.c @@ -1,463 +1,462 @@ -/*************************************************************************** - reverb.c - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 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 "stdafx.h" -#include "reverb.h" - -#define _IN_REVERB - -// will be included from spu.c -#ifdef _IN_SPU - -//////////////////////////////////////////////////////////////////////// -// globals -//////////////////////////////////////////////////////////////////////// - -// REVERB info and timing vars... - -int * sRVBPlay = 0; -int * sRVBEnd = 0; -int * sRVBStart = 0; -int iReverbOff = -1; // some delay factor for reverb -int iReverbRepeat = 0; -int iReverbNum = 1; - -//////////////////////////////////////////////////////////////////////// -// SET REVERB -//////////////////////////////////////////////////////////////////////// - -void SetREVERB(unsigned short val) -{ - switch(val) - { - case 0x0000: iReverbOff=-1; break; // off - case 0x007D: iReverbOff=32; iReverbNum=2; iReverbRepeat=128; break; // ok room - - case 0x0033: iReverbOff=32; iReverbNum=2; iReverbRepeat=64; break; // studio small - case 0x00B1: iReverbOff=48; iReverbNum=2; iReverbRepeat=96; break; // ok studio medium - case 0x00E3: iReverbOff=64; iReverbNum=2; iReverbRepeat=128; break; // ok studio large ok - - case 0x01A5: iReverbOff=128; iReverbNum=4; iReverbRepeat=32; break; // ok hall - case 0x033D: iReverbOff=256; iReverbNum=4; iReverbRepeat=64; break; // space echo - case 0x0001: iReverbOff=184; iReverbNum=3; iReverbRepeat=128; break; // echo/delay - case 0x0017: iReverbOff=128; iReverbNum=2; iReverbRepeat=128; break; // half echo - default: iReverbOff=32; iReverbNum=1; iReverbRepeat=0; break; - } -} - -//////////////////////////////////////////////////////////////////////// -// START REVERB -//////////////////////////////////////////////////////////////////////// - -INLINE void StartREVERB(int ch) -{ - if(s_chan[ch].bReverb && (spuCtrl&0x80)) // reverb possible? - { - if(iUseReverb==2) s_chan[ch].bRVBActive=1; - else - if(iUseReverb==1 && iReverbOff>0) // -> fake reverb used? - { - s_chan[ch].bRVBActive=1; // -> activate it - s_chan[ch].iRVBOffset=iReverbOff*45; - s_chan[ch].iRVBRepeat=iReverbRepeat*45; - s_chan[ch].iRVBNum =iReverbNum; - } - } - else s_chan[ch].bRVBActive=0; // else -> no reverb -} - -//////////////////////////////////////////////////////////////////////// -// HELPER FOR NEILL'S REVERB: re-inits our reverb mixing buf -//////////////////////////////////////////////////////////////////////// - -static INLINE void InitREVERB(void) -{ - if(iUseReverb==2) - {memset(sRVBStart,0,NSSIZE*2*4);} -} - -//////////////////////////////////////////////////////////////////////// -// STORE REVERB -//////////////////////////////////////////////////////////////////////// - -INLINE void StoreREVERB(int ch,int ns) -{ - if(iUseReverb==0) return; - else - if(iUseReverb==2) // -------------------------------- // Neil's reverb - { - const int iRxl=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000; - const int iRxr=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000; - - ns<<=1; - - *(sRVBStart+ns) +=iRxl; // -> we mix all active reverb channels into an extra buffer - *(sRVBStart+ns+1)+=iRxr; - } - else // --------------------------------------------- // Pete's easy fake reverb - { - int * pN;int iRn,iRr=0; - - // we use the half channel volume (/0x8000) for the first reverb effects, quarter for next and so on - - int iRxl=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x8000; - int iRxr=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x8000; - - for(iRn=1;iRn<=s_chan[ch].iRVBNum;iRn++,iRr+=s_chan[ch].iRVBRepeat,iRxl/=2,iRxr/=2) - { - pN=sRVBPlay+((s_chan[ch].iRVBOffset+iRr+ns)<<1); - if(pN>=sRVBEnd) pN=sRVBStart+(pN-sRVBEnd); - - (*pN)+=iRxl; - pN++; - (*pN)+=iRxr; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static INLINE int g_buffer(int iOff) // get_buffer content helper: takes care about wraps -{ - short * p=(short *)spuMem; - iOff=(iOff*4)+rvb.CurrAddr; - while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000); - while(iOff0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000); - while(iOff32767L) iVal=32767L; - *(p+iOff)=(short)iVal; -} - -//////////////////////////////////////////////////////////////////////// - -static INLINE void s_buffer1(int iOff,int iVal) // set_buffer (+1 sample) content helper: takes care about wraps and clipping -{ - short * p=(short *)spuMem; - iOff=(iOff*4)+rvb.CurrAddr+1; - while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000); - while(iOff32767L) iVal=32767L; - *(p+iOff)=(short)iVal; -} - -//////////////////////////////////////////////////////////////////////// - -static INLINE int MixREVERBLeft(int ns) -{ - if(iUseReverb==0) return 0; - else - if(iUseReverb==2) - { - static int iCnt=0; // this func will be called with 44.1 khz - - if(!rvb.StartAddr) // reverb is off - { - rvb.iLastRVBLeft=rvb.iLastRVBRight=rvb.iRVBLeft=rvb.iRVBRight=0; - return 0; - } - - iCnt++; - - if(iCnt&1) // we work on every second left value: downsample to 22 khz - { - if(spuCtrl&0x80) // -> reverb on? oki - { - int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1; - - const int INPUT_SAMPLE_L=*(sRVBStart+(ns<<1)); - const int INPUT_SAMPLE_R=*(sRVBStart+(ns<<1)+1); - - const int IIR_INPUT_A0 = (g_buffer(rvb.IIR_SRC_A0) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb.IN_COEF_L)/32768L; - const int IIR_INPUT_A1 = (g_buffer(rvb.IIR_SRC_A1) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb.IN_COEF_R)/32768L; - const int IIR_INPUT_B0 = (g_buffer(rvb.IIR_SRC_B0) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb.IN_COEF_L)/32768L; - const int IIR_INPUT_B1 = (g_buffer(rvb.IIR_SRC_B1) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb.IN_COEF_R)/32768L; - - const int IIR_A0 = (IIR_INPUT_A0 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_A0) * (32768L - rvb.IIR_ALPHA))/32768L; - const int IIR_A1 = (IIR_INPUT_A1 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_A1) * (32768L - rvb.IIR_ALPHA))/32768L; - const int IIR_B0 = (IIR_INPUT_B0 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_B0) * (32768L - rvb.IIR_ALPHA))/32768L; - const int IIR_B1 = (IIR_INPUT_B1 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_B1) * (32768L - rvb.IIR_ALPHA))/32768L; - - s_buffer1(rvb.IIR_DEST_A0, IIR_A0); - s_buffer1(rvb.IIR_DEST_A1, IIR_A1); - s_buffer1(rvb.IIR_DEST_B0, IIR_B0); - s_buffer1(rvb.IIR_DEST_B1, IIR_B1); - - ACC0 = (g_buffer(rvb.ACC_SRC_A0) * rvb.ACC_COEF_A)/32768L + - (g_buffer(rvb.ACC_SRC_B0) * rvb.ACC_COEF_B)/32768L + - (g_buffer(rvb.ACC_SRC_C0) * rvb.ACC_COEF_C)/32768L + - (g_buffer(rvb.ACC_SRC_D0) * rvb.ACC_COEF_D)/32768L; - ACC1 = (g_buffer(rvb.ACC_SRC_A1) * rvb.ACC_COEF_A)/32768L + - (g_buffer(rvb.ACC_SRC_B1) * rvb.ACC_COEF_B)/32768L + - (g_buffer(rvb.ACC_SRC_C1) * rvb.ACC_COEF_C)/32768L + - (g_buffer(rvb.ACC_SRC_D1) * rvb.ACC_COEF_D)/32768L; - - FB_A0 = g_buffer(rvb.MIX_DEST_A0 - rvb.FB_SRC_A); - FB_A1 = g_buffer(rvb.MIX_DEST_A1 - rvb.FB_SRC_A); - FB_B0 = g_buffer(rvb.MIX_DEST_B0 - rvb.FB_SRC_B); - FB_B1 = g_buffer(rvb.MIX_DEST_B1 - rvb.FB_SRC_B); - - s_buffer(rvb.MIX_DEST_A0, ACC0 - (FB_A0 * rvb.FB_ALPHA)/32768L); - s_buffer(rvb.MIX_DEST_A1, ACC1 - (FB_A1 * rvb.FB_ALPHA)/32768L); - - s_buffer(rvb.MIX_DEST_B0, (rvb.FB_ALPHA * ACC0)/32768L - (FB_A0 * (int)(rvb.FB_ALPHA^0xFFFF8000))/32768L - (FB_B0 * rvb.FB_X)/32768L); - s_buffer(rvb.MIX_DEST_B1, (rvb.FB_ALPHA * ACC1)/32768L - (FB_A1 * (int)(rvb.FB_ALPHA^0xFFFF8000))/32768L - (FB_B1 * rvb.FB_X)/32768L); - - rvb.iLastRVBLeft = rvb.iRVBLeft; - rvb.iLastRVBRight = rvb.iRVBRight; - - rvb.iRVBLeft = (g_buffer(rvb.MIX_DEST_A0)+g_buffer(rvb.MIX_DEST_B0))/3; - rvb.iRVBRight = (g_buffer(rvb.MIX_DEST_A1)+g_buffer(rvb.MIX_DEST_B1))/3; - - rvb.iRVBLeft = (rvb.iRVBLeft * rvb.VolLeft) / 0x4000; - rvb.iRVBRight = (rvb.iRVBRight * rvb.VolRight) / 0x4000; - - rvb.CurrAddr++; - if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr; - - return rvb.iLastRVBLeft+(rvb.iRVBLeft-rvb.iLastRVBLeft)/2; - } - else // -> reverb off - { - rvb.iLastRVBLeft=rvb.iLastRVBRight=rvb.iRVBLeft=rvb.iRVBRight=0; - } - - rvb.CurrAddr++; - if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr; - } - - return rvb.iLastRVBLeft; - } - else // easy fake reverb: - { - const int iRV=*sRVBPlay; // -> simply take the reverb mix buf value - *sRVBPlay++=0; // -> init it after - if(sRVBPlay>=sRVBEnd) sRVBPlay=sRVBStart; // -> and take care about wrap arounds - return iRV; // -> return reverb mix buf val - } -} - -//////////////////////////////////////////////////////////////////////// - -static INLINE int MixREVERBRight(void) -{ - if(iUseReverb==0) return 0; - else - if(iUseReverb==2) // Neill's reverb: - { - int i=rvb.iLastRVBRight+(rvb.iRVBRight-rvb.iLastRVBRight)/2; - rvb.iLastRVBRight=rvb.iRVBRight; - return i; // -> just return the last right reverb val (little bit scaled by the previous right val) - } - else // easy fake reverb: - { - const int iRV=*sRVBPlay; // -> simply take the reverb mix buf value - *sRVBPlay++=0; // -> init it after - if(sRVBPlay>=sRVBEnd) sRVBPlay=sRVBStart; // -> and take care about wrap arounds - return iRV; // -> return reverb mix buf val - } -} - -//////////////////////////////////////////////////////////////////////// - -#endif - -/* ------------------------------------------------------------------------------ -PSX reverb hardware notes -by Neill Corlett ------------------------------------------------------------------------------ - -Yadda yadda disclaimer yadda probably not perfect yadda well it's okay anyway -yadda yadda. - ------------------------------------------------------------------------------ - -Basics ------- - -- The reverb buffer is 22khz 16-bit mono PCM. -- It starts at the reverb address given by 1DA2, extends to - the end of sound RAM, and wraps back to the 1DA2 address. - -Setting the address at 1DA2 resets the current reverb work address. - -This work address ALWAYS increments every 1/22050 sec., regardless of -whether reverb is enabled (bit 7 of 1DAA set). - -And the contents of the reverb buffer ALWAYS play, scaled by the -"reverberation depth left/right" volumes (1D84/1D86). -(which, by the way, appear to be scaled so 3FFF=approx. 1.0, 4000=-1.0) - ------------------------------------------------------------------------------ - -Register names --------------- - -These are probably not their real names. -These are probably not even correct names. -We will use them anyway, because we can. - -1DC0: FB_SRC_A (offset) -1DC2: FB_SRC_B (offset) -1DC4: IIR_ALPHA (coef.) -1DC6: ACC_COEF_A (coef.) -1DC8: ACC_COEF_B (coef.) -1DCA: ACC_COEF_C (coef.) -1DCC: ACC_COEF_D (coef.) -1DCE: IIR_COEF (coef.) -1DD0: FB_ALPHA (coef.) -1DD2: FB_X (coef.) -1DD4: IIR_DEST_A0 (offset) -1DD6: IIR_DEST_A1 (offset) -1DD8: ACC_SRC_A0 (offset) -1DDA: ACC_SRC_A1 (offset) -1DDC: ACC_SRC_B0 (offset) -1DDE: ACC_SRC_B1 (offset) -1DE0: IIR_SRC_A0 (offset) -1DE2: IIR_SRC_A1 (offset) -1DE4: IIR_DEST_B0 (offset) -1DE6: IIR_DEST_B1 (offset) -1DE8: ACC_SRC_C0 (offset) -1DEA: ACC_SRC_C1 (offset) -1DEC: ACC_SRC_D0 (offset) -1DEE: ACC_SRC_D1 (offset) -1DF0: IIR_SRC_B1 (offset) -1DF2: IIR_SRC_B0 (offset) -1DF4: MIX_DEST_A0 (offset) -1DF6: MIX_DEST_A1 (offset) -1DF8: MIX_DEST_B0 (offset) -1DFA: MIX_DEST_B1 (offset) -1DFC: IN_COEF_L (coef.) -1DFE: IN_COEF_R (coef.) - -The coefficients are signed fractional values. --32768 would be -1.0 - 32768 would be 1.0 (if it were possible... the highest is of course 32767) - -The offsets are (byte/8) offsets into the reverb buffer. -i.e. you multiply them by 8, you get byte offsets. -You can also think of them as (samples/4) offsets. -They appear to be signed. They can be negative. -None of the documented presets make them negative, though. - -Yes, 1DF0 and 1DF2 appear to be backwards. Not a typo. - ------------------------------------------------------------------------------ - -What it does ------------- - -We take all reverb sources: -- regular channels that have the reverb bit on -- cd and external sources, if their reverb bits are on -and mix them into one stereo 44100hz signal. - -Lowpass/downsample that to 22050hz. The PSX uses a proper bandlimiting -algorithm here, but I haven't figured out the hysterically exact specifics. -I use an 8-tap filter with these coefficients, which are nice but probably -not the real ones: - -0.037828187894 -0.157538631280 -0.321159685278 -0.449322115345 -0.449322115345 -0.321159685278 -0.157538631280 -0.037828187894 - -So we have two input samples (INPUT_SAMPLE_L, INPUT_SAMPLE_R) every 22050hz. - -* IN MY EMULATION, I divide these by 2 to make it clip less. - (and of course the L/R output coefficients are adjusted to compensate) - The real thing appears to not do this. - -At every 22050hz tick: -- If the reverb bit is enabled (bit 7 of 1DAA), execute the reverb - steady-state algorithm described below -- AFTERWARDS, retrieve the "wet out" L and R samples from the reverb buffer - (This part may not be exactly right and I guessed at the coefs. TODO: check later.) - L is: 0.333 * (buffer[MIX_DEST_A0] + buffer[MIX_DEST_B0]) - R is: 0.333 * (buffer[MIX_DEST_A1] + buffer[MIX_DEST_B1]) -- Advance the current buffer position by 1 sample - -The wet out L and R are then upsampled to 44100hz and played at the -"reverberation depth left/right" (1D84/1D86) volume, independent of the main -volume. - ------------------------------------------------------------------------------ - -Reverb steady-state -------------------- - -The reverb steady-state algorithm is fairly clever, and of course by -"clever" I mean "batshit insane". - -buffer[x] is relative to the current buffer position, not the beginning of -the buffer. Note that all buffer offsets must wrap around so they're -contained within the reverb work area. - -Clipping is performed at the end... maybe also sooner, but definitely at -the end. - -IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L; -IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R; -IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L; -IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R; - -IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA); -IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA); -IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA); -IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA); - -buffer[IIR_DEST_A0 + 1sample] = IIR_A0; -buffer[IIR_DEST_A1 + 1sample] = IIR_A1; -buffer[IIR_DEST_B0 + 1sample] = IIR_B0; -buffer[IIR_DEST_B1 + 1sample] = IIR_B1; - -ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A + - buffer[ACC_SRC_B0] * ACC_COEF_B + - buffer[ACC_SRC_C0] * ACC_COEF_C + - buffer[ACC_SRC_D0] * ACC_COEF_D; -ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A + - buffer[ACC_SRC_B1] * ACC_COEF_B + - buffer[ACC_SRC_C1] * ACC_COEF_C + - buffer[ACC_SRC_D1] * ACC_COEF_D; - -FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A]; -FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A]; -FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B]; -FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B]; - -buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA; -buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA; -buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X; -buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X; - ------------------------------------------------------------------------------ -*/ - +/*************************************************************************** + reverb.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 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 "stdafx.h" + +#define _IN_REVERB + +// will be included from spu.c +#ifdef _IN_SPU + +//////////////////////////////////////////////////////////////////////// +// globals +//////////////////////////////////////////////////////////////////////// + +// REVERB info and timing vars... + +int * sRVBPlay = 0; +int * sRVBEnd = 0; +int * sRVBStart = 0; +int iReverbOff = -1; // some delay factor for reverb +int iReverbRepeat = 0; +int iReverbNum = 1; + +//////////////////////////////////////////////////////////////////////// +// SET REVERB +//////////////////////////////////////////////////////////////////////// + +void SetREVERB(unsigned short val) +{ + switch(val) + { + case 0x0000: iReverbOff=-1; break; // off + case 0x007D: iReverbOff=32; iReverbNum=2; iReverbRepeat=128; break; // ok room + + case 0x0033: iReverbOff=32; iReverbNum=2; iReverbRepeat=64; break; // studio small + case 0x00B1: iReverbOff=48; iReverbNum=2; iReverbRepeat=96; break; // ok studio medium + case 0x00E3: iReverbOff=64; iReverbNum=2; iReverbRepeat=128; break; // ok studio large ok + + case 0x01A5: iReverbOff=128; iReverbNum=4; iReverbRepeat=32; break; // ok hall + case 0x033D: iReverbOff=256; iReverbNum=4; iReverbRepeat=64; break; // space echo + case 0x0001: iReverbOff=184; iReverbNum=3; iReverbRepeat=128; break; // echo/delay + case 0x0017: iReverbOff=128; iReverbNum=2; iReverbRepeat=128; break; // half echo + default: iReverbOff=32; iReverbNum=1; iReverbRepeat=0; break; + } +} + +//////////////////////////////////////////////////////////////////////// +// START REVERB +//////////////////////////////////////////////////////////////////////// + +INLINE void StartREVERB(int ch) +{ + if(s_chan[ch].bReverb && (spuCtrl&0x80)) // reverb possible? + { + if(iUseReverb==2) s_chan[ch].bRVBActive=1; + else + if(iUseReverb==1 && iReverbOff>0) // -> fake reverb used? + { + s_chan[ch].bRVBActive=1; // -> activate it + s_chan[ch].iRVBOffset=iReverbOff*45; + s_chan[ch].iRVBRepeat=iReverbRepeat*45; + s_chan[ch].iRVBNum =iReverbNum; + } + } + else s_chan[ch].bRVBActive=0; // else -> no reverb +} + +//////////////////////////////////////////////////////////////////////// +// HELPER FOR NEILL'S REVERB: re-inits our reverb mixing buf +//////////////////////////////////////////////////////////////////////// + +INLINE void InitREVERB(void) +{ + if(iUseReverb==2) + {memset(sRVBStart,0,NSSIZE*2*4);} +} + +//////////////////////////////////////////////////////////////////////// +// STORE REVERB +//////////////////////////////////////////////////////////////////////// + +INLINE void StoreREVERB(int ch,int ns) +{ + if(iUseReverb==0) return; + else + if(iUseReverb==2) // -------------------------------- // Neil's reverb + { + const int iRxl=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000; + const int iRxr=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000; + + ns<<=1; + + *(sRVBStart+ns) +=iRxl; // -> we mix all active reverb channels into an extra buffer + *(sRVBStart+ns+1)+=iRxr; + } + else // --------------------------------------------- // Pete's easy fake reverb + { + int * pN;int iRn,iRr=0; + + // we use the half channel volume (/0x8000) for the first reverb effects, quarter for next and so on + + int iRxl=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x8000; + int iRxr=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x8000; + + for(iRn=1;iRn<=s_chan[ch].iRVBNum;iRn++,iRr+=s_chan[ch].iRVBRepeat,iRxl/=2,iRxr/=2) + { + pN=sRVBPlay+((s_chan[ch].iRVBOffset+iRr+ns)<<1); + if(pN>=sRVBEnd) pN=sRVBStart+(pN-sRVBEnd); + + (*pN)+=iRxl; + pN++; + (*pN)+=iRxr; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int g_buffer(int iOff) // get_buffer content helper: takes care about wraps +{ + short * p=(short *)spuMem; + iOff=(iOff*4)+rvb.CurrAddr; + while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000); + while(iOff0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000); + while(iOff32767L) iVal=32767L; + *(p+iOff)=(short)iVal; +} + +//////////////////////////////////////////////////////////////////////// + +INLINE void s_buffer1(int iOff,int iVal) // set_buffer (+1 sample) content helper: takes care about wraps and clipping +{ + short * p=(short *)spuMem; + iOff=(iOff*4)+rvb.CurrAddr+1; + while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000); + while(iOff32767L) iVal=32767L; + *(p+iOff)=(short)iVal; +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int MixREVERBLeft(int ns) +{ + if(iUseReverb==0) return 0; + else + if(iUseReverb==2) + { + static int iCnt=0; // this func will be called with 44.1 khz + + if(!rvb.StartAddr) // reverb is off + { + rvb.iLastRVBLeft=rvb.iLastRVBRight=rvb.iRVBLeft=rvb.iRVBRight=0; + return 0; + } + + iCnt++; + + if(iCnt&1) // we work on every second left value: downsample to 22 khz + { + if(spuCtrl&0x80) // -> reverb on? oki + { + int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1; + + const int INPUT_SAMPLE_L=*(sRVBStart+(ns<<1)); + const int INPUT_SAMPLE_R=*(sRVBStart+(ns<<1)+1); + + const int IIR_INPUT_A0 = (g_buffer(rvb.IIR_SRC_A0) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb.IN_COEF_L)/32768L; + const int IIR_INPUT_A1 = (g_buffer(rvb.IIR_SRC_A1) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb.IN_COEF_R)/32768L; + const int IIR_INPUT_B0 = (g_buffer(rvb.IIR_SRC_B0) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb.IN_COEF_L)/32768L; + const int IIR_INPUT_B1 = (g_buffer(rvb.IIR_SRC_B1) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb.IN_COEF_R)/32768L; + + const int IIR_A0 = (IIR_INPUT_A0 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_A0) * (32768L - rvb.IIR_ALPHA))/32768L; + const int IIR_A1 = (IIR_INPUT_A1 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_A1) * (32768L - rvb.IIR_ALPHA))/32768L; + const int IIR_B0 = (IIR_INPUT_B0 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_B0) * (32768L - rvb.IIR_ALPHA))/32768L; + const int IIR_B1 = (IIR_INPUT_B1 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_B1) * (32768L - rvb.IIR_ALPHA))/32768L; + + s_buffer1(rvb.IIR_DEST_A0, IIR_A0); + s_buffer1(rvb.IIR_DEST_A1, IIR_A1); + s_buffer1(rvb.IIR_DEST_B0, IIR_B0); + s_buffer1(rvb.IIR_DEST_B1, IIR_B1); + + ACC0 = (g_buffer(rvb.ACC_SRC_A0) * rvb.ACC_COEF_A)/32768L + + (g_buffer(rvb.ACC_SRC_B0) * rvb.ACC_COEF_B)/32768L + + (g_buffer(rvb.ACC_SRC_C0) * rvb.ACC_COEF_C)/32768L + + (g_buffer(rvb.ACC_SRC_D0) * rvb.ACC_COEF_D)/32768L; + ACC1 = (g_buffer(rvb.ACC_SRC_A1) * rvb.ACC_COEF_A)/32768L + + (g_buffer(rvb.ACC_SRC_B1) * rvb.ACC_COEF_B)/32768L + + (g_buffer(rvb.ACC_SRC_C1) * rvb.ACC_COEF_C)/32768L + + (g_buffer(rvb.ACC_SRC_D1) * rvb.ACC_COEF_D)/32768L; + + FB_A0 = g_buffer(rvb.MIX_DEST_A0 - rvb.FB_SRC_A); + FB_A1 = g_buffer(rvb.MIX_DEST_A1 - rvb.FB_SRC_A); + FB_B0 = g_buffer(rvb.MIX_DEST_B0 - rvb.FB_SRC_B); + FB_B1 = g_buffer(rvb.MIX_DEST_B1 - rvb.FB_SRC_B); + + s_buffer(rvb.MIX_DEST_A0, ACC0 - (FB_A0 * rvb.FB_ALPHA)/32768L); + s_buffer(rvb.MIX_DEST_A1, ACC1 - (FB_A1 * rvb.FB_ALPHA)/32768L); + + s_buffer(rvb.MIX_DEST_B0, (rvb.FB_ALPHA * ACC0)/32768L - (FB_A0 * (int)(rvb.FB_ALPHA^0xFFFF8000))/32768L - (FB_B0 * rvb.FB_X)/32768L); + s_buffer(rvb.MIX_DEST_B1, (rvb.FB_ALPHA * ACC1)/32768L - (FB_A1 * (int)(rvb.FB_ALPHA^0xFFFF8000))/32768L - (FB_B1 * rvb.FB_X)/32768L); + + rvb.iLastRVBLeft = rvb.iRVBLeft; + rvb.iLastRVBRight = rvb.iRVBRight; + + rvb.iRVBLeft = (g_buffer(rvb.MIX_DEST_A0)+g_buffer(rvb.MIX_DEST_B0))/3; + rvb.iRVBRight = (g_buffer(rvb.MIX_DEST_A1)+g_buffer(rvb.MIX_DEST_B1))/3; + + rvb.iRVBLeft = (rvb.iRVBLeft * rvb.VolLeft) / 0x4000; + rvb.iRVBRight = (rvb.iRVBRight * rvb.VolRight) / 0x4000; + + rvb.CurrAddr++; + if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr; + + return rvb.iLastRVBLeft+(rvb.iRVBLeft-rvb.iLastRVBLeft)/2; + } + else // -> reverb off + { + rvb.iLastRVBLeft=rvb.iLastRVBRight=rvb.iRVBLeft=rvb.iRVBRight=0; + } + + rvb.CurrAddr++; + if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr; + } + + return rvb.iLastRVBLeft; + } + else // easy fake reverb: + { + const int iRV=*sRVBPlay; // -> simply take the reverb mix buf value + *sRVBPlay++=0; // -> init it after + if(sRVBPlay>=sRVBEnd) sRVBPlay=sRVBStart; // -> and take care about wrap arounds + return iRV; // -> return reverb mix buf val + } +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int MixREVERBRight(void) +{ + if(iUseReverb==0) return 0; + else + if(iUseReverb==2) // Neill's reverb: + { + int i=rvb.iLastRVBRight+(rvb.iRVBRight-rvb.iLastRVBRight)/2; + rvb.iLastRVBRight=rvb.iRVBRight; + return i; // -> just return the last right reverb val (little bit scaled by the previous right val) + } + else // easy fake reverb: + { + const int iRV=*sRVBPlay; // -> simply take the reverb mix buf value + *sRVBPlay++=0; // -> init it after + if(sRVBPlay>=sRVBEnd) sRVBPlay=sRVBStart; // -> and take care about wrap arounds + return iRV; // -> return reverb mix buf val + } +} + +//////////////////////////////////////////////////////////////////////// + +#endif + +/* +----------------------------------------------------------------------------- +PSX reverb hardware notes +by Neill Corlett +----------------------------------------------------------------------------- + +Yadda yadda disclaimer yadda probably not perfect yadda well it's okay anyway +yadda yadda. + +----------------------------------------------------------------------------- + +Basics +------ + +- The reverb buffer is 22khz 16-bit mono PCM. +- It starts at the reverb address given by 1DA2, extends to + the end of sound RAM, and wraps back to the 1DA2 address. + +Setting the address at 1DA2 resets the current reverb work address. + +This work address ALWAYS increments every 1/22050 sec., regardless of +whether reverb is enabled (bit 7 of 1DAA set). + +And the contents of the reverb buffer ALWAYS play, scaled by the +"reverberation depth left/right" volumes (1D84/1D86). +(which, by the way, appear to be scaled so 3FFF=approx. 1.0, 4000=-1.0) + +----------------------------------------------------------------------------- + +Register names +-------------- + +These are probably not their real names. +These are probably not even correct names. +We will use them anyway, because we can. + +1DC0: FB_SRC_A (offset) +1DC2: FB_SRC_B (offset) +1DC4: IIR_ALPHA (coef.) +1DC6: ACC_COEF_A (coef.) +1DC8: ACC_COEF_B (coef.) +1DCA: ACC_COEF_C (coef.) +1DCC: ACC_COEF_D (coef.) +1DCE: IIR_COEF (coef.) +1DD0: FB_ALPHA (coef.) +1DD2: FB_X (coef.) +1DD4: IIR_DEST_A0 (offset) +1DD6: IIR_DEST_A1 (offset) +1DD8: ACC_SRC_A0 (offset) +1DDA: ACC_SRC_A1 (offset) +1DDC: ACC_SRC_B0 (offset) +1DDE: ACC_SRC_B1 (offset) +1DE0: IIR_SRC_A0 (offset) +1DE2: IIR_SRC_A1 (offset) +1DE4: IIR_DEST_B0 (offset) +1DE6: IIR_DEST_B1 (offset) +1DE8: ACC_SRC_C0 (offset) +1DEA: ACC_SRC_C1 (offset) +1DEC: ACC_SRC_D0 (offset) +1DEE: ACC_SRC_D1 (offset) +1DF0: IIR_SRC_B1 (offset) +1DF2: IIR_SRC_B0 (offset) +1DF4: MIX_DEST_A0 (offset) +1DF6: MIX_DEST_A1 (offset) +1DF8: MIX_DEST_B0 (offset) +1DFA: MIX_DEST_B1 (offset) +1DFC: IN_COEF_L (coef.) +1DFE: IN_COEF_R (coef.) + +The coefficients are signed fractional values. +-32768 would be -1.0 + 32768 would be 1.0 (if it were possible... the highest is of course 32767) + +The offsets are (byte/8) offsets into the reverb buffer. +i.e. you multiply them by 8, you get byte offsets. +You can also think of them as (samples/4) offsets. +They appear to be signed. They can be negative. +None of the documented presets make them negative, though. + +Yes, 1DF0 and 1DF2 appear to be backwards. Not a typo. + +----------------------------------------------------------------------------- + +What it does +------------ + +We take all reverb sources: +- regular channels that have the reverb bit on +- cd and external sources, if their reverb bits are on +and mix them into one stereo 44100hz signal. + +Lowpass/downsample that to 22050hz. The PSX uses a proper bandlimiting +algorithm here, but I haven't figured out the hysterically exact specifics. +I use an 8-tap filter with these coefficients, which are nice but probably +not the real ones: + +0.037828187894 +0.157538631280 +0.321159685278 +0.449322115345 +0.449322115345 +0.321159685278 +0.157538631280 +0.037828187894 + +So we have two input samples (INPUT_SAMPLE_L, INPUT_SAMPLE_R) every 22050hz. + +* IN MY EMULATION, I divide these by 2 to make it clip less. + (and of course the L/R output coefficients are adjusted to compensate) + The real thing appears to not do this. + +At every 22050hz tick: +- If the reverb bit is enabled (bit 7 of 1DAA), execute the reverb + steady-state algorithm described below +- AFTERWARDS, retrieve the "wet out" L and R samples from the reverb buffer + (This part may not be exactly right and I guessed at the coefs. TODO: check later.) + L is: 0.333 * (buffer[MIX_DEST_A0] + buffer[MIX_DEST_B0]) + R is: 0.333 * (buffer[MIX_DEST_A1] + buffer[MIX_DEST_B1]) +- Advance the current buffer position by 1 sample + +The wet out L and R are then upsampled to 44100hz and played at the +"reverberation depth left/right" (1D84/1D86) volume, independent of the main +volume. + +----------------------------------------------------------------------------- + +Reverb steady-state +------------------- + +The reverb steady-state algorithm is fairly clever, and of course by +"clever" I mean "batshit insane". + +buffer[x] is relative to the current buffer position, not the beginning of +the buffer. Note that all buffer offsets must wrap around so they're +contained within the reverb work area. + +Clipping is performed at the end... maybe also sooner, but definitely at +the end. + +IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L; +IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R; +IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L; +IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R; + +IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA); +IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA); +IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA); +IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA); + +buffer[IIR_DEST_A0 + 1sample] = IIR_A0; +buffer[IIR_DEST_A1 + 1sample] = IIR_A1; +buffer[IIR_DEST_B0 + 1sample] = IIR_B0; +buffer[IIR_DEST_B1 + 1sample] = IIR_B1; + +ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A + + buffer[ACC_SRC_B0] * ACC_COEF_B + + buffer[ACC_SRC_C0] * ACC_COEF_C + + buffer[ACC_SRC_D0] * ACC_COEF_D; +ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A + + buffer[ACC_SRC_B1] * ACC_COEF_B + + buffer[ACC_SRC_C1] * ACC_COEF_C + + buffer[ACC_SRC_D1] * ACC_COEF_D; + +FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A]; +FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A]; +FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B]; +FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B]; + +buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA; +buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA; +buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X; +buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X; + +----------------------------------------------------------------------------- +*/ + diff --git a/plugins/dfsound/sdl.c b/plugins/dfsound/sdl.c index f3cf92d2..5f80a1ff 100644 --- a/plugins/dfsound/sdl.c +++ b/plugins/dfsound/sdl.c @@ -1,137 +1,135 @@ -/* SDL Driver for P.E.Op.S Sound Plugin - * Copyright (c) 2010, Wei Mingzhi . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA - */ - -#include "stdafx.h" - -#include "dsoundoss.h" - -#include "externals.h" -#include - -#define BUFFER_SIZE 22050 - -short *pSndBuffer = NULL; -int iBufSize = 0; -volatile int iReadPos = 0, iWritePos = 0; - -static void SOUND_FillAudio(void *unused, Uint8 *stream, int len) { - short *p = (short *)stream; - - len /= sizeof(short); - - while (iReadPos != iWritePos && len > 0) { - *p++ = pSndBuffer[iReadPos++]; - if (iReadPos >= iBufSize) iReadPos = 0; - --len; - } - - // Fill remaining space with zero - while (len > 0) { - *p++ = 0; - --len; - } -} - -static void InitSDL() { - if (SDL_WasInit(SDL_INIT_EVERYTHING)) { - SDL_InitSubSystem(SDL_INIT_AUDIO); - } else { - SDL_Init(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE); - } -} - -static void DestroySDL() { - if (SDL_WasInit(SDL_INIT_EVERYTHING & ~SDL_INIT_AUDIO)) { - SDL_QuitSubSystem(SDL_INIT_AUDIO); - } else { - SDL_Quit(); - } -} - -void SetupSound(void) { - SDL_AudioSpec spec; - - if (pSndBuffer != NULL) return; - - InitSDL(); - - spec.freq = 44100; - spec.format = AUDIO_S16SYS; - spec.channels = iDisStereo ? 1 : 2; - spec.samples = 1024; - spec.callback = SOUND_FillAudio; - - if (SDL_OpenAudio(&spec, NULL) < 0) { - DestroySDL(); - return; - } - - iBufSize = BUFFER_SIZE; - if (iDisStereo) iBufSize /= 2; - - pSndBuffer = (short *)malloc(iBufSize * sizeof(short)); - if (pSndBuffer == NULL) { - SDL_CloseAudio(); - return; - } - - iReadPos = 0; - iWritePos = 0; - - SDL_PauseAudio(0); -} - -void RemoveSound(void) { - if (pSndBuffer == NULL) return; - - SDL_CloseAudio(); - DestroySDL(); - - free(pSndBuffer); - pSndBuffer = NULL; -} - -unsigned long SoundGetBytesBuffered(void) { - int size; - - if (pSndBuffer == NULL) return SOUNDSIZE; - - size = iReadPos - iWritePos; - if (size <= 0) size += iBufSize; - - if (size < iBufSize / 2) return SOUNDSIZE; - - return 0; -} - -void SoundFeedStreamData(unsigned char *pSound, long lBytes) { - short *p = (short *)pSound; - - if (pSndBuffer == NULL) return; - - while (lBytes > 0) { - if (((iWritePos + 1) % iBufSize) == iReadPos) break; - - pSndBuffer[iWritePos] = *p++; - - ++iWritePos; - if (iWritePos >= iBufSize) iWritePos = 0; - - lBytes -= sizeof(short); - } -} +/* SDL Driver for P.E.Op.S Sound Plugin + * Copyright (c) 2010, Wei Mingzhi . + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA + */ + +#include "stdafx.h" + +#include "externals.h" +#include + +#define BUFFER_SIZE 22050 + +short *pSndBuffer = NULL; +int iBufSize = 0; +volatile int iReadPos = 0, iWritePos = 0; + +static void SOUND_FillAudio(void *unused, Uint8 *stream, int len) { + short *p = (short *)stream; + + len /= sizeof(short); + + while (iReadPos != iWritePos && len > 0) { + *p++ = pSndBuffer[iReadPos++]; + if (iReadPos >= iBufSize) iReadPos = 0; + --len; + } + + // Fill remaining space with zero + while (len > 0) { + *p++ = 0; + --len; + } +} + +static void InitSDL() { + if (SDL_WasInit(SDL_INIT_EVERYTHING)) { + SDL_InitSubSystem(SDL_INIT_AUDIO); + } else { + SDL_Init(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE); + } +} + +static void DestroySDL() { + if (SDL_WasInit(SDL_INIT_EVERYTHING & ~SDL_INIT_AUDIO)) { + SDL_QuitSubSystem(SDL_INIT_AUDIO); + } else { + SDL_Quit(); + } +} + +void SetupSound(void) { + SDL_AudioSpec spec; + + if (pSndBuffer != NULL) return; + + InitSDL(); + + spec.freq = 44100; + spec.format = AUDIO_S16SYS; + spec.channels = iDisStereo ? 1 : 2; + spec.samples = 1024; + spec.callback = SOUND_FillAudio; + + if (SDL_OpenAudio(&spec, NULL) < 0) { + DestroySDL(); + return; + } + + iBufSize = BUFFER_SIZE; + if (iDisStereo) iBufSize /= 2; + + pSndBuffer = (short *)malloc(iBufSize * sizeof(short)); + if (pSndBuffer == NULL) { + SDL_CloseAudio(); + return; + } + + iReadPos = 0; + iWritePos = 0; + + SDL_PauseAudio(0); +} + +void RemoveSound(void) { + if (pSndBuffer == NULL) return; + + SDL_CloseAudio(); + DestroySDL(); + + free(pSndBuffer); + pSndBuffer = NULL; +} + +unsigned long SoundGetBytesBuffered(void) { + int size; + + if (pSndBuffer == NULL) return SOUNDSIZE; + + size = iReadPos - iWritePos; + if (size <= 0) size += iBufSize; + + if (size < iBufSize / 2) return SOUNDSIZE; + + return 0; +} + +void SoundFeedStreamData(unsigned char *pSound, long lBytes) { + short *p = (short *)pSound; + + if (pSndBuffer == NULL) return; + + while (lBytes > 0) { + if (((iWritePos + 1) % iBufSize) == iReadPos) break; + + pSndBuffer[iWritePos] = *p++; + + ++iWritePos; + if (iWritePos >= iBufSize) iWritePos = 0; + + lBytes -= sizeof(short); + } +} diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c index 36e916a1..56fc6ac8 100644 --- a/plugins/dfsound/spu.c +++ b/plugins/dfsound/spu.c @@ -1,1380 +1,1382 @@ -/*************************************************************************** - spu.c - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 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 "stdafx.h" - -#define _IN_SPU - -#include "externals.h" -#include "cfg.h" -#include "dsoundoss.h" -#include "regs.h" -#include "spu.h" - -#ifdef _WINDOWS -#include "debug.h" -#include "record.h" -#endif - -#if defined (_WINDOWS) -static char * libraryName = N_("DirectSound Driver"); -#elif defined (USEMACOSX) -static char * libraryName = N_("Mac OS X Sound"); -#elif defined (USEALSA) -static char * libraryName = N_("ALSA Sound"); -#elif defined (USEOSS) -static char * libraryName = N_("OSS Sound"); -#elif defined (USESDL) -static char * libraryName = N_("SDL Sound"); -#elif defined (USEPULSEAUDIO) -static char * libraryName = N_("PulseAudio Sound"); -#else -static char * libraryName = N_("NULL Sound"); -#endif -#if 0 -static char * libraryInfo = N_("P.E.Op.S. Sound Driver V1.7\nCoded by Pete Bernert and the P.E.Op.S. team\n"); -#endif - -// globals - -// psx buffer / addresses - -unsigned short regArea[10000]; -unsigned short spuMem[256*1024]; -unsigned char * spuMemC; -unsigned char * pSpuIrq=0; -unsigned char * pSpuBuffer; -unsigned char * pMixIrq=0; - -// user settings - -int iVolume=3; -int iXAPitch=1; -int iUseTimer=2; -int iSPUIRQWait=1; -int iDebugMode=0; -int iRecordMode=0; -int iUseReverb=2; -int iUseInterpolation=2; -int iDisStereo=0; -int iFreqResponse=0; - -// MAIN infos struct for each channel - -SPUCHAN s_chan[MAXCHAN+1]; // channel + 1 infos (1 is security for fmod handling) -REVERBInfo rvb; - -unsigned long dwNoiseVal=1; // global noise generator -unsigned long dwNoiseCount; // global noise generator -unsigned long dwNoiseClock; // global noise generator -int iSpuAsyncWait=0; - -unsigned short spuCtrl=0; // some vars to store psx reg infos -unsigned short spuStat=0; -unsigned short spuIrq=0; -unsigned long spuAddr=0xffffffff; // address into spu mem -int bEndThread=0; // thread handlers -int bThreadEnded=0; -int bSpuInit=0; -int bSPUIsOpen=0; - -#ifdef _WINDOWS -HWND hWMain=0; // window handle -HWND hWDebug=0; -HWND hWRecord=0; -static HANDLE hMainThread; -#else -static pthread_t thread = (pthread_t)-1; // thread id (linux) -#endif - -uint32_t dwNewChannel=0; // flags for faster testing, if new channel starts - -void (CALLBACK *irqCallback)(void)=0; // func of main emu, called on spu irq -void (CALLBACK *cddavCallback)(unsigned short,unsigned short)=0; - -// certain globals (were local before, but with the new timeproc I need em global) - -static const int f[5][2] = { { 0, 0 }, - { 60, 0 }, - { 115, -52 }, - { 98, -55 }, - { 122, -60 } }; -int SSumR[NSSIZE]; -int SSumL[NSSIZE]; -int iFMod[NSSIZE]; -int iCycle = 0; -short * pS; - -int lastch=-1; // last channel processed on spu irq in timer mode -static int lastns=0; // last ns pos -static int iSecureStart=0; // secure start counter - -//////////////////////////////////////////////////////////////////////// -// CODE AREA -//////////////////////////////////////////////////////////////////////// - -// dirty inline func includes - -#include "reverb.c" -#include "adsr.c" - -//////////////////////////////////////////////////////////////////////// -// helpers for simple interpolation - -// -// easy interpolation on upsampling, no special filter, just "Pete's common sense" tm -// -// instead of having n equal sample values in a row like: -// ____ -// |____ -// -// we compare the current delta change with the next delta change. -// -// if curr_delta is positive, -// -// - and next delta is smaller (or changing direction): -// \. -// -__ -// -// - and next delta significant (at least twice) bigger: -// --_ -// \. -// -// - and next delta is nearly same: -// \. -// \. -// -// -// if curr_delta is negative, -// -// - and next delta is smaller (or changing direction): -// _-- -// / -// -// - and next delta significant (at least twice) bigger: -// / -// __- -// -// - and next delta is nearly same: -// / -// / -// - - -static INLINE void InterpolateUp(int ch) -{ - if(s_chan[ch].SB[32]==1) // flag == 1? calc step and set flag... and don't change the value in this pass - { - const int id1=s_chan[ch].SB[30]-s_chan[ch].SB[29]; // curr delta to next val - const int id2=s_chan[ch].SB[31]-s_chan[ch].SB[30]; // and next delta to next-next val :) - - s_chan[ch].SB[32]=0; - - if(id1>0) // curr delta positive - { - if(id2id1) - {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;} - else - if(id2>(id1<<1)) - s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L; - else - s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L; - } - } - else - if(s_chan[ch].SB[32]==2) // flag 1: calc step and set flag... and don't change the value in this pass - { - s_chan[ch].SB[32]=0; - - s_chan[ch].SB[28]=(s_chan[ch].SB[28]*s_chan[ch].sinc)/0x20000L; - if(s_chan[ch].sinc<=0x8000) - s_chan[ch].SB[29]=s_chan[ch].SB[30]-(s_chan[ch].SB[28]*((0x10000/s_chan[ch].sinc)-1)); - else s_chan[ch].SB[29]+=s_chan[ch].SB[28]; - } - else // no flags? add bigger val (if possible), calc smaller step, set flag1 - s_chan[ch].SB[29]+=s_chan[ch].SB[28]; -} - -// -// even easier interpolation on downsampling, also no special filter, again just "Pete's common sense" tm -// - -static INLINE void InterpolateDown(int ch) -{ - if(s_chan[ch].sinc>=0x20000L) // we would skip at least one val? - { - s_chan[ch].SB[29]+=(s_chan[ch].SB[30]-s_chan[ch].SB[29])/2; // add easy weight - if(s_chan[ch].sinc>=0x30000L) // we would skip even more vals? - s_chan[ch].SB[29]+=(s_chan[ch].SB[31]-s_chan[ch].SB[30])/2;// add additional next weight - } -} - -//////////////////////////////////////////////////////////////////////// -// helpers for gauss interpolation - -#define gval0 (((short*)(&s_chan[ch].SB[29]))[gpos]) -#define gval(x) (((short*)(&s_chan[ch].SB[29]))[(gpos+x)&3]) - -#include "gauss_i.h" - -//////////////////////////////////////////////////////////////////////// - -#include "xa.c" - -//////////////////////////////////////////////////////////////////////// -// START SOUND... called by main thread to setup a new sound on a channel -//////////////////////////////////////////////////////////////////////// - -static INLINE void StartSound(int ch) -{ - StartADSR(ch); - StartREVERB(ch); - - // fussy timing issues - do in VoiceOn - //s_chan[ch].pCurr=s_chan[ch].pStart; // set sample start - //s_chan[ch].bStop=0; - //s_chan[ch].bOn=1; - - s_chan[ch].s_1=0; // init mixing vars - s_chan[ch].s_2=0; - s_chan[ch].iSBPos=28; - - s_chan[ch].bNew=0; // init channel flags - - s_chan[ch].SB[29]=0; // init our interpolation helpers - s_chan[ch].SB[30]=0; - - if(iUseInterpolation>=2) // gauss interpolation? - {s_chan[ch].spos=0x30000L;s_chan[ch].SB[28]=0;} // -> start with more decoding - else {s_chan[ch].spos=0x10000L;s_chan[ch].SB[31]=0;} // -> no/simple interpolation starts with one 44100 decoding - - dwNewChannel&=~(1< take it and calc steps - s_chan[ch].sinc=s_chan[ch].iRawPitch<<4; - if(!s_chan[ch].sinc) s_chan[ch].sinc=1; - if(iUseInterpolation==1) s_chan[ch].SB[32]=1; // -> freq change in simle imterpolation mode: set flag -} - -//////////////////////////////////////////////////////////////////////// - -static INLINE void FModChangeFrequency(int ch,int ns) -{ - int NP=s_chan[ch].iRawPitch; - - NP=((32768L+iFMod[ns])*NP)/32768L; - - if(NP>0x3fff) NP=0x3fff; - if(NP<0x1) NP=0x1; - - NP=(44100L*NP)/(4096L); // calc frequency - - s_chan[ch].iActFreq=NP; - s_chan[ch].iUsedFreq=NP; - s_chan[ch].sinc=(((NP/10)<<16)/4410); - if(!s_chan[ch].sinc) s_chan[ch].sinc=1; - if(iUseInterpolation==1) // freq change in simple interpolation mode - s_chan[ch].SB[32]=1; - iFMod[ns]=0; -} - -//////////////////////////////////////////////////////////////////////// - -/* -Noise Algorithm -- Dr.Hell (Xebra PS1 emu) -- 100% accurate (waveform + frequency) -- http://drhell.web.fc2.com - - -Level change cycle -Freq = 0x8000 >> (NoiseClock >> 2); - -Frequency of half cycle -Half = ((NoiseClock & 3) * 2) / (4 + (NoiseClock & 3)); -- 0 = (0*2)/(4+0) = 0/4 -- 1 = (1*2)/(4+1) = 2/5 -- 2 = (2*2)/(4+2) = 4/6 -- 3 = (3*2)/(4+3) = 6/7 - -------------------------------- - -5*6*7 = 210 -4 - 0*0 = 0 -5 - 42*2 = 84 -6 - 35*4 = 140 -7 - 30*6 = 180 -*/ - -// Noise Waveform - Dr. Hell (Xebra) -char NoiseWaveAdd [64] = { - 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1 -}; - -unsigned short NoiseFreqAdd[5] = { - 0, 84, 140, 180, 210 -}; - -static INLINE void NoiseClock() -{ - unsigned int level; - - level = 0x8000 >> (dwNoiseClock >> 2); - level <<= 16; - - dwNoiseCount += 0x10000; - - // Dr. Hell - fraction - dwNoiseCount += NoiseFreqAdd[ dwNoiseClock & 3 ]; - if( (dwNoiseCount&0xffff) >= NoiseFreqAdd[4] ) { - dwNoiseCount += 0x10000; - dwNoiseCount -= NoiseFreqAdd[ dwNoiseClock & 3 ]; - } - - if( dwNoiseCount >= level ) - { - while( dwNoiseCount >= level ) - dwNoiseCount -= level; - - // Dr. Hell - form - dwNoiseVal = (dwNoiseVal<<1) | NoiseWaveAdd[ (dwNoiseVal>>10) & 63 ]; - } -} - -static INLINE int iGetNoiseVal(int ch) -{ - int fa; - - fa = (short) dwNoiseVal; - - // no clip need - //if(fa>32767L) fa=32767L; - //if(fa<-32767L) fa=-32767L; - - // don't upset VAG decoder - //if(iUseInterpolation<2) // no gauss/cubic interpolation? - //pChannel->SB[29] = fa; // -> store noise val in "current sample" slot - - // boost volume - no more! - //return fa * 3 / 2; - return fa; -} - -//////////////////////////////////////////////////////////////////////// - -static INLINE void StoreInterpolationVal(int ch,int fa) -{ - /* - // fmod channel = sound output - if(s_chan[ch].bFMod==2) // fmod freq channel - s_chan[ch].SB[29]=fa; - else - */ - { - if((spuCtrl&0x4000)==0) fa=0; // muted? - else // else adjust - { - if(fa>32767L) fa=32767L; - if(fa<-32767L) fa=-32767L; - } - - if(iUseInterpolation>=2) // gauss/cubic interpolation - { - int gpos = s_chan[ch].SB[28]; - gval0 = fa; - gpos = (gpos+1) & 3; - s_chan[ch].SB[28] = gpos; - } - else - if(iUseInterpolation==1) // simple interpolation - { - s_chan[ch].SB[28] = 0; - s_chan[ch].SB[29] = s_chan[ch].SB[30]; // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour' - s_chan[ch].SB[30] = s_chan[ch].SB[31]; - s_chan[ch].SB[31] = fa; - s_chan[ch].SB[32] = 1; // -> flag: calc new interolation - } - else s_chan[ch].SB[29]=fa; // no interpolation - } -} - -//////////////////////////////////////////////////////////////////////// - -static INLINE int iGetInterpolationVal(int ch) -{ - int fa; - - // fmod channel = sound output - //if(s_chan[ch].bFMod==2) return s_chan[ch].SB[29]; - - switch(iUseInterpolation) - { - //--------------------------------------------------// - case 3: // cubic interpolation - { - long xd;int gpos; - xd = ((s_chan[ch].spos) >> 1)+1; - gpos = s_chan[ch].SB[28]; - - fa = gval(3) - 3*gval(2) + 3*gval(1) - gval0; - fa *= (xd - (2<<15)) / 6; - fa >>= 15; - fa += gval(2) - gval(1) - gval(1) + gval0; - fa *= (xd - (1<<15)) >> 1; - fa >>= 15; - fa += gval(1) - gval0; - fa *= xd; - fa >>= 15; - fa = fa + gval0; - - } break; - //--------------------------------------------------// - case 2: // gauss interpolation - { - int vl, vr;int gpos; - vl = (s_chan[ch].spos >> 6) & ~3; - gpos = s_chan[ch].SB[28]; - vr=(gauss[vl]*gval0)&~2047; - vr+=(gauss[vl+1]*gval(1))&~2047; - vr+=(gauss[vl+2]*gval(2))&~2047; - vr+=(gauss[vl+3]*gval(3))&~2047; - fa = vr>>11; - } break; - //--------------------------------------------------// - case 1: // simple interpolation - { - if(s_chan[ch].sinc<0x10000L) // -> upsampling? - InterpolateUp(ch); // --> interpolate up - else InterpolateDown(ch); // --> else down - fa=s_chan[ch].SB[29]; - } break; - //--------------------------------------------------// - default: // no interpolation - { - fa=s_chan[ch].SB[29]; - } break; - //--------------------------------------------------// - } - - return fa; -} - -//////////////////////////////////////////////////////////////////////// -// MAIN SPU FUNCTION -// here is the main job handler... thread, timer or direct func call -// basically the whole sound processing is done in this fat func! -//////////////////////////////////////////////////////////////////////// - -// 5 ms waiting phase, if buffer is full and no new sound has to get started -// .. can be made smaller (smallest val: 1 ms), but bigger waits give -// better performance - -#define PAUSE_W 1 -#define PAUSE_L 1000 - -//////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS -static VOID CALLBACK MAINProc(UINT nTimerId, UINT msg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) -#else -static void *MAINThread(void *arg) -#endif -{ - int s_1,s_2,fa,ns; - int voldiv = iVolume; - - unsigned char * start;unsigned int nSample; - int ch,predict_nr,shift_factor,flags,d,s; - int bIRQReturn=0; - - // mute output - if( voldiv == 5 ) voldiv = 0x7fffffff; - - while(!bEndThread) // until we are shutting down - { - // ok, at the beginning we are looking if there is - // enuff free place in the dsound/oss buffer to - // fill in new data, or if there is a new channel to start. - // if not, we wait (thread) or return (timer/spuasync) - // until enuff free place is available/a new channel gets - // started - - if(dwNewChannel) // new channel should start immedately? - { // (at least one bit 0 ... MAXCHANNEL is set?) - iSecureStart++; // -> set iSecure - if(iSecureStart>1) iSecureStart=0; // (if it is set 5 times - that means on 5 tries a new samples has been started - in a row, we will reset it, to give the sound update a chance) - } - else iSecureStart=0; // 0: no new channel should start - - while(!iSecureStart && !bEndThread && // no new start? no thread end? - (SoundGetBytesBuffered()>TESTSIZE)) // and still enuff data in sound buffer? - { - iSecureStart=0; // reset secure - -#ifdef _WINDOWS - if(iUseTimer) // no-thread mode? - { - if(iUseTimer==1) // -> ok, timer mode 1: setup a oneshot timer of x ms to wait - timeSetEvent(PAUSE_W,1,MAINProc,0,TIME_ONESHOT); - return; // -> and done this time (timer mode 1 or 2) - } - // win thread mode: - Sleep(PAUSE_W); // sleep for x ms (win) -#else - if(iUseTimer) return 0; // linux no-thread mode? bye - usleep(PAUSE_L); // else sleep for x ms (linux) -#endif - - if(dwNewChannel) iSecureStart=1; // if a new channel kicks in (or, of course, sound buffer runs low), we will leave the loop - } - - //--------------------------------------------------// continue from irq handling in timer mode? - - if(lastch>=0) // will be -1 if no continue is pending - { - ch=lastch; ns=lastns; lastch=-1; // -> setup all kind of vars to continue - goto GOON; // -> directly jump to the continue point - } - - //--------------------------------------------------// - //- main channel loop -// - //--------------------------------------------------// - { - ns=0; - while(ns=0x10000L) - { - if(s_chan[ch].iSBPos==28) // 28 reached? - { -#if 0 - // Xenogears - Anima Relic dungeon (exp gain) - if( s_chan[ch].bLoopJump == 1 ) - s_chan[ch].pCurr = s_chan[ch].pLoop; - - s_chan[ch].bLoopJump = 0; -#endif - - - start=s_chan[ch].pCurr; // set up the current pos - - if (s_chan[ch].iSilent==1 || start == (unsigned char*)-1) // special "stop" sign - { - // silence = let channel keep running (IRQs) - //s_chan[ch].bOn=0; // -> turn everything off - s_chan[ch].iSilent=2; - - s_chan[ch].ADSRX.lVolume=0; - s_chan[ch].ADSRX.EnvelopeVol=0; - } - - s_chan[ch].iSBPos=0; - - //////////////////////////////////////////// spu irq handler here? mmm... do it later - - s_1=s_chan[ch].s_1; - s_2=s_chan[ch].s_2; - - predict_nr=(int)*start;start++; - shift_factor=predict_nr&0xf; - predict_nr >>= 4; - flags=(int)*start;start++; - - // -------------------------------------- // - - for (nSample=0;nSample<28;start++) - { - d=(int)*start; - s=((d&0xf)<<12); - if(s&0x8000) s|=0xffff0000; - - fa=(s >> shift_factor); - fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); - s_2=s_1;s_1=fa; - s=((d & 0xf0) << 8); - - s_chan[ch].SB[nSample++]=fa; - - if(s&0x8000) s|=0xffff0000; - fa=(s>>shift_factor); - fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); - s_2=s_1;s_1=fa; - - s_chan[ch].SB[nSample++]=fa; - } - - //////////////////////////////////////////// irq check - - if(irqCallback && (spuCtrl&0x40)) // some callback and irq active? - { - if((pSpuIrq > start-16 && // irq address reached? - pSpuIrq <= start) || - ((flags&1) && // special: irq on looping addr, when stop/loop flag is set - (pSpuIrq > s_chan[ch].pLoop-16 && - pSpuIrq <= s_chan[ch].pLoop))) - { - s_chan[ch].iIrqDone=1; // -> debug flag - irqCallback(); // -> call main emu - - if(iSPUIRQWait) // -> option: wait after irq for main emu - { - iSpuAsyncWait=1; - bIRQReturn=1; - } - } - } - - //////////////////////////////////////////// flag handler - - /* - SPU2-X: - $4 = set loop to current block - $2 = keep envelope on (no mute) - $1 = jump to loop address - - silence means no volume (ADSR keeps playing!!) - */ - -#if 0 - if(flags&4) - s_chan[ch].pLoop=start-16; -#else - // Jungle Book - Rhythm 'n Groove - use external loop address - // - fixes music player (+IRQ generate) - if((flags&4) && (s_chan[ch].bIgnoreLoop == 0)) - s_chan[ch].pLoop=start-16; -#endif - - // Jungle Book - Rhythm 'n Groove - don't reset ignore status - // - fixes gameplay speed (IRQ hits) - //s_chan[ch].bIgnoreLoop = 0; - - - if(flags&1) - { - // ...? - //s_chan[ch].bIgnoreLoop = 0; - - // Xenogears - 7 = play missing sounds -#if 0 - // set jump flag - pChannel->bLoopJump = 1; -#else - start = s_chan[ch].pLoop; -#endif - - // silence = keep playing..? - if( (flags&2) == 0 ) { - s_chan[ch].iSilent = 1; - - // silence = don't start release phase - //s_chan[ch].bStop = 1; - - //start = (unsigned char *) -1; - } - } - -#if 0 - // crash check - if( start == 0 ) - start = (unsigned char *) -1; - if( start >= spuMemC + 0x80000 ) - start = spuMemC - 0x80000; -#endif - - s_chan[ch].pCurr=start; // store values for next cycle - s_chan[ch].s_1=s_1; - s_chan[ch].s_2=s_2; - - if(bIRQReturn) // special return for "spu irq - wait for cpu action" - { - bIRQReturn=0; - if(iUseTimer!=2) - { - DWORD dwWatchTime=timeGetTime_spu()+2500; - - while(iSpuAsyncWait && !bEndThread && - timeGetTime_spu() store 1T sample data, use that to do fmod on next channel - - // mix fmod channel into output - // - Xenogears save icon (high pitch) - { - ////////////////////////////////////////////// - // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff) - - if(s_chan[ch].iMute) - s_chan[ch].sval=0; // debug mute - else - { - SSumL[ns]+=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000L; - SSumR[ns]+=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000L; - } - - ////////////////////////////////////////////// - // now let us store sound data for reverb - - if(s_chan[ch].bRVBActive) StoreREVERB(ch,ns); - } - - s_chan[ch].spos += s_chan[ch].sinc; - } - //////////////////////////////////////////////// - // ok, go on until 1 ms data of this channel is collected - - ns++; - } // end ns - } - - //---------------------------------------------------// - //- here we have another 1 ms of sound data - //---------------------------------------------------// - // mix XA infos (if any) - - MixXA(); - - /////////////////////////////////////////////////////// - // mix all channels (including reverb) into one buffer - - if(iDisStereo) // no stereo? - { - int dl, dr; - for (ns = 0; ns < NSSIZE; ns++) - { - SSumL[ns] += MixREVERBLeft(ns); - - dl = SSumL[ns] / voldiv; SSumL[ns] = 0; - if (dl < -32767) dl = -32767; if (dl > 32767) dl = 32767; - - SSumR[ns] += MixREVERBRight(); - - dr = SSumR[ns] / voldiv; SSumR[ns] = 0; - if (dr < -32767) dr = -32767; if (dr > 32767) dr = 32767; - *pS++ = (dl + dr) / 2; - } - } - else // stereo: - for (ns = 0; ns < NSSIZE; ns++) - { - static double _interpolation_coefficient = 3.759285613; - - if(iFreqResponse) { - int sl,sr; - double ldiff, rdiff, avg, tmp; - - SSumL[ns]+=MixREVERBLeft(ns); - SSumR[ns]+=MixREVERBRight(); - - sl = SSumL[ns]; SSumL[ns]=0; - sr = SSumR[ns]; SSumR[ns]=0; - - - /* - Frequency Response - - William Pitcock (nenolod) (UPSE PSF player) - - accurate (!) - - http://nenolod.net - */ - - avg = ((sl + sr) / 2); - ldiff = sl - avg; - rdiff = sr - avg; - - tmp = avg + ldiff * _interpolation_coefficient; - if (tmp < -32768) - tmp = -32768; - if (tmp > 32767) - tmp = 32767; - sl = (int)tmp; - - tmp = avg + rdiff * _interpolation_coefficient; - if (tmp < -32768) - tmp = -32768; - if (tmp > 32767) - tmp = 32767; - sr = (int)tmp; - - - *pS++=sl/voldiv; - *pS++=sr/voldiv; - } else { - SSumL[ns]+=MixREVERBLeft(ns); - - d=SSumL[ns]/voldiv;SSumL[ns]=0; - if(d<-32767) d=-32767;if(d>32767) d=32767; - *pS++=d; - - SSumR[ns]+=MixREVERBRight(); - - d=SSumR[ns]/voldiv;SSumR[ns]=0; - if(d<-32767) d=-32767;if(d>32767) d=32767; - *pS++=d; - } - } - - ////////////////////////////////////////////////////// - // special irq handling in the decode buffers (0x0000-0x1000) - // we know: - // the decode buffers are located in spu memory in the following way: - // 0x0000-0x03ff CD audio left - // 0x0400-0x07ff CD audio right - // 0x0800-0x0bff Voice 1 - // 0x0c00-0x0fff Voice 3 - // and decoded data is 16 bit for one sample - // we assume: - // even if voices 1/3 are off or no cd audio is playing, the internal - // play positions will move on and wrap after 0x400 bytes. - // Therefore: we just need a pointer from spumem+0 to spumem+3ff, and - // increase this pointer on each sample by 2 bytes. If this pointer - // (or 0x400 offsets of this pointer) hits the spuirq address, we generate - // an IRQ. Only problem: the "wait for cpu" option is kinda hard to do here - // in some of Peops timer modes. So: we ignore this option here (for now). - - if(pMixIrq && irqCallback) - { - for(ns=0;ns=pMixIrq+(ch*0x400) && pSpuIrqspuMemC+0x3ff) pMixIrq=spuMemC; - } - } - - InitREVERB(); - - ////////////////////////////////////////////////////// - // feed the sound - // latency = 25 ms (less pops, crackles, smoother) - - //if(iCycle++>=20) - iCycle += APU_CYCLES_UPDATE; - if(iCycle > 44000/1000*LATENCY + 100*LATENCY/1000) - { - SoundFeedStreamData((unsigned char *)pSpuBuffer, - ((unsigned char *)pS) - ((unsigned char *)pSpuBuffer)); - pS = (short *)pSpuBuffer; - iCycle = 0; - } - - - if( iUseTimer == 2 ) - break; - } - - // end of big main loop... - - bThreadEnded = 1; - -#ifndef _WINDOWS - return 0; -#endif -} - -//////////////////////////////////////////////////////////////////////// -// WINDOWS THREAD... simply calls the timer func and stays forever :) -//////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS - -DWORD WINAPI MAINThreadEx(LPVOID lpParameter) -{ - MAINProc(0,0,0,0,0); - return 0; -} - -#endif - -// SPU ASYNC... even newer epsxe func -// 1 time every 'cycle' cycles... harhar - -long cpu_cycles; -void CALLBACK SPUasync(uint32_t cycle) -{ - cpu_cycles += cycle; - - if(iSpuAsyncWait) - { - iSpuAsyncWait++; - if(iSpuAsyncWait<=64) return; - iSpuAsyncWait=0; - - cpu_cycles = cycle; - } - -#ifdef _WINDOWS - if(iDebugMode==2) - { - if(IsWindow(hWDebug)) DestroyWindow(hWDebug); - hWDebug=0;iDebugMode=0; - } - if(iRecordMode==2) - { - if(IsWindow(hWRecord)) DestroyWindow(hWRecord); - hWRecord=0;iRecordMode=0; - } -#endif - - if(iUseTimer==2) // special mode, only used in Linux by this spu (or if you enable the experimental Windows mode) - { - if(!bSpuInit) return; // -> no init, no call - - // note: usable precision difference (not using interval_time) - while( cpu_cycles >= CPU_CLOCK / 44100 * NSSIZE ) - { - #ifdef _WINDOWS - MAINProc(0,0,0,0,0); // -> experimental win mode... not really tested... don't like the drawbacks - #else - MAINThread(0); // -> linux high-compat mode - #endif - - cpu_cycles -= CPU_CLOCK / 44100 * NSSIZE; - } - } -} - -// SPU UPDATE... new epsxe func -// 1 time every 32 hsync lines -// (312/32)x50 in pal -// (262/32)x60 in ntsc - -// since epsxe 1.5.2 (linux) uses SPUupdate, not SPUasync, I will -// leave that func in the linux port, until epsxe linux is using -// the async function as well - -#if 0 -void CALLBACK SPUupdate(void) -{ - SPUasync(0); -} -#endif - -// XA AUDIO - -void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap) -{ - if(!xap) return; - if(!xap->freq) return; // no xa freq ? bye - - FeedXA(xap); // call main XA feeder -} - -// CDDA AUDIO -void CALLBACK SPUplayCDDAchannel(short *pcm, int nbytes) -{ - if (!pcm) return; - if (nbytes<=0) return; - - FeedCDDA((unsigned char *)pcm, nbytes); -} - -// SETUPTIMER: init of certain buffers and threads/timers -void SetupTimer(void) -{ - memset(SSumR,0,NSSIZE*sizeof(int)); // init some mixing buffers - memset(SSumL,0,NSSIZE*sizeof(int)); - memset(iFMod,0,NSSIZE*sizeof(int)); - pS=(short *)pSpuBuffer; // setup soundbuffer pointer - - bEndThread=0; // init thread vars - bThreadEnded=0; - bSpuInit=1; // flag: we are inited - -#ifdef _WINDOWS - - if(iUseTimer==1) // windows: use timer - { - timeBeginPeriod(1); - timeSetEvent(1,1,MAINProc,0,TIME_ONESHOT); - } - else - if(iUseTimer==0) // windows: use thread - { - //_beginthread(MAINThread,0,NULL); - DWORD dw; - hMainThread=CreateThread(NULL,0,MAINThreadEx,0,0,&dw); - SetThreadPriority(hMainThread, - //THREAD_PRIORITY_TIME_CRITICAL); - THREAD_PRIORITY_HIGHEST); - } - -#else - - if(!iUseTimer) // linux: use thread - { - pthread_create(&thread, NULL, MAINThread, NULL); - } - -#endif -} - -// REMOVETIMER: kill threads/timers -void RemoveTimer(void) -{ - bEndThread=1; // raise flag to end thread - -#ifdef _WINDOWS - - if(iUseTimer!=2) // windows thread? - { - while(!bThreadEnded) {Sleep(5L);} // -> wait till thread has ended - Sleep(5L); - } - if(iUseTimer==1) timeEndPeriod(1); // windows timer? stop it - -#else - if(!iUseTimer) // linux tread? - { - int i=0; - while(!bThreadEnded && i<2000) {usleep(1000L);i++;} // -> wait until thread has ended - if(thread!=(pthread_t)-1) {pthread_cancel(thread);thread=(pthread_t)-1;} // -> cancel thread anyway - } - -#endif - - bThreadEnded=0; // no more spu is running - bSpuInit=0; -} - -// SETUPSTREAMS: init most of the spu buffers -static void SetupStreams(void) -{ - int i; - - pSpuBuffer=(unsigned char *)malloc(32768); // alloc mixing buffer - - if(iUseReverb==1) i=88200*2; - else i=NSSIZE*2; - - sRVBStart = (int *)malloc(i*4); // alloc reverb buffer - memset(sRVBStart,0,i*4); - sRVBEnd = sRVBStart + i; - sRVBPlay = sRVBStart; - - XAStart = // alloc xa buffer - (uint32_t *)malloc(44100 * sizeof(uint32_t)); - XAEnd = XAStart + 44100; - XAPlay = XAStart; - XAFeed = XAStart; - - CDDAStart = // alloc cdda buffer - (uint32_t *)malloc(44100 * sizeof(uint32_t)); - CDDAEnd = CDDAStart + 44100; - CDDAPlay = CDDAStart; - CDDAFeed = CDDAStart; - - for(i=0;i init sustain - s_chan[i].iMute=0; - s_chan[i].iIrqDone=0; - s_chan[i].pLoop=spuMemC; - s_chan[i].pStart=spuMemC; - s_chan[i].pCurr=spuMemC; - } - - pMixIrq=spuMemC; // enable decoded buffer irqs by setting the address -} - -// REMOVESTREAMS: free most buffer -static void RemoveStreams(void) -{ - free(pSpuBuffer); // free mixing buffer - pSpuBuffer = NULL; - free(sRVBStart); // free reverb buffer - sRVBStart = NULL; - free(XAStart); // free XA buffer - XAStart = NULL; - free(CDDAStart); // free CDDA buffer - CDDAStart = NULL; -} - -// INIT/EXIT STUFF - -// SPUINIT: this func will be called first by the main emu -long CALLBACK SPUinit(void) -{ - spuMemC = (unsigned char *)spuMem; // just small setup - memset((void *)&rvb, 0, sizeof(REVERBInfo)); - InitADSR(); - - iVolume = 3; - iReverbOff = -1; - spuIrq = 0; - spuAddr = 0xffffffff; - bEndThread = 0; - bThreadEnded = 0; - spuMemC = (unsigned char *)spuMem; - pMixIrq = 0; - memset((void *)s_chan, 0, (MAXCHAN + 1) * sizeof(SPUCHAN)); - pSpuIrq = 0; - iSPUIRQWait = 1; - lastch = -1; - - ReadConfig(); // read user stuff - SetupStreams(); // prepare streaming - - return 0; -} - -// SPUOPEN: called by main emu after init -#ifdef _WINDOWS -long CALLBACK SPUopen(HWND hW) -#else -long SPUopen(void) -#endif -{ - if (bSPUIsOpen) return 0; // security for some stupid main emus - -#ifdef _WINDOWS - LastWrite=0xffffffff;LastPlay=0; // init some play vars - if(!IsWindow(hW)) hW=GetActiveWindow(); - hWMain = hW; // store hwnd -#endif - - SetupSound(); // setup sound (before init!) - SetupTimer(); // timer for feeding data - - bSPUIsOpen = 1; - -#ifdef _WINDOWS - if(iDebugMode) // windows debug dialog - { - hWDebug=CreateDialog(hInst,MAKEINTRESOURCE(IDD_DEBUG), - NULL,(DLGPROC)DebugDlgProc); - SetWindowPos(hWDebug,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); - UpdateWindow(hWDebug); - SetFocus(hWMain); - } - - if(iRecordMode) // windows recording dialog - { - hWRecord=CreateDialog(hInst,MAKEINTRESOURCE(IDD_RECORD), - NULL,(DLGPROC)RecordDlgProc); - SetWindowPos(hWRecord,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); - UpdateWindow(hWRecord); - SetFocus(hWMain); - } -#endif - - return PSE_SPU_ERR_SUCCESS; -} - -// SPUCLOSE: called before shutdown -long CALLBACK SPUclose(void) -{ - if (!bSPUIsOpen) return 0; // some security - - bSPUIsOpen = 0; // no more open - -#ifdef _WINDOWS - if(IsWindow(hWDebug)) DestroyWindow(hWDebug); - hWDebug=0; - if(IsWindow(hWRecord)) DestroyWindow(hWRecord); - hWRecord=0; -#endif - - RemoveTimer(); // no more feeding - RemoveSound(); // no more sound handling - - return 0; -} - -// SPUSHUTDOWN: called by main emu on final exit -long CALLBACK SPUshutdown(void) -{ - SPUclose(); - RemoveStreams(); // no more streaming - - return 0; -} - -// SPUTEST: we don't test, we are always fine ;) -long CALLBACK SPUtest(void) -{ - return 0; -} - -// SPUCONFIGURE: call config dialog -long CALLBACK SPUconfigure(void) -{ -#if defined (_WINDOWS) - DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG), - GetActiveWindow(),(DLGPROC)DSoundDlgProc); -#elif defined (_MACOSX) - DoConfiguration(); -#else - StartCfgTool("CFG"); -#endif - - return 0; -} - -// SPUABOUT: show about window -void CALLBACK SPUabout(void) -{ -#if defined (_WINDOWS) - DialogBox(hInst,MAKEINTRESOURCE(IDD_ABOUT), - GetActiveWindow(),(DLGPROC)AboutDlgProc); -#elif defined (_MACOSX) - DoAbout(); -#else - StartCfgTool("ABOUT"); -#endif -} - -// SETUP CALLBACKS -// this functions will be called once, -// passes a callback that should be called on SPU-IRQ/cdda volume change -void CALLBACK SPUregisterCallback(void (CALLBACK *callback)(void)) -{ - irqCallback = callback; -} - -#if 0 -void CALLBACK SPUregisterCDDAVolume(void (CALLBACK *CDDAVcallback)(unsigned short,unsigned short)) -{ - cddavCallback = CDDAVcallback; -} -#endif - -// COMMON PLUGIN INFO FUNCS -char * CALLBACK PSEgetLibName(void) -{ - return _(libraryName); -} - -unsigned long CALLBACK PSEgetLibType(void) -{ - return PSE_LT_SPU; -} - -unsigned long CALLBACK PSEgetLibVersion(void) -{ - return (1 << 16) | (1 << 8); -} - -#if 0 -char * SPUgetLibInfos(void) -{ - return _(libraryInfo); -} -#endif +/*************************************************************************** + spu.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 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 "stdafx.h" + +#define _IN_SPU + +#include "externals.h" +#include "cfg.h" +#include "dsoundoss.h" +#include "regs.h" + +#ifdef _WINDOWS +#include "debug.h" +#include "record.h" +#endif + +#ifdef ENABLE_NLS +#include +#include +#define _(x) gettext(x) +#define N_(x) (x) +#else +#define _(x) (x) +#define N_(x) (x) +#endif + +#if defined (_WINDOWS) +static char * libraryName = N_("DirectSound Driver"); +#elif defined (USEMACOSX) +static char * libraryName = N_("Mac OS X Sound"); +#elif defined (USEALSA) +static char * libraryName = N_("ALSA Sound"); +#elif defined (USEOSS) +static char * libraryName = N_("OSS Sound"); +#elif defined (USESDL) +static char * libraryName = N_("SDL Sound"); +#elif defined (USEPULSEAUDIO) +static char * libraryName = N_("PulseAudio Sound"); +#else +static char * libraryName = N_("NULL Sound"); +#endif + +static char * libraryInfo = N_("P.E.Op.S. Sound Driver V1.7\nCoded by Pete Bernert and the P.E.Op.S. team\n"); + +// globals + +// psx buffer / addresses + +unsigned short regArea[10000]; +unsigned short spuMem[256*1024]; +unsigned char * spuMemC; +unsigned char * pSpuIrq=0; +unsigned char * pSpuBuffer; +unsigned char * pMixIrq=0; + +// user settings + +int iVolume=3; +int iXAPitch=1; +int iUseTimer=2; +int iSPUIRQWait=1; +int iDebugMode=0; +int iRecordMode=0; +int iUseReverb=2; +int iUseInterpolation=2; +int iDisStereo=0; +int iFreqResponse=0; + +// MAIN infos struct for each channel + +SPUCHAN s_chan[MAXCHAN+1]; // channel + 1 infos (1 is security for fmod handling) +REVERBInfo rvb; + +unsigned long dwNoiseVal=1; // global noise generator +unsigned long dwNoiseCount; // global noise generator +unsigned long dwNoiseClock; // global noise generator +int iSpuAsyncWait=0; + +unsigned short spuCtrl=0; // some vars to store psx reg infos +unsigned short spuStat=0; +unsigned short spuIrq=0; +unsigned long spuAddr=0xffffffff; // address into spu mem +int bEndThread=0; // thread handlers +int bThreadEnded=0; +int bSpuInit=0; +int bSPUIsOpen=0; + +#ifdef _WINDOWS +HWND hWMain=0; // window handle +HWND hWDebug=0; +HWND hWRecord=0; +static HANDLE hMainThread; +#else +static pthread_t thread = (pthread_t)-1; // thread id (linux) +#endif + +uint32_t dwNewChannel=0; // flags for faster testing, if new channel starts + +void (CALLBACK *irqCallback)(void)=0; // func of main emu, called on spu irq +void (CALLBACK *cddavCallback)(unsigned short,unsigned short)=0; + +// certain globals (were local before, but with the new timeproc I need em global) + +static const int f[5][2] = { { 0, 0 }, + { 60, 0 }, + { 115, -52 }, + { 98, -55 }, + { 122, -60 } }; +int SSumR[NSSIZE]; +int SSumL[NSSIZE]; +int iFMod[NSSIZE]; +int iCycle = 0; +short * pS; + +int lastch=-1; // last channel processed on spu irq in timer mode +static int lastns=0; // last ns pos +static int iSecureStart=0; // secure start counter + +//////////////////////////////////////////////////////////////////////// +// CODE AREA +//////////////////////////////////////////////////////////////////////// + +// dirty inline func includes + +#include "reverb.c" +#include "adsr.c" + +//////////////////////////////////////////////////////////////////////// +// helpers for simple interpolation + +// +// easy interpolation on upsampling, no special filter, just "Pete's common sense" tm +// +// instead of having n equal sample values in a row like: +// ____ +// |____ +// +// we compare the current delta change with the next delta change. +// +// if curr_delta is positive, +// +// - and next delta is smaller (or changing direction): +// \. +// -__ +// +// - and next delta significant (at least twice) bigger: +// --_ +// \. +// +// - and next delta is nearly same: +// \. +// \. +// +// +// if curr_delta is negative, +// +// - and next delta is smaller (or changing direction): +// _-- +// / +// +// - and next delta significant (at least twice) bigger: +// / +// __- +// +// - and next delta is nearly same: +// / +// / +// + + +INLINE void InterpolateUp(int ch) +{ + if(s_chan[ch].SB[32]==1) // flag == 1? calc step and set flag... and don't change the value in this pass + { + const int id1=s_chan[ch].SB[30]-s_chan[ch].SB[29]; // curr delta to next val + const int id2=s_chan[ch].SB[31]-s_chan[ch].SB[30]; // and next delta to next-next val :) + + s_chan[ch].SB[32]=0; + + if(id1>0) // curr delta positive + { + if(id2id1) + {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;} + else + if(id2>(id1<<1)) + s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L; + else + s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L; + } + } + else + if(s_chan[ch].SB[32]==2) // flag 1: calc step and set flag... and don't change the value in this pass + { + s_chan[ch].SB[32]=0; + + s_chan[ch].SB[28]=(s_chan[ch].SB[28]*s_chan[ch].sinc)/0x20000L; + if(s_chan[ch].sinc<=0x8000) + s_chan[ch].SB[29]=s_chan[ch].SB[30]-(s_chan[ch].SB[28]*((0x10000/s_chan[ch].sinc)-1)); + else s_chan[ch].SB[29]+=s_chan[ch].SB[28]; + } + else // no flags? add bigger val (if possible), calc smaller step, set flag1 + s_chan[ch].SB[29]+=s_chan[ch].SB[28]; +} + +// +// even easier interpolation on downsampling, also no special filter, again just "Pete's common sense" tm +// + +INLINE void InterpolateDown(int ch) +{ + if(s_chan[ch].sinc>=0x20000L) // we would skip at least one val? + { + s_chan[ch].SB[29]+=(s_chan[ch].SB[30]-s_chan[ch].SB[29])/2; // add easy weight + if(s_chan[ch].sinc>=0x30000L) // we would skip even more vals? + s_chan[ch].SB[29]+=(s_chan[ch].SB[31]-s_chan[ch].SB[30])/2;// add additional next weight + } +} + +//////////////////////////////////////////////////////////////////////// +// helpers for gauss interpolation + +#define gval0 (((short*)(&s_chan[ch].SB[29]))[gpos]) +#define gval(x) (((short*)(&s_chan[ch].SB[29]))[(gpos+x)&3]) + +#include "gauss_i.h" + +//////////////////////////////////////////////////////////////////////// + +#include "xa.c" + +//////////////////////////////////////////////////////////////////////// +// START SOUND... called by main thread to setup a new sound on a channel +//////////////////////////////////////////////////////////////////////// + +INLINE void StartSound(int ch) +{ + StartADSR(ch); + StartREVERB(ch); + + // fussy timing issues - do in VoiceOn + //s_chan[ch].pCurr=s_chan[ch].pStart; // set sample start + //s_chan[ch].bStop=0; + //s_chan[ch].bOn=1; + + s_chan[ch].s_1=0; // init mixing vars + s_chan[ch].s_2=0; + s_chan[ch].iSBPos=28; + + s_chan[ch].bNew=0; // init channel flags + + s_chan[ch].SB[29]=0; // init our interpolation helpers + s_chan[ch].SB[30]=0; + + if(iUseInterpolation>=2) // gauss interpolation? + {s_chan[ch].spos=0x30000L;s_chan[ch].SB[28]=0;} // -> start with more decoding + else {s_chan[ch].spos=0x10000L;s_chan[ch].SB[31]=0;} // -> no/simple interpolation starts with one 44100 decoding + + dwNewChannel&=~(1< take it and calc steps + s_chan[ch].sinc=s_chan[ch].iRawPitch<<4; + if(!s_chan[ch].sinc) s_chan[ch].sinc=1; + if(iUseInterpolation==1) s_chan[ch].SB[32]=1; // -> freq change in simle imterpolation mode: set flag +} + +//////////////////////////////////////////////////////////////////////// + +INLINE void FModChangeFrequency(int ch,int ns) +{ + int NP=s_chan[ch].iRawPitch; + + NP=((32768L+iFMod[ns])*NP)/32768L; + + if(NP>0x3fff) NP=0x3fff; + if(NP<0x1) NP=0x1; + + NP=(44100L*NP)/(4096L); // calc frequency + + s_chan[ch].iActFreq=NP; + s_chan[ch].iUsedFreq=NP; + s_chan[ch].sinc=(((NP/10)<<16)/4410); + if(!s_chan[ch].sinc) s_chan[ch].sinc=1; + if(iUseInterpolation==1) // freq change in simple interpolation mode + s_chan[ch].SB[32]=1; + iFMod[ns]=0; +} + +//////////////////////////////////////////////////////////////////////// + +/* +Noise Algorithm +- Dr.Hell (Xebra PS1 emu) +- 100% accurate (waveform + frequency) +- http://drhell.web.fc2.com + + +Level change cycle +Freq = 0x8000 >> (NoiseClock >> 2); + +Frequency of half cycle +Half = ((NoiseClock & 3) * 2) / (4 + (NoiseClock & 3)); +- 0 = (0*2)/(4+0) = 0/4 +- 1 = (1*2)/(4+1) = 2/5 +- 2 = (2*2)/(4+2) = 4/6 +- 3 = (3*2)/(4+3) = 6/7 + +------------------------------- + +5*6*7 = 210 +4 - 0*0 = 0 +5 - 42*2 = 84 +6 - 35*4 = 140 +7 - 30*6 = 180 +*/ + +// Noise Waveform - Dr. Hell (Xebra) +char NoiseWaveAdd [64] = { + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1 +}; + +unsigned short NoiseFreqAdd[5] = { + 0, 84, 140, 180, 210 +}; + +INLINE void NoiseClock() +{ + unsigned int level; + + level = 0x8000 >> (dwNoiseClock >> 2); + level <<= 16; + + dwNoiseCount += 0x10000; + + // Dr. Hell - fraction + dwNoiseCount += NoiseFreqAdd[ dwNoiseClock & 3 ]; + if( (dwNoiseCount&0xffff) >= NoiseFreqAdd[4] ) { + dwNoiseCount += 0x10000; + dwNoiseCount -= NoiseFreqAdd[ dwNoiseClock & 3 ]; + } + + if( dwNoiseCount >= level ) + { + while( dwNoiseCount >= level ) + dwNoiseCount -= level; + + // Dr. Hell - form + dwNoiseVal = (dwNoiseVal<<1) | NoiseWaveAdd[ (dwNoiseVal>>10) & 63 ]; + } +} + +INLINE int iGetNoiseVal(int ch) +{ + int fa; + + fa = (short) dwNoiseVal; + + // no clip need + //if(fa>32767L) fa=32767L; + //if(fa<-32767L) fa=-32767L; + + // don't upset VAG decoder + //if(iUseInterpolation<2) // no gauss/cubic interpolation? + //pChannel->SB[29] = fa; // -> store noise val in "current sample" slot + + // boost volume - no more! + //return fa * 3 / 2; + return fa; +} + +//////////////////////////////////////////////////////////////////////// + +INLINE void StoreInterpolationVal(int ch,int fa) +{ + /* + // fmod channel = sound output + if(s_chan[ch].bFMod==2) // fmod freq channel + s_chan[ch].SB[29]=fa; + else + */ + { + if((spuCtrl&0x4000)==0) fa=0; // muted? + else // else adjust + { + if(fa>32767L) fa=32767L; + if(fa<-32767L) fa=-32767L; + } + + if(iUseInterpolation>=2) // gauss/cubic interpolation + { + int gpos = s_chan[ch].SB[28]; + gval0 = fa; + gpos = (gpos+1) & 3; + s_chan[ch].SB[28] = gpos; + } + else + if(iUseInterpolation==1) // simple interpolation + { + s_chan[ch].SB[28] = 0; + s_chan[ch].SB[29] = s_chan[ch].SB[30]; // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour' + s_chan[ch].SB[30] = s_chan[ch].SB[31]; + s_chan[ch].SB[31] = fa; + s_chan[ch].SB[32] = 1; // -> flag: calc new interolation + } + else s_chan[ch].SB[29]=fa; // no interpolation + } +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int iGetInterpolationVal(int ch) +{ + int fa; + + // fmod channel = sound output + //if(s_chan[ch].bFMod==2) return s_chan[ch].SB[29]; + + switch(iUseInterpolation) + { + //--------------------------------------------------// + case 3: // cubic interpolation + { + long xd;int gpos; + xd = ((s_chan[ch].spos) >> 1)+1; + gpos = s_chan[ch].SB[28]; + + fa = gval(3) - 3*gval(2) + 3*gval(1) - gval0; + fa *= (xd - (2<<15)) / 6; + fa >>= 15; + fa += gval(2) - gval(1) - gval(1) + gval0; + fa *= (xd - (1<<15)) >> 1; + fa >>= 15; + fa += gval(1) - gval0; + fa *= xd; + fa >>= 15; + fa = fa + gval0; + + } break; + //--------------------------------------------------// + case 2: // gauss interpolation + { + int vl, vr;int gpos; + vl = (s_chan[ch].spos >> 6) & ~3; + gpos = s_chan[ch].SB[28]; + vr=(gauss[vl]*gval0)&~2047; + vr+=(gauss[vl+1]*gval(1))&~2047; + vr+=(gauss[vl+2]*gval(2))&~2047; + vr+=(gauss[vl+3]*gval(3))&~2047; + fa = vr>>11; + } break; + //--------------------------------------------------// + case 1: // simple interpolation + { + if(s_chan[ch].sinc<0x10000L) // -> upsampling? + InterpolateUp(ch); // --> interpolate up + else InterpolateDown(ch); // --> else down + fa=s_chan[ch].SB[29]; + } break; + //--------------------------------------------------// + default: // no interpolation + { + fa=s_chan[ch].SB[29]; + } break; + //--------------------------------------------------// + } + + return fa; +} + +//////////////////////////////////////////////////////////////////////// +// MAIN SPU FUNCTION +// here is the main job handler... thread, timer or direct func call +// basically the whole sound processing is done in this fat func! +//////////////////////////////////////////////////////////////////////// + +// 5 ms waiting phase, if buffer is full and no new sound has to get started +// .. can be made smaller (smallest val: 1 ms), but bigger waits give +// better performance + +#define PAUSE_W 1 +#define PAUSE_L 1000 + +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +static VOID CALLBACK MAINProc(UINT nTimerId, UINT msg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) +#else +static void *MAINThread(void *arg) +#endif +{ + int s_1,s_2,fa,ns; + int voldiv = iVolume; + + unsigned char * start;unsigned int nSample; + int ch,predict_nr,shift_factor,flags,d,s; + int bIRQReturn=0; + + // mute output + if( voldiv == 5 ) voldiv = 0x7fffffff; + + while(!bEndThread) // until we are shutting down + { + // ok, at the beginning we are looking if there is + // enuff free place in the dsound/oss buffer to + // fill in new data, or if there is a new channel to start. + // if not, we wait (thread) or return (timer/spuasync) + // until enuff free place is available/a new channel gets + // started + + if(dwNewChannel) // new channel should start immedately? + { // (at least one bit 0 ... MAXCHANNEL is set?) + iSecureStart++; // -> set iSecure + if(iSecureStart>1) iSecureStart=0; // (if it is set 5 times - that means on 5 tries a new samples has been started - in a row, we will reset it, to give the sound update a chance) + } + else iSecureStart=0; // 0: no new channel should start + + while(!iSecureStart && !bEndThread && // no new start? no thread end? + (SoundGetBytesBuffered()>TESTSIZE)) // and still enuff data in sound buffer? + { + iSecureStart=0; // reset secure + +#ifdef _WINDOWS + if(iUseTimer) // no-thread mode? + { + if(iUseTimer==1) // -> ok, timer mode 1: setup a oneshot timer of x ms to wait + timeSetEvent(PAUSE_W,1,MAINProc,0,TIME_ONESHOT); + return; // -> and done this time (timer mode 1 or 2) + } + // win thread mode: + Sleep(PAUSE_W); // sleep for x ms (win) +#else + if(iUseTimer) return 0; // linux no-thread mode? bye + usleep(PAUSE_L); // else sleep for x ms (linux) +#endif + + if(dwNewChannel) iSecureStart=1; // if a new channel kicks in (or, of course, sound buffer runs low), we will leave the loop + } + + //--------------------------------------------------// continue from irq handling in timer mode? + + if(lastch>=0) // will be -1 if no continue is pending + { + ch=lastch; ns=lastns; lastch=-1; // -> setup all kind of vars to continue + goto GOON; // -> directly jump to the continue point + } + + //--------------------------------------------------// + //- main channel loop -// + //--------------------------------------------------// + { + ns=0; + while(ns=0x10000L) + { + if(s_chan[ch].iSBPos==28) // 28 reached? + { +#if 0 + // Xenogears - Anima Relic dungeon (exp gain) + if( s_chan[ch].bLoopJump == 1 ) + s_chan[ch].pCurr = s_chan[ch].pLoop; + + s_chan[ch].bLoopJump = 0; +#endif + + + start=s_chan[ch].pCurr; // set up the current pos + + if (s_chan[ch].iSilent==1 || start == (unsigned char*)-1) // special "stop" sign + { + // silence = let channel keep running (IRQs) + //s_chan[ch].bOn=0; // -> turn everything off + s_chan[ch].iSilent=2; + + s_chan[ch].ADSRX.lVolume=0; + s_chan[ch].ADSRX.EnvelopeVol=0; + } + + s_chan[ch].iSBPos=0; + + //////////////////////////////////////////// spu irq handler here? mmm... do it later + + s_1=s_chan[ch].s_1; + s_2=s_chan[ch].s_2; + + predict_nr=(int)*start;start++; + shift_factor=predict_nr&0xf; + predict_nr >>= 4; + flags=(int)*start;start++; + + // -------------------------------------- // + + for (nSample=0;nSample<28;start++) + { + d=(int)*start; + s=((d&0xf)<<12); + if(s&0x8000) s|=0xffff0000; + + fa=(s >> shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1;s_1=fa; + s=((d & 0xf0) << 8); + + s_chan[ch].SB[nSample++]=fa; + + if(s&0x8000) s|=0xffff0000; + fa=(s>>shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1;s_1=fa; + + s_chan[ch].SB[nSample++]=fa; + } + + //////////////////////////////////////////// irq check + + if(irqCallback && (spuCtrl&0x40)) // some callback and irq active? + { + if((pSpuIrq > start-16 && // irq address reached? + pSpuIrq <= start) || + ((flags&1) && // special: irq on looping addr, when stop/loop flag is set + (pSpuIrq > s_chan[ch].pLoop-16 && + pSpuIrq <= s_chan[ch].pLoop))) + { + s_chan[ch].iIrqDone=1; // -> debug flag + irqCallback(); // -> call main emu + + if(iSPUIRQWait) // -> option: wait after irq for main emu + { + iSpuAsyncWait=1; + bIRQReturn=1; + } + } + } + + //////////////////////////////////////////// flag handler + + /* + SPU2-X: + $4 = set loop to current block + $2 = keep envelope on (no mute) + $1 = jump to loop address + + silence means no volume (ADSR keeps playing!!) + */ + +#if 0 + if(flags&4) + s_chan[ch].pLoop=start-16; +#else + // Jungle Book - Rhythm 'n Groove - use external loop address + // - fixes music player (+IRQ generate) + if((flags&4) && (s_chan[ch].bIgnoreLoop == 0)) + s_chan[ch].pLoop=start-16; +#endif + + // Jungle Book - Rhythm 'n Groove - don't reset ignore status + // - fixes gameplay speed (IRQ hits) + //s_chan[ch].bIgnoreLoop = 0; + + + if(flags&1) + { + // ...? + //s_chan[ch].bIgnoreLoop = 0; + + // Xenogears - 7 = play missing sounds +#if 0 + // set jump flag + pChannel->bLoopJump = 1; +#else + start = s_chan[ch].pLoop; +#endif + + // silence = keep playing..? + if( (flags&2) == 0 ) { + s_chan[ch].iSilent = 1; + + // silence = don't start release phase + //s_chan[ch].bStop = 1; + + //start = (unsigned char *) -1; + } + } + +#if 0 + // crash check + if( start == 0 ) + start = (unsigned char *) -1; + if( start >= spuMemC + 0x80000 ) + start = spuMemC - 0x80000; +#endif + + s_chan[ch].pCurr=start; // store values for next cycle + s_chan[ch].s_1=s_1; + s_chan[ch].s_2=s_2; + + if(bIRQReturn) // special return for "spu irq - wait for cpu action" + { + bIRQReturn=0; + if(iUseTimer!=2) + { + DWORD dwWatchTime=timeGetTime_spu()+2500; + + while(iSpuAsyncWait && !bEndThread && + timeGetTime_spu() store 1T sample data, use that to do fmod on next channel + + // mix fmod channel into output + // - Xenogears save icon (high pitch) + { + ////////////////////////////////////////////// + // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff) + + if(s_chan[ch].iMute) + s_chan[ch].sval=0; // debug mute + else + { + SSumL[ns]+=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000L; + SSumR[ns]+=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000L; + } + + ////////////////////////////////////////////// + // now let us store sound data for reverb + + if(s_chan[ch].bRVBActive) StoreREVERB(ch,ns); + } + + s_chan[ch].spos += s_chan[ch].sinc; + } + //////////////////////////////////////////////// + // ok, go on until 1 ms data of this channel is collected + + ns++; + } // end ns + } + + //---------------------------------------------------// + //- here we have another 1 ms of sound data + //---------------------------------------------------// + // mix XA infos (if any) + + MixXA(); + + /////////////////////////////////////////////////////// + // mix all channels (including reverb) into one buffer + + if(iDisStereo) // no stereo? + { + int dl, dr; + for (ns = 0; ns < NSSIZE; ns++) + { + SSumL[ns] += MixREVERBLeft(ns); + + dl = SSumL[ns] / voldiv; SSumL[ns] = 0; + if (dl < -32767) dl = -32767; if (dl > 32767) dl = 32767; + + SSumR[ns] += MixREVERBRight(); + + dr = SSumR[ns] / voldiv; SSumR[ns] = 0; + if (dr < -32767) dr = -32767; if (dr > 32767) dr = 32767; + *pS++ = (dl + dr) / 2; + } + } + else // stereo: + for (ns = 0; ns < NSSIZE; ns++) + { + static double _interpolation_coefficient = 3.759285613; + + if(iFreqResponse) { + int sl,sr; + double ldiff, rdiff, avg, tmp; + + SSumL[ns]+=MixREVERBLeft(ns); + SSumR[ns]+=MixREVERBRight(); + + sl = SSumL[ns]; SSumL[ns]=0; + sr = SSumR[ns]; SSumR[ns]=0; + + + /* + Frequency Response + - William Pitcock (nenolod) (UPSE PSF player) + - accurate (!) + - http://nenolod.net + */ + + avg = ((sl + sr) / 2); + ldiff = sl - avg; + rdiff = sr - avg; + + tmp = avg + ldiff * _interpolation_coefficient; + if (tmp < -32768) + tmp = -32768; + if (tmp > 32767) + tmp = 32767; + sl = (int)tmp; + + tmp = avg + rdiff * _interpolation_coefficient; + if (tmp < -32768) + tmp = -32768; + if (tmp > 32767) + tmp = 32767; + sr = (int)tmp; + + + *pS++=sl/voldiv; + *pS++=sr/voldiv; + } else { + SSumL[ns]+=MixREVERBLeft(ns); + + d=SSumL[ns]/voldiv;SSumL[ns]=0; + if(d<-32767) d=-32767;if(d>32767) d=32767; + *pS++=d; + + SSumR[ns]+=MixREVERBRight(); + + d=SSumR[ns]/voldiv;SSumR[ns]=0; + if(d<-32767) d=-32767;if(d>32767) d=32767; + *pS++=d; + } + } + + ////////////////////////////////////////////////////// + // special irq handling in the decode buffers (0x0000-0x1000) + // we know: + // the decode buffers are located in spu memory in the following way: + // 0x0000-0x03ff CD audio left + // 0x0400-0x07ff CD audio right + // 0x0800-0x0bff Voice 1 + // 0x0c00-0x0fff Voice 3 + // and decoded data is 16 bit for one sample + // we assume: + // even if voices 1/3 are off or no cd audio is playing, the internal + // play positions will move on and wrap after 0x400 bytes. + // Therefore: we just need a pointer from spumem+0 to spumem+3ff, and + // increase this pointer on each sample by 2 bytes. If this pointer + // (or 0x400 offsets of this pointer) hits the spuirq address, we generate + // an IRQ. Only problem: the "wait for cpu" option is kinda hard to do here + // in some of Peops timer modes. So: we ignore this option here (for now). + + if(pMixIrq && irqCallback) + { + for(ns=0;ns=pMixIrq+(ch*0x400) && pSpuIrqspuMemC+0x3ff) pMixIrq=spuMemC; + } + } + + InitREVERB(); + + ////////////////////////////////////////////////////// + // feed the sound + // latency = 25 ms (less pops, crackles, smoother) + + //if(iCycle++>=20) + iCycle += APU_CYCLES_UPDATE; + if(iCycle > 44000/1000*LATENCY + 100*LATENCY/1000) + { + SoundFeedStreamData((unsigned char *)pSpuBuffer, + ((unsigned char *)pS) - ((unsigned char *)pSpuBuffer)); + pS = (short *)pSpuBuffer; + iCycle = 0; + } + + + if( iUseTimer == 2 ) + break; + } + + // end of big main loop... + + bThreadEnded = 1; + +#ifndef _WINDOWS + return 0; +#endif +} + +//////////////////////////////////////////////////////////////////////// +// WINDOWS THREAD... simply calls the timer func and stays forever :) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS + +DWORD WINAPI MAINThreadEx(LPVOID lpParameter) +{ + MAINProc(0,0,0,0,0); + return 0; +} + +#endif + +// SPU ASYNC... even newer epsxe func +// 1 time every 'cycle' cycles... harhar + +long cpu_cycles; +void CALLBACK SPUasync(unsigned long cycle) +{ + cpu_cycles += cycle; + + if(iSpuAsyncWait) + { + iSpuAsyncWait++; + if(iSpuAsyncWait<=64) return; + iSpuAsyncWait=0; + + cpu_cycles = cycle; + } + +#ifdef _WINDOWS + if(iDebugMode==2) + { + if(IsWindow(hWDebug)) DestroyWindow(hWDebug); + hWDebug=0;iDebugMode=0; + } + if(iRecordMode==2) + { + if(IsWindow(hWRecord)) DestroyWindow(hWRecord); + hWRecord=0;iRecordMode=0; + } +#endif + + if(iUseTimer==2) // special mode, only used in Linux by this spu (or if you enable the experimental Windows mode) + { + if(!bSpuInit) return; // -> no init, no call + + // note: usable precision difference (not using interval_time) + while( cpu_cycles >= CPU_CLOCK / 44100 * NSSIZE ) + { + #ifdef _WINDOWS + MAINProc(0,0,0,0,0); // -> experimental win mode... not really tested... don't like the drawbacks + #else + MAINThread(0); // -> linux high-compat mode + #endif + + cpu_cycles -= CPU_CLOCK / 44100 * NSSIZE; + } + } +} + +// SPU UPDATE... new epsxe func +// 1 time every 32 hsync lines +// (312/32)x50 in pal +// (262/32)x60 in ntsc + +// since epsxe 1.5.2 (linux) uses SPUupdate, not SPUasync, I will +// leave that func in the linux port, until epsxe linux is using +// the async function as well + +void CALLBACK SPUupdate(void) +{ + SPUasync(0); +} + +// XA AUDIO + +void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap) +{ + if(!xap) return; + if(!xap->freq) return; // no xa freq ? bye + + FeedXA(xap); // call main XA feeder +} + +// CDDA AUDIO +void CALLBACK SPUplayCDDAchannel(short *pcm, int nbytes) +{ + if (!pcm) return; + if (nbytes<=0) return; + + FeedCDDA((unsigned char *)pcm, nbytes); +} + +// SETUPTIMER: init of certain buffers and threads/timers +void SetupTimer(void) +{ + memset(SSumR,0,NSSIZE*sizeof(int)); // init some mixing buffers + memset(SSumL,0,NSSIZE*sizeof(int)); + memset(iFMod,0,NSSIZE*sizeof(int)); + pS=(short *)pSpuBuffer; // setup soundbuffer pointer + + bEndThread=0; // init thread vars + bThreadEnded=0; + bSpuInit=1; // flag: we are inited + +#ifdef _WINDOWS + + if(iUseTimer==1) // windows: use timer + { + timeBeginPeriod(1); + timeSetEvent(1,1,MAINProc,0,TIME_ONESHOT); + } + else + if(iUseTimer==0) // windows: use thread + { + //_beginthread(MAINThread,0,NULL); + DWORD dw; + hMainThread=CreateThread(NULL,0,MAINThreadEx,0,0,&dw); + SetThreadPriority(hMainThread, + //THREAD_PRIORITY_TIME_CRITICAL); + THREAD_PRIORITY_HIGHEST); + } + +#else + + if(!iUseTimer) // linux: use thread + { + pthread_create(&thread, NULL, MAINThread, NULL); + } + +#endif +} + +// REMOVETIMER: kill threads/timers +void RemoveTimer(void) +{ + bEndThread=1; // raise flag to end thread + +#ifdef _WINDOWS + + if(iUseTimer!=2) // windows thread? + { + while(!bThreadEnded) {Sleep(5L);} // -> wait till thread has ended + Sleep(5L); + } + if(iUseTimer==1) timeEndPeriod(1); // windows timer? stop it + +#else + if(!iUseTimer) // linux tread? + { + int i=0; + while(!bThreadEnded && i<2000) {usleep(1000L);i++;} // -> wait until thread has ended + if(thread!=(pthread_t)-1) {pthread_cancel(thread);thread=(pthread_t)-1;} // -> cancel thread anyway + } + +#endif + + bThreadEnded=0; // no more spu is running + bSpuInit=0; +} + +// SETUPSTREAMS: init most of the spu buffers +void SetupStreams(void) +{ + int i; + + pSpuBuffer=(unsigned char *)malloc(32768); // alloc mixing buffer + + if(iUseReverb==1) i=88200*2; + else i=NSSIZE*2; + + sRVBStart = (int *)malloc(i*4); // alloc reverb buffer + memset(sRVBStart,0,i*4); + sRVBEnd = sRVBStart + i; + sRVBPlay = sRVBStart; + + XAStart = // alloc xa buffer + (uint32_t *)malloc(44100 * sizeof(uint32_t)); + XAEnd = XAStart + 44100; + XAPlay = XAStart; + XAFeed = XAStart; + + CDDAStart = // alloc cdda buffer + (uint32_t *)malloc(44100 * sizeof(uint32_t)); + CDDAEnd = CDDAStart + 44100; + CDDAPlay = CDDAStart; + CDDAFeed = CDDAStart; + + for(i=0;i init sustain + s_chan[i].iMute=0; + s_chan[i].iIrqDone=0; + s_chan[i].pLoop=spuMemC; + s_chan[i].pStart=spuMemC; + s_chan[i].pCurr=spuMemC; + } + + pMixIrq=spuMemC; // enable decoded buffer irqs by setting the address +} + +// REMOVESTREAMS: free most buffer +void RemoveStreams(void) +{ + free(pSpuBuffer); // free mixing buffer + pSpuBuffer = NULL; + free(sRVBStart); // free reverb buffer + sRVBStart = NULL; + free(XAStart); // free XA buffer + XAStart = NULL; + free(CDDAStart); // free CDDA buffer + CDDAStart = NULL; +} + +// INIT/EXIT STUFF + +// SPUINIT: this func will be called first by the main emu +long CALLBACK SPUinit(void) +{ + spuMemC = (unsigned char *)spuMem; // just small setup + memset((void *)&rvb, 0, sizeof(REVERBInfo)); + InitADSR(); + + iVolume = 3; + iReverbOff = -1; + spuIrq = 0; + spuAddr = 0xffffffff; + bEndThread = 0; + bThreadEnded = 0; + spuMemC = (unsigned char *)spuMem; + pMixIrq = 0; + memset((void *)s_chan, 0, (MAXCHAN + 1) * sizeof(SPUCHAN)); + pSpuIrq = 0; + iSPUIRQWait = 1; + lastch = -1; + + ReadConfig(); // read user stuff + SetupStreams(); // prepare streaming + + return 0; +} + +// SPUOPEN: called by main emu after init +#ifdef _WINDOWS +long CALLBACK SPUopen(HWND hW) +#else +long SPUopen(void) +#endif +{ + if (bSPUIsOpen) return 0; // security for some stupid main emus + +#ifdef _WINDOWS + LastWrite=0xffffffff;LastPlay=0; // init some play vars + if(!IsWindow(hW)) hW=GetActiveWindow(); + hWMain = hW; // store hwnd +#endif + + SetupSound(); // setup sound (before init!) + SetupTimer(); // timer for feeding data + + bSPUIsOpen = 1; + +#ifdef _WINDOWS + if(iDebugMode) // windows debug dialog + { + hWDebug=CreateDialog(hInst,MAKEINTRESOURCE(IDD_DEBUG), + NULL,(DLGPROC)DebugDlgProc); + SetWindowPos(hWDebug,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + UpdateWindow(hWDebug); + SetFocus(hWMain); + } + + if(iRecordMode) // windows recording dialog + { + hWRecord=CreateDialog(hInst,MAKEINTRESOURCE(IDD_RECORD), + NULL,(DLGPROC)RecordDlgProc); + SetWindowPos(hWRecord,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + UpdateWindow(hWRecord); + SetFocus(hWMain); + } +#endif + + return PSE_SPU_ERR_SUCCESS; +} + +// SPUCLOSE: called before shutdown +long CALLBACK SPUclose(void) +{ + if (!bSPUIsOpen) return 0; // some security + + bSPUIsOpen = 0; // no more open + +#ifdef _WINDOWS + if(IsWindow(hWDebug)) DestroyWindow(hWDebug); + hWDebug=0; + if(IsWindow(hWRecord)) DestroyWindow(hWRecord); + hWRecord=0; +#endif + + RemoveTimer(); // no more feeding + RemoveSound(); // no more sound handling + + return 0; +} + +// SPUSHUTDOWN: called by main emu on final exit +long CALLBACK SPUshutdown(void) +{ + SPUclose(); + RemoveStreams(); // no more streaming + + return 0; +} + +// SPUTEST: we don't test, we are always fine ;) +long CALLBACK SPUtest(void) +{ + return 0; +} + +// SPUCONFIGURE: call config dialog +long CALLBACK SPUconfigure(void) +{ +#if defined (_WINDOWS) + DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG), + GetActiveWindow(),(DLGPROC)DSoundDlgProc); +#elif defined (_MACOSX) + DoConfiguration(); +#else + StartCfgTool("CFG"); +#endif + + return 0; +} + +// SPUABOUT: show about window +void CALLBACK SPUabout(void) +{ +#if defined (_WINDOWS) + DialogBox(hInst,MAKEINTRESOURCE(IDD_ABOUT), + GetActiveWindow(),(DLGPROC)AboutDlgProc); +#elif defined (_MACOSX) + DoAbout(); +#else + StartCfgTool("ABOUT"); +#endif +} + +// SETUP CALLBACKS +// this functions will be called once, +// passes a callback that should be called on SPU-IRQ/cdda volume change +void CALLBACK SPUregisterCallback(void (CALLBACK *callback)(void)) +{ + irqCallback = callback; +} + +void CALLBACK SPUregisterCDDAVolume(void (CALLBACK *CDDAVcallback)(unsigned short,unsigned short)) +{ + cddavCallback = CDDAVcallback; +} + +// COMMON PLUGIN INFO FUNCS +char * CALLBACK PSEgetLibName(void) +{ + return _(libraryName); +} + +unsigned long CALLBACK PSEgetLibType(void) +{ + return PSE_LT_SPU; +} + +unsigned long CALLBACK PSEgetLibVersion(void) +{ + return (1 << 16) | (1 << 8); +} + +char * SPUgetLibInfos(void) +{ + return _(libraryInfo); +} diff --git a/plugins/dfsound/spu.h b/plugins/dfsound/spu.h index 8d492485..8912684b 100644 --- a/plugins/dfsound/spu.h +++ b/plugins/dfsound/spu.h @@ -1,22 +1,21 @@ -/*************************************************************************** - spu.h - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 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. * - * * - ***************************************************************************/ - -void SetupTimer(void); -void RemoveTimer(void); -void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap); -void CALLBACK SPUplayCDDAchannel(short *pcm, int bytes); -extern int lastch; \ No newline at end of file +/*************************************************************************** + spu.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 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. * + * * + ***************************************************************************/ + +void SetupTimer(void); +void RemoveTimer(void); +void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap); +void CALLBACK SPUplayCDDAchannel(short *pcm, int bytes); \ No newline at end of file diff --git a/plugins/dfsound/spucfg-0.1df/main.c b/plugins/dfsound/spucfg-0.1df/main.c index 8bea2b58..fc5976cb 100644 --- a/plugins/dfsound/spucfg-0.1df/main.c +++ b/plugins/dfsound/spucfg-0.1df/main.c @@ -1,274 +1,274 @@ -#include "config.h" - -#include -#include -#include -#include -#include - -#include -#include - -#ifdef ENABLE_NLS -#include -#include -#endif - -#define READBINARY "rb" -#define WRITEBINARY "wb" -#define CONFIG_FILENAME "dfsound.cfg" - -void SaveConfig(GtkWidget *widget, gpointer user_datal); - -/* This function checks for the value being outside the accepted range, - and returns the appropriate boundary value */ -static int set_limit (char *p, int len, int lower, int upper) -{ - int val = 0; - - if (p) - val = atoi(p + len); - - if (val < lower) - val = lower; - if (val > upper) - val = upper; - - return val; -} - -static void on_about_clicked (GtkWidget *widget, gpointer user_data) -{ - gtk_widget_destroy (widget); - exit (0); -} - -static void OnConfigClose(GtkWidget *widget, gpointer user_data) -{ - GladeXML *xml = (GladeXML *)user_data; - - gtk_widget_destroy(glade_xml_get_widget(xml, "CfgWnd")); - gtk_exit(0); -} - -int main(int argc, char *argv[]) -{ - GtkWidget *widget; - GladeXML *xml; - FILE *in; - char t[256]; - int len, val = 0; - char *pB, *p; - char cfg[255]; - -#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: cfgDFSound {ABOUT | CFG}\n"); - return 0; - } - - if (strcmp(argv[1], "CFG") != 0 && strcmp(argv[1], "ABOUT") != 0) { - printf ("Usage: cfgDFSound {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), "dfsound PCSX Sound Plugin"); - gtk_about_dialog_set_version (GTK_ABOUT_DIALOG (widget), "1.6"); - 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", - G_CALLBACK(on_about_clicked), NULL, NULL, G_CONNECT_AFTER); - - gtk_widget_show (widget); - gtk_main(); - - return 0; - } - - xml = glade_xml_new(DATADIR "dfsound.glade2", "CfgWnd", NULL); - if (!xml) { - g_warning("We could not load the interface!"); - return 255; - } - - strcpy(cfg, CONFIG_FILENAME); - - in = fopen(cfg, READBINARY); - if (in) { - pB = (char *)malloc(32767); - memset(pB, 0, 32767); - len = fread(pB, 1, 32767, in); - fclose(in); - } else { - pB = 0; - printf ("Error - no configuration file\n"); - /* TODO Raise error - no configuration file */ - } - - /* ADB TODO Replace a lot of the following with common functions */ - if (pB) { - strcpy(t, "\nVolume"); - p = strstr(pB, t); - if (p) { - p = strstr(p, "="); - len = 1; - } - val = set_limit (p, len, -1, 4) + 1; - } else val = 2; - - gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "cbVolume2")), val); - - if (pB) { - strcpy(t, "\nUseInterpolation"); - p = strstr(pB, t); - if (p) { - p = strstr(p, "="); - len = 1; - } - val = set_limit (p, len, 0, 3); - } else val = 2; - - gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "cbInterpolation2")), val); - - if (pB) { - strcpy(t, "\nXAPitch"); - p = strstr(pB, t); - if (p) { - p = strstr(p, "="); - len = 1; - } - val = set_limit (p, len, 0, 1); - } else val = 0; - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkXASpeed")), val); - - if (pB) { - strcpy(t, "\nHighCompMode"); - p = strstr(pB, t); - if (p) { - p = strstr(p, "="); - len = 1; - } - val = set_limit (p, len, 0, 1); - } else val = 1; - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkHiCompat")), val); - - if (pB) { - strcpy(t, "\nSPUIRQWait"); - p = strstr(pB, t); - if (p) { - p = strstr(p, "="); - len = 1; - } - - val = set_limit (p, len, 0, 1); - } else val = 1; - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkIRQWait")), val); - - if (pB) { - strcpy(t, "\nDisStereo"); - p = strstr(pB, t); - if (p) { - p = strstr(p, "="); - len = 1; - } - - val = set_limit (p, len, 0, 1); - } else val = 0; - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkDisStereo")), val); - - if (pB) { - strcpy(t, "\nFreqResponse"); - p = strstr(pB, t); - if (p) { - p = strstr(p, "="); - len = 1; - } - - val = set_limit (p, len, 0, 1); - } else val = 0; - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkFreqResponse")), val); - - if (pB) { - strcpy(t, "\nUseReverb"); - p = strstr(pB, t); - if (p) { - p = strstr(p, "="); - len = 1; - } - val = set_limit (p, len, 0, 2); - } else val = 2; - - gtk_combo_box_set_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "cbReverb2")), val); - - if (pB) - free(pB); - - widget = glade_xml_get_widget(xml, "CfgWnd"); - g_signal_connect_data(GTK_OBJECT(widget), "destroy", - G_CALLBACK(SaveConfig), xml, NULL, 0); - - widget = glade_xml_get_widget(xml, "btn_close"); - g_signal_connect_data(GTK_OBJECT(widget), "clicked", - G_CALLBACK(OnConfigClose), xml, NULL, G_CONNECT_AFTER); - - gtk_main(); - return 0; -} - -void SaveConfig(GtkWidget *widget, gpointer user_data) -{ - GladeXML *xml = (GladeXML *)user_data; - FILE *fp; - int val; - - fp = fopen(CONFIG_FILENAME, WRITEBINARY); - if (fp == NULL) { - fprintf(stderr, "Unable to write to configuration file %s!\n", CONFIG_FILENAME); - gtk_exit(0); - } - - val = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "cbVolume2"))); - fprintf(fp, "\nVolume = %d\n", val - 1); - - val = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "cbInterpolation2"))); - fprintf(fp, "\nUseInterpolation = %d\n", val); - - val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "chkXASpeed"))); - fprintf(fp, "\nXAPitch = %d\n", val); - - val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "chkHiCompat"))); - fprintf(fp, "\nHighCompMode = %d\n", val); - - val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "chkIRQWait"))); - fprintf(fp, "\nSPUIRQWait = %d\n", val); - - val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "chkDisStereo"))); - fprintf(fp, "\nDisStereo = %d\n", val); - - val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "chkFreqResponse"))); - fprintf(fp, "\nFreqResponse = %d\n", val); - - val = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "cbReverb2"))); - fprintf(fp, "\nUseReverb = %d\n", val); - - fclose(fp); - gtk_exit(0); -} +#include "config.h" + +#include +#include +#include +#include +#include + +#include +#include + +#ifdef ENABLE_NLS +#include +#include +#endif + +#define READBINARY "rb" +#define WRITEBINARY "wb" +#define CONFIG_FILENAME "dfsound.cfg" + +void SaveConfig(GtkWidget *widget, gpointer user_datal); + +/* 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); + + if (val < lower) + val = lower; + if (val > upper) + val = upper; + + return val; +} + +void on_about_clicked (GtkWidget *widget, gpointer user_data) +{ + gtk_widget_destroy (widget); + exit (0); +} + +void OnConfigClose(GtkWidget *widget, gpointer user_data) +{ + GladeXML *xml = (GladeXML *)user_data; + + gtk_widget_destroy(glade_xml_get_widget(xml, "CfgWnd")); + gtk_exit(0); +} + +int main(int argc, char *argv[]) +{ + GtkWidget *widget; + GladeXML *xml; + FILE *in; + char t[256]; + int len, val = 0; + char *pB, *p; + char cfg[255]; + +#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: cfgDFSound {ABOUT | CFG}\n"); + return 0; + } + + if (strcmp(argv[1], "CFG") != 0 && strcmp(argv[1], "ABOUT") != 0) { + printf ("Usage: cfgDFSound {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), "dfsound PCSX Sound Plugin"); + gtk_about_dialog_set_version (GTK_ABOUT_DIALOG (widget), "1.6"); + 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", + G_CALLBACK(on_about_clicked), NULL, NULL, G_CONNECT_AFTER); + + gtk_widget_show (widget); + gtk_main(); + + return 0; + } + + xml = glade_xml_new(DATADIR "dfsound.glade2", "CfgWnd", NULL); + if (!xml) { + g_warning("We could not load the interface!"); + return 255; + } + + strcpy(cfg, CONFIG_FILENAME); + + in = fopen(cfg, READBINARY); + if (in) { + pB = (char *)malloc(32767); + memset(pB, 0, 32767); + len = fread(pB, 1, 32767, in); + fclose(in); + } else { + pB = 0; + printf ("Error - no configuration file\n"); + /* TODO Raise error - no configuration file */ + } + + /* ADB TODO Replace a lot of the following with common functions */ + if (pB) { + strcpy(t, "\nVolume"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, -1, 4) + 1; + } else val = 2; + + gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "cbVolume2")), val); + + if (pB) { + strcpy(t, "\nUseInterpolation"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, 0, 3); + } else val = 2; + + gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "cbInterpolation2")), val); + + if (pB) { + strcpy(t, "\nXAPitch"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, 0, 1); + } else val = 0; + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkXASpeed")), val); + + if (pB) { + strcpy(t, "\nHighCompMode"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, 0, 1); + } else val = 1; + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkHiCompat")), val); + + if (pB) { + strcpy(t, "\nSPUIRQWait"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + + val = set_limit (p, len, 0, 1); + } else val = 1; + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkIRQWait")), val); + + if (pB) { + strcpy(t, "\nDisStereo"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + + val = set_limit (p, len, 0, 1); + } else val = 0; + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkDisStereo")), val); + + if (pB) { + strcpy(t, "\nFreqResponse"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + + val = set_limit (p, len, 0, 1); + } else val = 0; + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkFreqResponse")), val); + + if (pB) { + strcpy(t, "\nUseReverb"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, 0, 2); + } else val = 2; + + gtk_combo_box_set_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "cbReverb2")), val); + + if (pB) + free(pB); + + widget = glade_xml_get_widget(xml, "CfgWnd"); + g_signal_connect_data(GTK_OBJECT(widget), "destroy", + G_CALLBACK(SaveConfig), xml, NULL, 0); + + widget = glade_xml_get_widget(xml, "btn_close"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + G_CALLBACK(OnConfigClose), xml, NULL, G_CONNECT_AFTER); + + gtk_main(); + return 0; +} + +void SaveConfig(GtkWidget *widget, gpointer user_data) +{ + GladeXML *xml = (GladeXML *)user_data; + FILE *fp; + int val; + + fp = fopen(CONFIG_FILENAME, WRITEBINARY); + if (fp == NULL) { + fprintf(stderr, "Unable to write to configuration file %s!\n", CONFIG_FILENAME); + gtk_exit(0); + } + + val = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "cbVolume2"))); + fprintf(fp, "\nVolume = %d\n", val - 1); + + val = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "cbInterpolation2"))); + fprintf(fp, "\nUseInterpolation = %d\n", val); + + val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "chkXASpeed"))); + fprintf(fp, "\nXAPitch = %d\n", val); + + val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "chkHiCompat"))); + fprintf(fp, "\nHighCompMode = %d\n", val); + + val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "chkIRQWait"))); + fprintf(fp, "\nSPUIRQWait = %d\n", val); + + val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "chkDisStereo"))); + fprintf(fp, "\nDisStereo = %d\n", val); + + val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "chkFreqResponse"))); + fprintf(fp, "\nFreqResponse = %d\n", val); + + val = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "cbReverb2"))); + fprintf(fp, "\nUseReverb = %d\n", val); + + fclose(fp); + gtk_exit(0); +} diff --git a/plugins/dfsound/stdafx.h b/plugins/dfsound/stdafx.h index 5ba6c625..15ad99fa 100644 --- a/plugins/dfsound/stdafx.h +++ b/plugins/dfsound/stdafx.h @@ -1,66 +1,68 @@ -/*************************************************************************** - StdAfx.h - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 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. * - * * - ***************************************************************************/ - -#ifdef _WINDOWS - -#define WIN32_LEAN_AND_MEAN -#define STRICT -#include -#include -#include "mmsystem.h" -#include -#include - -#ifndef INLINE -#define INLINE __inline -#endif - -#include "resource.h" - -#pragma warning (disable:4996) - -#else - -#ifndef _MACOSX -#include "config.h" -#endif -#include -#include -#include -#include -#include -#ifdef USEOSS -#include -#endif -#include -#include -#define RRand(range) (random()%range) -#include -#include -#include - -#undef CALLBACK -#define CALLBACK -#define DWORD unsigned long -#define LOWORD(l) ((unsigned short)(l)) -#define HIWORD(l) ((unsigned short)(((unsigned long)(l) >> 16) & 0xFFFF)) - -#ifndef INLINE -#define INLINE inline -#endif - -#endif +/*************************************************************************** + StdAfx.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 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. * + * * + ***************************************************************************/ + +#ifdef _WINDOWS + +#define WIN32_LEAN_AND_MEAN +#define STRICT +#include +#include +#include "mmsystem.h" +#include +#include + +#ifndef INLINE +#define INLINE __inline +#endif + +#include "resource.h" + +#pragma warning (disable:4996) + +#else + +#ifndef _MACOSX +#include "config.h" +#endif +#include +#include +#include +#include +#include +#ifdef USEOSS +#include +#endif +#include +#include +#define RRand(range) (random()%range) +#include +#include +#include + +#undef CALLBACK +#define CALLBACK +#define DWORD unsigned long +#define LOWORD(l) ((unsigned short)(l)) +#define HIWORD(l) ((unsigned short)(((unsigned long)(l) >> 16) & 0xFFFF)) + +#ifndef INLINE +#define INLINE inline +#endif + +#endif + +#include "psemuxa.h" diff --git a/plugins/dfsound/xa.c b/plugins/dfsound/xa.c index a0ba86e8..bec405bd 100644 --- a/plugins/dfsound/xa.c +++ b/plugins/dfsound/xa.c @@ -1,412 +1,408 @@ -/*************************************************************************** - xa.c - description - ------------------- - begin : Wed May 15 2002 - copyright : (C) 2002 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 "stdafx.h" - -#include "xa.h" - -#define _IN_XA -#include - -// will be included from spu.c -#ifdef _IN_SPU - -//////////////////////////////////////////////////////////////////////// -// XA GLOBALS -//////////////////////////////////////////////////////////////////////// - -xa_decode_t * xapGlobal=0; - -uint32_t * XAFeed = NULL; -uint32_t * XAPlay = NULL; -uint32_t * XAStart = NULL; -uint32_t * XAEnd = NULL; - -uint32_t XARepeat = 0; -uint32_t XALastVal = 0; - -uint32_t * CDDAFeed = NULL; -uint32_t * CDDAPlay = NULL; -uint32_t * CDDAStart = NULL; -uint32_t * CDDAEnd = NULL; - -int iLeftXAVol = 0x8000; -int iRightXAVol = 0x8000; - -#if 0 -static int gauss_ptr = 0; -static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - -#define gvall0 gauss_window[gauss_ptr] -#define gvall(x) gauss_window[(gauss_ptr+x)&3] -#define gvalr0 gauss_window[4+gauss_ptr] -#define gvalr(x) gauss_window[4+((gauss_ptr+x)&3)] -#endif - -long cdxa_dbuf_ptr; - -//////////////////////////////////////////////////////////////////////// -// MIX XA & CDDA -//////////////////////////////////////////////////////////////////////// - -static int lastxa_lc, lastxa_rc; -static int lastcd_lc, lastcd_rc; - -INLINE void MixXA(void) -{ - int ns; - int lc,rc; - unsigned long cdda_l; - - lc = 0; - rc = 0; - - for(ns=0;ns>16) & 0xffff); - - if( lc < -32768 ) lc = -32768; - if( rc < -32768 ) rc = -32768; - if( lc > 32767 ) lc = 32767; - if( rc > 32767 ) rc = 32767; - - SSumL[ns]+=lc; - SSumR[ns]+=rc; - - // improve crackle - buffer under - // - not update fast enough - lastxa_lc = lc; - lastxa_rc = rc; - - -#if 0 - if( cdxa_dbuf_ptr >= 0x400 ) - cdxa_dbuf_ptr = 0; - spuMem[ (cdxa_dbuf_ptr + 0)/2 ] = lc; - spuMem[ (cdxa_dbuf_ptr + 0x400)/2 ] = rc; - cdxa_dbuf_ptr += 2; -#endif - } - - if(XAPlay==XAFeed && XARepeat) - { - //XARepeat--; - for(;ns= 0x400 ) - cdxa_dbuf_ptr = 0; - spuMem[ (cdxa_dbuf_ptr + 0)/2 ] = lastxa_rc; - spuMem[ (cdxa_dbuf_ptr + 0x400)/2 ] = lastxa_rc; - cdxa_dbuf_ptr += 2; -#endif - } - } - - for(ns=0;ns>16) & 0xffff); - - if( lc < -32768 ) lc = -32768; - if( rc < -32768 ) rc = -32768; - if( lc > 32767 ) lc = 32767; - if( rc > 32767 ) rc = 32767; - - SSumL[ns]+=lc; - SSumR[ns]+=rc; - -#if 0 - // Vib Ribbon - playback - if( cdxa_dbuf_ptr >= 0x400 ) - cdxa_dbuf_ptr = 0; - spuMem[ (cdxa_dbuf_ptr + 0)/2 ] = lc; - spuMem[ (cdxa_dbuf_ptr + 0x400)/2 ] = rc; - cdxa_dbuf_ptr += 2; -#endif - - // improve crackle - buffer under - // - not update fast enough - lastcd_lc = lc; - lastcd_rc = rc; - } - - - if(CDDAPlay==CDDAFeed && XARepeat) - { - //XARepeat--; - for(;ns= 0x400 ) - cdxa_dbuf_ptr = 0; - spuMem[ (cdxa_dbuf_ptr + 0)/2 ] = lastcd_lc; - spuMem[ (cdxa_dbuf_ptr + 0x400)/2 ] = lastcd_rc; - cdxa_dbuf_ptr += 2; -#endif - - SSumL[ns]+=lastcd_lc; - SSumR[ns]+=lastcd_rc; - } - } -} - -//////////////////////////////////////////////////////////////////////// -// small linux time helper... only used for watchdog -//////////////////////////////////////////////////////////////////////// - -#ifndef _WINDOWS - -unsigned long timeGetTime_spu() -{ - struct timeval tv; - gettimeofday(&tv, 0); // well, maybe there are better ways - return tv.tv_sec * 1000 + tv.tv_usec/1000; // to do that, but at least it works -} - -#endif - -//////////////////////////////////////////////////////////////////////// -// FEED XA -//////////////////////////////////////////////////////////////////////// - -INLINE void FeedXA(xa_decode_t *xap) -{ - int sinc,spos,i,iSize,iPlace; - - if(!bSPUIsOpen) return; - - xapGlobal = xap; // store info for save states - XARepeat = 100; // set up repeat - -#ifdef XA_HACK - iSize=((45500*xap->nsamples)/xap->freq); // get size -#else - iSize=((44100*xap->nsamples)/xap->freq); // get size -#endif - if(!iSize) return; // none? bye - - if(XAFeed=10) - { - if(!dwFPS) dwFPS=1; - dw1=1000000/dwFPS; - if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1; - else dwL1=dw1; - dw2=(xap->freq*100/xap->nsamples); - if((!dw1)||((dw2+100)>=dw1)) iLastSize=0; - else - { - iLastSize=iSize*dw2/dw1; - if(iLastSize>iPlace) iLastSize=iPlace; - iSize=iLastSize; - } - iFPSCnt=0;dwFPS=0; - } - else - { - if(iLastSize) iSize=iLastSize; - } - } - //----------------------------------------------------// - - spos=0x10000L; - sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size - - if(xap->stereo) -{ - uint32_t * pS=(uint32_t *)xap->pcm; - uint32_t l=0; - - if(iXAPitch) - { - int32_t l1,l2;short s; - for(i=0;i=0x10000L) - { - l = *pS++; - spos -= 0x10000L; - } - - s=(short)LOWORD(l); - l1=s; - l1=(l1*iPlace)/iSize; - if(l1<-32767) l1=-32767; - if(l1> 32767) l1=32767; - s=(short)HIWORD(l); - l2=s; - l2=(l2*iPlace)/iSize; - if(l2<-32767) l2=-32767; - if(l2> 32767) l2=32767; - l=(l1&0xffff)|(l2<<16); - - *XAFeed++=l; - - if(XAFeed==XAEnd) XAFeed=XAStart; - if(XAFeed==XAPlay) - { - if(XAPlay!=XAStart) XAFeed=XAPlay-1; - break; - } - - spos += sinc; - } - } - else - { - for(i=0;i=0x10000L) - { - l = *pS++; - spos -= 0x10000L; - } - - *XAFeed++=l; - - if(XAFeed==XAEnd) XAFeed=XAStart; - if(XAFeed==XAPlay) - { - if(XAPlay!=XAStart) XAFeed=XAPlay-1; - break; - } - - spos += sinc; - } - } - } - else - { - unsigned short * pS=(unsigned short *)xap->pcm; - uint32_t l;short s=0; - - if(iXAPitch) - { - int32_t l1; - for(i=0;i=0x10000L) - { - s = *pS++; - spos -= 0x10000L; - } - l1=s; - - l1=(l1*iPlace)/iSize; - if(l1<-32767) l1=-32767; - if(l1> 32767) l1=32767; - l=(l1&0xffff)|(l1<<16); - *XAFeed++=l; - - if(XAFeed==XAEnd) XAFeed=XAStart; - if(XAFeed==XAPlay) - { - if(XAPlay!=XAStart) XAFeed=XAPlay-1; - break; - } - - spos += sinc; - } - } - else - { - for(i=0;i=0x10000L) - { - s = *pS++; - spos -= 0x10000L; - } - l=s; - - *XAFeed++=((l&0xffff)|(l<<16)); - - if(XAFeed==XAEnd) XAFeed=XAStart; - if(XAFeed==XAPlay) - { - if(XAPlay!=XAStart) XAFeed=XAPlay-1; - break; - } - - spos += sinc; - } - } - } -} - -//////////////////////////////////////////////////////////////////////// -// FEED CDDA -//////////////////////////////////////////////////////////////////////// - -unsigned int cdda_ptr; - -INLINE void FeedCDDA(unsigned char *pcm, int nBytes) -{ - while(nBytes>0) - { - if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart; - while(CDDAFeed==CDDAPlay-1|| - (CDDAFeed==CDDAEnd-1&&CDDAPlay==CDDAStart)) - { -#ifdef _WINDOWS - if (!iUseTimer) Sleep(1); - else return; -#else - if (!iUseTimer) usleep(1000); - else return; -#endif - } - *CDDAFeed++=(*pcm | (*(pcm+1)<<8) | (*(pcm+2)<<16) | (*(pcm+3)<<24)); - nBytes-=4; - pcm+=4; - } -} - -#endif +/*************************************************************************** + xa.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 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 "stdafx.h" + +#define _IN_XA +#include + +// will be included from spu.c +#ifdef _IN_SPU + +//////////////////////////////////////////////////////////////////////// +// XA GLOBALS +//////////////////////////////////////////////////////////////////////// + +xa_decode_t * xapGlobal=0; + +uint32_t * XAFeed = NULL; +uint32_t * XAPlay = NULL; +uint32_t * XAStart = NULL; +uint32_t * XAEnd = NULL; + +uint32_t XARepeat = 0; +uint32_t XALastVal = 0; + +uint32_t * CDDAFeed = NULL; +uint32_t * CDDAPlay = NULL; +uint32_t * CDDAStart = NULL; +uint32_t * CDDAEnd = NULL; + +int iLeftXAVol = 0x8000; +int iRightXAVol = 0x8000; + +static int gauss_ptr = 0; +static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + +#define gvall0 gauss_window[gauss_ptr] +#define gvall(x) gauss_window[(gauss_ptr+x)&3] +#define gvalr0 gauss_window[4+gauss_ptr] +#define gvalr(x) gauss_window[4+((gauss_ptr+x)&3)] + +long cdxa_dbuf_ptr; + +//////////////////////////////////////////////////////////////////////// +// MIX XA & CDDA +//////////////////////////////////////////////////////////////////////// + +static int lastxa_lc, lastxa_rc; +static int lastcd_lc, lastcd_rc; + +INLINE void MixXA(void) +{ + int ns; + int lc,rc; + unsigned long cdda_l; + + lc = 0; + rc = 0; + + for(ns=0;ns>16) & 0xffff); + + if( lc < -32768 ) lc = -32768; + if( rc < -32768 ) rc = -32768; + if( lc > 32767 ) lc = 32767; + if( rc > 32767 ) rc = 32767; + + SSumL[ns]+=lc; + SSumR[ns]+=rc; + + // improve crackle - buffer under + // - not update fast enough + lastxa_lc = lc; + lastxa_rc = rc; + + +#if 0 + if( cdxa_dbuf_ptr >= 0x400 ) + cdxa_dbuf_ptr = 0; + spuMem[ (cdxa_dbuf_ptr + 0)/2 ] = lc; + spuMem[ (cdxa_dbuf_ptr + 0x400)/2 ] = rc; + cdxa_dbuf_ptr += 2; +#endif + } + + if(XAPlay==XAFeed && XARepeat) + { + //XARepeat--; + for(;ns= 0x400 ) + cdxa_dbuf_ptr = 0; + spuMem[ (cdxa_dbuf_ptr + 0)/2 ] = lastxa_rc; + spuMem[ (cdxa_dbuf_ptr + 0x400)/2 ] = lastxa_rc; + cdxa_dbuf_ptr += 2; +#endif + } + } + + for(ns=0;ns>16) & 0xffff); + + if( lc < -32768 ) lc = -32768; + if( rc < -32768 ) rc = -32768; + if( lc > 32767 ) lc = 32767; + if( rc > 32767 ) rc = 32767; + + SSumL[ns]+=lc; + SSumR[ns]+=rc; + +#if 0 + // Vib Ribbon - playback + if( cdxa_dbuf_ptr >= 0x400 ) + cdxa_dbuf_ptr = 0; + spuMem[ (cdxa_dbuf_ptr + 0)/2 ] = lc; + spuMem[ (cdxa_dbuf_ptr + 0x400)/2 ] = rc; + cdxa_dbuf_ptr += 2; +#endif + + // improve crackle - buffer under + // - not update fast enough + lastcd_lc = lc; + lastcd_rc = rc; + } + + + if(CDDAPlay==CDDAFeed && XARepeat) + { + //XARepeat--; + for(;ns= 0x400 ) + cdxa_dbuf_ptr = 0; + spuMem[ (cdxa_dbuf_ptr + 0)/2 ] = lastcd_lc; + spuMem[ (cdxa_dbuf_ptr + 0x400)/2 ] = lastcd_rc; + cdxa_dbuf_ptr += 2; +#endif + + SSumL[ns]+=lastcd_lc; + SSumR[ns]+=lastcd_rc; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// small linux time helper... only used for watchdog +//////////////////////////////////////////////////////////////////////// + +#ifndef _WINDOWS + +unsigned long timeGetTime_spu() +{ + struct timeval tv; + gettimeofday(&tv, 0); // well, maybe there are better ways + return tv.tv_sec * 1000 + tv.tv_usec/1000; // to do that, but at least it works +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// FEED XA +//////////////////////////////////////////////////////////////////////// + +INLINE void FeedXA(xa_decode_t *xap) +{ + int sinc,spos,i,iSize,iPlace,vl,vr; + + if(!bSPUIsOpen) return; + + xapGlobal = xap; // store info for save states + XARepeat = 100; // set up repeat + +#ifdef XA_HACK + iSize=((45500*xap->nsamples)/xap->freq); // get size +#else + iSize=((44100*xap->nsamples)/xap->freq); // get size +#endif + if(!iSize) return; // none? bye + + if(XAFeed=10) + { + if(!dwFPS) dwFPS=1; + dw1=1000000/dwFPS; + if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1; + else dwL1=dw1; + dw2=(xap->freq*100/xap->nsamples); + if((!dw1)||((dw2+100)>=dw1)) iLastSize=0; + else + { + iLastSize=iSize*dw2/dw1; + if(iLastSize>iPlace) iLastSize=iPlace; + iSize=iLastSize; + } + iFPSCnt=0;dwFPS=0; + } + else + { + if(iLastSize) iSize=iLastSize; + } + } + //----------------------------------------------------// + + spos=0x10000L; + sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size + + if(xap->stereo) +{ + uint32_t * pS=(uint32_t *)xap->pcm; + uint32_t l=0; + + if(iXAPitch) + { + int32_t l1,l2;short s; + for(i=0;i=0x10000L) + { + l = *pS++; + spos -= 0x10000L; + } + + s=(short)LOWORD(l); + l1=s; + l1=(l1*iPlace)/iSize; + if(l1<-32767) l1=-32767; + if(l1> 32767) l1=32767; + s=(short)HIWORD(l); + l2=s; + l2=(l2*iPlace)/iSize; + if(l2<-32767) l2=-32767; + if(l2> 32767) l2=32767; + l=(l1&0xffff)|(l2<<16); + + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + else + { + for(i=0;i=0x10000L) + { + l = *pS++; + spos -= 0x10000L; + } + + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + } + else + { + unsigned short * pS=(unsigned short *)xap->pcm; + uint32_t l;short s=0; + + if(iXAPitch) + { + int32_t l1; + for(i=0;i=0x10000L) + { + s = *pS++; + spos -= 0x10000L; + } + l1=s; + + l1=(l1*iPlace)/iSize; + if(l1<-32767) l1=-32767; + if(l1> 32767) l1=32767; + l=(l1&0xffff)|(l1<<16); + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + else + { + for(i=0;i=0x10000L) + { + s = *pS++; + spos -= 0x10000L; + } + l=s; + + *XAFeed++=((l&0xffff)|(l<<16)); + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + } +} + +//////////////////////////////////////////////////////////////////////// +// FEED CDDA +//////////////////////////////////////////////////////////////////////// + +unsigned int cdda_ptr; + +INLINE void FeedCDDA(unsigned char *pcm, int nBytes) +{ + while(nBytes>0) + { + if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart; + while(CDDAFeed==CDDAPlay-1|| + (CDDAFeed==CDDAEnd-1&&CDDAPlay==CDDAStart)) + { +#ifdef _WINDOWS + if (!iUseTimer) Sleep(1); + else return; +#else + if (!iUseTimer) usleep(1000); + else return; +#endif + } + *CDDAFeed++=(*pcm | (*(pcm+1)<<8) | (*(pcm+2)<<16) | (*(pcm+3)<<24)); + nBytes-=4; + pcm+=4; + } +} + +#endif diff --git a/plugins/dfxvideo/cfg.c b/plugins/dfxvideo/cfg.c index 04148486..70c08461 100644 --- a/plugins/dfxvideo/cfg.c +++ b/plugins/dfxvideo/cfg.c @@ -1,318 +1,318 @@ -/*************************************************************************** - cfg.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. * - * * - ***************************************************************************/ - -#define _IN_CFG - -#include -#include -#include - -#undef FALSE -#undef TRUE -#define MAKELONG(low,high) ((unsigned long)(((unsigned short)(low)) | (((unsigned long)((unsigned short)(high))) << 16))) - -#include "externals.h" -#include "cfg.h" -#include "gpu.h" - -char * pConfigFile = NULL; - -// CONFIG FILE helpers.... -// some helper macros: - -#define GetValue(name, var) \ - p = strstr(pB, name); \ - if (p != NULL) { \ - p+=strlen(name); \ - while ((*p == ' ') || (*p == '=')) p++; \ - if (*p != '\n') var = atoi(p); \ - } - -#define GetFloatValue(name, var) \ - p = strstr(pB, name); \ - if (p != NULL) { \ - p+=strlen(name); \ - while ((*p == ' ') || (*p == '=')) p++; \ - if (*p != '\n') var = (float)atof(p); \ - } - -#define SetValue(name, var) \ - p = strstr(pB, name); \ - if (p != NULL) { \ - p+=strlen(name); \ - while ((*p == ' ') || (*p == '=')) p++; \ - if (*p != '\n') { \ - len = sprintf(t1, "%d", var); \ - strncpy(p, t1, len); \ - if (p[len] != ' ' && p[len] != '\n' && p[len] != 0) p[len] = ' '; \ - } \ - } \ - else { \ - size+=sprintf(pB+size, "%s = %d\n", name, var); \ - } - -#define SetFloatValue(name, var) \ - p = strstr(pB, name); \ - if (p != NULL) { \ - p+=strlen(name); \ - while ((*p == ' ') || (*p == '=')) p++; \ - if (*p != '\n') { \ - len = sprintf(t1, "%.1f", (double)var); \ - strncpy(p, t1, len); \ - if (p[len] != ' ' && p[len] != '\n' && p[len] != 0) p[len] = ' '; \ - } \ - } \ - else { \ - size+=sprintf(pB+size, "%s = %.1f\n", name, (double)var); \ - } - -static void ReadConfigFile() -{ - struct stat buf; - FILE *in;char t[256];int len, size; - char * pB, * p; - - if(pConfigFile) - strcpy(t,pConfigFile); - else - { - strcpy(t,"dfxvideo.cfg"); - in = fopen(t,"rb"); - if (!in) - { - strcpy(t,"cfg/dfxvideo.cfg"); - in = fopen(t,"rb"); - if(!in) sprintf(t,"%s/.pcsx/plugins/dfxvideo.cfg",getenv("HOME")); - else fclose(in); - } - else fclose(in); - } - - if (stat(t, &buf) == -1) return; - size = buf.st_size; - - in = fopen(t,"rb"); - if (!in) return; - - pB=(char *)malloc(size + 1); - memset(pB,0,size + 1); - - len = fread(pB, 1, size, in); - fclose(in); - - GetValue("ResX", iResX); - if(iResX<20) iResX=20; - iResX=(iResX/4)*4; - - GetValue("ResY", iResY); - if(iResY<20) iResY=20; - iResY=(iResY/4)*4; - - iWinSize=MAKELONG(iResX,iResY); - - GetValue("NoStretch", iUseNoStretchBlt); - - GetValue("Dithering", iUseDither); - - GetValue("FullScreen", iWindowMode); - if(iWindowMode!=0) iWindowMode=0; - else iWindowMode=1; - - GetValue("ShowFPS", iShowFPS); - if(iShowFPS<0) iShowFPS=0; - if(iShowFPS>1) iShowFPS=1; - - GetValue("Maintain43", iMaintainAspect); - if(iMaintainAspect<0) iMaintainAspect=0; - if(iMaintainAspect>1) iMaintainAspect=1; - - GetValue("UseFrameLimit", UseFrameLimit); - if(UseFrameLimit<0) UseFrameLimit=0; - if(UseFrameLimit>1) UseFrameLimit=1; - - GetValue("UseFrameSkip", UseFrameSkip); - if(UseFrameSkip<0) UseFrameSkip=0; - if(UseFrameSkip>1) UseFrameSkip=1; - - GetValue("FPSDetection", iFrameLimit); - if(iFrameLimit<1) iFrameLimit=1; - if(iFrameLimit>2) iFrameLimit=2; - - GetFloatValue("FrameRate", fFrameRate); - fFrameRate/=10; - if(fFrameRate<10.0f) fFrameRate=10.0f; - if(fFrameRate>1000.0f) fFrameRate=1000.0f; - - GetValue("CfgFixes", dwCfgFixes); - - GetValue("UseFixes", iUseFixes); - if(iUseFixes<0) iUseFixes=0; - if(iUseFixes>1) iUseFixes=1; - - free(pB); -} - -static void ExecCfg(char *arg) { - char cfg[256]; - struct stat buf; - - strcpy(cfg, "./cfgDFXVideo"); - if (stat(cfg, &buf) != -1) { - if (fork() == 0) { - execl(cfg, "cfgDFXVideo", arg, NULL); - exit(0); - } - return; - } - - strcpy(cfg, "./cfg/cfgDFXVideo"); - if (stat(cfg, &buf) != -1) { - if (fork() == 0) { - execl(cfg, "cfgDFXVideo", arg, NULL); - exit(0); - } - return; - } - - sprintf(cfg, "%s/.pcsx/plugins/cfg/cfgDFXVideo", getenv("HOME")); - if (stat(cfg, &buf) != -1) { - if (fork() == 0) { - execl(cfg, "cfgDFXVideo", arg, NULL); - exit(0); - } - return; - } - - printf("ERROR: cfgDFXVideo file not found!\n"); -} - -void SoftDlgProc(void) -{ - ExecCfg("CFG"); -} - -void AboutDlgProc(void) -{ - char args[256]; - - sprintf(args, "ABOUT"); - ExecCfg(args); -} - -void ReadConfig(void) -{ - // defaults - iResX=640;iResY=480; - iWinSize=MAKELONG(iResX,iResY); - iColDepth=32; - iWindowMode=1; - iMaintainAspect=0; - UseFrameLimit=1; - UseFrameSkip=0; - iFrameLimit=2; - fFrameRate=200.0f; - dwCfgFixes=0; - iUseFixes=0; - iUseNoStretchBlt=0; - iUseDither=0; - iShowFPS=0; - - // read sets - ReadConfigFile(); - - // additional checks - if(!iColDepth) iColDepth=32; - if(iUseFixes) dwActFixes=dwCfgFixes; - SetFixes(); -} - -void WriteConfig(void) { - - struct stat buf; - FILE *out;char t[256];int len, size; - char * pB, * p; char t1[8]; - - if(pConfigFile) - strcpy(t,pConfigFile); - else - { - strcpy(t,"dfxvideo.cfg"); - out = fopen(t,"rb"); - if (!out) - { - strcpy(t,"cfg/dfxvideo.cfg"); - out = fopen(t,"rb"); - if(!out) sprintf(t,"%s/.pcsx/plugins/dfxvideo.cfg",getenv("HOME")); - else fclose(out); - } - else fclose(out); - } - - if (stat(t, &buf) != -1) size = buf.st_size; - else size = 0; - - out = fopen(t,"rb"); - if (!out) { - // defaults - iResX=640;iResY=480; - iColDepth=32; - iWindowMode=1; - iMaintainAspect=0; - UseFrameLimit=0; - UseFrameSkip=0; - iFrameLimit=2; - fFrameRate=200.0f; - dwCfgFixes=0; - iUseFixes=0; - iUseNoStretchBlt=0; - iUseDither=0; - iShowFPS=0; - - size = 0; - pB=(char *)malloc(4096); - memset(pB,0,4096); - } - else { - pB=(char *)malloc(size+4096); - memset(pB,0,size+4096); - - len = fread(pB, 1, size, out); - fclose(out); - } - - SetValue("ResX", iResX); - SetValue("ResY", iResY); - SetValue("NoStretch", iUseNoStretchBlt); - SetValue("Dithering", iUseDither); - SetValue("FullScreen", !iWindowMode); - SetValue("ShowFPS", iShowFPS); - SetValue("Maintain43", iMaintainAspect); - SetValue("UseFrameLimit", UseFrameLimit); - SetValue("UseFrameSkip", UseFrameSkip); - SetValue("FPSDetection", iFrameLimit); - SetFloatValue("FrameRate", fFrameRate); - SetValue("CfgFixes", (unsigned int)dwCfgFixes); - SetValue("UseFixes", iUseFixes); - - out = fopen(t,"wb"); - if (!out) return; - - len = fwrite(pB, 1, size, out); - fclose(out); - - free(pB); -} +/*************************************************************************** + cfg.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. * + * * + ***************************************************************************/ + +#define _IN_CFG + +#include +#include +#include + +#undef FALSE +#undef TRUE +#define MAKELONG(low,high) ((unsigned long)(((unsigned short)(low)) | (((unsigned long)((unsigned short)(high))) << 16))) + +#include "externals.h" +#include "cfg.h" +#include "gpu.h" + +char * pConfigFile = NULL; + +// CONFIG FILE helpers.... +// some helper macros: + +#define GetValue(name, var) \ + p = strstr(pB, name); \ + if (p != NULL) { \ + p+=strlen(name); \ + while ((*p == ' ') || (*p == '=')) p++; \ + if (*p != '\n') var = atoi(p); \ + } + +#define GetFloatValue(name, var) \ + p = strstr(pB, name); \ + if (p != NULL) { \ + p+=strlen(name); \ + while ((*p == ' ') || (*p == '=')) p++; \ + if (*p != '\n') var = (float)atof(p); \ + } + +#define SetValue(name, var) \ + p = strstr(pB, name); \ + if (p != NULL) { \ + p+=strlen(name); \ + while ((*p == ' ') || (*p == '=')) p++; \ + if (*p != '\n') { \ + len = sprintf(t1, "%d", var); \ + strncpy(p, t1, len); \ + if (p[len] != ' ' && p[len] != '\n' && p[len] != 0) p[len] = ' '; \ + } \ + } \ + else { \ + size+=sprintf(pB+size, "%s = %d\n", name, var); \ + } + +#define SetFloatValue(name, var) \ + p = strstr(pB, name); \ + if (p != NULL) { \ + p+=strlen(name); \ + while ((*p == ' ') || (*p == '=')) p++; \ + if (*p != '\n') { \ + len = sprintf(t1, "%.1f", (double)var); \ + strncpy(p, t1, len); \ + if (p[len] != ' ' && p[len] != '\n' && p[len] != 0) p[len] = ' '; \ + } \ + } \ + else { \ + size+=sprintf(pB+size, "%s = %.1f\n", name, (double)var); \ + } + +void ReadConfigFile() +{ + struct stat buf; + FILE *in;char t[256];int len, size; + char * pB, * p; + + if(pConfigFile) + strcpy(t,pConfigFile); + else + { + strcpy(t,"dfxvideo.cfg"); + in = fopen(t,"rb"); + if (!in) + { + strcpy(t,"cfg/dfxvideo.cfg"); + in = fopen(t,"rb"); + if(!in) sprintf(t,"%s/.pcsx/plugins/dfxvideo.cfg",getenv("HOME")); + else fclose(in); + } + else fclose(in); + } + + if (stat(t, &buf) == -1) return; + size = buf.st_size; + + in = fopen(t,"rb"); + if (!in) return; + + pB=(char *)malloc(size + 1); + memset(pB,0,size + 1); + + len = fread(pB, 1, size, in); + fclose(in); + + GetValue("ResX", iResX); + if(iResX<20) iResX=20; + iResX=(iResX/4)*4; + + GetValue("ResY", iResY); + if(iResY<20) iResY=20; + iResY=(iResY/4)*4; + + iWinSize=MAKELONG(iResX,iResY); + + GetValue("NoStretch", iUseNoStretchBlt); + + GetValue("Dithering", iUseDither); + + GetValue("FullScreen", iWindowMode); + if(iWindowMode!=0) iWindowMode=0; + else iWindowMode=1; + + GetValue("ShowFPS", iShowFPS); + if(iShowFPS<0) iShowFPS=0; + if(iShowFPS>1) iShowFPS=1; + + GetValue("Maintain43", iMaintainAspect); + if(iMaintainAspect<0) iMaintainAspect=0; + if(iMaintainAspect>1) iMaintainAspect=1; + + GetValue("UseFrameLimit", UseFrameLimit); + if(UseFrameLimit<0) UseFrameLimit=0; + if(UseFrameLimit>1) UseFrameLimit=1; + + GetValue("UseFrameSkip", UseFrameSkip); + if(UseFrameSkip<0) UseFrameSkip=0; + if(UseFrameSkip>1) UseFrameSkip=1; + + GetValue("FPSDetection", iFrameLimit); + if(iFrameLimit<1) iFrameLimit=1; + if(iFrameLimit>2) iFrameLimit=2; + + GetFloatValue("FrameRate", fFrameRate); + fFrameRate/=10; + if(fFrameRate<10.0f) fFrameRate=10.0f; + if(fFrameRate>1000.0f) fFrameRate=1000.0f; + + GetValue("CfgFixes", dwCfgFixes); + + GetValue("UseFixes", iUseFixes); + if(iUseFixes<0) iUseFixes=0; + if(iUseFixes>1) iUseFixes=1; + + free(pB); +} + +void ExecCfg(char *arg) { + char cfg[256]; + struct stat buf; + + strcpy(cfg, "./cfgDFXVideo"); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgDFXVideo", arg, NULL); + exit(0); + } + return; + } + + strcpy(cfg, "./cfg/cfgDFXVideo"); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgDFXVideo", arg, NULL); + exit(0); + } + return; + } + + sprintf(cfg, "%s/.pcsx/plugins/cfg/cfgDFXVideo", getenv("HOME")); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgDFXVideo", arg, NULL); + exit(0); + } + return; + } + + printf("ERROR: cfgDFXVideo file not found!\n"); +} + +void SoftDlgProc(void) +{ + ExecCfg("CFG"); +} + +void AboutDlgProc(void) +{ + char args[256]; + + sprintf(args, "ABOUT"); + ExecCfg(args); +} + +void ReadConfig(void) +{ + // defaults + iResX=640;iResY=480; + iWinSize=MAKELONG(iResX,iResY); + iColDepth=32; + iWindowMode=1; + iMaintainAspect=0; + UseFrameLimit=1; + UseFrameSkip=0; + iFrameLimit=2; + fFrameRate=200.0f; + dwCfgFixes=0; + iUseFixes=0; + iUseNoStretchBlt=0; + iUseDither=0; + iShowFPS=0; + + // read sets + ReadConfigFile(); + + // additional checks + if(!iColDepth) iColDepth=32; + if(iUseFixes) dwActFixes=dwCfgFixes; + SetFixes(); +} + +void WriteConfig(void) { + + struct stat buf; + FILE *out;char t[256];int len, size; + char * pB, * p; char t1[8]; + + if(pConfigFile) + strcpy(t,pConfigFile); + else + { + strcpy(t,"dfxvideo.cfg"); + out = fopen(t,"rb"); + if (!out) + { + strcpy(t,"cfg/dfxvideo.cfg"); + out = fopen(t,"rb"); + if(!out) sprintf(t,"%s/.pcsx/plugins/dfxvideo.cfg",getenv("HOME")); + else fclose(out); + } + else fclose(out); + } + + if (stat(t, &buf) != -1) size = buf.st_size; + else size = 0; + + out = fopen(t,"rb"); + if (!out) { + // defaults + iResX=640;iResY=480; + iColDepth=32; + iWindowMode=1; + iMaintainAspect=0; + UseFrameLimit=0; + UseFrameSkip=0; + iFrameLimit=2; + fFrameRate=200.0f; + dwCfgFixes=0; + iUseFixes=0; + iUseNoStretchBlt=0; + iUseDither=0; + iShowFPS=0; + + size = 0; + pB=(char *)malloc(4096); + memset(pB,0,4096); + } + else { + pB=(char *)malloc(size+4096); + memset(pB,0,size+4096); + + len = fread(pB, 1, size, out); + fclose(out); + } + + SetValue("ResX", iResX); + SetValue("ResY", iResY); + SetValue("NoStretch", iUseNoStretchBlt); + SetValue("Dithering", iUseDither); + SetValue("FullScreen", !iWindowMode); + SetValue("ShowFPS", iShowFPS); + SetValue("Maintain43", iMaintainAspect); + SetValue("UseFrameLimit", UseFrameLimit); + SetValue("UseFrameSkip", UseFrameSkip); + SetValue("FPSDetection", iFrameLimit); + SetFloatValue("FrameRate", fFrameRate); + SetValue("CfgFixes", (unsigned int)dwCfgFixes); + SetValue("UseFixes", iUseFixes); + + out = fopen(t,"wb"); + if (!out) return; + + len = fwrite(pB, 1, size, out); + fclose(out); + + free(pB); +} diff --git a/plugins/dfxvideo/draw.c b/plugins/dfxvideo/draw.c index 52d665a9..26281753 100644 --- a/plugins/dfxvideo/draw.c +++ b/plugins/dfxvideo/draw.c @@ -1,2149 +1,2153 @@ -/*************************************************************************** - draw.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. * - * * - ***************************************************************************/ - -#define _IN_DRAW - -#include "externals.h" -#include "gpu.h" -#include "draw.h" -#include "prim.h" -#include "menu.h" -#include "interp.h" -#include "swap.h" - -// misc globals -int iResX; -int iResY; -long lLowerpart; -BOOL bIsFirstFrame = TRUE; -BOOL bCheckMask = FALSE; -unsigned short sSetMask = 0; -unsigned long lSetMask = 0; -int iDesktopCol = 16; -int iShowFPS = 0; -int iWinSize; -int iMaintainAspect = 0; -int iUseNoStretchBlt = 0; -int iFastFwd = 0; -int iDebugMode = 0; -int iFVDisplay = 0; -PSXPoint_t ptCursorPoint[8]; -unsigned short usCursorActive = 0; - -//unsigned int LUT16to32[65536]; -//unsigned int RGBtoYUV[65536]; - -#include -#include -#include -#include -#include -int xv_port = -1; -int xv_id = -1; -int xv_depth = 0; -int yuv_port = -1; -int yuv_id = -1; -int use_yuv = 0; -int xv_vsync = 0; - -XShmSegmentInfo shminfo; -int finalw,finalh; - -#include - -// prototypes -void hq2x_32( unsigned char * srcPtr, DWORD srcPitch, unsigned char * dstPtr, int width, int height); -void hq3x_32( unsigned char * srcPtr, DWORD srcPitch, unsigned char * dstPtr, int width, int height); - -//////////////////////////////////////////////////////////////////////// -// generic 2xSaI helpers -//////////////////////////////////////////////////////////////////////// - -void * pSaISmallBuff=NULL; -void * pSaIBigBuff=NULL; - -#define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D)) - -static __inline int GetResult1(DWORD A, DWORD B, DWORD C, DWORD D, DWORD E) -{ - int x = 0; - int y = 0; - int r = 0; - if (A == C) x+=1; else if (B == C) y+=1; - if (A == D) x+=1; else if (B == D) y+=1; - if (x <= 1) r+=1; - if (y <= 1) r-=1; - return r; -} - -static __inline int GetResult2(DWORD A, DWORD B, DWORD C, DWORD D, DWORD E) -{ - int x = 0; - int y = 0; - int r = 0; - if (A == C) x+=1; else if (B == C) y+=1; - if (A == D) x+=1; else if (B == D) y+=1; - if (x <= 1) r-=1; - if (y <= 1) r+=1; - return r; -} - -/* Convert RGB to YUV */ -static __inline uint32_t rgb_to_yuv(uint8_t R, uint8_t G, uint8_t B) { - uint8_t Y = min(abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13, 235); - uint8_t U = min(abs(R * -1214 + G * -2384 + B * 3598 + 4096 + 1048576) >> 13, 240); - uint8_t V = min(abs(R * 3598 + G * -3013 + B * -585 + 4096 + 1048576) >> 13, 240); - -#ifdef __BIG_ENDIAN__ - return Y << 24 | U << 16 | Y << 8 | V; -#else - return Y << 24 | V << 16 | Y << 8 | U; -#endif -} - -#define colorMask8 0x00FEFEFE -#define lowPixelMask8 0x00010101 -#define qcolorMask8 0x00FCFCFC -#define qlowpixelMask8 0x00030303 - -#define INTERPOLATE8(A, B) ((((A & colorMask8) >> 1) + ((B & colorMask8) >> 1) + (A & B & lowPixelMask8))) -#define Q_INTERPOLATE8(A, B, C, D) (((((A & qcolorMask8) >> 2) + ((B & qcolorMask8) >> 2) + ((C & qcolorMask8) >> 2) + ((D & qcolorMask8) >> 2) \ - + ((((A & qlowpixelMask8) + (B & qlowpixelMask8) + (C & qlowpixelMask8) + (D & qlowpixelMask8)) >> 2) & qlowpixelMask8)))) - - -static void Super2xSaI_ex8(unsigned char *srcPtr, DWORD srcPitch, - unsigned char *dstBitmap, int width, int height) -{ - DWORD dstPitch = srcPitch<<1; - DWORD srcPitchHalf = srcPitch>>1; - int finWidth = srcPitch>>2; - DWORD line; - DWORD *dP; - DWORD *bP; - int iXA,iXB,iXC,iYA,iYB,iYC,finish; - DWORD color4, color5, color6; - DWORD color1, color2, color3; - DWORD colorA0, colorA1, colorA2, colorA3, - colorB0, colorB1, colorB2, colorB3, - colorS1, colorS2; - DWORD product1a, product1b, - product2a, product2b; - - finalw=width<<1; - finalh=height<<1; - - line = 0; - - { - for (; height; height-=1) - { - bP = (DWORD *)srcPtr; - dP = (DWORD *)(dstBitmap + line*dstPitch); - for (finish = width; finish; finish -= 1 ) - { -//--------------------------------------- B1 B2 -// 4 5 6 S2 -// 1 2 3 S1 -// A1 A2 - if(finish==finWidth) iXA=0; - else iXA=1; - if(finish>4) {iXB=1;iXC=2;} - else - if(finish>3) {iXB=1;iXC=1;} - else {iXB=0;iXC=0;} - if(line==0) {iYA=0;} - else {iYA=finWidth;} - if(height>4) {iYB=finWidth;iYC=srcPitchHalf;} - else - if(height>3) {iYB=finWidth;iYC=finWidth;} - else {iYB=0;iYC=0;} - - colorB0 = *(bP- iYA - iXA); - colorB1 = *(bP- iYA); - colorB2 = *(bP- iYA + iXB); - colorB3 = *(bP- iYA + iXC); - - color4 = *(bP - iXA); - color5 = *(bP); - color6 = *(bP + iXB); - colorS2 = *(bP + iXC); - - color1 = *(bP + iYB - iXA); - color2 = *(bP + iYB); - color3 = *(bP + iYB + iXB); - colorS1= *(bP + iYB + iXC); - - colorA0 = *(bP + iYC - iXA); - colorA1 = *(bP + iYC); - colorA2 = *(bP + iYC + iXB); - colorA3 = *(bP + iYC + iXC); - - if (color2 == color6 && color5 != color3) - { - product2b = product1b = color2; - } - else - if (color5 == color3 && color2 != color6) - { - product2b = product1b = color5; - } - else - if (color5 == color3 && color2 == color6) - { - register int r = 0; - - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff), (colorA1&0x00ffffff)); - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff), (colorB1&0x00ffffff)); - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff)); - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff)); - - if (r > 0) - product2b = product1b = color6; - else - if (r < 0) - product2b = product1b = color5; - else - { - product2b = product1b = INTERPOLATE8(color5, color6); - } - } - else - { - if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) - product2b = Q_INTERPOLATE8 (color3, color3, color3, color2); - else - if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) - product2b = Q_INTERPOLATE8 (color2, color2, color2, color3); - else - product2b = INTERPOLATE8 (color2, color3); - - if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) - product1b = Q_INTERPOLATE8 (color6, color6, color6, color5); - else - if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) - product1b = Q_INTERPOLATE8 (color6, color5, color5, color5); - else - product1b = INTERPOLATE8 (color5, color6); - } - - if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) - product2a = INTERPOLATE8(color2, color5); - else - if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) - product2a = INTERPOLATE8(color2, color5); - else - product2a = color2; - - if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) - product1a = INTERPOLATE8(color2, color5); - else - if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) - product1a = INTERPOLATE8(color2, color5); - else - product1a = color5; - - *dP=product1a; - *(dP+1)=product1b; - *(dP+(srcPitchHalf))=product2a; - *(dP+1+(srcPitchHalf))=product2b; - - bP += 1; - dP += 2; - }//end of for ( finish= width etc..) - - line += 2; - srcPtr += srcPitch; - }; //endof: for (; height; height--) - } -} - -//////////////////////////////////////////////////////////////////////// - -static void Std2xSaI_ex8(unsigned char *srcPtr, DWORD srcPitch, - unsigned char *dstBitmap, int width, int height) -{ - DWORD dstPitch = srcPitch<<1; - DWORD srcPitchHalf = srcPitch>>1; - int finWidth = srcPitch>>2; - DWORD line; - DWORD *dP; - DWORD *bP; - int iXA,iXB,iXC,iYA,iYB,iYC,finish; - - finalw=width<<1; - finalh=height<<1; - - DWORD colorA, colorB; - DWORD colorC, colorD, - colorE, colorF, colorG, colorH, - colorI, colorJ, colorK, colorL, - colorM, colorN, colorO, colorP; - DWORD product, product1, product2; - - line = 0; - - { - for (; height; height-=1) - { - bP = (DWORD *)srcPtr; - dP = (DWORD *)(dstBitmap + line*dstPitch); - for (finish = width; finish; finish -= 1 ) - { -//--------------------------------------- -// Map of the pixels: I|E F|J -// G|A B|K -// H|C D|L -// M|N O|P - if(finish==finWidth) iXA=0; - else iXA=1; - if(finish>4) {iXB=1;iXC=2;} - else - if(finish>3) {iXB=1;iXC=1;} - else {iXB=0;iXC=0;} - if(line==0) {iYA=0;} - else {iYA=finWidth;} - if(height>4) {iYB=finWidth;iYC=srcPitchHalf;} - else - if(height>3) {iYB=finWidth;iYC=finWidth;} - else {iYB=0;iYC=0;} - - colorI = *(bP- iYA - iXA); - colorE = *(bP- iYA); - colorF = *(bP- iYA + iXB); - colorJ = *(bP- iYA + iXC); - - colorG = *(bP - iXA); - colorA = *(bP); - colorB = *(bP + iXB); - colorK = *(bP + iXC); - - colorH = *(bP + iYB - iXA); - colorC = *(bP + iYB); - colorD = *(bP + iYB + iXB); - colorL = *(bP + iYB + iXC); - - colorM = *(bP + iYC - iXA); - colorN = *(bP + iYC); - colorO = *(bP + iYC + iXB); - colorP = *(bP + iYC + iXC); - - - if((colorA == colorD) && (colorB != colorC)) - { - if(((colorA == colorE) && (colorB == colorL)) || - ((colorA == colorC) && (colorA == colorF) && - (colorB != colorE) && (colorB == colorJ))) - { - product = colorA; - } - else - { - product = INTERPOLATE8(colorA, colorB); - } - - if(((colorA == colorG) && (colorC == colorO)) || - ((colorA == colorB) && (colorA == colorH) && - (colorG != colorC) && (colorC == colorM))) - { - product1 = colorA; - } - else - { - product1 = INTERPOLATE8(colorA, colorC); - } - product2 = colorA; - } - else - if((colorB == colorC) && (colorA != colorD)) - { - if(((colorB == colorF) && (colorA == colorH)) || - ((colorB == colorE) && (colorB == colorD) && - (colorA != colorF) && (colorA == colorI))) - { - product = colorB; - } - else - { - product = INTERPOLATE8(colorA, colorB); - } - - if(((colorC == colorH) && (colorA == colorF)) || - ((colorC == colorG) && (colorC == colorD) && - (colorA != colorH) && (colorA == colorI))) - { - product1 = colorC; - } - else - { - product1=INTERPOLATE8(colorA, colorC); - } - product2 = colorB; - } - else - if((colorA == colorD) && (colorB == colorC)) - { - if (colorA == colorB) - { - product = colorA; - product1 = colorA; - product2 = colorA; - } - else - { - register int r = 0; - product1 = INTERPOLATE8(colorA, colorC); - product = INTERPOLATE8(colorA, colorB); - - r += GetResult1 (colorA&0x00FFFFFF, colorB&0x00FFFFFF, colorG&0x00FFFFFF, colorE&0x00FFFFFF, colorI&0x00FFFFFF); - r += GetResult2 (colorB&0x00FFFFFF, colorA&0x00FFFFFF, colorK&0x00FFFFFF, colorF&0x00FFFFFF, colorJ&0x00FFFFFF); - r += GetResult2 (colorB&0x00FFFFFF, colorA&0x00FFFFFF, colorH&0x00FFFFFF, colorN&0x00FFFFFF, colorM&0x00FFFFFF); - r += GetResult1 (colorA&0x00FFFFFF, colorB&0x00FFFFFF, colorL&0x00FFFFFF, colorO&0x00FFFFFF, colorP&0x00FFFFFF); - - if (r > 0) - product2 = colorA; - else - if (r < 0) - product2 = colorB; - else - { - product2 = Q_INTERPOLATE8(colorA, colorB, colorC, colorD); - } - } - } - else - { - product2 = Q_INTERPOLATE8(colorA, colorB, colorC, colorD); - - if ((colorA == colorC) && (colorA == colorF) && - (colorB != colorE) && (colorB == colorJ)) - { - product = colorA; - } - else - if ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI)) - { - product = colorB; - } - else - { - product = INTERPOLATE8(colorA, colorB); - } - - if ((colorA == colorB) && (colorA == colorH) && - (colorG != colorC) && (colorC == colorM)) - { - product1 = colorA; - } - else - if ((colorC == colorG) && (colorC == colorD) && - (colorA != colorH) && (colorA == colorI)) - { - product1 = colorC; - } - else - { - product1 = INTERPOLATE8(colorA, colorC); - } - } - -////////////////////////// - - *dP=colorA; - *(dP+1)=product; - *(dP+(srcPitchHalf))=product1; - *(dP+1+(srcPitchHalf))=product2; - - bP += 1; - dP += 2; - }//end of for ( finish= width etc..) - - line += 2; - srcPtr += srcPitch; - }; //endof: for (; height; height--) - } -} - -//////////////////////////////////////////////////////////////////////// - -static void SuperEagle_ex8(unsigned char *srcPtr, DWORD srcPitch, - unsigned char *dstBitmap, int width, int height) -{ - DWORD dstPitch = srcPitch<<1; - DWORD srcPitchHalf = srcPitch>>1; - int finWidth = srcPitch>>2; - DWORD line; - DWORD *dP; - DWORD *bP; - int iXA,iXB,iXC,iYA,iYB,iYC,finish; - DWORD color4, color5, color6; - DWORD color1, color2, color3; - DWORD colorA1, colorA2, - colorB1, colorB2, - colorS1, colorS2; - DWORD product1a, product1b, - product2a, product2b; - - finalw=width<<1; - finalh=height<<1; - - line = 0; - - { - for (; height; height-=1) - { - bP = (DWORD *)srcPtr; - dP = (DWORD *)(dstBitmap + line*dstPitch); - for (finish = width; finish; finish -= 1 ) - { - if(finish==finWidth) iXA=0; - else iXA=1; - if(finish>4) {iXB=1;iXC=2;} - else - if(finish>3) {iXB=1;iXC=1;} - else {iXB=0;iXC=0;} - if(line==0) {iYA=0;} - else {iYA=finWidth;} - if(height>4) {iYB=finWidth;iYC=srcPitchHalf;} - else - if(height>3) {iYB=finWidth;iYC=finWidth;} - else {iYB=0;iYC=0;} - - colorB1 = *(bP- iYA); - colorB2 = *(bP- iYA + iXB); - - color4 = *(bP - iXA); - color5 = *(bP); - color6 = *(bP + iXB); - colorS2 = *(bP + iXC); - - color1 = *(bP + iYB - iXA); - color2 = *(bP + iYB); - color3 = *(bP + iYB + iXB); - colorS1= *(bP + iYB + iXC); - - colorA1 = *(bP + iYC); - colorA2 = *(bP + iYC + iXB); - - if(color2 == color6 && color5 != color3) - { - product1b = product2a = color2; - if((color1 == color2) || - (color6 == colorB2)) - { - product1a = INTERPOLATE8(color2, color5); - product1a = INTERPOLATE8(color2, product1a); - } - else - { - product1a = INTERPOLATE8(color5, color6); - } - - if((color6 == colorS2) || - (color2 == colorA1)) - { - product2b = INTERPOLATE8(color2, color3); - product2b = INTERPOLATE8(color2, product2b); - } - else - { - product2b = INTERPOLATE8(color2, color3); - } - } - else - if (color5 == color3 && color2 != color6) - { - product2b = product1a = color5; - - if ((colorB1 == color5) || - (color3 == colorS1)) - { - product1b = INTERPOLATE8(color5, color6); - product1b = INTERPOLATE8(color5, product1b); - } - else - { - product1b = INTERPOLATE8(color5, color6); - } - - if ((color3 == colorA2) || - (color4 == color5)) - { - product2a = INTERPOLATE8(color5, color2); - product2a = INTERPOLATE8(color5, product2a); - } - else - { - product2a = INTERPOLATE8(color2, color3); - } - } - else - if (color5 == color3 && color2 == color6) - { - register int r = 0; - - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff), (colorA1&0x00ffffff)); - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff), (colorB1&0x00ffffff)); - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff)); - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff)); - - if (r > 0) - { - product1b = product2a = color2; - product1a = product2b = INTERPOLATE8(color5, color6); - } - else - if (r < 0) - { - product2b = product1a = color5; - product1b = product2a = INTERPOLATE8(color5, color6); - } - else - { - product2b = product1a = color5; - product1b = product2a = color2; - } - } - else - { - product2b = product1a = INTERPOLATE8(color2, color6); - product2b = Q_INTERPOLATE8(color3, color3, color3, product2b); - product1a = Q_INTERPOLATE8(color5, color5, color5, product1a); - - product2a = product1b = INTERPOLATE8(color5, color3); - product2a = Q_INTERPOLATE8(color2, color2, color2, product2a); - product1b = Q_INTERPOLATE8(color6, color6, color6, product1b); - } - -//////////////////////////////// - - *dP=product1a; - *(dP+1)=product1b; - *(dP+(srcPitchHalf))=product2a; - *(dP+1+(srcPitchHalf))=product2b; - - bP += 1; - dP += 2; - }//end of for ( finish= width etc..) - - line += 2; - srcPtr += srcPitch; - }; //endof: for (; height; height--) - } -} - -///////////////////////// - -//#include - -static __inline void scale2x_32_def_whole(uint32_t* dst0, uint32_t* dst1, const uint32_t* src0, const uint32_t* src1, const uint32_t* src2, unsigned count) -{ - - //assert(count >= 2); - - // first pixel - if (src0[0] != src2[0] && src1[0] != src1[1]) { - dst0[0] = src1[0] == src0[0] ? src0[0] : src1[0]; - dst0[1] = src1[1] == src0[0] ? src0[0] : src1[0]; - dst1[0] = src1[0] == src2[0] ? src2[0] : src1[0]; - dst1[1] = src1[1] == src2[0] ? src2[0] : src1[0]; - } else { - dst0[0] = src1[0]; - dst0[1] = src1[0]; - dst1[0] = src1[0]; - dst1[1] = src1[0]; - } - ++src0; - ++src1; - ++src2; - dst0 += 2; - dst1 += 2; - - // central pixels - count -= 2; - while (count) { - if (src0[0] != src2[0] && src1[-1] != src1[1]) { - dst0[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; - dst0[1] = src1[1] == src0[0] ? src0[0] : src1[0]; - dst1[0] = src1[-1] == src2[0] ? src2[0] : src1[0]; - dst1[1] = src1[1] == src2[0] ? src2[0] : src1[0]; - } else { - dst0[0] = src1[0]; - dst0[1] = src1[0]; - dst1[0] = src1[0]; - dst1[1] = src1[0]; - } - - ++src0; - ++src1; - ++src2; - dst0 += 2; - dst1 += 2; - --count; - } - - // last pixel - if (src0[0] != src2[0] && src1[-1] != src1[0]) { - dst0[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; - dst0[1] = src1[0] == src0[0] ? src0[0] : src1[0]; - dst1[0] = src1[-1] == src2[0] ? src2[0] : src1[0]; - dst1[1] = src1[0] == src2[0] ? src2[0] : src1[0]; - } else { - dst0[0] = src1[0]; - dst0[1] = src1[0]; - dst1[0] = src1[0]; - dst1[1] = src1[0]; - } -} - -static void Scale2x_ex8(unsigned char *srcPtr, DWORD srcPitch, - unsigned char *dstPtr, int width, int height) -{ - //const int srcpitch = srcPitch; - const int dstPitch = srcPitch<<1; - - int count = height; - - finalw=width<<1; - finalh=height<<1; - - uint32_t *dst0 = (uint32_t *)dstPtr; - uint32_t *dst1 = dst0 + (dstPitch >> 2); - - uint32_t *src0 = (uint32_t *)srcPtr; - uint32_t *src1 = src0 + (srcPitch >> 2); - uint32_t *src2 = src1 + (srcPitch >> 2); - scale2x_32_def_whole(dst0, dst1, src0, src0, src1, width); - - count -= 2; - while(count) { - dst0 += dstPitch >> 1; - dst1 += dstPitch >> 1; - scale2x_32_def_whole(dst0, dst1, src0, src0, src1, width); - src0 = src1; - src1 = src2; - src2 += srcPitch >> 2; - --count; - } - dst0 += dstPitch >> 1; - dst1 += dstPitch >> 1; - scale2x_32_def_whole(dst0, dst1, src0, src1, src1, width); - -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void scale3x_32_def_whole(uint32_t* dst0, uint32_t* dst1, uint32_t* dst2, const uint32_t* src0, const uint32_t* src1, const uint32_t* src2, unsigned count) -{ - //assert(count >= 2); - - //first pixel - if (src0[0] != src2[0] && src1[0] != src1[1]) { - dst0[0] = src1[0]; - dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0]; - dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0]; - dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; - dst1[1] = src1[0]; - dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; - dst2[0] = src1[0]; - dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0]; - dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0]; - } else { - dst0[0] = src1[0]; - dst0[1] = src1[0]; - dst0[2] = src1[0]; - dst1[0] = src1[0]; - dst1[1] = src1[0]; - dst1[2] = src1[0]; - dst2[0] = src1[0]; - dst2[1] = src1[0]; - dst2[2] = src1[0]; - } - ++src0; - ++src1; - ++src2; - dst0 += 3; - dst1 += 3; - dst2 += 3; - - //central pixels - count -= 2; - while (count) { - if (src0[0] != src2[0] && src1[-1] != src1[1]) { - dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; - dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; - dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0]; - dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; - dst1[1] = src1[0]; - dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; - dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0]; - dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0]; - dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0]; - } else { - dst0[0] = src1[0]; - dst0[1] = src1[0]; - dst0[2] = src1[0]; - dst1[0] = src1[0]; - dst1[1] = src1[0]; - dst1[2] = src1[0]; - dst2[0] = src1[0]; - dst2[1] = src1[0]; - dst2[2] = src1[0]; - } - - ++src0; - ++src1; - ++src2; - dst0 += 3; - dst1 += 3; - dst2 += 3; - --count; - } - - // last pixel - if (src0[0] != src2[0] && src1[-1] != src1[0]) { - dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; - dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; - dst0[2] = src1[0]; - dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; - dst1[1] = src1[0]; - dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; - dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0]; - dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0]; - dst2[2] = src1[0]; - } else { - dst0[0] = src1[0]; - dst0[1] = src1[0]; - dst0[2] = src1[0]; - dst1[0] = src1[0]; - dst1[1] = src1[0]; - dst1[2] = src1[0]; - dst2[0] = src1[0]; - dst2[1] = src1[0]; - dst2[2] = src1[0]; - } -} - - -static void Scale3x_ex8(unsigned char *srcPtr, DWORD srcPitch, - unsigned char *dstPtr, int width, int height) -{ - int count = height; - - int dstPitch = srcPitch*3; - int dstRowPixels = dstPitch>>2; - - finalw=width*3; - finalh=height*3; - - uint32_t *dst0 = (uint32_t *)dstPtr; - uint32_t *dst1 = dst0 + dstRowPixels; - uint32_t *dst2 = dst1 + dstRowPixels; - - uint32_t *src0 = (uint32_t *)srcPtr; - uint32_t *src1 = src0 + (srcPitch >> 2); - uint32_t *src2 = src1 + (srcPitch >> 2); - scale3x_32_def_whole(dst0, dst1, dst2, src0, src0, src2, width); - - count -= 2; - while(count) { - dst0 += dstRowPixels*3; - dst1 += dstRowPixels*3; - dst2 += dstRowPixels*3; - - scale3x_32_def_whole(dst0, dst1, dst2, src0, src1, src2, width); - src0 = src1; - src1 = src2; - src2 += srcPitch >> 2; - --count; - } - - dst0 += dstRowPixels*3; - dst1 += dstRowPixels*3; - dst2 += dstRowPixels*3; - - scale3x_32_def_whole(dst0, dst1, dst2, src0, src1, src1, width); -} - - -//////////////////////////////////////////////////////////////////////// - -#ifndef MAX -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#endif - - -//////////////////////////////////////////////////////////////////////// -// X STUFF :) -//////////////////////////////////////////////////////////////////////// - - -static Cursor cursor; -XVisualInfo vi; -static XVisualInfo *myvisual; -Display *display; -static Colormap colormap; -Window window; -static GC hGC; -static XImage * Ximage; -static XvImage * XCimage; -static XImage * XPimage=0; -char * Xpixels; -char * pCaptionText; - -static int fx=0; - - -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, 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 - -static void DestroyDisplay(void) -{ - if(display) - { - XFreeColormap(display, colormap); - if(hGC) - { - XFreeGC(display,hGC); - hGC = 0; - } - if(Ximage) - { - XDestroyImage(Ximage); - Ximage=0; - } - if(XCimage) - { - XFree(XCimage); - XCimage=0; - } - - XShmDetach(display,&shminfo); - shmdt(shminfo.shmaddr); - shmctl(shminfo.shmid,IPC_RMID,NULL); - - Atom atom_vsync = xv_intern_atom_if_exists(display, "XV_SYNC_TO_VBLANK"); - if (atom_vsync != None) { - XvSetPortAttribute(display, xv_port, atom_vsync, xv_vsync); - } - - XSync(display,False); - - XCloseDisplay(display); - } -} - -static int depth=0; -int root_window_id=0; - - -// Create display - -static void CreateDisplay(void) -{ - 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 - display = XOpenDisplay(NULL); - - if (!display) - { - fprintf (stderr,"Failed to open display!!!\n"); - DestroyDisplay(); - return; - } - - myscreen=DefaultScreen(display); - - // desktop fullscreen switch - if (!iWindowMode) fx = 1; - - screen=DefaultScreenOfDisplay(display); - - root_window_id=RootWindow(display,DefaultScreen(display)); - - //Look for an Xvideo RGB port - ret = XvQueryAdaptors(display, root_window_id, &p_num_adaptors, &ai); - if (ret != Success) { - if (ret == XvBadExtension) - printf("XvBadExtension returned at XvQueryExtension.\n"); - else - if (ret == XvBadAlloc) - printf("XvBadAlloc returned at XvQueryExtension.\n"); - else - printf("other error happaned at XvQueryAdaptors.\n"); - - exit(-1); - } - - depth = DefaultDepth(display, myscreen); - - 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(display, p, &formats); - for (j = 0; j < formats; j++) { - //backup YUV mode - //hmm, should I bother check guid == 55595659-0000-0010-8000-00aa00389b71? - //and check byte order? fo[j].byte_order == LSBFirst -#ifdef __BIG_ENDIAN__ - if ( fo[j].type == XvYUV && fo[j].bits_per_pixel == 16 && fo[j].format == XvPacked && strncmp("YUYV", fo[j].component_order, 5) == 0 ) -#else - if ( fo[j].type == XvYUV && fo[j].bits_per_pixel == 16 && fo[j].format == XvPacked && strncmp("UYVY", fo[j].component_order, 5) == 0 ) -#endif - { - yuv_port = p; - yuv_id = fo[j].id; - } - if (fo[j].type == XvRGB && fo[j].bits_per_pixel == 32) - { - xv_port = p; - xv_id = fo[j].id; - xv_depth = fo[j].depth; - printf("RGB mode found. id: %x, depth: %d\n", xv_id, xv_depth); - - if (xv_depth != depth) { - printf("Warning: Depth does not match screen depth (%d)\n", depth); - } - else { - //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 (xv_port == -1 && yuv_port == -1) - { - printf("RGB & YUV not found. Quitting.\n"); - exit(-1); - } - else if (xv_port == -1 && yuv_port != -1) - { - use_yuv = 1; - printf("RGB not found. Using YUV.\n"); - xv_port = yuv_port; - xv_id = yuv_id; - } - else if (xv_depth && xv_depth != depth && yuv_port != -1) - { - use_yuv = 1; - printf("Acceptable RGB mode not found. Using YUV.\n"); - xv_port = yuv_port; - xv_id = yuv_id; - } - - Atom atom_vsync = xv_intern_atom_if_exists(display, "XV_SYNC_TO_VBLANK"); - if (atom_vsync != None) { - XvGetPortAttribute(display, xv_port, atom_vsync, &xv_vsync); - XvSetPortAttribute(display, xv_port, atom_vsync, 0); - } - -myvisual = 0; - -if(XMatchVisualInfo(display,myscreen, depth, TrueColor, &vi)) - myvisual = &vi; - -if (!myvisual) -{ - fprintf(stderr,"Failed to obtain visual!\n"); - DestroyDisplay(); - return; -} - - if(myvisual->red_mask==0x00007c00 && - myvisual->green_mask==0x000003e0 && - myvisual->blue_mask==0x0000001f) - {iColDepth=15;} - else - if(myvisual->red_mask==0x0000f800 && - myvisual->green_mask==0x000007e0 && - myvisual->blue_mask==0x0000001f) - {iColDepth=16;} - else - if(myvisual->red_mask==0x00ff0000 && - myvisual->green_mask==0x0000ff00 && - myvisual->blue_mask==0x000000ff) - {iColDepth=32;} - else - { - iColDepth=0; -/* fprintf(stderr,"COLOR DEPTH NOT SUPPORTED!\n"); - fprintf(stderr,"r: %08lx\n",myvisual->red_mask); - fprintf(stderr,"g: %08lx\n",myvisual->green_mask); - fprintf(stderr,"b: %08lx\n",myvisual->blue_mask); - DestroyDisplay(); - return;*/ - } - - // pffff... much work for a simple blank cursor... oh, well... - if(iWindowMode) cursor=XCreateFontCursor(display,XC_trek); - else - { - Pixmap p1,p2; - XImage * img; - XColor b,w; - char * idata; - XGCValues GCv; - GC GCc; - - memset(&b,0,sizeof(XColor)); - memset(&w,0,sizeof(XColor)); - idata=(char *)malloc(8); - memset(idata,0,8); - - p1=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1); - p2=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1); - - img = XCreateImage(display,myvisual->visual, - 1,XYBitmap,0,idata,8,8,8,1); - - GCv.function = GXcopy; - GCv.foreground = ~0; - GCv.background = 0; - GCv.plane_mask = AllPlanes; - GCc = XCreateGC(display,p1, - (GCFunction|GCForeground|GCBackground|GCPlaneMask),&GCv); - - XPutImage(display, p1,GCc,img,0,0,0,0,8,8); - XPutImage(display, p2,GCc,img,0,0,0,0,8,8); - XFreeGC(display, GCc); - - cursor = XCreatePixmapCursor(display,p1,p2,&b,&w,0,0); - - XFreePixmap(display,p1); - XFreePixmap(display,p2); - XDestroyImage(img); // will free idata as well - } - - colormap=XCreateColormap(display,root_window_id, - 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=colormap; - winattr.cursor=None; - - window=XCreateWindow(display,root_window_id, - 0,0,iResX,iResY, - 0,myvisual->depth, - InputOutput,myvisual->visual, - CWBorderPixel | CWBackPixel | - CWEventMask | CWDontPropagate | - CWColormap | CWCursor, - &winattr); - - if(!window) - { - fprintf(stderr,"Failed in XCreateWindow()!!!\n"); - DestroyDisplay(); - return; - } - - delwindow = XInternAtom(display,"WM_DELETE_WINDOW",0); - XSetWMProtocols(display, window, &delwindow, 1); - - hints.flags=USPosition|USSize; - hints.base_width = iResX; - hints.base_height = iResY; - - wm_hints.input=1; - wm_hints.flags=InputHint; - - XSetWMHints(display,window,&wm_hints); - XSetWMNormalHints(display,window,&hints); - if(pCaptionText) - XStoreName(display,window,pCaptionText); - else XStoreName(display,window,"P.E.Op.S SoftX PSX Gpu"); - - XDefineCursor(display,window,cursor); - - // hack to get rid of window title bar - if (fx) - { - mwmhints.flags=MWM_HINTS_DECORATIONS; - mwmhints.decorations=0; - mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0); - XChangeProperty(display,window,mwmatom,mwmatom,32, - PropModeReplace,(unsigned char *)&mwmhints,4); - } - - // key stuff - XSelectInput(display, - window, - FocusChangeMask | ExposureMask | - KeyPressMask | KeyReleaseMask - ); - - XMapRaised(display,window); - XClearWindow(display,window); - XWindowEvent(display,window,ExposureMask,&event); - - if (fx) // fullscreen - { - 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); - - // 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(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); - } - } - - gcv.foreground = 0x0000FF00; // green letters for the FPS bar; do we need to take care of endianess? - gcv.background = 0x00000000; - gcv.graphics_exposures = False; - hGC = XCreateGC(display,window, - GCGraphicsExposures | GCForeground | GCBackground, &gcv); - if(!hGC) - { - fprintf(stderr,"No gfx context!!!\n"); - DestroyDisplay(); - } - - uint32_t color; - - /* fix the green back ground in YUV mode */ - if(use_yuv) - color = rgb_to_yuv(0x00, 0x00, 0x00); - else - color = 0; - - Xpixels = (char *)malloc(8*8*4); - for(i = 0; i < 8*8; ++i) - ((uint32_t *)Xpixels)[i] = color; - - XCimage = XvCreateImage(display,xv_port,xv_id, - (char *)Xpixels, 8, 8); - - -/* -Allocate max that could be needed: -Big(est?) PSX res: 640x512 -32bpp (times 4) -2xsai func= 3xwidth,3xheight -= approx 11.8mb -*/ -shminfo.shmid = shmget(IPC_PRIVATE, 640*512*4*3*3, IPC_CREAT | 0777); -shminfo.shmaddr = shmat(shminfo.shmid, 0, 0); -shminfo.readOnly = 0; - - if (!XShmAttach(display, &shminfo)) { - printf("XShmAttach failed !\n"); - exit (-1); - } - - { - uint32_t *pShmaddr = (uint32_t *)shminfo.shmaddr; - for(i = 0; i < 640*512*3*3; ++i) - pShmaddr[i] = color; - } -} - -void (*p2XSaIFunc) (unsigned char *, DWORD, unsigned char *, int, int); -unsigned char *pBackBuffer = 0; - -static void BlitScreen32(unsigned char *surf, int32_t x, int32_t y) -{ - unsigned char *pD; - unsigned int startxy; - uint32_t lu; - unsigned short s; - unsigned short row, column; - unsigned short dx = PreviousPSXDisplay.Range.x1; - unsigned short dy = PreviousPSXDisplay.DisplayMode.y; - - int32_t lPitch = PSXDisplay.DisplayMode.x << 2; - - uint32_t *destpix; - - if (PreviousPSXDisplay.Range.y0) // centering needed? - { - memset(surf, 0, (PreviousPSXDisplay.Range.y0 >> 1) * lPitch); - - dy -= PreviousPSXDisplay.Range.y0; - surf += (PreviousPSXDisplay.Range.y0 >> 1) * lPitch; - - memset(surf + dy * lPitch, - 0, ((PreviousPSXDisplay.Range.y0 + 1) >> 1) * lPitch); - } - - if (PreviousPSXDisplay.Range.x0) - { - for (column = 0; column < dy; column++) - { - destpix = (uint32_t *)(surf + (column * lPitch)); - memset(destpix, 0, PreviousPSXDisplay.Range.x0 << 2); - } - surf += PreviousPSXDisplay.Range.x0 << 2; - } - - if (PSXDisplay.RGB24) - { - for (column = 0; column < dy; column++) - { - startxy = ((1024) * (column + y)) + x; - pD = (unsigned char *)&psxVuw[startxy]; - destpix = (uint32_t *)(surf + (column * lPitch)); - for (row = 0; row < dx; row++) - { - lu = *((uint32_t *)pD); - destpix[row] = - 0xff000000 | (RED(lu) << 16) | (GREEN(lu) << 8) | (BLUE(lu)); - pD += 3; - } - } - } - else - { - for (column = 0;column> 7) & 0xf8)) | 0xff000000; - } - } - } -} - - - -static void BlitToYUV(unsigned char * surf,int32_t x,int32_t y) -{ - unsigned char * pD; - unsigned int startxy; - uint32_t lu;unsigned short s; - unsigned short row,column; - unsigned short dx = PreviousPSXDisplay.Range.x1; - unsigned short dy = PreviousPSXDisplay.DisplayMode.y; - int R,G,B; - - int32_t lPitch = PSXDisplay.DisplayMode.x << 2; - uint32_t *destpix; - - if (PreviousPSXDisplay.Range.y0) // centering needed? - { - for (column = 0; column < (PreviousPSXDisplay.Range.y0 >> 1); column++) - { - destpix = (uint32_t *)(surf + column * lPitch); - for (row = 0; row < dx; row++) - { - destpix[row] = (4 << 24) | (128 << 16) | (4 << 8) | 128; - } - } - - dy -= PreviousPSXDisplay.Range.y0; - surf += (PreviousPSXDisplay.Range.y0 >> 1) * lPitch; - - for (column = 0; column < (PreviousPSXDisplay.Range.y0 + 1) >> 1; column++) - { - destpix = (uint32_t *)(surf + (dy + column) * lPitch); - for (row = 0; row < dx; row++) - { - destpix[row] = (4 << 24) | (128 << 16) | (4 << 8) | 128; - } - } - } - - if (PreviousPSXDisplay.Range.x0) - { - for (column = 0; column < dy; column++) - { - destpix = (uint32_t *)(surf + (column * lPitch)); - for (row = 0; row < PreviousPSXDisplay.Range.x0; row++) - { - destpix[row] = (4 << 24) | (128 << 16) | (4 << 8) | 128; - } - } - surf += PreviousPSXDisplay.Range.x0 << 2; - } - - if (PSXDisplay.RGB24) - { - for (column = 0; column < dy; column++) - { - startxy = (1024 * (column + y)) + x; - pD = (unsigned char *)&psxVuw[startxy]; - destpix = (uint32_t *)(surf + (column * lPitch)); - for (row = 0; row < dx; row++) - { - lu = *((uint32_t *)pD); - - R = RED(lu); - G = GREEN(lu); - B = BLUE(lu); - - destpix[row] = rgb_to_yuv(R, G, B); - - pD += 3; - } - } - } - else - { - for (column = 0; column < dy; column++) - { - startxy = (1024 * (column + y)) + x; - destpix = (uint32_t *)(surf + (column * lPitch)); - for (row = 0; row < dx; row++) - { - s = GETLE16(&psxVuw[startxy++]); - - R = (s << 3) &0xf8; - G = (s >> 2) &0xf8; - B = (s >> 7) &0xf8; - - destpix[row] = rgb_to_yuv(R, G, B); - - } - } - } -} - -//dst will have half the pitch (32bit to 16bit) -static void RGB2YUV(uint32_t *s, int width, int height, uint32_t *d) -{ - int x,y; - int R,G,B, Y1,Y2,U,V; - - for (y=0; y>1; x++) { - R = (*s >> 16) & 0xff; - G = (*s >> 8) & 0xff; - B = *s & 0xff; - s++; - - Y1 = min(abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13, 235); - U = min(abs(R * -1214 + G * -2384 + B * 3598 + 4096 + 1048576) >> 13, 240); - V = min(abs(R * 3598 + G * -3013 + B * -585 + 4096 + 1048576) >> 13, 240); - - R = (*s >> 16) & 0xff; - G = (*s >> 8) & 0xff; - B = *s & 0xff; - s++; - - Y2 = min(abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13, 235); - -#ifdef __BIG_ENDIAN__ - *d = V | Y2 << 8 | U << 16 | Y1 << 24; -#else - *d = U | Y1 << 8 | V << 16 | Y2 << 24; -#endif - d++; - } - } -} - -/* 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 - */ -static __inline void MaintainAspect(uint32_t * dx, uint32_t * dy, uint32_t * dw, uint32_t * dh) -{ - - double ratio_x = ((double)*dw) / ((double)PSXDisplay.DisplayMode.x) ; - double ratio_y = ((double)*dh) / ((double)PSXDisplay.DisplayMode.y); - - double ratio; - if (ratio_x < ratio_y) { - ratio = ratio_x; - } else { - ratio = ratio_y; - } - - uint32_t tw = (uint32_t) floor(PSXDisplay.DisplayMode.x * ratio); - uint32_t th = (uint32_t) floor(PSXDisplay.DisplayMode.y * ratio); - - *dx = (uint32_t) floor((*dw - tw) / 2.0); - *dy = (uint32_t) floor((*dh - th) / 2.0); - *dw = tw; - *dh = th; -} - -void DoBufferSwap(void) -{ - Screen *screen; - Window _dw; - XvImage *xvi; - unsigned int dstx, dsty; - unsigned int _d, _w, _h; //don't care about _d - - finalw = PSXDisplay.DisplayMode.x; - finalh = PSXDisplay.DisplayMode.y; - - if (finalw == 0 || finalh == 0) - return; - - XSync(display,False); - - if(use_yuv) { - if (iUseNoStretchBlt==0 || finalw > 320 || finalh > 256) { - BlitToYUV((unsigned char *)shminfo.shmaddr, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y); - finalw <<= 1; - } else { - BlitScreen32((unsigned char *)pBackBuffer, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y); - p2XSaIFunc(pBackBuffer, finalw<<2, (unsigned char *)pSaIBigBuff,finalw,finalh); - RGB2YUV( (uint32_t*)pSaIBigBuff, finalw, finalh, (uint32_t*)shminfo.shmaddr); - } - } else if(iUseNoStretchBlt==0 || finalw > 320 || finalh > 256) { - BlitScreen32((unsigned char *)shminfo.shmaddr, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y); - } else { - BlitScreen32((unsigned char *)pBackBuffer, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y); - p2XSaIFunc(pBackBuffer, finalw<<2, (unsigned char *)shminfo.shmaddr,finalw,finalh); - } - - XGetGeometry(display, window, &_dw, (int *)&_d, (int *)&_d, &_w, &_h, &_d, &_d); - if (use_yuv) { - xvi = XvShmCreateImage(display, yuv_port, yuv_id, 0, finalw, finalh, &shminfo); - } else - xvi = XvShmCreateImage(display, xv_port, xv_id, 0, finalw, finalh, &shminfo); - - xvi->data = shminfo.shmaddr; - - screen=DefaultScreenOfDisplay(display); - //screennum = DefaultScreen(display); - - if (!iWindowMode) { - _w = screen->width; - _h = screen->height; - } - - dstx = 0; - dsty = 0; - - if (iMaintainAspect) - MaintainAspect(&dstx, &dsty, &_w, &_h); - -/*Whistler: too slow/laggy so commented out for now - if(iRumbleTime) - { - dstx += (rand() % iRumbleVal) - iRumbleVal / 2; - _w -= (rand() % iRumbleVal) - iRumbleVal / 2; - dsty += (rand() % iRumbleVal) - iRumbleVal / 2; - _h -= (rand() % iRumbleVal) - iRumbleVal / 2; - iRumbleTime--; - } -*/ - XvShmPutImage(display, xv_port, window, hGC, xvi, - 0,0, //src x,y - finalw,finalh, //src w,h - dstx,dsty, //dst x,y - _w, _h, //dst w,h - 1 - ); - - if(ulKeybits&KEY_SHOWFPS) //DisplayText(); c // paint menu text - { - if(szDebugText[0] && ((time(NULL) - tStart) < 2)) - { - strcpy(szDispBuf,szDebugText); - } - else - { - szDebugText[0]=0; - strcat(szDispBuf,szMenuBuf); - } - - //XPutImage(display,window,hGC, XFimage, - // 0, 0, 0, 0, 220,15); - - XDrawImageString(display,window,hGC,2,13,szDispBuf,strlen(szDispBuf)); - } - - //if(XPimage) DisplayPic(); - - XFree(xvi); -} - -void DoClearScreenBuffer(void) // CLEAR DX BUFFER -{ - Window _dw; - unsigned int _d, _w, _h; //don't care about _d - - XGetGeometry(display, window, &_dw, (int *)&_d, (int *)&_d, &_w, &_h, &_d, &_d); - - XvPutImage(display, xv_port, window, hGC, XCimage, - 0, 0, 8, 8, 0, 0, _w, _h); - //XSync(display,False); -} - -void DoClearFrontBuffer(void) // CLEAR DX BUFFER -{/* - XPutImage(display,window,hGC, XCimage, - 0, 0, 0, 0, iResX, iResY); - XSync(display,False);*/ -} - -static int Xinitialize() -{ - iDesktopCol=32; - - - if(iUseNoStretchBlt>0) - { - pBackBuffer=(unsigned char *)malloc(640*512*sizeof(uint32_t)); - memset(pBackBuffer,0,640*512*sizeof(uint32_t)); - if (use_yuv) { - pSaIBigBuff=malloc(640*512*4*3*3); - memset(pSaIBigBuff,0,640*512*4*3*3); - } - } - - p2XSaIFunc=NULL; - - if(iUseNoStretchBlt==1) - { - p2XSaIFunc=Std2xSaI_ex8; - } - - if(iUseNoStretchBlt==2) - { - p2XSaIFunc=Super2xSaI_ex8; - } - - if(iUseNoStretchBlt==3) - { - p2XSaIFunc=SuperEagle_ex8; - } - - if(iUseNoStretchBlt==4) - { - p2XSaIFunc=Scale2x_ex8; - } - if(iUseNoStretchBlt==5) - { - p2XSaIFunc=Scale3x_ex8; - } - if(iUseNoStretchBlt==6) - { - p2XSaIFunc=hq2x_32; - } - if(iUseNoStretchBlt==7) - { - p2XSaIFunc=hq3x_32; - } - - bUsingTWin=FALSE; - - InitMenu(); - - bIsFirstFrame = FALSE; // done - - if(iShowFPS) - { - iShowFPS=0; - ulKeybits|=KEY_SHOWFPS; - szDispBuf[0]=0; - BuildDispMenu(0); - } - - return 0; -} - -static void Xcleanup() // X CLEANUP -{ - CloseMenu(); - - if(iUseNoStretchBlt>0) - { - if(pBackBuffer) free(pBackBuffer); - pBackBuffer=0; - if(pSaIBigBuff) free(pSaIBigBuff); - pSaIBigBuff=0; - } -} - -unsigned long ulInitDisplay(void) -{ - CreateDisplay(); // x stuff - Xinitialize(); // init x - return (unsigned long)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; - } - } - } - - XPimage = XCreateImage(display,myvisual->visual, - depth, ZPixmap, 0, - (char *)p, - 128, 96, - depth>16 ? 32 : 16, - 0); -} - -void DestroyPic(void) -{ - if(XPimage) - { /* - XPutImage(display,window,hGC, XCimage, - 0, 0, 0, 0, iResX, iResY);*/ - XDestroyImage(XPimage); - XPimage=0; - } -} - -void DisplayPic(void) -{ - XPutImage(display,window,hGC, XPimage, - 0, 0, iResX-128, 0,128,96); -} - -void ShowGpuPic(void) -{ -} - -void ShowTextGpuPic(void) -{ -} - -static void hq2x_32_def(uint32_t * dst0, uint32_t * dst1, const uint32_t * src0, const uint32_t * src1, const uint32_t * src2, unsigned count) -{ - static unsigned char cache_vert_mask[640]; - unsigned char cache_horiz_mask = 0; - - unsigned i; - unsigned char mask; - uint32_t c[9]; - - if (src0 == src1) //processing first row - memset(cache_vert_mask, 0, count); - - for(i=0;i0) { - c[0] = src0[-1]; - c[3] = src1[-1]; - c[6] = src2[-1]; - } else { - c[0] = c[1]; - c[3] = c[4]; - c[6] = c[7]; - } - - if (i> 2); - - uint32_t *src0 = (uint32_t *)srcPtr; - uint32_t *src1 = src0 + (srcPitch >> 2); - uint32_t *src2 = src1 + (srcPitch >> 2); - hq2x_32_def(dst0, dst1, src0, src0, src1, width); - - - count -= 2; - while(count) { - dst0 += dstPitch >> 1; //next 2 lines (dstPitch / 4 char per int * 2) - dst1 += dstPitch >> 1; - hq2x_32_def(dst0, dst1, src0, src1, src2, width); - src0 = src1; - src1 = src2; - src2 += srcPitch >> 2; - --count; - } - dst0 += dstPitch >> 1; - dst1 += dstPitch >> 1; - hq2x_32_def(dst0, dst1, src0, src1, src1, width); -} - -static void hq3x_32_def(uint32_t* dst0, uint32_t* dst1, uint32_t* dst2, const uint32_t* src0, const uint32_t* src1, const uint32_t* src2, unsigned count) -{ - static unsigned char cache_vert_mask[640]; - unsigned char cache_horiz_mask = 0; - - unsigned i; - unsigned char mask; - uint32_t c[9]; - - if (src0 == src1) //processing first row - memset(cache_vert_mask, 0, count); - - for(i=0;i0) { - c[0] = src0[-1]; - c[3] = src1[-1]; - c[6] = src2[-1]; - } else { - c[0] = c[1]; - c[3] = c[4]; - c[6] = c[7]; - } - - if (i>2; - - finalw=width*3; - finalh=height*3; - - uint32_t *dst0 = (uint32_t *)dstPtr; - uint32_t *dst1 = dst0 + dstRowPixels; - uint32_t *dst2 = dst1 + dstRowPixels; - - uint32_t *src0 = (uint32_t *)srcPtr; - uint32_t *src1 = src0 + (srcPitch >> 2); - uint32_t *src2 = src1 + (srcPitch >> 2); - hq3x_32_def(dst0, dst1, dst2, src0, src0, src2, width); - - count -= 2; - while(count) { - dst0 += dstRowPixels * 3; - dst1 += dstRowPixels * 3; - dst2 += dstRowPixels * 3; - - hq3x_32_def(dst0, dst1, dst2, src0, src1, src2, width); - src0 = src1; - src1 = src2; - src2 += srcPitch >> 2; - --count; - } - dst0 += dstRowPixels * 3; - dst1 += dstRowPixels * 3; - dst2 += dstRowPixels * 3; - - hq3x_32_def(dst0, dst1, dst2, src0, src1, src1, width); - -} +/*************************************************************************** + draw.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. * + * * + ***************************************************************************/ + +#define _IN_DRAW + +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "prim.h" +#include "menu.h" +#include "interp.h" +#include "swap.h" + +// misc globals +int iResX; +int iResY; +long lLowerpart; +BOOL bIsFirstFrame = TRUE; +BOOL bCheckMask = FALSE; +unsigned short sSetMask = 0; +unsigned long lSetMask = 0; +int iDesktopCol = 16; +int iShowFPS = 0; +int iWinSize; +int iMaintainAspect = 0; +int iUseNoStretchBlt = 0; +int iFastFwd = 0; +int iDebugMode = 0; +int iFVDisplay = 0; +PSXPoint_t ptCursorPoint[8]; +unsigned short usCursorActive = 0; + +//unsigned int LUT16to32[65536]; +//unsigned int RGBtoYUV[65536]; + +#include +#include +#include +#include +#include +int xv_port = -1; +int xv_id = -1; +int xv_depth = 0; +int yuv_port = -1; +int yuv_id = -1; +int use_yuv = 0; +int xv_vsync = 0; + +XShmSegmentInfo shminfo; +int finalw,finalh; + +extern XvImage *XvShmCreateImage(Display*, XvPortID, int, char*, int, int, XShmSegmentInfo*); + +#include + +// prototypes +void hq2x_32( unsigned char * srcPtr, DWORD srcPitch, unsigned char * dstPtr, int width, int height); +void hq3x_32( unsigned char * srcPtr, DWORD srcPitch, unsigned char * dstPtr, int width, int height); + +//////////////////////////////////////////////////////////////////////// +// generic 2xSaI helpers +//////////////////////////////////////////////////////////////////////// + +void * pSaISmallBuff=NULL; +void * pSaIBigBuff=NULL; + +#define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D)) + +static __inline int GetResult1(DWORD A, DWORD B, DWORD C, DWORD D, DWORD E) +{ + int x = 0; + int y = 0; + int r = 0; + if (A == C) x+=1; else if (B == C) y+=1; + if (A == D) x+=1; else if (B == D) y+=1; + if (x <= 1) r+=1; + if (y <= 1) r-=1; + return r; +} + +static __inline int GetResult2(DWORD A, DWORD B, DWORD C, DWORD D, DWORD E) +{ + int x = 0; + int y = 0; + int r = 0; + if (A == C) x+=1; else if (B == C) y+=1; + if (A == D) x+=1; else if (B == D) y+=1; + if (x <= 1) r-=1; + if (y <= 1) r+=1; + return r; +} + +/* Convert RGB to YUV */ +__inline uint32_t rgb_to_yuv(uint8_t R, uint8_t G, uint8_t B) { + uint8_t Y = min(abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13, 235); + uint8_t U = min(abs(R * -1214 + G * -2384 + B * 3598 + 4096 + 1048576) >> 13, 240); + uint8_t V = min(abs(R * 3598 + G * -3013 + B * -585 + 4096 + 1048576) >> 13, 240); + +#ifdef __BIG_ENDIAN__ + return Y << 24 | U << 16 | Y << 8 | V; +#else + return Y << 24 | V << 16 | Y << 8 | U; +#endif +} + +#define colorMask8 0x00FEFEFE +#define lowPixelMask8 0x00010101 +#define qcolorMask8 0x00FCFCFC +#define qlowpixelMask8 0x00030303 + +#define INTERPOLATE8(A, B) ((((A & colorMask8) >> 1) + ((B & colorMask8) >> 1) + (A & B & lowPixelMask8))) +#define Q_INTERPOLATE8(A, B, C, D) (((((A & qcolorMask8) >> 2) + ((B & qcolorMask8) >> 2) + ((C & qcolorMask8) >> 2) + ((D & qcolorMask8) >> 2) \ + + ((((A & qlowpixelMask8) + (B & qlowpixelMask8) + (C & qlowpixelMask8) + (D & qlowpixelMask8)) >> 2) & qlowpixelMask8)))) + + +void Super2xSaI_ex8(unsigned char *srcPtr, DWORD srcPitch, + unsigned char *dstBitmap, int width, int height) +{ + DWORD dstPitch = srcPitch<<1; + DWORD srcPitchHalf = srcPitch>>1; + int finWidth = srcPitch>>2; + DWORD line; + DWORD *dP; + DWORD *bP; + int iXA,iXB,iXC,iYA,iYB,iYC,finish; + DWORD color4, color5, color6; + DWORD color1, color2, color3; + DWORD colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, + colorS1, colorS2; + DWORD product1a, product1b, + product2a, product2b; + + finalw=width<<1; + finalh=height<<1; + + line = 0; + + { + for (; height; height-=1) + { + bP = (DWORD *)srcPtr; + dP = (DWORD *)(dstBitmap + line*dstPitch); + for (finish = width; finish; finish -= 1 ) + { +//--------------------------------------- B1 B2 +// 4 5 6 S2 +// 1 2 3 S1 +// A1 A2 + if(finish==finWidth) iXA=0; + else iXA=1; + if(finish>4) {iXB=1;iXC=2;} + else + if(finish>3) {iXB=1;iXC=1;} + else {iXB=0;iXC=0;} + if(line==0) {iYA=0;} + else {iYA=finWidth;} + if(height>4) {iYB=finWidth;iYC=srcPitchHalf;} + else + if(height>3) {iYB=finWidth;iYC=finWidth;} + else {iYB=0;iYC=0;} + + colorB0 = *(bP- iYA - iXA); + colorB1 = *(bP- iYA); + colorB2 = *(bP- iYA + iXB); + colorB3 = *(bP- iYA + iXC); + + color4 = *(bP - iXA); + color5 = *(bP); + color6 = *(bP + iXB); + colorS2 = *(bP + iXC); + + color1 = *(bP + iYB - iXA); + color2 = *(bP + iYB); + color3 = *(bP + iYB + iXB); + colorS1= *(bP + iYB + iXC); + + colorA0 = *(bP + iYC - iXA); + colorA1 = *(bP + iYC); + colorA2 = *(bP + iYC + iXB); + colorA3 = *(bP + iYC + iXC); + + if (color2 == color6 && color5 != color3) + { + product2b = product1b = color2; + } + else + if (color5 == color3 && color2 != color6) + { + product2b = product1b = color5; + } + else + if (color5 == color3 && color2 == color6) + { + register int r = 0; + + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff), (colorA1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff), (colorB1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff)); + + if (r > 0) + product2b = product1b = color6; + else + if (r < 0) + product2b = product1b = color5; + else + { + product2b = product1b = INTERPOLATE8(color5, color6); + } + } + else + { + if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) + product2b = Q_INTERPOLATE8 (color3, color3, color3, color2); + else + if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) + product2b = Q_INTERPOLATE8 (color2, color2, color2, color3); + else + product2b = INTERPOLATE8 (color2, color3); + + if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) + product1b = Q_INTERPOLATE8 (color6, color6, color6, color5); + else + if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) + product1b = Q_INTERPOLATE8 (color6, color5, color5, color5); + else + product1b = INTERPOLATE8 (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) + product2a = INTERPOLATE8(color2, color5); + else + if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE8(color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) + product1a = INTERPOLATE8(color2, color5); + else + if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE8(color2, color5); + else + product1a = color5; + + *dP=product1a; + *(dP+1)=product1b; + *(dP+(srcPitchHalf))=product2a; + *(dP+1+(srcPitchHalf))=product2b; + + bP += 1; + dP += 2; + }//end of for ( finish= width etc..) + + line += 2; + srcPtr += srcPitch; + }; //endof: for (; height; height--) + } +} + +//////////////////////////////////////////////////////////////////////// + +void Std2xSaI_ex8(unsigned char *srcPtr, DWORD srcPitch, + unsigned char *dstBitmap, int width, int height) +{ + DWORD dstPitch = srcPitch<<1; + DWORD srcPitchHalf = srcPitch>>1; + int finWidth = srcPitch>>2; + DWORD line; + DWORD *dP; + DWORD *bP; + int iXA,iXB,iXC,iYA,iYB,iYC,finish; + + finalw=width<<1; + finalh=height<<1; + + DWORD colorA, colorB; + DWORD colorC, colorD, + colorE, colorF, colorG, colorH, + colorI, colorJ, colorK, colorL, + colorM, colorN, colorO, colorP; + DWORD product, product1, product2; + + line = 0; + + { + for (; height; height-=1) + { + bP = (DWORD *)srcPtr; + dP = (DWORD *)(dstBitmap + line*dstPitch); + for (finish = width; finish; finish -= 1 ) + { +//--------------------------------------- +// Map of the pixels: I|E F|J +// G|A B|K +// H|C D|L +// M|N O|P + if(finish==finWidth) iXA=0; + else iXA=1; + if(finish>4) {iXB=1;iXC=2;} + else + if(finish>3) {iXB=1;iXC=1;} + else {iXB=0;iXC=0;} + if(line==0) {iYA=0;} + else {iYA=finWidth;} + if(height>4) {iYB=finWidth;iYC=srcPitchHalf;} + else + if(height>3) {iYB=finWidth;iYC=finWidth;} + else {iYB=0;iYC=0;} + + colorI = *(bP- iYA - iXA); + colorE = *(bP- iYA); + colorF = *(bP- iYA + iXB); + colorJ = *(bP- iYA + iXC); + + colorG = *(bP - iXA); + colorA = *(bP); + colorB = *(bP + iXB); + colorK = *(bP + iXC); + + colorH = *(bP + iYB - iXA); + colorC = *(bP + iYB); + colorD = *(bP + iYB + iXB); + colorL = *(bP + iYB + iXC); + + colorM = *(bP + iYC - iXA); + colorN = *(bP + iYC); + colorO = *(bP + iYC + iXB); + colorP = *(bP + iYC + iXC); + + + if((colorA == colorD) && (colorB != colorC)) + { + if(((colorA == colorE) && (colorB == colorL)) || + ((colorA == colorC) && (colorA == colorF) && + (colorB != colorE) && (colorB == colorJ))) + { + product = colorA; + } + else + { + product = INTERPOLATE8(colorA, colorB); + } + + if(((colorA == colorG) && (colorC == colorO)) || + ((colorA == colorB) && (colorA == colorH) && + (colorG != colorC) && (colorC == colorM))) + { + product1 = colorA; + } + else + { + product1 = INTERPOLATE8(colorA, colorC); + } + product2 = colorA; + } + else + if((colorB == colorC) && (colorA != colorD)) + { + if(((colorB == colorF) && (colorA == colorH)) || + ((colorB == colorE) && (colorB == colorD) && + (colorA != colorF) && (colorA == colorI))) + { + product = colorB; + } + else + { + product = INTERPOLATE8(colorA, colorB); + } + + if(((colorC == colorH) && (colorA == colorF)) || + ((colorC == colorG) && (colorC == colorD) && + (colorA != colorH) && (colorA == colorI))) + { + product1 = colorC; + } + else + { + product1=INTERPOLATE8(colorA, colorC); + } + product2 = colorB; + } + else + if((colorA == colorD) && (colorB == colorC)) + { + if (colorA == colorB) + { + product = colorA; + product1 = colorA; + product2 = colorA; + } + else + { + register int r = 0; + product1 = INTERPOLATE8(colorA, colorC); + product = INTERPOLATE8(colorA, colorB); + + r += GetResult1 (colorA&0x00FFFFFF, colorB&0x00FFFFFF, colorG&0x00FFFFFF, colorE&0x00FFFFFF, colorI&0x00FFFFFF); + r += GetResult2 (colorB&0x00FFFFFF, colorA&0x00FFFFFF, colorK&0x00FFFFFF, colorF&0x00FFFFFF, colorJ&0x00FFFFFF); + r += GetResult2 (colorB&0x00FFFFFF, colorA&0x00FFFFFF, colorH&0x00FFFFFF, colorN&0x00FFFFFF, colorM&0x00FFFFFF); + r += GetResult1 (colorA&0x00FFFFFF, colorB&0x00FFFFFF, colorL&0x00FFFFFF, colorO&0x00FFFFFF, colorP&0x00FFFFFF); + + if (r > 0) + product2 = colorA; + else + if (r < 0) + product2 = colorB; + else + { + product2 = Q_INTERPOLATE8(colorA, colorB, colorC, colorD); + } + } + } + else + { + product2 = Q_INTERPOLATE8(colorA, colorB, colorC, colorD); + + if ((colorA == colorC) && (colorA == colorF) && + (colorB != colorE) && (colorB == colorJ)) + { + product = colorA; + } + else + if ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI)) + { + product = colorB; + } + else + { + product = INTERPOLATE8(colorA, colorB); + } + + if ((colorA == colorB) && (colorA == colorH) && + (colorG != colorC) && (colorC == colorM)) + { + product1 = colorA; + } + else + if ((colorC == colorG) && (colorC == colorD) && + (colorA != colorH) && (colorA == colorI)) + { + product1 = colorC; + } + else + { + product1 = INTERPOLATE8(colorA, colorC); + } + } + +////////////////////////// + + *dP=colorA; + *(dP+1)=product; + *(dP+(srcPitchHalf))=product1; + *(dP+1+(srcPitchHalf))=product2; + + bP += 1; + dP += 2; + }//end of for ( finish= width etc..) + + line += 2; + srcPtr += srcPitch; + }; //endof: for (; height; height--) + } +} + +//////////////////////////////////////////////////////////////////////// + +void SuperEagle_ex8(unsigned char *srcPtr, DWORD srcPitch, + unsigned char *dstBitmap, int width, int height) +{ + DWORD dstPitch = srcPitch<<1; + DWORD srcPitchHalf = srcPitch>>1; + int finWidth = srcPitch>>2; + DWORD line; + DWORD *dP; + DWORD *bP; + int iXA,iXB,iXC,iYA,iYB,iYC,finish; + DWORD color4, color5, color6; + DWORD color1, color2, color3; + DWORD colorA1, colorA2, + colorB1, colorB2, + colorS1, colorS2; + DWORD product1a, product1b, + product2a, product2b; + + finalw=width<<1; + finalh=height<<1; + + line = 0; + + { + for (; height; height-=1) + { + bP = (DWORD *)srcPtr; + dP = (DWORD *)(dstBitmap + line*dstPitch); + for (finish = width; finish; finish -= 1 ) + { + if(finish==finWidth) iXA=0; + else iXA=1; + if(finish>4) {iXB=1;iXC=2;} + else + if(finish>3) {iXB=1;iXC=1;} + else {iXB=0;iXC=0;} + if(line==0) {iYA=0;} + else {iYA=finWidth;} + if(height>4) {iYB=finWidth;iYC=srcPitchHalf;} + else + if(height>3) {iYB=finWidth;iYC=finWidth;} + else {iYB=0;iYC=0;} + + colorB1 = *(bP- iYA); + colorB2 = *(bP- iYA + iXB); + + color4 = *(bP - iXA); + color5 = *(bP); + color6 = *(bP + iXB); + colorS2 = *(bP + iXC); + + color1 = *(bP + iYB - iXA); + color2 = *(bP + iYB); + color3 = *(bP + iYB + iXB); + colorS1= *(bP + iYB + iXC); + + colorA1 = *(bP + iYC); + colorA2 = *(bP + iYC + iXB); + + if(color2 == color6 && color5 != color3) + { + product1b = product2a = color2; + if((color1 == color2) || + (color6 == colorB2)) + { + product1a = INTERPOLATE8(color2, color5); + product1a = INTERPOLATE8(color2, product1a); + } + else + { + product1a = INTERPOLATE8(color5, color6); + } + + if((color6 == colorS2) || + (color2 == colorA1)) + { + product2b = INTERPOLATE8(color2, color3); + product2b = INTERPOLATE8(color2, product2b); + } + else + { + product2b = INTERPOLATE8(color2, color3); + } + } + else + if (color5 == color3 && color2 != color6) + { + product2b = product1a = color5; + + if ((colorB1 == color5) || + (color3 == colorS1)) + { + product1b = INTERPOLATE8(color5, color6); + product1b = INTERPOLATE8(color5, product1b); + } + else + { + product1b = INTERPOLATE8(color5, color6); + } + + if ((color3 == colorA2) || + (color4 == color5)) + { + product2a = INTERPOLATE8(color5, color2); + product2a = INTERPOLATE8(color5, product2a); + } + else + { + product2a = INTERPOLATE8(color2, color3); + } + } + else + if (color5 == color3 && color2 == color6) + { + register int r = 0; + + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff), (colorA1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff), (colorB1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff)); + + if (r > 0) + { + product1b = product2a = color2; + product1a = product2b = INTERPOLATE8(color5, color6); + } + else + if (r < 0) + { + product2b = product1a = color5; + product1b = product2a = INTERPOLATE8(color5, color6); + } + else + { + product2b = product1a = color5; + product1b = product2a = color2; + } + } + else + { + product2b = product1a = INTERPOLATE8(color2, color6); + product2b = Q_INTERPOLATE8(color3, color3, color3, product2b); + product1a = Q_INTERPOLATE8(color5, color5, color5, product1a); + + product2a = product1b = INTERPOLATE8(color5, color3); + product2a = Q_INTERPOLATE8(color2, color2, color2, product2a); + product1b = Q_INTERPOLATE8(color6, color6, color6, product1b); + } + +//////////////////////////////// + + *dP=product1a; + *(dP+1)=product1b; + *(dP+(srcPitchHalf))=product2a; + *(dP+1+(srcPitchHalf))=product2b; + + bP += 1; + dP += 2; + }//end of for ( finish= width etc..) + + line += 2; + srcPtr += srcPitch; + }; //endof: for (; height; height--) + } +} + +///////////////////////// + +//#include + +static __inline void scale2x_32_def_whole(uint32_t* dst0, uint32_t* dst1, const uint32_t* src0, const uint32_t* src1, const uint32_t* src2, unsigned count) +{ + + //assert(count >= 2); + + // first pixel + if (src0[0] != src2[0] && src1[0] != src1[1]) { + dst0[0] = src1[0] == src0[0] ? src0[0] : src1[0]; + dst0[1] = src1[1] == src0[0] ? src0[0] : src1[0]; + dst1[0] = src1[0] == src2[0] ? src2[0] : src1[0]; + dst1[1] = src1[1] == src2[0] ? src2[0] : src1[0]; + } else { + dst0[0] = src1[0]; + dst0[1] = src1[0]; + dst1[0] = src1[0]; + dst1[1] = src1[0]; + } + ++src0; + ++src1; + ++src2; + dst0 += 2; + dst1 += 2; + + // central pixels + count -= 2; + while (count) { + if (src0[0] != src2[0] && src1[-1] != src1[1]) { + dst0[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; + dst0[1] = src1[1] == src0[0] ? src0[0] : src1[0]; + dst1[0] = src1[-1] == src2[0] ? src2[0] : src1[0]; + dst1[1] = src1[1] == src2[0] ? src2[0] : src1[0]; + } else { + dst0[0] = src1[0]; + dst0[1] = src1[0]; + dst1[0] = src1[0]; + dst1[1] = src1[0]; + } + + ++src0; + ++src1; + ++src2; + dst0 += 2; + dst1 += 2; + --count; + } + + // last pixel + if (src0[0] != src2[0] && src1[-1] != src1[0]) { + dst0[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; + dst0[1] = src1[0] == src0[0] ? src0[0] : src1[0]; + dst1[0] = src1[-1] == src2[0] ? src2[0] : src1[0]; + dst1[1] = src1[0] == src2[0] ? src2[0] : src1[0]; + } else { + dst0[0] = src1[0]; + dst0[1] = src1[0]; + dst1[0] = src1[0]; + dst1[1] = src1[0]; + } +} + +void Scale2x_ex8(unsigned char *srcPtr, DWORD srcPitch, + unsigned char *dstPtr, int width, int height) +{ + //const int srcpitch = srcPitch; + const int dstPitch = srcPitch<<1; + + int count = height; + + finalw=width<<1; + finalh=height<<1; + + uint32_t *dst0 = (uint32_t *)dstPtr; + uint32_t *dst1 = dst0 + (dstPitch >> 2); + + uint32_t *src0 = (uint32_t *)srcPtr; + uint32_t *src1 = src0 + (srcPitch >> 2); + uint32_t *src2 = src1 + (srcPitch >> 2); + scale2x_32_def_whole(dst0, dst1, src0, src0, src1, width); + + count -= 2; + while(count) { + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + scale2x_32_def_whole(dst0, dst1, src0, src0, src1, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + scale2x_32_def_whole(dst0, dst1, src0, src1, src1, width); + +} + +//////////////////////////////////////////////////////////////////////// + +static __inline void scale3x_32_def_whole(uint32_t* dst0, uint32_t* dst1, uint32_t* dst2, const uint32_t* src0, const uint32_t* src1, const uint32_t* src2, unsigned count) +{ + //assert(count >= 2); + + //first pixel + if (src0[0] != src2[0] && src1[0] != src1[1]) { + dst0[0] = src1[0]; + dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0]; + dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0]; + dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; + dst1[1] = src1[0]; + dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; + dst2[0] = src1[0]; + dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0]; + dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0]; + } else { + dst0[0] = src1[0]; + dst0[1] = src1[0]; + dst0[2] = src1[0]; + dst1[0] = src1[0]; + dst1[1] = src1[0]; + dst1[2] = src1[0]; + dst2[0] = src1[0]; + dst2[1] = src1[0]; + dst2[2] = src1[0]; + } + ++src0; + ++src1; + ++src2; + dst0 += 3; + dst1 += 3; + dst2 += 3; + + //central pixels + count -= 2; + while (count) { + if (src0[0] != src2[0] && src1[-1] != src1[1]) { + dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; + dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; + dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0]; + dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; + dst1[1] = src1[0]; + dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0]; + dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0]; + dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0]; + dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0]; + } else { + dst0[0] = src1[0]; + dst0[1] = src1[0]; + dst0[2] = src1[0]; + dst1[0] = src1[0]; + dst1[1] = src1[0]; + dst1[2] = src1[0]; + dst2[0] = src1[0]; + dst2[1] = src1[0]; + dst2[2] = src1[0]; + } + + ++src0; + ++src1; + ++src2; + dst0 += 3; + dst1 += 3; + dst2 += 3; + --count; + } + + // last pixel + if (src0[0] != src2[0] && src1[-1] != src1[0]) { + dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0]; + dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0]; + dst0[2] = src1[0]; + dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0]; + dst1[1] = src1[0]; + dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0]; + dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0]; + dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0]; + dst2[2] = src1[0]; + } else { + dst0[0] = src1[0]; + dst0[1] = src1[0]; + dst0[2] = src1[0]; + dst1[0] = src1[0]; + dst1[1] = src1[0]; + dst1[2] = src1[0]; + dst2[0] = src1[0]; + dst2[1] = src1[0]; + dst2[2] = src1[0]; + } +} + + +void Scale3x_ex8(unsigned char *srcPtr, DWORD srcPitch, + unsigned char *dstPtr, int width, int height) +{ + int count = height; + + int dstPitch = srcPitch*3; + int dstRowPixels = dstPitch>>2; + + finalw=width*3; + finalh=height*3; + + uint32_t *dst0 = (uint32_t *)dstPtr; + uint32_t *dst1 = dst0 + dstRowPixels; + uint32_t *dst2 = dst1 + dstRowPixels; + + uint32_t *src0 = (uint32_t *)srcPtr; + uint32_t *src1 = src0 + (srcPitch >> 2); + uint32_t *src2 = src1 + (srcPitch >> 2); + scale3x_32_def_whole(dst0, dst1, dst2, src0, src0, src2, width); + + count -= 2; + while(count) { + dst0 += dstRowPixels*3; + dst1 += dstRowPixels*3; + dst2 += dstRowPixels*3; + + scale3x_32_def_whole(dst0, dst1, dst2, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + + dst0 += dstRowPixels*3; + dst1 += dstRowPixels*3; + dst2 += dstRowPixels*3; + + scale3x_32_def_whole(dst0, dst1, dst2, src0, src1, src1, width); +} + + +//////////////////////////////////////////////////////////////////////// + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + + +//////////////////////////////////////////////////////////////////////// +// X STUFF :) +//////////////////////////////////////////////////////////////////////// + + +static Cursor cursor; +XVisualInfo vi; +static XVisualInfo *myvisual; +Display *display; +static Colormap colormap; +Window window; +static GC hGC; +static XImage * Ximage; +static XvImage * XCimage; +static XImage * XPimage=0; +char * Xpixels; +char * pCaptionText; + +static int fx=0; + + +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, 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(display) + { + XFreeColormap(display, colormap); + if(hGC) + { + XFreeGC(display,hGC); + hGC = 0; + } + if(Ximage) + { + XDestroyImage(Ximage); + Ximage=0; + } + if(XCimage) + { + XFree(XCimage); + XCimage=0; + } + + XShmDetach(display,&shminfo); + shmdt(shminfo.shmaddr); + shmctl(shminfo.shmid,IPC_RMID,NULL); + + Atom atom_vsync = xv_intern_atom_if_exists(display, "XV_SYNC_TO_VBLANK"); + if (atom_vsync != None) { + XvSetPortAttribute(display, xv_port, atom_vsync, xv_vsync); + } + + XSync(display,False); + + XCloseDisplay(display); + } +} + +static int depth=0; +int root_window_id=0; + + +// Create display + +void CreateDisplay(void) +{ + 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 + display = XOpenDisplay(NULL); + + if (!display) + { + fprintf (stderr,"Failed to open display!!!\n"); + DestroyDisplay(); + return; + } + + myscreen=DefaultScreen(display); + + // desktop fullscreen switch + if (!iWindowMode) fx = 1; + + screen=DefaultScreenOfDisplay(display); + + root_window_id=RootWindow(display,DefaultScreen(display)); + + //Look for an Xvideo RGB port + ret = XvQueryAdaptors(display, root_window_id, &p_num_adaptors, &ai); + if (ret != Success) { + if (ret == XvBadExtension) + printf("XvBadExtension returned at XvQueryExtension.\n"); + else + if (ret == XvBadAlloc) + printf("XvBadAlloc returned at XvQueryExtension.\n"); + else + printf("other error happaned at XvQueryAdaptors.\n"); + + exit(-1); + } + + depth = DefaultDepth(display, myscreen); + + 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(display, p, &formats); + for (j = 0; j < formats; j++) { + //backup YUV mode + //hmm, should I bother check guid == 55595659-0000-0010-8000-00aa00389b71? + //and check byte order? fo[j].byte_order == LSBFirst +#ifdef __BIG_ENDIAN__ + if ( fo[j].type == XvYUV && fo[j].bits_per_pixel == 16 && fo[j].format == XvPacked && strncmp("YUYV", fo[j].component_order, 5) == 0 ) +#else + if ( fo[j].type == XvYUV && fo[j].bits_per_pixel == 16 && fo[j].format == XvPacked && strncmp("UYVY", fo[j].component_order, 5) == 0 ) +#endif + { + yuv_port = p; + yuv_id = fo[j].id; + } + if (fo[j].type == XvRGB && fo[j].bits_per_pixel == 32) + { + xv_port = p; + xv_id = fo[j].id; + xv_depth = fo[j].depth; + printf("RGB mode found. id: %x, depth: %d\n", xv_id, xv_depth); + + if (xv_depth != depth) { + printf("Warning: Depth does not match screen depth (%d)\n", depth); + } + else { + //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 (xv_port == -1 && yuv_port == -1) + { + printf("RGB & YUV not found. Quitting.\n"); + exit(-1); + } + else if (xv_port == -1 && yuv_port != -1) + { + use_yuv = 1; + printf("RGB not found. Using YUV.\n"); + xv_port = yuv_port; + xv_id = yuv_id; + } + else if (xv_depth && xv_depth != depth && yuv_port != -1) + { + use_yuv = 1; + printf("Acceptable RGB mode not found. Using YUV.\n"); + xv_port = yuv_port; + xv_id = yuv_id; + } + + Atom atom_vsync = xv_intern_atom_if_exists(display, "XV_SYNC_TO_VBLANK"); + if (atom_vsync != None) { + XvGetPortAttribute(display, xv_port, atom_vsync, &xv_vsync); + XvSetPortAttribute(display, xv_port, atom_vsync, 0); + } + +myvisual = 0; + +if(XMatchVisualInfo(display,myscreen, depth, TrueColor, &vi)) + myvisual = &vi; + +if (!myvisual) +{ + fprintf(stderr,"Failed to obtain visual!\n"); + DestroyDisplay(); + return; +} + + if(myvisual->red_mask==0x00007c00 && + myvisual->green_mask==0x000003e0 && + myvisual->blue_mask==0x0000001f) + {iColDepth=15;} + else + if(myvisual->red_mask==0x0000f800 && + myvisual->green_mask==0x000007e0 && + myvisual->blue_mask==0x0000001f) + {iColDepth=16;} + else + if(myvisual->red_mask==0x00ff0000 && + myvisual->green_mask==0x0000ff00 && + myvisual->blue_mask==0x000000ff) + {iColDepth=32;} + else + { + iColDepth=0; +/* fprintf(stderr,"COLOR DEPTH NOT SUPPORTED!\n"); + fprintf(stderr,"r: %08lx\n",myvisual->red_mask); + fprintf(stderr,"g: %08lx\n",myvisual->green_mask); + fprintf(stderr,"b: %08lx\n",myvisual->blue_mask); + DestroyDisplay(); + return;*/ + } + + // pffff... much work for a simple blank cursor... oh, well... + if(iWindowMode) cursor=XCreateFontCursor(display,XC_trek); + else + { + Pixmap p1,p2; + XImage * img; + XColor b,w; + char * idata; + XGCValues GCv; + GC GCc; + + memset(&b,0,sizeof(XColor)); + memset(&w,0,sizeof(XColor)); + idata=(char *)malloc(8); + memset(idata,0,8); + + p1=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1); + p2=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1); + + img = XCreateImage(display,myvisual->visual, + 1,XYBitmap,0,idata,8,8,8,1); + + GCv.function = GXcopy; + GCv.foreground = ~0; + GCv.background = 0; + GCv.plane_mask = AllPlanes; + GCc = XCreateGC(display,p1, + (GCFunction|GCForeground|GCBackground|GCPlaneMask),&GCv); + + XPutImage(display, p1,GCc,img,0,0,0,0,8,8); + XPutImage(display, p2,GCc,img,0,0,0,0,8,8); + XFreeGC(display, GCc); + + cursor = XCreatePixmapCursor(display,p1,p2,&b,&w,0,0); + + XFreePixmap(display,p1); + XFreePixmap(display,p2); + XDestroyImage(img); // will free idata as well + } + + colormap=XCreateColormap(display,root_window_id, + 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=colormap; + winattr.cursor=None; + + window=XCreateWindow(display,root_window_id, + 0,0,iResX,iResY, + 0,myvisual->depth, + InputOutput,myvisual->visual, + CWBorderPixel | CWBackPixel | + CWEventMask | CWDontPropagate | + CWColormap | CWCursor, + &winattr); + + if(!window) + { + fprintf(stderr,"Failed in XCreateWindow()!!!\n"); + DestroyDisplay(); + return; + } + + delwindow = XInternAtom(display,"WM_DELETE_WINDOW",0); + XSetWMProtocols(display, window, &delwindow, 1); + + hints.flags=USPosition|USSize; + hints.base_width = iResX; + hints.base_height = iResY; + + wm_hints.input=1; + wm_hints.flags=InputHint; + + XSetWMHints(display,window,&wm_hints); + XSetWMNormalHints(display,window,&hints); + if(pCaptionText) + XStoreName(display,window,pCaptionText); + else XStoreName(display,window,"P.E.Op.S SoftX PSX Gpu"); + + XDefineCursor(display,window,cursor); + + // hack to get rid of window title bar + if (fx) + { + mwmhints.flags=MWM_HINTS_DECORATIONS; + mwmhints.decorations=0; + mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0); + XChangeProperty(display,window,mwmatom,mwmatom,32, + PropModeReplace,(unsigned char *)&mwmhints,4); + } + + // key stuff + XSelectInput(display, + window, + FocusChangeMask | ExposureMask | + KeyPressMask | KeyReleaseMask + ); + + XMapRaised(display,window); + XClearWindow(display,window); + XWindowEvent(display,window,ExposureMask,&event); + + if (fx) // fullscreen + { + 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); + + // 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(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); + } + } + + gcv.foreground = 0x0000FF00; // green letters for the FPS bar; do we need to take care of endianess? + gcv.background = 0x00000000; + gcv.graphics_exposures = False; + hGC = XCreateGC(display,window, + GCGraphicsExposures | GCForeground | GCBackground, &gcv); + if(!hGC) + { + fprintf(stderr,"No gfx context!!!\n"); + DestroyDisplay(); + } + + uint32_t color; + + /* fix the green back ground in YUV mode */ + if(use_yuv) + color = rgb_to_yuv(0x00, 0x00, 0x00); + else + color = 0; + + Xpixels = (char *)malloc(8*8*4); + for(i = 0; i < 8*8; ++i) + ((uint32_t *)Xpixels)[i] = color; + + XCimage = XvCreateImage(display,xv_port,xv_id, + (char *)Xpixels, 8, 8); + + +/* +Allocate max that could be needed: +Big(est?) PSX res: 640x512 +32bpp (times 4) +2xsai func= 3xwidth,3xheight += approx 11.8mb +*/ +shminfo.shmid = shmget(IPC_PRIVATE, 640*512*4*3*3, IPC_CREAT | 0777); +shminfo.shmaddr = shmat(shminfo.shmid, 0, 0); +shminfo.readOnly = 0; + + if (!XShmAttach(display, &shminfo)) { + printf("XShmAttach failed !\n"); + exit (-1); + } + + { + uint32_t *pShmaddr = (uint32_t *)shminfo.shmaddr; + for(i = 0; i < 640*512*3*3; ++i) + pShmaddr[i] = color; + } +} + +void (*p2XSaIFunc) (unsigned char *, DWORD, unsigned char *, int, int); +unsigned char *pBackBuffer = 0; + +void BlitScreen32(unsigned char *surf, int32_t x, int32_t y) +{ + unsigned char *pD; + unsigned int startxy; + uint32_t lu; + unsigned short s; + unsigned short row, column; + unsigned short dx = PreviousPSXDisplay.Range.x1; + unsigned short dy = PreviousPSXDisplay.DisplayMode.y; + + int32_t lPitch = PSXDisplay.DisplayMode.x << 2; + + uint32_t *destpix; + + if (PreviousPSXDisplay.Range.y0) // centering needed? + { + memset(surf, 0, (PreviousPSXDisplay.Range.y0 >> 1) * lPitch); + + dy -= PreviousPSXDisplay.Range.y0; + surf += (PreviousPSXDisplay.Range.y0 >> 1) * lPitch; + + memset(surf + dy * lPitch, + 0, ((PreviousPSXDisplay.Range.y0 + 1) >> 1) * lPitch); + } + + if (PreviousPSXDisplay.Range.x0) + { + for (column = 0; column < dy; column++) + { + destpix = (uint32_t *)(surf + (column * lPitch)); + memset(destpix, 0, PreviousPSXDisplay.Range.x0 << 2); + } + surf += PreviousPSXDisplay.Range.x0 << 2; + } + + if (PSXDisplay.RGB24) + { + for (column = 0; column < dy; column++) + { + startxy = ((1024) * (column + y)) + x; + pD = (unsigned char *)&psxVuw[startxy]; + destpix = (uint32_t *)(surf + (column * lPitch)); + for (row = 0; row < dx; row++) + { + lu = *((uint32_t *)pD); + destpix[row] = + 0xff000000 | (RED(lu) << 16) | (GREEN(lu) << 8) | (BLUE(lu)); + pD += 3; + } + } + } + else + { + for (column = 0;column> 7) & 0xf8)) | 0xff000000; + } + } + } +} + + + +void BlitToYUV(unsigned char * surf,int32_t x,int32_t y) +{ + unsigned char * pD; + unsigned int startxy; + uint32_t lu;unsigned short s; + unsigned short row,column; + unsigned short dx = PreviousPSXDisplay.Range.x1; + unsigned short dy = PreviousPSXDisplay.DisplayMode.y; + int R,G,B; + + int32_t lPitch = PSXDisplay.DisplayMode.x << 2; + uint32_t *destpix; + + if (PreviousPSXDisplay.Range.y0) // centering needed? + { + for (column = 0; column < (PreviousPSXDisplay.Range.y0 >> 1); column++) + { + destpix = (uint32_t *)(surf + column * lPitch); + for (row = 0; row < dx; row++) + { + destpix[row] = (4 << 24) | (128 << 16) | (4 << 8) | 128; + } + } + + dy -= PreviousPSXDisplay.Range.y0; + surf += (PreviousPSXDisplay.Range.y0 >> 1) * lPitch; + + for (column = 0; column < (PreviousPSXDisplay.Range.y0 + 1) >> 1; column++) + { + destpix = (uint32_t *)(surf + (dy + column) * lPitch); + for (row = 0; row < dx; row++) + { + destpix[row] = (4 << 24) | (128 << 16) | (4 << 8) | 128; + } + } + } + + if (PreviousPSXDisplay.Range.x0) + { + for (column = 0; column < dy; column++) + { + destpix = (uint32_t *)(surf + (column * lPitch)); + for (row = 0; row < PreviousPSXDisplay.Range.x0; row++) + { + destpix[row] = (4 << 24) | (128 << 16) | (4 << 8) | 128; + } + } + surf += PreviousPSXDisplay.Range.x0 << 2; + } + + if (PSXDisplay.RGB24) + { + for (column = 0; column < dy; column++) + { + startxy = (1024 * (column + y)) + x; + pD = (unsigned char *)&psxVuw[startxy]; + destpix = (uint32_t *)(surf + (column * lPitch)); + for (row = 0; row < dx; row++) + { + lu = *((uint32_t *)pD); + + R = RED(lu); + G = GREEN(lu); + B = BLUE(lu); + + destpix[row] = rgb_to_yuv(R, G, B); + + pD += 3; + } + } + } + else + { + for (column = 0; column < dy; column++) + { + startxy = (1024 * (column + y)) + x; + destpix = (uint32_t *)(surf + (column * lPitch)); + for (row = 0; row < dx; row++) + { + s = GETLE16(&psxVuw[startxy++]); + + R = (s << 3) &0xf8; + G = (s >> 2) &0xf8; + B = (s >> 7) &0xf8; + + destpix[row] = rgb_to_yuv(R, G, B); + + } + } + } +} + +//dst will have half the pitch (32bit to 16bit) +void RGB2YUV(uint32_t *s, int width, int height, uint32_t *d) +{ + int x,y; + int R,G,B, Y1,Y2,U,V; + + for (y=0; y>1; x++) { + R = (*s >> 16) & 0xff; + G = (*s >> 8) & 0xff; + B = *s & 0xff; + s++; + + Y1 = min(abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13, 235); + U = min(abs(R * -1214 + G * -2384 + B * 3598 + 4096 + 1048576) >> 13, 240); + V = min(abs(R * 3598 + G * -3013 + B * -585 + 4096 + 1048576) >> 13, 240); + + R = (*s >> 16) & 0xff; + G = (*s >> 8) & 0xff; + B = *s & 0xff; + s++; + + Y2 = min(abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13, 235); + +#ifdef __BIG_ENDIAN__ + *d = V | Y2 << 8 | U << 16 | Y1 << 24; +#else + *d = U | Y1 << 8 | V << 16 | Y2 << 24; +#endif + d++; + } + } +} + +extern time_t tStart; + +/* 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 MaintainAspect(uint32_t * dx, uint32_t * dy, uint32_t * dw, uint32_t * dh) +{ + + double ratio_x = ((double)*dw) / ((double)PSXDisplay.DisplayMode.x) ; + double ratio_y = ((double)*dh) / ((double)PSXDisplay.DisplayMode.y); + + double ratio; + if (ratio_x < ratio_y) { + ratio = ratio_x; + } else { + ratio = ratio_y; + } + + uint32_t tw = (uint32_t) floor(PSXDisplay.DisplayMode.x * ratio); + uint32_t th = (uint32_t) floor(PSXDisplay.DisplayMode.y * ratio); + + *dx = (uint32_t) floor((*dw - tw) / 2.0); + *dy = (uint32_t) floor((*dh - th) / 2.0); + *dw = tw; + *dh = th; +} + +void DoBufferSwap(void) +{ + Screen *screen; + Window _dw; + XvImage *xvi; + unsigned int dstx, dsty; + unsigned int _d, _w, _h; //don't care about _d + + finalw = PSXDisplay.DisplayMode.x; + finalh = PSXDisplay.DisplayMode.y; + + if (finalw == 0 || finalh == 0) + return; + + XSync(display,False); + + if(use_yuv) { + if (iUseNoStretchBlt==0 || finalw > 320 || finalh > 256) { + BlitToYUV((unsigned char *)shminfo.shmaddr, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y); + finalw <<= 1; + } else { + BlitScreen32((unsigned char *)pBackBuffer, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y); + p2XSaIFunc(pBackBuffer, finalw<<2, (unsigned char *)pSaIBigBuff,finalw,finalh); + RGB2YUV( (uint32_t*)pSaIBigBuff, finalw, finalh, (uint32_t*)shminfo.shmaddr); + } + } else if(iUseNoStretchBlt==0 || finalw > 320 || finalh > 256) { + BlitScreen32((unsigned char *)shminfo.shmaddr, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y); + } else { + BlitScreen32((unsigned char *)pBackBuffer, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y); + p2XSaIFunc(pBackBuffer, finalw<<2, (unsigned char *)shminfo.shmaddr,finalw,finalh); + } + + XGetGeometry(display, window, &_dw, (int *)&_d, (int *)&_d, &_w, &_h, &_d, &_d); + if (use_yuv) { + xvi = XvShmCreateImage(display, yuv_port, yuv_id, 0, finalw, finalh, &shminfo); + } else + xvi = XvShmCreateImage(display, xv_port, xv_id, 0, finalw, finalh, &shminfo); + + xvi->data = shminfo.shmaddr; + + screen=DefaultScreenOfDisplay(display); + //screennum = DefaultScreen(display); + + if (!iWindowMode) { + _w = screen->width; + _h = screen->height; + } + + dstx = 0; + dsty = 0; + + if (iMaintainAspect) + MaintainAspect(&dstx, &dsty, &_w, &_h); + +/*Whistler: too slow/laggy so commented out for now + if(iRumbleTime) + { + dstx += (rand() % iRumbleVal) - iRumbleVal / 2; + _w -= (rand() % iRumbleVal) - iRumbleVal / 2; + dsty += (rand() % iRumbleVal) - iRumbleVal / 2; + _h -= (rand() % iRumbleVal) - iRumbleVal / 2; + iRumbleTime--; + } +*/ + XvShmPutImage(display, xv_port, window, hGC, xvi, + 0,0, //src x,y + finalw,finalh, //src w,h + dstx,dsty, //dst x,y + _w, _h, //dst w,h + 1 + ); + + if(ulKeybits&KEY_SHOWFPS) //DisplayText(); c // paint menu text + { + if(szDebugText[0] && ((time(NULL) - tStart) < 2)) + { + strcpy(szDispBuf,szDebugText); + } + else + { + szDebugText[0]=0; + strcat(szDispBuf,szMenuBuf); + } + + //XPutImage(display,window,hGC, XFimage, + // 0, 0, 0, 0, 220,15); + + XDrawImageString(display,window,hGC,2,13,szDispBuf,strlen(szDispBuf)); + } + + //if(XPimage) DisplayPic(); + + XFree(xvi); +} + +void DoClearScreenBuffer(void) // CLEAR DX BUFFER +{ + Window _dw; + unsigned int _d, _w, _h; //don't care about _d + + XGetGeometry(display, window, &_dw, (int *)&_d, (int *)&_d, &_w, &_h, &_d, &_d); + + XvPutImage(display, xv_port, window, hGC, XCimage, + 0, 0, 8, 8, 0, 0, _w, _h); + //XSync(display,False); +} + +void DoClearFrontBuffer(void) // CLEAR DX BUFFER +{/* + XPutImage(display,window,hGC, XCimage, + 0, 0, 0, 0, iResX, iResY); + XSync(display,False);*/ +} + +int Xinitialize() +{ + iDesktopCol=32; + + + if(iUseNoStretchBlt>0) + { + pBackBuffer=(unsigned char *)malloc(640*512*sizeof(uint32_t)); + memset(pBackBuffer,0,640*512*sizeof(uint32_t)); + if (use_yuv) { + pSaIBigBuff=malloc(640*512*4*3*3); + memset(pSaIBigBuff,0,640*512*4*3*3); + } + } + + p2XSaIFunc=NULL; + + if(iUseNoStretchBlt==1) + { + p2XSaIFunc=Std2xSaI_ex8; + } + + if(iUseNoStretchBlt==2) + { + p2XSaIFunc=Super2xSaI_ex8; + } + + if(iUseNoStretchBlt==3) + { + p2XSaIFunc=SuperEagle_ex8; + } + + if(iUseNoStretchBlt==4) + { + p2XSaIFunc=Scale2x_ex8; + } + if(iUseNoStretchBlt==5) + { + p2XSaIFunc=Scale3x_ex8; + } + if(iUseNoStretchBlt==6) + { + p2XSaIFunc=hq2x_32; + } + if(iUseNoStretchBlt==7) + { + p2XSaIFunc=hq3x_32; + } + + bUsingTWin=FALSE; + + InitMenu(); + + bIsFirstFrame = FALSE; // done + + if(iShowFPS) + { + iShowFPS=0; + ulKeybits|=KEY_SHOWFPS; + szDispBuf[0]=0; + BuildDispMenu(0); + } + + return 0; +} + +void Xcleanup() // X CLEANUP +{ + CloseMenu(); + + if(iUseNoStretchBlt>0) + { + if(pBackBuffer) free(pBackBuffer); + pBackBuffer=0; + if(pSaIBigBuff) free(pSaIBigBuff); + pSaIBigBuff=0; + } +} + +unsigned long ulInitDisplay(void) +{ + CreateDisplay(); // x stuff + Xinitialize(); // init x + return (unsigned long)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; + } + } + } + + XPimage = XCreateImage(display,myvisual->visual, + depth, ZPixmap, 0, + (char *)p, + 128, 96, + depth>16 ? 32 : 16, + 0); +} + +void DestroyPic(void) +{ + if(XPimage) + { /* + XPutImage(display,window,hGC, XCimage, + 0, 0, 0, 0, iResX, iResY);*/ + XDestroyImage(XPimage); + XPimage=0; + } +} + +void DisplayPic(void) +{ + XPutImage(display,window,hGC, XPimage, + 0, 0, iResX-128, 0,128,96); +} + +void ShowGpuPic(void) +{ +} + +void ShowTextGpuPic(void) +{ +} + +static void hq2x_32_def(uint32_t * dst0, uint32_t * dst1, const uint32_t * src0, const uint32_t * src1, const uint32_t * src2, unsigned count) +{ + static unsigned char cache_vert_mask[640]; + unsigned char cache_horiz_mask = 0; + + unsigned i; + unsigned char mask; + uint32_t c[9]; + + if (src0 == src1) //processing first row + memset(cache_vert_mask, 0, count); + + for(i=0;i0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = c[1]; + c[3] = c[4]; + c[6] = c[7]; + } + + if (i> 2); + + uint32_t *src0 = (uint32_t *)srcPtr; + uint32_t *src1 = src0 + (srcPitch >> 2); + uint32_t *src2 = src1 + (srcPitch >> 2); + hq2x_32_def(dst0, dst1, src0, src0, src1, width); + + + count -= 2; + while(count) { + dst0 += dstPitch >> 1; //next 2 lines (dstPitch / 4 char per int * 2) + dst1 += dstPitch >> 1; + hq2x_32_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + hq2x_32_def(dst0, dst1, src0, src1, src1, width); +} + +static void hq3x_32_def(uint32_t* dst0, uint32_t* dst1, uint32_t* dst2, const uint32_t* src0, const uint32_t* src1, const uint32_t* src2, unsigned count) +{ + static unsigned char cache_vert_mask[640]; + unsigned char cache_horiz_mask = 0; + + unsigned i; + unsigned char mask; + uint32_t c[9]; + + if (src0 == src1) //processing first row + memset(cache_vert_mask, 0, count); + + for(i=0;i0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = c[1]; + c[3] = c[4]; + c[6] = c[7]; + } + + if (i>2; + + finalw=width*3; + finalh=height*3; + + uint32_t *dst0 = (uint32_t *)dstPtr; + uint32_t *dst1 = dst0 + dstRowPixels; + uint32_t *dst2 = dst1 + dstRowPixels; + + uint32_t *src0 = (uint32_t *)srcPtr; + uint32_t *src1 = src0 + (srcPitch >> 2); + uint32_t *src2 = src1 + (srcPitch >> 2); + hq3x_32_def(dst0, dst1, dst2, src0, src0, src2, width); + + count -= 2; + while(count) { + dst0 += dstRowPixels * 3; + dst1 += dstRowPixels * 3; + dst2 += dstRowPixels * 3; + + hq3x_32_def(dst0, dst1, dst2, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + dst0 += dstRowPixels * 3; + dst1 += dstRowPixels * 3; + dst2 += dstRowPixels * 3; + + hq3x_32_def(dst0, dst1, dst2, src0, src1, src1, width); + +} diff --git a/plugins/dfxvideo/draw.h b/plugins/dfxvideo/draw.h index a769d795..c5391547 100644 --- a/plugins/dfxvideo/draw.h +++ b/plugins/dfxvideo/draw.h @@ -1,58 +1,46 @@ -/*************************************************************************** - draw.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_DRAW_H_ -#define _GPU_DRAW_H_ - -void DoBufferSwap(void); -void DoClearScreenBuffer(void); -void DoClearFrontBuffer(void); -unsigned long ulInitDisplay(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; - -#ifdef _WINDOWS -void MoveScanLineArea(HWND hwnd); -#endif - -#if !defined(_WINDOWS) && !defined (_MACGL) -extern Display *display; -extern Window window; -extern int root_window_id; -#endif - -#ifndef _WINDOWS -extern char * Xpixels; -#endif - -#include -extern time_t tStart; -/////////////////////////////////////////////////////////////////////// - -#endif // _GPU_DRAW_H_ +/*************************************************************************** + draw.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_DRAW_H_ +#define _GPU_DRAW_H_ + +void DoBufferSwap(void); +void DoClearScreenBuffer(void); +void DoClearFrontBuffer(void); +unsigned long ulInitDisplay(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; + +#ifdef _WINDOWS +void MoveScanLineArea(HWND hwnd); +#endif + +/////////////////////////////////////////////////////////////////////// + +#endif // _GPU_DRAW_H_ diff --git a/plugins/dfxvideo/fps.c b/plugins/dfxvideo/fps.c index b1734789..67753a8e 100644 --- a/plugins/dfxvideo/fps.c +++ b/plugins/dfxvideo/fps.c @@ -1,357 +1,357 @@ -/*************************************************************************** - fps.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. * - * * - ***************************************************************************/ - -#define _IN_FPS - -#include - -#include "externals.h" -#include "fps.h" -#include "gpu.h" - -// FPS stuff -float fFrameRateHz=0; -DWORD dwFrameRateTicks=16; -float fFrameRate; -int iFrameLimit; -int UseFrameLimit=0; -int UseFrameSkip=0; - -// FPS skipping / limit -BOOL bInitCap = TRUE; -float fps_skip = 0; -float fps_cur = 0; - -#define MAXLACE 16 - -void CheckFrameRate(void) -{ - if(UseFrameSkip) // skipping mode? - { - if(!(dwActFixes&0x80)) // not old skipping mode? - { - dwLaceCnt++; // -> store cnt of vsync between frames - if(dwLaceCnt>=MAXLACE && UseFrameLimit) // -> if there are many laces without screen toggling, - { // do std frame limitation - if(dwLaceCnt==MAXLACE) bInitCap=TRUE; - FrameCap(); - } - } - else if(UseFrameLimit) FrameCap(); - calcfps(); // -> calc fps display in skipping mode - } - else // non-skipping mode: - { - if(UseFrameLimit) FrameCap(); // -> do it - if(ulKeybits&KEY_SHOWFPS) calcfps(); // -> and calc fps display - } -} - -#define TIMEBASE 100000 - -static unsigned long timeGetTime() -{ - 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 FrameCap (void) -{ - static unsigned long curticks, lastticks, _ticks_since_last_update; - static unsigned int TicksToWait = 0; - int overslept=0, tickstogo=0; - BOOL Waiting = TRUE; - - { - curticks = timeGetTime(); - _ticks_since_last_update = curticks - lastticks; - - if((_ticks_since_last_update > TicksToWait) || - (curticks dwFrameRateTicks) - TicksToWait=0; - else - TicksToWait=dwFrameRateTicks - overslept; - } - else - { - while (Waiting) - { - curticks = timeGetTime(); - _ticks_since_last_update = curticks - lastticks; - tickstogo = TicksToWait - _ticks_since_last_update; - if ((_ticks_since_last_update > TicksToWait) || - (curticks < lastticks) || tickstogo < overslept) - { - Waiting = FALSE; - lastticks = curticks; - overslept = _ticks_since_last_update - TicksToWait; - TicksToWait = dwFrameRateTicks - overslept; - return; - } - if (tickstogo >= 200 && !(dwActFixes&16)) - usleep(tickstogo*10 - 200); - } - } - } -} - -#define MAXSKIP 120 - -void FrameSkip(void) -{ - static int iNumSkips=0,iAdditionalSkip=0; // number of additional frames to skip - static DWORD dwLastLace=0; // helper var for frame limitation - static DWORD curticks, lastticks, _ticks_since_last_update; - int tickstogo=0; - static int overslept=0; - - if(!dwLaceCnt) return; // important: if no updatelace happened, we ignore it completely - - if(iNumSkips) // we are in skipping mode? - { - dwLastLace+=dwLaceCnt; // -> calc frame limit helper (number of laces) - bSkipNextFrame = TRUE; // -> we skip next frame - iNumSkips--; // -> ok, one done - } - else // ok, no additional skipping has to be done... - { // we check now, if some limitation is needed, or a new skipping has to get started - DWORD dwWaitTime; - - if(bInitCap || bSkipNextFrame) // first time or we skipped before? - { - if(UseFrameLimit && !bInitCap) // frame limit wanted and not first time called? - { - DWORD dwT=_ticks_since_last_update; // -> that's the time of the last drawn frame - dwLastLace+=dwLaceCnt; // -> and that's the number of updatelace since the start of the last drawn frame - - curticks = timeGetTime(); // -> now we calc the time of the last drawn frame + the time we spent skipping - _ticks_since_last_update= dwT+curticks - lastticks; - - dwWaitTime=dwLastLace*dwFrameRateTicks; // -> and now we calc the time the real psx would have needed - - if(_ticks_since_last_update we were too fast? - { - if((dwWaitTime-_ticks_since_last_update)> // -> some more security, to prevent - (60*dwFrameRateTicks)) // wrong waiting times - _ticks_since_last_update=dwWaitTime; - - while(_ticks_since_last_update loop until we have reached the real psx time - { // (that's the additional limitation, yup) - curticks = timeGetTime(); - _ticks_since_last_update = dwT+curticks - lastticks; - } - } - else // we were still too slow ?!!? - { - if(iAdditionalSkip well, somewhen we really have to stop skipping on very slow systems - { - iAdditionalSkip++; // -> inc our watchdog var - dwLaceCnt=0; // -> reset lace count - lastticks = timeGetTime(); - return; // -> done, we will skip next frame to get more speed - } - } - } - - bInitCap=FALSE; // -> ok, we have inited the frameskip func - iAdditionalSkip=0; // -> init additional skip - bSkipNextFrame=FALSE; // -> we don't skip the next frame - lastticks = timeGetTime(); // -> we store the start time of the next frame - dwLaceCnt=0; // -> and we start to count the laces - dwLastLace=0; - _ticks_since_last_update=0; - return; // -> done, the next frame will get drawn - } - - bSkipNextFrame=FALSE; // init the frame skip signal to 'no skipping' first - - curticks = timeGetTime(); // get the current time (we are now at the end of one drawn frame) - _ticks_since_last_update = curticks - lastticks; - - dwLastLace=dwLaceCnt; // store curr count (frame limitation helper) - dwWaitTime=dwLaceCnt*dwFrameRateTicks; // calc the 'real psx lace time' - if (dwWaitTime >= overslept) - dwWaitTime-=overslept; - - if(_ticks_since_last_update>dwWaitTime) // hey, we needed way too long for that frame... - { - if(UseFrameLimit) // if limitation, we skip just next frame, - { // and decide after, if we need to do more - iNumSkips=0; - } - else - { - iNumSkips=_ticks_since_last_update/dwWaitTime; // -> calc number of frames to skip to catch up - iNumSkips--; // -> since we already skip next frame, one down - if(iNumSkips>MAXSKIP) iNumSkips=MAXSKIP; // -> well, somewhere we have to draw a line - } - bSkipNextFrame = TRUE; // -> signal for skipping the next frame - } - else // we were faster than real psx? fine :) - if(UseFrameLimit) // frame limit used? so we wait til the 'real psx time' has been reached - { - if(dwLaceCnt>MAXLACE) // -> security check - _ticks_since_last_update=dwWaitTime; - - while(_ticks_since_last_update just do a waiting loop... - { - curticks = timeGetTime(); - _ticks_since_last_update = curticks - lastticks; - - tickstogo = dwWaitTime - _ticks_since_last_update; - if (tickstogo-overslept >= 200 && !(dwActFixes&16)) - usleep(tickstogo*10 - 200); - } - } - overslept = _ticks_since_last_update - dwWaitTime; - if (overslept < 0) - overslept = 0; - lastticks = timeGetTime(); // ok, start time of the next frame - } - - dwLaceCnt=0; // init lace counter -} - -void calcfps(void) -{ - static unsigned long curticks,_ticks_since_last_update,lastticks; - static long fps_cnt = 0; - static unsigned long fps_tck = 1; - static long fpsskip_cnt = 0; - static unsigned long fpsskip_tck = 1; - - { - curticks = timeGetTime(); - _ticks_since_last_update=curticks-lastticks; - - if(UseFrameSkip && !UseFrameLimit && _ticks_since_last_update) - fps_skip=min(fps_skip,((float)TIMEBASE/(float)_ticks_since_last_update+1.0f)); - - lastticks = curticks; - } - - if(UseFrameSkip && UseFrameLimit) - { - fpsskip_tck += _ticks_since_last_update; - - if(++fpsskip_cnt==2) - { - fps_skip = (float)2000/(float)fpsskip_tck; - fps_skip +=6.0f; - fpsskip_cnt = 0; - fpsskip_tck = 1; - } - } - - fps_tck += _ticks_since_last_update; - - if(++fps_cnt==20) - { - fps_cur = (float)(TIMEBASE*20)/(float)fps_tck; - - fps_cnt = 0; - fps_tck = 1; - - //if(UseFrameLimit && fps_cur>fFrameRateHz) // optical adjust ;) avoids flickering fps display - //fps_cur=fFrameRateHz; - } - -} - -void PCFrameCap (void) -{ - static unsigned long curticks, lastticks, _ticks_since_last_update; - static unsigned long TicksToWait = 0; - BOOL Waiting = TRUE; - - while (Waiting) - { - curticks = timeGetTime(); - _ticks_since_last_update = curticks - lastticks; - if ((_ticks_since_last_update > TicksToWait) || - (curticks < lastticks)) - { - Waiting = FALSE; - lastticks = curticks; - TicksToWait = (TIMEBASE/ (unsigned long)fFrameRateHz); - } - } -} - -void PCcalcfps(void) -{ - static unsigned long curticks,_ticks_since_last_update,lastticks; - static long fps_cnt = 0; - static float fps_acc = 0; - float CurrentFPS=0; - - curticks = timeGetTime(); - _ticks_since_last_update=curticks-lastticks; - if(_ticks_since_last_update) - CurrentFPS=(float)TIMEBASE/(float)_ticks_since_last_update; - else CurrentFPS = 0; - lastticks = curticks; - - fps_acc += CurrentFPS; - - if(++fps_cnt==10) - { - fps_cur = fps_acc / 10; - fps_acc = 0; - fps_cnt = 0; - } - - fps_skip=CurrentFPS+1.0f; -} - -void SetAutoFrameCap(void) -{ - if(iFrameLimit==1) - { - fFrameRateHz = fFrameRate; - dwFrameRateTicks=(TIMEBASE*100 / (unsigned long)(fFrameRateHz*100)); - return; - } - - if(dwActFixes&32) - { - if (PSXDisplay.Interlaced) - fFrameRateHz = PSXDisplay.PAL?50.0f:60.0f; - else fFrameRateHz = PSXDisplay.PAL?25.0f:30.0f; - } - else - { - fFrameRateHz = PSXDisplay.PAL?50.0f:59.94f; - dwFrameRateTicks=(TIMEBASE*100 / (unsigned long)(fFrameRateHz*100)); - } -} - -void SetFPSHandler(void) -{ -} - -void InitFPS(void) -{ - if(!fFrameRate) fFrameRate=200.0f; - if(fFrameRateHz==0) fFrameRateHz=fFrameRate; // set user framerate - dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz); -} +/*************************************************************************** + fps.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. * + * * + ***************************************************************************/ + +#define _IN_FPS + +#include + +#include "externals.h" +#include "fps.h" +#include "gpu.h" + +// FPS stuff +float fFrameRateHz=0; +DWORD dwFrameRateTicks=16; +float fFrameRate; +int iFrameLimit; +int UseFrameLimit=0; +int UseFrameSkip=0; + +// FPS skipping / limit +BOOL bInitCap = TRUE; +float fps_skip = 0; +float fps_cur = 0; + +#define MAXLACE 16 + +void CheckFrameRate(void) +{ + if(UseFrameSkip) // skipping mode? + { + if(!(dwActFixes&0x80)) // not old skipping mode? + { + dwLaceCnt++; // -> store cnt of vsync between frames + if(dwLaceCnt>=MAXLACE && UseFrameLimit) // -> if there are many laces without screen toggling, + { // do std frame limitation + if(dwLaceCnt==MAXLACE) bInitCap=TRUE; + FrameCap(); + } + } + else if(UseFrameLimit) FrameCap(); + calcfps(); // -> calc fps display in skipping mode + } + else // non-skipping mode: + { + if(UseFrameLimit) FrameCap(); // -> do it + if(ulKeybits&KEY_SHOWFPS) calcfps(); // -> and calc fps display + } +} + +#define TIMEBASE 100000 + +unsigned long timeGetTime() +{ + 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 FrameCap (void) +{ + static unsigned long curticks, lastticks, _ticks_since_last_update; + static unsigned int TicksToWait = 0; + int overslept=0, tickstogo=0; + BOOL Waiting = TRUE; + + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + + if((_ticks_since_last_update > TicksToWait) || + (curticks dwFrameRateTicks) + TicksToWait=0; + else + TicksToWait=dwFrameRateTicks - overslept; + } + else + { + while (Waiting) + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + tickstogo = TicksToWait - _ticks_since_last_update; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks) || tickstogo < overslept) + { + Waiting = FALSE; + lastticks = curticks; + overslept = _ticks_since_last_update - TicksToWait; + TicksToWait = dwFrameRateTicks - overslept; + return; + } + if (tickstogo >= 200 && !(dwActFixes&16)) + usleep(tickstogo*10 - 200); + } + } + } +} + +#define MAXSKIP 120 + +void FrameSkip(void) +{ + static int iNumSkips=0,iAdditionalSkip=0; // number of additional frames to skip + static DWORD dwLastLace=0; // helper var for frame limitation + static DWORD curticks, lastticks, _ticks_since_last_update; + int tickstogo=0; + static int overslept=0; + + if(!dwLaceCnt) return; // important: if no updatelace happened, we ignore it completely + + if(iNumSkips) // we are in skipping mode? + { + dwLastLace+=dwLaceCnt; // -> calc frame limit helper (number of laces) + bSkipNextFrame = TRUE; // -> we skip next frame + iNumSkips--; // -> ok, one done + } + else // ok, no additional skipping has to be done... + { // we check now, if some limitation is needed, or a new skipping has to get started + DWORD dwWaitTime; + + if(bInitCap || bSkipNextFrame) // first time or we skipped before? + { + if(UseFrameLimit && !bInitCap) // frame limit wanted and not first time called? + { + DWORD dwT=_ticks_since_last_update; // -> that's the time of the last drawn frame + dwLastLace+=dwLaceCnt; // -> and that's the number of updatelace since the start of the last drawn frame + + curticks = timeGetTime(); // -> now we calc the time of the last drawn frame + the time we spent skipping + _ticks_since_last_update= dwT+curticks - lastticks; + + dwWaitTime=dwLastLace*dwFrameRateTicks; // -> and now we calc the time the real psx would have needed + + if(_ticks_since_last_update we were too fast? + { + if((dwWaitTime-_ticks_since_last_update)> // -> some more security, to prevent + (60*dwFrameRateTicks)) // wrong waiting times + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_update loop until we have reached the real psx time + { // (that's the additional limitation, yup) + curticks = timeGetTime(); + _ticks_since_last_update = dwT+curticks - lastticks; + } + } + else // we were still too slow ?!!? + { + if(iAdditionalSkip well, somewhen we really have to stop skipping on very slow systems + { + iAdditionalSkip++; // -> inc our watchdog var + dwLaceCnt=0; // -> reset lace count + lastticks = timeGetTime(); + return; // -> done, we will skip next frame to get more speed + } + } + } + + bInitCap=FALSE; // -> ok, we have inited the frameskip func + iAdditionalSkip=0; // -> init additional skip + bSkipNextFrame=FALSE; // -> we don't skip the next frame + lastticks = timeGetTime(); // -> we store the start time of the next frame + dwLaceCnt=0; // -> and we start to count the laces + dwLastLace=0; + _ticks_since_last_update=0; + return; // -> done, the next frame will get drawn + } + + bSkipNextFrame=FALSE; // init the frame skip signal to 'no skipping' first + + curticks = timeGetTime(); // get the current time (we are now at the end of one drawn frame) + _ticks_since_last_update = curticks - lastticks; + + dwLastLace=dwLaceCnt; // store curr count (frame limitation helper) + dwWaitTime=dwLaceCnt*dwFrameRateTicks; // calc the 'real psx lace time' + if (dwWaitTime >= overslept) + dwWaitTime-=overslept; + + if(_ticks_since_last_update>dwWaitTime) // hey, we needed way too long for that frame... + { + if(UseFrameLimit) // if limitation, we skip just next frame, + { // and decide after, if we need to do more + iNumSkips=0; + } + else + { + iNumSkips=_ticks_since_last_update/dwWaitTime; // -> calc number of frames to skip to catch up + iNumSkips--; // -> since we already skip next frame, one down + if(iNumSkips>MAXSKIP) iNumSkips=MAXSKIP; // -> well, somewhere we have to draw a line + } + bSkipNextFrame = TRUE; // -> signal for skipping the next frame + } + else // we were faster than real psx? fine :) + if(UseFrameLimit) // frame limit used? so we wait til the 'real psx time' has been reached + { + if(dwLaceCnt>MAXLACE) // -> security check + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_update just do a waiting loop... + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + + tickstogo = dwWaitTime - _ticks_since_last_update; + if (tickstogo-overslept >= 200 && !(dwActFixes&16)) + usleep(tickstogo*10 - 200); + } + } + overslept = _ticks_since_last_update - dwWaitTime; + if (overslept < 0) + overslept = 0; + lastticks = timeGetTime(); // ok, start time of the next frame + } + + dwLaceCnt=0; // init lace counter +} + +void calcfps(void) +{ + static unsigned long curticks,_ticks_since_last_update,lastticks; + static long fps_cnt = 0; + static unsigned long fps_tck = 1; + static long fpsskip_cnt = 0; + static unsigned long fpsskip_tck = 1; + + { + curticks = timeGetTime(); + _ticks_since_last_update=curticks-lastticks; + + if(UseFrameSkip && !UseFrameLimit && _ticks_since_last_update) + fps_skip=min(fps_skip,((float)TIMEBASE/(float)_ticks_since_last_update+1.0f)); + + lastticks = curticks; + } + + if(UseFrameSkip && UseFrameLimit) + { + fpsskip_tck += _ticks_since_last_update; + + if(++fpsskip_cnt==2) + { + fps_skip = (float)2000/(float)fpsskip_tck; + fps_skip +=6.0f; + fpsskip_cnt = 0; + fpsskip_tck = 1; + } + } + + fps_tck += _ticks_since_last_update; + + if(++fps_cnt==20) + { + fps_cur = (float)(TIMEBASE*20)/(float)fps_tck; + + fps_cnt = 0; + fps_tck = 1; + + //if(UseFrameLimit && fps_cur>fFrameRateHz) // optical adjust ;) avoids flickering fps display + //fps_cur=fFrameRateHz; + } + +} + +void PCFrameCap (void) +{ + static unsigned long curticks, lastticks, _ticks_since_last_update; + static unsigned long TicksToWait = 0; + BOOL Waiting = TRUE; + + while (Waiting) + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + Waiting = FALSE; + lastticks = curticks; + TicksToWait = (TIMEBASE/ (unsigned long)fFrameRateHz); + } + } +} + +void PCcalcfps(void) +{ + static unsigned long curticks,_ticks_since_last_update,lastticks; + static long fps_cnt = 0; + static float fps_acc = 0; + float CurrentFPS=0; + + curticks = timeGetTime(); + _ticks_since_last_update=curticks-lastticks; + if(_ticks_since_last_update) + CurrentFPS=(float)TIMEBASE/(float)_ticks_since_last_update; + else CurrentFPS = 0; + lastticks = curticks; + + fps_acc += CurrentFPS; + + if(++fps_cnt==10) + { + fps_cur = fps_acc / 10; + fps_acc = 0; + fps_cnt = 0; + } + + fps_skip=CurrentFPS+1.0f; +} + +void SetAutoFrameCap(void) +{ + if(iFrameLimit==1) + { + fFrameRateHz = fFrameRate; + dwFrameRateTicks=(TIMEBASE*100 / (unsigned long)(fFrameRateHz*100)); + return; + } + + if(dwActFixes&32) + { + if (PSXDisplay.Interlaced) + fFrameRateHz = PSXDisplay.PAL?50.0f:60.0f; + else fFrameRateHz = PSXDisplay.PAL?25.0f:30.0f; + } + else + { + fFrameRateHz = PSXDisplay.PAL?50.0f:59.94f; + dwFrameRateTicks=(TIMEBASE*100 / (unsigned long)(fFrameRateHz*100)); + } +} + +void SetFPSHandler(void) +{ +} + +void InitFPS(void) +{ + if(!fFrameRate) fFrameRate=200.0f; + if(fFrameRateHz==0) fFrameRateHz=fFrameRate; // set user framerate + dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz); +} diff --git a/plugins/dfxvideo/gpu.c b/plugins/dfxvideo/gpu.c index e74331ae..bd14f28f 100644 --- a/plugins/dfxvideo/gpu.c +++ b/plugins/dfxvideo/gpu.c @@ -1,2312 +1,2295 @@ -/*************************************************************************** - gpu.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. * - * * - ***************************************************************************/ - -#if !defined(_MACGL) && !defined(_WINDOWS) -#include "config.h" -#endif - -#define _IN_GPU - -#include "externals.h" -#include "gpu.h" -#include "draw.h" -#include "cfg.h" -#include "prim.h" -#include "stdint.h" -#include "psemu_plugin_defs.h" -#include "menu.h" -#include "key.h" -#include "fps.h" -#include "swap.h" -#include "psemu_plugin_defs.h" - -#ifdef _WINDOWS -#include "resource.h" -#include "record.h" -#endif - -//////////////////////////////////////////////////////////////////////// -// PPDK developer must change libraryName field and can change revision and build -//////////////////////////////////////////////////////////////////////// - -const unsigned char version = 1; // do not touch - library for PSEmu 1.x -const unsigned char revision = 1; -const unsigned char build = 17; // increase that with each version - -#if defined (_WINDOWS) -static char *libraryName = N_("Soft Driver"); -#if 0 -static char *libraryInfo = N_("P.E.Op.S. Soft Driver V1.17\nCoded by Pete Bernert and the P.E.Op.S. team\n"); -#endif -#elif defined (_MACGL) -static char *libraryName = N_("SoftGL Driver"); -#if 0 -static char *libraryInfo = N_("P.E.Op.S. SoftGL Driver V1.17\nCoded by Pete Bernert and the P.E.Op.S. team\n"); -#endif -#else -static char *libraryName = N_("XVideo Driver"); -#if 0 -static char *libraryInfo = N_("P.E.Op.S. Xvideo Driver V1.17\nCoded by Pete Bernert and the P.E.Op.S. team\n"); -#endif -#endif - -static char *PluginAuthor = N_("Pete Bernert and the P.E.Op.S. team"); - -//////////////////////////////////////////////////////////////////////// -// memory image of the PSX vram -//////////////////////////////////////////////////////////////////////// - -unsigned char *psxVSecure; -unsigned char *psxVub; -signed char *psxVsb; -unsigned short *psxVuw; -unsigned short *psxVuw_eom; -signed short *psxVsw; -uint32_t *psxVul; -int32_t *psxVsl; - -//////////////////////////////////////////////////////////////////////// -// GPU globals -//////////////////////////////////////////////////////////////////////// - -static long lGPUdataRet; -long lGPUstatusRet; -char szDispBuf[64]; -char szMenuBuf[36]; -char szDebugText[512]; -uint32_t ulStatusControl[256]; - -static uint32_t gpuDataM[256]; -static unsigned char gpuCommand = 0; -static long gpuDataC = 0; -static long gpuDataP = 0; - -VRAMLoad_t VRAMWrite; -VRAMLoad_t VRAMRead; -DATAREGISTERMODES DataWriteMode; -DATAREGISTERMODES DataReadMode; - -BOOL bSkipNextFrame = FALSE; -DWORD dwLaceCnt=0; -int iColDepth; -int iWindowMode; -short sDispWidths[8] = {256,320,512,640,368,384,512,640}; -PSXDisplay_t PSXDisplay; -PSXDisplay_t PreviousPSXDisplay; -long lSelectedSlot=0; -BOOL bChangeWinMode=FALSE; -BOOL bDoLazyUpdate=FALSE; -uint32_t lGPUInfoVals[16]; -static int iFakePrimBusy=0; -uint32_t vBlank=0; -int iRumbleVal=0; -int iRumbleTime=0; - -#ifdef _WINDOWS - -//////////////////////////////////////////////////////////////////////// -// screensaver stuff: dynamically load kernel32.dll to avoid export dependeny -//////////////////////////////////////////////////////////////////////// - -int iStopSaver=0; -HINSTANCE kernel32LibHandle = NULL; - -// A stub function, that does nothing .... but it does "nothing" well :) -EXECUTION_STATE WINAPI STUB_SetThreadExecutionState(EXECUTION_STATE esFlags) -{ - return esFlags; -} - -// The dynamic version of the system call is prepended with a "D_" -EXECUTION_STATE (WINAPI *D_SetThreadExecutionState)(EXECUTION_STATE esFlags) = STUB_SetThreadExecutionState; - -static BOOL LoadKernel32(void) -{ - // Get a handle to the kernel32.dll (which is actually already loaded) - kernel32LibHandle = LoadLibrary("kernel32.dll"); - - // If we've got a handle, then locate the entry point for the SetThreadExecutionState function - if (kernel32LibHandle != NULL) - { - if ((D_SetThreadExecutionState = (EXECUTION_STATE (WINAPI *)(EXECUTION_STATE))GetProcAddress (kernel32LibHandle, "SetThreadExecutionState")) == NULL) - D_SetThreadExecutionState = STUB_SetThreadExecutionState; - } - - return TRUE; -} - -static BOOL FreeKernel32(void) -{ - // Release the handle to kernel32.dll - if (kernel32LibHandle != NULL) - FreeLibrary(kernel32LibHandle); - - // Set to stub function, to avoid nasty suprises if called :) - D_SetThreadExecutionState = STUB_SetThreadExecutionState; - - return TRUE; -} -#else - -// Linux: Stub the functions -static BOOL LoadKernel32(void) -{ - return TRUE; -} - -static BOOL FreeKernel32(void) -{ - return TRUE; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -// some misc external display funcs -//////////////////////////////////////////////////////////////////////// - -#include -time_t tStart; - -void CALLBACK GPUdisplayText(char * pText) // some debug func -{ - if(!pText) {szDebugText[0]=0;return;} - if(strlen(pText)>511) return; - time(&tStart); - strcpy(szDebugText,pText); -} - -//////////////////////////////////////////////////////////////////////// - -#if 0 -void CALLBACK GPUdisplayFlags(unsigned long dwFlags) // some info func -{ - dwCoreFlags=dwFlags; - BuildDispMenu(0); -} -#endif - -//////////////////////////////////////////////////////////////////////// -// stuff to make this a true PDK module -//////////////////////////////////////////////////////////////////////// - -char * CALLBACK PSEgetLibName(void) -{ - return _(libraryName); -} - -unsigned long CALLBACK PSEgetLibType(void) -{ - return PSE_LT_GPU; -} - -unsigned long CALLBACK PSEgetLibVersion(void) -{ - return version<<16|revision<<8|build; -} - -#if 0 -char * GPUgetLibInfos(void) -{ - return _(libraryInfo); -} -#endif - -//////////////////////////////////////////////////////////////////////// -// Snapshot func -//////////////////////////////////////////////////////////////////////// - -static 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); - //----------------------------------------------------// - if(iCfg && iWindowMode) - sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize)); - else - sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY); - 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; -} - -static void DoTextSnapShot(int iNum) -{ - FILE *txtfile; - char szTxt[256]; - char *pB; - -#ifdef _WINDOWS - sprintf(szTxt,"snap\\pcsx%04d.txt",iNum); -#else - sprintf(szTxt,"%s/pcsx%04d.txt",getenv("HOME"),iNum); -#endif - - if ((txtfile = fopen(szTxt, "wb")) == NULL) - return; - - pB = pGetConfigInfos(0); - if (pB) - { - if(fwrite(pB, strlen(pB), 1, txtfile) != 1) { - fclose(txtfile); - free(pB); - remove(szTxt); - return; - } - free(pB); - } - fclose(txtfile); -} - -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 = 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] = PreviousPSXDisplay.Range.x1 % 256; - header[0x13] = 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; - - if(fwrite(header, 0x36, 1, bmpfile) != 1) { - fclose(bmpfile); - remove(filename); - return; - } - 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; - } - } - if(fwrite(line, PreviousPSXDisplay.Range.x1 * 3, 1, bmpfile) != 1) { - fclose(bmpfile); - remove(filename); - return; - } - } - if(fwrite(empty, 0x2, 1, bmpfile) != 1) { - fclose(bmpfile); - remove(filename); - return; - } - if(fclose(bmpfile) != 0) { - remove(filename); - return; - } - - DoTextSnapShot(snapshotnr); -} - -//////////////////////////////////////////////////////////////////////// -// INIT, will be called after lib load... well, just do some var init... -//////////////////////////////////////////////////////////////////////// - -long CALLBACK GPUinit() // GPU INIT -{ - memset(ulStatusControl,0,256*sizeof(uint32_t)); // init save state scontrol field - - szDebugText[0] = 0; // init debug text buffer - - psxVSecure = (unsigned char *)malloc((iGPUHeight*2)*1024 + (1024*1024)); // always alloc one extra MB for soft drawing funcs security - if (!psxVSecure) - return -1; - - //!!! ATTENTION !!! - psxVub=psxVSecure + 512 * 1024; // security offset into double sized psx vram! - - psxVsb=(signed char *)psxVub; // different ways of accessing PSX VRAM - psxVsw=(signed short *)psxVub; - psxVsl=(int32_t *)psxVub; - psxVuw=(unsigned short *)psxVub; - psxVul=(uint32_t *)psxVub; - - psxVuw_eom=psxVuw+1024*iGPUHeight; // pre-calc of end of vram - - memset(psxVSecure,0x00,(iGPUHeight*2)*1024 + (1024*1024)); - memset(lGPUInfoVals,0x00,16*sizeof(uint32_t)); - - SetFPSHandler(); - - PSXDisplay.RGB24 = FALSE; // init some stuff - PSXDisplay.Interlaced = FALSE; - PSXDisplay.DrawOffset.x = 0; - PSXDisplay.DrawOffset.y = 0; - PSXDisplay.DisplayMode.x= 320; - PSXDisplay.DisplayMode.y= 240; - PreviousPSXDisplay.DisplayMode.x= 320; - PreviousPSXDisplay.DisplayMode.y= 240; - PSXDisplay.Disabled = FALSE; - PreviousPSXDisplay.Range.x0 =0; - PreviousPSXDisplay.Range.y0 =0; - PSXDisplay.Range.x0=0; - PSXDisplay.Range.x1=0; - PreviousPSXDisplay.DisplayModeNew.y=0; - PSXDisplay.Double = 1; - lGPUdataRet = 0x400; - - DataWriteMode = DR_NORMAL; - - // Reset transfer values, to prevent mis-transfer of data - memset(&VRAMWrite, 0, sizeof(VRAMLoad_t)); - memset(&VRAMRead, 0, sizeof(VRAMLoad_t)); - - // device initialised already ! - lGPUstatusRet = 0x14802000; - GPUIsIdle; - GPUIsReadyForCommands; - bDoVSyncUpdate = TRUE; - vBlank = 0; - - // Get a handle for kernel32.dll, and access the required export function - LoadKernel32(); - - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// Here starts all... -//////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS -long CALLBACK GPUopen(HWND hwndGPU) // GPU OPEN -{ - hWGPU = hwndGPU; // store hwnd - - SetKeyHandler(); // sub-class window - - if(bChangeWinMode) ReadWinSizeConfig(); // alt+enter toggle? - else // or first time startup? - { - ReadConfig(); // read registry - InitFPS(); - } - - bIsFirstFrame = TRUE; // we have to init later - bDoVSyncUpdate = TRUE; - - ulInitDisplay(); // setup direct draw - - if(iStopSaver) - D_SetThreadExecutionState(ES_SYSTEM_REQUIRED|ES_DISPLAY_REQUIRED|ES_CONTINUOUS); - - - return 0; -} - -#else - -long GPUopen(unsigned long * disp,char * CapText,char * CfgFile) -{ - unsigned long d; - - pCaptionText=CapText; - - - ReadConfig(); // read registry - - InitFPS(); - - bIsFirstFrame = TRUE; // we have to init later - bDoVSyncUpdate = TRUE; - - d=ulInitDisplay(); // setup x - - if(disp) - *disp=d; // wanna x pointer? ok - - if(d) return 0; - return -1; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -// time to leave... -//////////////////////////////////////////////////////////////////////// - -long CALLBACK GPUclose() // GPU CLOSE -{ -#ifdef _WINDOWS - if(RECORD_RECORDING==TRUE) {RECORD_Stop();RECORD_RECORDING=FALSE;BuildDispMenu(0);} -#endif - - ReleaseKeyHandler(); // de-subclass window - - CloseDisplay(); // shutdown direct draw - -#ifdef _WINDOWS - if(iStopSaver) - D_SetThreadExecutionState(ES_SYSTEM_REQUIRED|ES_DISPLAY_REQUIRED); -#endif - - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// I shot the sheriff -//////////////////////////////////////////////////////////////////////// - -long CALLBACK GPUshutdown() // GPU SHUTDOWN -{ - // screensaver: release the handle for kernel32.dll - FreeKernel32(); - - free(psxVSecure); - - return 0; // nothinh to do -} - -//////////////////////////////////////////////////////////////////////// -// Update display (swap buffers) -//////////////////////////////////////////////////////////////////////// - -void updateDisplay(void) // UPDATE DISPLAY -{ - if(PSXDisplay.Disabled) // disable? - { - DoClearFrontBuffer(); // -> clear frontbuffer - return; // -> and bye - } - - if(dwActFixes&32) // pc fps calculation fix - { - if(UseFrameLimit) PCFrameCap(); // -> brake - if(UseFrameSkip || ulKeybits&KEY_SHOWFPS) - PCcalcfps(); - } - - if(ulKeybits&KEY_SHOWFPS) // make fps display buf - { - sprintf(szDispBuf,"FPS %06.1f",fps_cur); - } - - if(iFastFwd) // fastfwd ? - { - static int fpscount; UseFrameSkip=1; - - if(!bSkipNextFrame) DoBufferSwap(); // -> to skip or not to skip - if(fpscount%6) // -> skip 6/7 frames - bSkipNextFrame = TRUE; - else bSkipNextFrame = FALSE; - fpscount++; - if(fpscount >= (int)fFrameRateHz) fpscount = 0; - return; - } - - if(UseFrameSkip) // skip ? - { - if(!bSkipNextFrame) DoBufferSwap(); // -> to skip or not to skip - if(dwActFixes&0xa0) // -> pc fps calculation fix/old skipping fix - { - if((fps_skip < fFrameRateHz) && !(bSkipNextFrame)) // -> skip max one in a row - {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;} - else bSkipNextFrame = FALSE; - } - else FrameSkip(); - } - else // no skip ? - { - DoBufferSwap(); // -> swap - } -} - -//////////////////////////////////////////////////////////////////////// -// roughly emulated screen centering bits... not complete !!! -//////////////////////////////////////////////////////////////////////// - -static void ChangeDispOffsetsX(void) // X CENTER -{ - long lx,l; - - if(!PSXDisplay.Range.x1) return; - - l=PreviousPSXDisplay.DisplayMode.x; - - l*=(long)PSXDisplay.Range.x1; - l/=2560;lx=l;l&=0xfffffff8; - - if(l==PreviousPSXDisplay.Range.y1) return; // abusing range.y1 for - PreviousPSXDisplay.Range.y1=(short)l; // storing last x range and test - - if(lx>=PreviousPSXDisplay.DisplayMode.x) - { - PreviousPSXDisplay.Range.x1= - (short)PreviousPSXDisplay.DisplayMode.x; - PreviousPSXDisplay.Range.x0=0; - } - else - { - PreviousPSXDisplay.Range.x1=(short)l; - - PreviousPSXDisplay.Range.x0= - (PSXDisplay.Range.x0-500)/8; - - if(PreviousPSXDisplay.Range.x0<0) - PreviousPSXDisplay.Range.x0=0; - - if((PreviousPSXDisplay.Range.x0+lx)> - PreviousPSXDisplay.DisplayMode.x) - { - PreviousPSXDisplay.Range.x0= - (short)(PreviousPSXDisplay.DisplayMode.x-lx); - PreviousPSXDisplay.Range.x0+=2; //??? - - PreviousPSXDisplay.Range.x1+=(short)(lx-l); - -#ifndef _WINDOWS - PreviousPSXDisplay.Range.x1-=2; // makes linux stretching easier -#endif - } - -#ifndef _WINDOWS - // some linux alignment security - PreviousPSXDisplay.Range.x0=PreviousPSXDisplay.Range.x0>>1; - PreviousPSXDisplay.Range.x0=PreviousPSXDisplay.Range.x0<<1; - PreviousPSXDisplay.Range.x1=PreviousPSXDisplay.Range.x1>>1; - PreviousPSXDisplay.Range.x1=PreviousPSXDisplay.Range.x1<<1; -#endif - - DoClearScreenBuffer(); - } - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// - -static void ChangeDispOffsetsY(void) // Y CENTER -{ - int iT,iO=PreviousPSXDisplay.Range.y0; - int iOldYOffset=PreviousPSXDisplay.DisplayModeNew.y; - -// new - - if((PreviousPSXDisplay.DisplayModeNew.x+PSXDisplay.DisplayModeNew.y)>iGPUHeight) - { - int dy1=iGPUHeight-PreviousPSXDisplay.DisplayModeNew.x; - int dy2=(PreviousPSXDisplay.DisplayModeNew.x+PSXDisplay.DisplayModeNew.y)-iGPUHeight; - - if(dy1>=dy2) - { - PreviousPSXDisplay.DisplayModeNew.y=-dy2; - } - else - { - PSXDisplay.DisplayPosition.y=0; - PreviousPSXDisplay.DisplayModeNew.y=-dy1; - } - } - else PreviousPSXDisplay.DisplayModeNew.y=0; - -// eon - - if(PreviousPSXDisplay.DisplayModeNew.y!=iOldYOffset) // if old offset!=new offset: recalc height - { - PSXDisplay.Height = PSXDisplay.Range.y1 - - PSXDisplay.Range.y0 + - PreviousPSXDisplay.DisplayModeNew.y; - PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double; - } - -// - - if(PSXDisplay.PAL) iT=48; else iT=28; - - if(PSXDisplay.Range.y0>=iT) - { - PreviousPSXDisplay.Range.y0= - (short)((PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double); - if(PreviousPSXDisplay.Range.y0<0) - PreviousPSXDisplay.Range.y0=0; - PSXDisplay.DisplayModeNew.y+= - PreviousPSXDisplay.Range.y0; - } - else - PreviousPSXDisplay.Range.y0=0; - - if(iO!=PreviousPSXDisplay.Range.y0) - { - DoClearScreenBuffer(); - } -} - -//////////////////////////////////////////////////////////////////////// -// check if update needed -//////////////////////////////////////////////////////////////////////// - -static void updateDisplayIfChanged(void) // UPDATE DISPLAY IF CHANGED -{ - if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) && - (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x)) - { - if((PSXDisplay.RGB24 == PSXDisplay.RGB24New) && - (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew)) return; - } - - PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos - - PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y; - PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x; - PreviousPSXDisplay.DisplayMode.x= // previous will hold - min(640,PSXDisplay.DisplayMode.x); // max 640x512... that's - PreviousPSXDisplay.DisplayMode.y= // the size of my - min(512,PSXDisplay.DisplayMode.y); // back buffer surface - PSXDisplay.Interlaced = PSXDisplay.InterlacedNew; - - PSXDisplay.DisplayEnd.x= // calc end of display - PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; - PSXDisplay.DisplayEnd.y= - PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; - PreviousPSXDisplay.DisplayEnd.x= - PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; - PreviousPSXDisplay.DisplayEnd.y= - PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; - - ChangeDispOffsetsX(); - - if(iFrameLimit==2) SetAutoFrameCap(); // -> set it - - if(UseFrameSkip) updateDisplay(); // stupid stuff when frame skipping enabled -} - -//////////////////////////////////////////////////////////////////////// - -#if defined(_WINDOWS) - -void ChangeWindowMode(void) // TOGGLE FULLSCREEN - WINDOW -{ - GPUclose(); - iWindowMode=!iWindowMode; - GPUopen(hWGPU); - bChangeWinMode=FALSE; - bDoVSyncUpdate=TRUE; -} - -#elif !defined (_MACGL) - -#include "draw.h" - -static void ChangeWindowMode(void) // TOGGLE FULLSCREEN - WINDOW -{ - 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=FALSE; - bDoVSyncUpdate=TRUE; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -// gun cursor func: player=0-7, x=0-511, y=0-255 -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUcursor(int iPlayer,int x,int y) -{ - if(iPlayer<0) return; - if(iPlayer>7) return; - - usCursorActive|=(1<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 -{ - //if(!(dwActFixes&1)) - //lGPUstatusRet^=0x80000000; // odd/even bit - - if(!(dwActFixes&32)) // std fps limitation? - CheckFrameRate(); - - if(PSXDisplay.Interlaced) // interlaced mode? - { - lGPUstatusRet^=0x80000000; - if(bDoVSyncUpdate && PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0) - { - updateDisplay(); - } - } - else // non-interlaced? - { - if(dwActFixes&64) // lazy screen update fix - { - if(bDoLazyUpdate && !UseFrameSkip) - updateDisplay(); - bDoLazyUpdate=FALSE; - } - else - { - if(bDoVSyncUpdate && !UseFrameSkip) // some primitives drawn? - updateDisplay(); // -> update display - } - } - -#ifdef _WINDOWS - if(RECORD_RECORDING) - if(RECORD_WriteFrame()==FALSE) - {RECORD_RECORDING=FALSE;RECORD_Stop();} -#endif - -#ifndef _MACGL - if(bChangeWinMode) ChangeWindowMode(); // toggle full - window mode -#endif - - bDoVSyncUpdate=FALSE; // vsync done -} - -//////////////////////////////////////////////////////////////////////// -// process read request from GPU status register -//////////////////////////////////////////////////////////////////////// - - -uint32_t CALLBACK GPUreadStatus(void) // READ STATUS -{ - if(dwActFixes&1) - { - static int iNumRead=0; // odd/even hack - if((iNumRead++)==2) - { - iNumRead=0; - lGPUstatusRet^=0x80000000; // interlaced bit toggle... we do it on every 3 read status... needed by some games (like ChronoCross) with old epsxe versions (1.5.2 and older) - } - } - - if(iFakePrimBusy) // 27.10.2007 - PETE : emulating some 'busy' while drawing... pfff - { - iFakePrimBusy--; - - if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims - { - GPUIsBusy; - GPUIsNotReadyForCommands; - } - else - { - GPUIsIdle; - GPUIsReadyForCommands; - } - } - return lGPUstatusRet | (vBlank ? 0x80000000 : 0 ); -} - -//////////////////////////////////////////////////////////////////////// -// processes data send to GPU status register -// these are always single packet commands. -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUwriteStatus(uint32_t gdata) // WRITE STATUS -{ - uint32_t lCommand=(gdata>>24)&0xff; - - ulStatusControl[lCommand]=gdata; // store command for freezing - - switch(lCommand) - { - //--------------------------------------------------// - // reset gpu - case 0x00: - memset(lGPUInfoVals,0x00,16*sizeof(uint32_t)); - lGPUstatusRet=0x14802000; - PSXDisplay.Disabled=1; - DataWriteMode=DataReadMode=DR_NORMAL; - PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0; - drawX=drawY=0;drawW=drawH=0; - sSetMask=0;lSetMask=0;bCheckMask=FALSE; - usMirror=0; - GlobalTextAddrX=0;GlobalTextAddrY=0; - GlobalTextTP=0;GlobalTextABR=0; - PSXDisplay.RGB24=FALSE; - PSXDisplay.Interlaced=FALSE; - bUsingTWin = FALSE; - return; - //--------------------------------------------------// - // dis/enable display - case 0x03: - - PreviousPSXDisplay.Disabled = PSXDisplay.Disabled; - PSXDisplay.Disabled = (gdata & 1); - - if(PSXDisplay.Disabled) - lGPUstatusRet|=GPUSTATUS_DISPLAYDISABLED; - else lGPUstatusRet&=~GPUSTATUS_DISPLAYDISABLED; - return; - - //--------------------------------------------------// - // setting transfer mode - case 0x04: - gdata &= 0x03; // Only want the lower two bits - - DataWriteMode=DataReadMode=DR_NORMAL; - if(gdata==0x02) DataWriteMode=DR_VRAMTRANSFER; - if(gdata==0x03) DataReadMode =DR_VRAMTRANSFER; - lGPUstatusRet&=~GPUSTATUS_DMABITS; // Clear the current settings of the DMA bits - lGPUstatusRet|=(gdata << 29); // Set the DMA bits according to the received data - - return; - //--------------------------------------------------// - // setting display position - case 0x05: - { - PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; - PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; - -//////// -/* - PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x3ff); - if (PSXDisplay.DisplayPosition.y & 0x200) - PSXDisplay.DisplayPosition.y |= 0xfffffc00; - if(PSXDisplay.DisplayPosition.y<0) - { - PreviousPSXDisplay.DisplayModeNew.y=PSXDisplay.DisplayPosition.y/PSXDisplay.Double; - PSXDisplay.DisplayPosition.y=0; - } - else PreviousPSXDisplay.DisplayModeNew.y=0; -*/ - -// new - if(iGPUHeight==1024) - { - if(dwGPUVersion==2) - PSXDisplay.DisplayPosition.y = (short)((gdata>>12)&0x3ff); - else PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x3ff); - } - else PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x1ff); - - // store the same val in some helper var, we need it on later compares - PreviousPSXDisplay.DisplayModeNew.x=PSXDisplay.DisplayPosition.y; - - if((PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayMode.y)>iGPUHeight) - { - int dy1=iGPUHeight-PSXDisplay.DisplayPosition.y; - int dy2=(PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayMode.y)-iGPUHeight; - - if(dy1>=dy2) - { - PreviousPSXDisplay.DisplayModeNew.y=-dy2; - } - else - { - PSXDisplay.DisplayPosition.y=0; - PreviousPSXDisplay.DisplayModeNew.y=-dy1; - } - } - else PreviousPSXDisplay.DisplayModeNew.y=0; -// eon - - PSXDisplay.DisplayPosition.x = (short)(gdata & 0x3ff); - PSXDisplay.DisplayEnd.x= - PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; - PSXDisplay.DisplayEnd.y= - PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y + PreviousPSXDisplay.DisplayModeNew.y; - PreviousPSXDisplay.DisplayEnd.x= - PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; - PreviousPSXDisplay.DisplayEnd.y= - PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y + PreviousPSXDisplay.DisplayModeNew.y; - - bDoVSyncUpdate=TRUE; - - if (!(PSXDisplay.Interlaced)) // stupid frame skipping option - { - if(UseFrameSkip) updateDisplay(); - if(dwActFixes&64) bDoLazyUpdate=TRUE; - } - }return; - //--------------------------------------------------// - // setting width - case 0x06: - - PSXDisplay.Range.x0=(short)(gdata & 0x7ff); - PSXDisplay.Range.x1=(short)((gdata>>12) & 0xfff); - - PSXDisplay.Range.x1-=PSXDisplay.Range.x0; - - ChangeDispOffsetsX(); - - return; - //--------------------------------------------------// - // setting height - case 0x07: - { - - PSXDisplay.Range.y0=(short)(gdata & 0x3ff); - PSXDisplay.Range.y1=(short)((gdata>>10) & 0x3ff); - - PreviousPSXDisplay.Height = PSXDisplay.Height; - - PSXDisplay.Height = PSXDisplay.Range.y1 - - PSXDisplay.Range.y0 + - PreviousPSXDisplay.DisplayModeNew.y; - - if(PreviousPSXDisplay.Height!=PSXDisplay.Height) - { - PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double; - - ChangeDispOffsetsY(); - - updateDisplayIfChanged(); - } - return; - } - //--------------------------------------------------// - // setting display infos - case 0x08: - - PSXDisplay.DisplayModeNew.x = - sDispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)]; - - if (gdata&0x04) PSXDisplay.Double=2; - else PSXDisplay.Double=1; - - PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double; - - ChangeDispOffsetsY(); - - PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC - PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor - PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace - - lGPUstatusRet&=~GPUSTATUS_WIDTHBITS; // Clear the width bits - lGPUstatusRet|= - (((gdata & 0x03) << 17) | - ((gdata & 0x40) << 10)); // Set the width bits - - if(PSXDisplay.InterlacedNew) - { - if(!PSXDisplay.Interlaced) - { - PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; - PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; - } - lGPUstatusRet|=GPUSTATUS_INTERLACED; - } - else lGPUstatusRet&=~GPUSTATUS_INTERLACED; - - if (PSXDisplay.PAL) - lGPUstatusRet|=GPUSTATUS_PAL; - else lGPUstatusRet&=~GPUSTATUS_PAL; - - if (PSXDisplay.Double==2) - lGPUstatusRet|=GPUSTATUS_DOUBLEHEIGHT; - else lGPUstatusRet&=~GPUSTATUS_DOUBLEHEIGHT; - - if (PSXDisplay.RGB24New) - lGPUstatusRet|=GPUSTATUS_RGB24; - else lGPUstatusRet&=~GPUSTATUS_RGB24; - - updateDisplayIfChanged(); - - return; - //--------------------------------------------------// - // ask about GPU version and other stuff - case 0x10: - - gdata&=0xff; - - switch(gdata) - { - case 0x02: - lGPUdataRet=lGPUInfoVals[INFO_TW]; // tw infos - return; - case 0x03: - lGPUdataRet=lGPUInfoVals[INFO_DRAWSTART]; // draw start - return; - case 0x04: - lGPUdataRet=lGPUInfoVals[INFO_DRAWEND]; // draw end - return; - case 0x05: - case 0x06: - lGPUdataRet=lGPUInfoVals[INFO_DRAWOFF]; // draw offset - return; - case 0x07: - if(dwGPUVersion==2) - lGPUdataRet=0x01; - else lGPUdataRet=0x02; // gpu type - return; - case 0x08: - case 0x0F: // some bios addr? - lGPUdataRet=0xBFC03720; - return; - } - return; - //--------------------------------------------------// - } -} - -//////////////////////////////////////////////////////////////////////// -// vram read/write helpers, needed by LEWPY's optimized vram read/write :) -//////////////////////////////////////////////////////////////////////// - -static __inline void FinishedVRAMWrite(void) -{ -/* -// NEWX - if(!PSXDisplay.Interlaced && UseFrameSkip) // stupid frame skipping - { - VRAMWrite.Width +=VRAMWrite.x; - VRAMWrite.Height+=VRAMWrite.y; - if(VRAMWrite.x=PSXDisplay.DisplayPosition.x && - VRAMWrite.y=PSXDisplay.DisplayPosition.y) - updateDisplay(); - } -*/ - - // Set register to NORMAL operation - DataWriteMode = DR_NORMAL; - // Reset transfer values, to prevent mis-transfer of data - VRAMWrite.x = 0; - VRAMWrite.y = 0; - VRAMWrite.Width = 0; - VRAMWrite.Height = 0; - VRAMWrite.ColsRemaining = 0; - VRAMWrite.RowsRemaining = 0; -} - -static __inline void FinishedVRAMRead(void) -{ - // Set register to NORMAL operation - DataReadMode = DR_NORMAL; - // Reset transfer values, to prevent mis-transfer of data - VRAMRead.x = 0; - VRAMRead.y = 0; - VRAMRead.Width = 0; - VRAMRead.Height = 0; - VRAMRead.ColsRemaining = 0; - VRAMRead.RowsRemaining = 0; - - // Indicate GPU is no longer ready for VRAM data in the STATUS REGISTER - lGPUstatusRet&=~GPUSTATUS_READYFORVRAM; -} - -//////////////////////////////////////////////////////////////////////// -// core read from vram -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUreadDataMem(uint32_t * pMem, int iSize) -{ - int i; - - if(DataReadMode!=DR_VRAMTRANSFER) return; - - GPUIsBusy; - - // adjust read ptr, if necessary - while(VRAMRead.ImagePtr>=psxVuw_eom) - VRAMRead.ImagePtr-=iGPUHeight*1024; - while(VRAMRead.ImagePtr 0) && (VRAMRead.RowsRemaining > 0)) - { - // lower 16 bit - lGPUdataRet=(uint32_t)GETLE16(VRAMRead.ImagePtr); - - VRAMRead.ImagePtr++; - if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; - VRAMRead.RowsRemaining --; - - if(VRAMRead.RowsRemaining<=0) - { - VRAMRead.RowsRemaining = VRAMRead.Width; - VRAMRead.ColsRemaining--; - VRAMRead.ImagePtr += 1024 - VRAMRead.Width; - if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; - } - - // higher 16 bit (always, even if it's an odd width) - lGPUdataRet|=(uint32_t)GETLE16(VRAMRead.ImagePtr)<<16; - PUTLE32(pMem, lGPUdataRet); pMem++; - - if(VRAMRead.ColsRemaining <= 0) - {FinishedVRAMRead();goto ENDREAD;} - - VRAMRead.ImagePtr++; - if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; - VRAMRead.RowsRemaining--; - if(VRAMRead.RowsRemaining<=0) - { - VRAMRead.RowsRemaining = VRAMRead.Width; - VRAMRead.ColsRemaining--; - VRAMRead.ImagePtr += 1024 - VRAMRead.Width; - if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; - } - if(VRAMRead.ColsRemaining <= 0) - {FinishedVRAMRead();goto ENDREAD;} - } - else {FinishedVRAMRead();goto ENDREAD;} - } - -ENDREAD: - GPUIsIdle; -} - - -//////////////////////////////////////////////////////////////////////// - -uint32_t CALLBACK GPUreadData(void) -{ - uint32_t l; - GPUreadDataMem(&l,1); - return 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; - GPUIsBusy; - GPUIsNotReadyForCommands; - -STARTVRAM: - - if(DataWriteMode==DR_VRAMTRANSFER) - { - BOOL bFinished=FALSE; - - // make sure we are in vram - while(VRAMWrite.ImagePtr>=psxVuw_eom) - VRAMWrite.ImagePtr-=iGPUHeight*1024; - while(VRAMWrite.ImagePtr0) - { - while(VRAMWrite.RowsRemaining>0) - { - if(i>=iSize) {goto ENDVRAM;} - i++; - - gdata=GETLE32(pMem); pMem++; - - PUTLE16(VRAMWrite.ImagePtr, (unsigned short)gdata); VRAMWrite.ImagePtr++; - if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; - VRAMWrite.RowsRemaining --; - - if(VRAMWrite.RowsRemaining <= 0) - { - VRAMWrite.ColsRemaining--; - if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width - { - gdata=(gdata&0xFFFF)|(((uint32_t)GETLE16(VRAMWrite.ImagePtr))<<16); - FinishedVRAMWrite(); - bDoVSyncUpdate=TRUE; - goto ENDVRAM; - } - VRAMWrite.RowsRemaining = VRAMWrite.Width; - VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; - } - - PUTLE16(VRAMWrite.ImagePtr, (unsigned short)(gdata>>16)); VRAMWrite.ImagePtr++; - if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; - VRAMWrite.RowsRemaining --; - } - - VRAMWrite.RowsRemaining = VRAMWrite.Width; - VRAMWrite.ColsRemaining--; - VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; - bFinished=TRUE; - } - - FinishedVRAMWrite(); - if(bFinished) bDoVSyncUpdate=TRUE; - } - -ENDVRAM: - - if(DataWriteMode==DR_NORMAL) - { - void (* *primFunc)(unsigned char *); - if(bSkipNextFrame) primFunc=primTableSkip; - else primFunc=primTableJ; - - for(;i>24) & 0xff); - -//if(command>=0xb0 && command<0xc0) auxprintf("b0 %x!!!!!!!!!\n",command); - - if(primTableCX[command]) - { - gpuDataC = primTableCX[command]; - gpuCommand = command; - PUTLE32(&gpuDataM[0], gdata); - gpuDataP = 1; - } - else continue; - } - else - { - PUTLE32(&gpuDataM[gpuDataP], gdata); - if(gpuDataC>128) - { - if((gpuDataC==254 && gpuDataP>=3) || - (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1))) - { - if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000) - gpuDataP=gpuDataC-1; - } - } - gpuDataP++; - } - - if(gpuDataP == gpuDataC) - { - gpuDataC=gpuDataP=0; - primFunc[gpuCommand]((unsigned char *)gpuDataM); - if(dwEmuFixes&0x0001 || dwActFixes&0x0400) // hack for emulating "gpu busy" in some games - iFakePrimBusy=4; - } - } - } - - lGPUdataRet=gdata; - - GPUIsReadyForCommands; - GPUIsIdle; -} - -//////////////////////////////////////////////////////////////////////// - -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 -//////////////////////////////////////////////////////////////////////// - -#if 0 -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(DataWriteMode==DR_VRAMTRANSFER) iT|=0x1; - if(DataReadMode ==DR_VRAMTRANSFER) iT|=0x2; - return iT; -} -#endif - -//////////////////////////////////////////////////////////////////////// -// call config dlg -//////////////////////////////////////////////////////////////////////// - -long CALLBACK GPUconfigure(void) -{ -#ifdef _WINDOWS - HWND hWP=GetActiveWindow(); - - DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGSOFT), - hWP,(DLGPROC)SoftDlgProc); -#else - SoftDlgProc(); -#endif - - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// sets all kind of act fixes -//////////////////////////////////////////////////////////////////////// - -void SetFixes(void) - { -#ifdef _WINDOWS - BOOL bOldPerformanceCounter=IsPerformanceCounter; // store curr timer mode - - if(dwActFixes&0x10) // check fix 0x10 - IsPerformanceCounter=FALSE; - else SetFPSHandler(); - - if(bOldPerformanceCounter!=IsPerformanceCounter) // we have change it? - InitFPS(); // -> init fps again -#endif - - if(dwActFixes&0x02) sDispWidths[4]=384; - else sDispWidths[4]=368; - } - -//////////////////////////////////////////////////////////////////////// -// process gpu commands -//////////////////////////////////////////////////////////////////////// - -unsigned long lUsedAddr[3]; - -static __inline BOOL CheckForEndlessLoop(unsigned long laddr) -{ - if(laddr==lUsedAddr[1]) return TRUE; - if(laddr==lUsedAddr[2]) return TRUE; - - if(laddr 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); - - GPUIsIdle; - - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// show about dlg -//////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS -BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch(uMsg) - { - case WM_COMMAND: - { - switch(LOWORD(wParam)) - {case IDOK: EndDialog(hW,TRUE);return TRUE;} - } - } - return FALSE; -} -#endif - -void CALLBACK GPUabout(void) // ABOUT -{ -#ifdef _WINDOWS - HWND hWP=GetActiveWindow(); // to be sure - DialogBox(hInst,MAKEINTRESOURCE(IDD_ABOUT), - hWP,(DLGPROC)AboutDlgProc); -#else - AboutDlgProc(); -#endif - - 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 -//////////////////////////////////////////////////////////////////////// - -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; - 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=lGPUstatusRet; - memcpy(pF->ulControl,ulStatusControl,256*sizeof(uint32_t)); - memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2); - - return 1; - } - - if(ulGetFreezeData!=0) return 0; // 0: set data - - lGPUstatusRet=pF->ulStatus; - memcpy(ulStatusControl,pF->ulControl,256*sizeof(uint32_t)); - memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2); - -// RESET TEXTURE STORE HERE, IF YOU USE SOMETHING LIKE THAT - - GPUwriteStatus(ulStatusControl[0]); - GPUwriteStatus(ulStatusControl[1]); - GPUwriteStatus(ulStatusControl[2]); - GPUwriteStatus(ulStatusControl[3]); - GPUwriteStatus(ulStatusControl[8]); // try to repair things - GPUwriteStatus(ulStatusControl[6]); - GPUwriteStatus(ulStatusControl[7]); - GPUwriteStatus(ulStatusControl[5]); - GPUwriteStatus(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 -} -}; - -//////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS /* used by commmented out linux version as well */ - -static 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 -} -#endif - -//////////////////////////////////////////////////////////////////////// -// 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 - -#ifdef _WINDOWS - -long CALLBACK GPUgetScreenPic(unsigned char * pMem) -{ - HRESULT ddrval;DDSURFACEDESC xddsd;unsigned char * pf; - int x,y,c,v;RECT r; - float XS,YS; - - memset(&xddsd, 0, sizeof(DDSURFACEDESC)); - xddsd.dwSize = sizeof(DDSURFACEDESC); - xddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; - xddsd.dwWidth = iResX; - xddsd.dwHeight = iResY; - - r.left=0; r.right =iResX; - r.top=0; r.bottom=iResY; - - if(iWindowMode) - { - POINT Point={0,0}; - ClientToScreen(DX.hWnd,&Point); - r.left+=Point.x;r.right+=Point.x; - r.top+=Point.y;r.bottom+=Point.y; - } - - XS=(float)iResX/128; - YS=(float)iResY/96; - - ddrval=IDirectDrawSurface_Lock(DX.DDSPrimary,NULL, &xddsd, DDLOCK_WAIT|DDLOCK_READONLY, NULL); - - if(ddrval==DDERR_SURFACELOST) IDirectDrawSurface_Restore(DX.DDSPrimary); - - pf=pMem; - - if(ddrval==DD_OK) - { - unsigned char * ps=(unsigned char *)xddsd.lpSurface; - - if(iDesktopCol==16) - { - unsigned short sx; - for(y=0;y<96;y++) - { - for(x=0;x<128;x++) - { - sx=*((unsigned short *)((ps)+ - r.top*xddsd.lPitch+ - (((int)((float)y*YS))*xddsd.lPitch)+ - r.left*2+ - ((int)((float)x*XS))*2)); - *(pf+0)=(sx&0x1f)<<3; - *(pf+1)=(sx&0x7e0)>>3; - *(pf+2)=(sx&0xf800)>>8; - pf+=3; - } - } - } - else - if(iDesktopCol==15) - { - unsigned short sx; - for(y=0;y<96;y++) - { - for(x=0;x<128;x++) - { - sx=*((unsigned short *)((ps)+ - r.top*xddsd.lPitch+ - (((int)((float)y*YS))*xddsd.lPitch)+ - r.left*2+ - ((int)((float)x*XS))*2)); - *(pf+0)=(sx&0x1f)<<3; - *(pf+1)=(sx&0x3e0)>>2; - *(pf+2)=(sx&0x7c00)>>7; - pf+=3; - } - } - } - else - { - unsigned long sx; - for(y=0;y<96;y++) - { - for(x=0;x<128;x++) - { - sx=*((unsigned long *)((ps)+ - r.top*xddsd.lPitch+ - (((int)((float)y*YS))*xddsd.lPitch)+ - r.left*4+ - ((int)((float)x*XS))*4)); - *(pf+0)=(unsigned char)((sx&0xff)); - *(pf+1)=(unsigned char)((sx&0xff00)>>8); - *(pf+2)=(unsigned char)((sx&0xff0000)>>16); - pf+=3; - } - } - } - } - - IDirectDrawSurface_Unlock(DX.DDSPrimary,&xddsd); - - ///////////////////////////////////////////////////////////////////// - // 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) - v=(c&0xc0)>>6; - PaintPicDot(pf,(unsigned char)v);pf+=3; // paint the dots into the rect - v=(c&0x30)>>4; - PaintPicDot(pf,(unsigned char)v);pf+=3; - v=(c&0x0c)>>2; - PaintPicDot(pf,(unsigned char)v);pf+=3; - v=c&0x03; - PaintPicDot(pf,(unsigned char)v);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 - } - return 0; -} - -#else - -// LINUX version: - -long GPUgetScreenPic(unsigned char * pMem) -{ - return -1; -/* - 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 - } - return 0; -*/ -} - -#endif - -//////////////////////////////////////////////////////////////////////// -// 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 - -long CALLBACK GPUshowScreenPic(unsigned char * pMem) -{ - DestroyPic(); // destroy old pic data - if(pMem==0) return 0; // done - CreatePic(pMem); // create new pic... don't free pMem or something like that... just read from it - return 0; -} - -#if 0 -void CALLBACK GPUsetfix(uint32_t dwFixBits) -{ - dwEmuFixes=dwFixBits; -} -#endif - -void CALLBACK GPUvBlank( int val ) -{ - vBlank = val; -} - -void CALLBACK GPUvisualVibration(uint32_t iSmall, uint32_t iBig) -{ - int iVibVal; - - if(PreviousPSXDisplay.DisplayMode.x) // calc min "shake pixel" from screen width - iVibVal=max(1,iResX/PreviousPSXDisplay.DisplayMode.x); - else iVibVal=1; - // big rumble: 4...15 sp ; small rumble 1...3 sp - if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig *iVibVal)/10)); - else iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10)); - - iRumbleTime=15; // let the rumble last 16 buffer swaps -} +/*************************************************************************** + gpu.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. * + * * + ***************************************************************************/ + +#if !defined(_MACGL) && !defined(_WINDOWS) +#include "config.h" +#endif + +#define _IN_GPU + +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "cfg.h" +#include "prim.h" +#include "stdint.h" +#include "psemu_plugin_defs.h" +#include "menu.h" +#include "key.h" +#include "fps.h" +#include "swap.h" + +#ifdef ENABLE_NLS +#include +#include +#define _(x) gettext(x) +#define N_(x) (x) +#else +#define _(x) (x) +#define N_(x) (x) +#endif + +#ifdef _WINDOWS +#include "resource.h" +#include "record.h" +#endif + +//////////////////////////////////////////////////////////////////////// +// PPDK developer must change libraryName field and can change revision and build +//////////////////////////////////////////////////////////////////////// + +const unsigned char version = 1; // do not touch - library for PSEmu 1.x +const unsigned char revision = 1; +const unsigned char build = 17; // increase that with each version + +#if defined (_WINDOWS) +static char *libraryName = N_("Soft Driver"); +static char *libraryInfo = N_("P.E.Op.S. Soft Driver V1.17\nCoded by Pete Bernert and the P.E.Op.S. team\n"); +#elif defined (_MACGL) +static char *libraryName = N_("SoftGL Driver"); +static char *libraryInfo = N_("P.E.Op.S. SoftGL Driver V1.17\nCoded by Pete Bernert and the P.E.Op.S. team\n"); +#else +static char *libraryName = N_("XVideo Driver"); +static char *libraryInfo = N_("P.E.Op.S. Xvideo Driver V1.17\nCoded by Pete Bernert and the P.E.Op.S. team\n"); +#endif + +static char *PluginAuthor = N_("Pete Bernert and the P.E.Op.S. team"); + +//////////////////////////////////////////////////////////////////////// +// memory image of the PSX vram +//////////////////////////////////////////////////////////////////////// + +unsigned char *psxVSecure; +unsigned char *psxVub; +signed char *psxVsb; +unsigned short *psxVuw; +unsigned short *psxVuw_eom; +signed short *psxVsw; +uint32_t *psxVul; +int32_t *psxVsl; + +//////////////////////////////////////////////////////////////////////// +// GPU globals +//////////////////////////////////////////////////////////////////////// + +static long lGPUdataRet; +long lGPUstatusRet; +char szDispBuf[64]; +char szMenuBuf[36]; +char szDebugText[512]; +uint32_t ulStatusControl[256]; + +static uint32_t gpuDataM[256]; +static unsigned char gpuCommand = 0; +static long gpuDataC = 0; +static long gpuDataP = 0; + +VRAMLoad_t VRAMWrite; +VRAMLoad_t VRAMRead; +DATAREGISTERMODES DataWriteMode; +DATAREGISTERMODES DataReadMode; + +BOOL bSkipNextFrame = FALSE; +DWORD dwLaceCnt=0; +int iColDepth; +int iWindowMode; +short sDispWidths[8] = {256,320,512,640,368,384,512,640}; +PSXDisplay_t PSXDisplay; +PSXDisplay_t PreviousPSXDisplay; +long lSelectedSlot=0; +BOOL bChangeWinMode=FALSE; +BOOL bDoLazyUpdate=FALSE; +uint32_t lGPUInfoVals[16]; +static int iFakePrimBusy=0; +uint32_t vBlank=0; +int iRumbleVal=0; +int iRumbleTime=0; + +#ifdef _WINDOWS + +//////////////////////////////////////////////////////////////////////// +// screensaver stuff: dynamically load kernel32.dll to avoid export dependeny +//////////////////////////////////////////////////////////////////////// + +int iStopSaver=0; +HINSTANCE kernel32LibHandle = NULL; + +// A stub function, that does nothing .... but it does "nothing" well :) +EXECUTION_STATE WINAPI STUB_SetThreadExecutionState(EXECUTION_STATE esFlags) +{ + return esFlags; +} + +// The dynamic version of the system call is prepended with a "D_" +EXECUTION_STATE (WINAPI *D_SetThreadExecutionState)(EXECUTION_STATE esFlags) = STUB_SetThreadExecutionState; + +BOOL LoadKernel32(void) +{ + // Get a handle to the kernel32.dll (which is actually already loaded) + kernel32LibHandle = LoadLibrary("kernel32.dll"); + + // If we've got a handle, then locate the entry point for the SetThreadExecutionState function + if (kernel32LibHandle != NULL) + { + if ((D_SetThreadExecutionState = (EXECUTION_STATE (WINAPI *)(EXECUTION_STATE))GetProcAddress (kernel32LibHandle, "SetThreadExecutionState")) == NULL) + D_SetThreadExecutionState = STUB_SetThreadExecutionState; + } + + return TRUE; +} + +BOOL FreeKernel32(void) +{ + // Release the handle to kernel32.dll + if (kernel32LibHandle != NULL) + FreeLibrary(kernel32LibHandle); + + // Set to stub function, to avoid nasty suprises if called :) + D_SetThreadExecutionState = STUB_SetThreadExecutionState; + + return TRUE; +} +#else + +// Linux: Stub the functions +BOOL LoadKernel32(void) +{ + return TRUE; +} + +BOOL FreeKernel32(void) +{ + return TRUE; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// some misc external display funcs +//////////////////////////////////////////////////////////////////////// + +#include +time_t tStart; + +void CALLBACK GPUdisplayText(char * pText) // some debug func +{ + if(!pText) {szDebugText[0]=0;return;} + if(strlen(pText)>511) return; + time(&tStart); + strcpy(szDebugText,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; +} + +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); + //----------------------------------------------------// + if(iCfg && iWindowMode) + sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize)); + else + sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY); + 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; +} + +static void DoTextSnapShot(int iNum) +{ + FILE *txtfile; + char szTxt[256]; + char *pB; + +#ifdef _WINDOWS + sprintf(szTxt,"snap\\pcsx%04d.txt",iNum); +#else + sprintf(szTxt,"%s/pcsx%04d.txt",getenv("HOME"),iNum); +#endif + + if ((txtfile = fopen(szTxt, "wb")) == NULL) + return; + + pB = pGetConfigInfos(0); + if (pB) + { + fwrite(pB, strlen(pB), 1, txtfile); + free(pB); + } + fclose(txtfile); +} + +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 = 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] = PreviousPSXDisplay.Range.x1 % 256; + header[0x13] = 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() // GPU INIT +{ + memset(ulStatusControl,0,256*sizeof(uint32_t)); // init save state scontrol field + + szDebugText[0] = 0; // init debug text buffer + + psxVSecure = (unsigned char *)malloc((iGPUHeight*2)*1024 + (1024*1024)); // always alloc one extra MB for soft drawing funcs security + if (!psxVSecure) + return -1; + + //!!! ATTENTION !!! + psxVub=psxVSecure + 512 * 1024; // security offset into double sized psx vram! + + psxVsb=(signed char *)psxVub; // different ways of accessing PSX VRAM + psxVsw=(signed short *)psxVub; + psxVsl=(int32_t *)psxVub; + psxVuw=(unsigned short *)psxVub; + psxVul=(uint32_t *)psxVub; + + psxVuw_eom=psxVuw+1024*iGPUHeight; // pre-calc of end of vram + + memset(psxVSecure,0x00,(iGPUHeight*2)*1024 + (1024*1024)); + memset(lGPUInfoVals,0x00,16*sizeof(uint32_t)); + + SetFPSHandler(); + + PSXDisplay.RGB24 = FALSE; // init some stuff + PSXDisplay.Interlaced = FALSE; + PSXDisplay.DrawOffset.x = 0; + PSXDisplay.DrawOffset.y = 0; + PSXDisplay.DisplayMode.x= 320; + PSXDisplay.DisplayMode.y= 240; + PreviousPSXDisplay.DisplayMode.x= 320; + PreviousPSXDisplay.DisplayMode.y= 240; + PSXDisplay.Disabled = FALSE; + PreviousPSXDisplay.Range.x0 =0; + PreviousPSXDisplay.Range.y0 =0; + PSXDisplay.Range.x0=0; + PSXDisplay.Range.x1=0; + PreviousPSXDisplay.DisplayModeNew.y=0; + PSXDisplay.Double = 1; + lGPUdataRet = 0x400; + + DataWriteMode = DR_NORMAL; + + // Reset transfer values, to prevent mis-transfer of data + memset(&VRAMWrite, 0, sizeof(VRAMLoad_t)); + memset(&VRAMRead, 0, sizeof(VRAMLoad_t)); + + // device initialised already ! + lGPUstatusRet = 0x14802000; + GPUIsIdle; + GPUIsReadyForCommands; + bDoVSyncUpdate = TRUE; + vBlank = 0; + + // Get a handle for kernel32.dll, and access the required export function + LoadKernel32(); + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// Here starts all... +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUopen(HWND hwndGPU) // GPU OPEN +{ + hWGPU = hwndGPU; // store hwnd + + SetKeyHandler(); // sub-class window + + if(bChangeWinMode) ReadWinSizeConfig(); // alt+enter toggle? + else // or first time startup? + { + ReadConfig(); // read registry + InitFPS(); + } + + bIsFirstFrame = TRUE; // we have to init later + bDoVSyncUpdate = TRUE; + + ulInitDisplay(); // setup direct draw + + if(iStopSaver) + D_SetThreadExecutionState(ES_SYSTEM_REQUIRED|ES_DISPLAY_REQUIRED|ES_CONTINUOUS); + + + return 0; +} + +#else + +long GPUopen(unsigned long * disp,char * CapText,char * CfgFile) +{ + unsigned long d; + + pCaptionText=CapText; + + + ReadConfig(); // read registry + + InitFPS(); + + bIsFirstFrame = TRUE; // we have to init later + bDoVSyncUpdate = TRUE; + + d=ulInitDisplay(); // setup x + + if(disp) + *disp=d; // wanna x pointer? ok + + if(d) return 0; + return -1; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// time to leave... +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUclose() // GPU CLOSE +{ +#ifdef _WINDOWS + if(RECORD_RECORDING==TRUE) {RECORD_Stop();RECORD_RECORDING=FALSE;BuildDispMenu(0);} +#endif + + ReleaseKeyHandler(); // de-subclass window + + CloseDisplay(); // shutdown direct draw + +#ifdef _WINDOWS + if(iStopSaver) + D_SetThreadExecutionState(ES_SYSTEM_REQUIRED|ES_DISPLAY_REQUIRED); +#endif + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// I shot the sheriff +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUshutdown() // GPU SHUTDOWN +{ + // screensaver: release the handle for kernel32.dll + FreeKernel32(); + + free(psxVSecure); + + return 0; // nothinh to do +} + +//////////////////////////////////////////////////////////////////////// +// Update display (swap buffers) +//////////////////////////////////////////////////////////////////////// + +void updateDisplay(void) // UPDATE DISPLAY +{ + if(PSXDisplay.Disabled) // disable? + { + DoClearFrontBuffer(); // -> clear frontbuffer + return; // -> and bye + } + + if(dwActFixes&32) // pc fps calculation fix + { + if(UseFrameLimit) PCFrameCap(); // -> brake + if(UseFrameSkip || ulKeybits&KEY_SHOWFPS) + PCcalcfps(); + } + + if(ulKeybits&KEY_SHOWFPS) // make fps display buf + { + sprintf(szDispBuf,"FPS %06.1f",fps_cur); + } + + if(iFastFwd) // fastfwd ? + { + static int fpscount; UseFrameSkip=1; + + if(!bSkipNextFrame) DoBufferSwap(); // -> to skip or not to skip + if(fpscount%6) // -> skip 6/7 frames + bSkipNextFrame = TRUE; + else bSkipNextFrame = FALSE; + fpscount++; + if(fpscount >= (int)fFrameRateHz) fpscount = 0; + return; + } + + if(UseFrameSkip) // skip ? + { + if(!bSkipNextFrame) DoBufferSwap(); // -> to skip or not to skip + if(dwActFixes&0xa0) // -> pc fps calculation fix/old skipping fix + { + if((fps_skip < fFrameRateHz) && !(bSkipNextFrame)) // -> skip max one in a row + {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;} + else bSkipNextFrame = FALSE; + } + else FrameSkip(); + } + else // no skip ? + { + DoBufferSwap(); // -> swap + } +} + +//////////////////////////////////////////////////////////////////////// +// roughly emulated screen centering bits... not complete !!! +//////////////////////////////////////////////////////////////////////// + +void ChangeDispOffsetsX(void) // X CENTER +{ + long lx,l; + + if(!PSXDisplay.Range.x1) return; + + l=PreviousPSXDisplay.DisplayMode.x; + + l*=(long)PSXDisplay.Range.x1; + l/=2560;lx=l;l&=0xfffffff8; + + if(l==PreviousPSXDisplay.Range.y1) return; // abusing range.y1 for + PreviousPSXDisplay.Range.y1=(short)l; // storing last x range and test + + if(lx>=PreviousPSXDisplay.DisplayMode.x) + { + PreviousPSXDisplay.Range.x1= + (short)PreviousPSXDisplay.DisplayMode.x; + PreviousPSXDisplay.Range.x0=0; + } + else + { + PreviousPSXDisplay.Range.x1=(short)l; + + PreviousPSXDisplay.Range.x0= + (PSXDisplay.Range.x0-500)/8; + + if(PreviousPSXDisplay.Range.x0<0) + PreviousPSXDisplay.Range.x0=0; + + if((PreviousPSXDisplay.Range.x0+lx)> + PreviousPSXDisplay.DisplayMode.x) + { + PreviousPSXDisplay.Range.x0= + (short)(PreviousPSXDisplay.DisplayMode.x-lx); + PreviousPSXDisplay.Range.x0+=2; //??? + + PreviousPSXDisplay.Range.x1+=(short)(lx-l); + +#ifndef _WINDOWS + PreviousPSXDisplay.Range.x1-=2; // makes linux stretching easier +#endif + } + +#ifndef _WINDOWS + // some linux alignment security + PreviousPSXDisplay.Range.x0=PreviousPSXDisplay.Range.x0>>1; + PreviousPSXDisplay.Range.x0=PreviousPSXDisplay.Range.x0<<1; + PreviousPSXDisplay.Range.x1=PreviousPSXDisplay.Range.x1>>1; + PreviousPSXDisplay.Range.x1=PreviousPSXDisplay.Range.x1<<1; +#endif + + DoClearScreenBuffer(); + } + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +void ChangeDispOffsetsY(void) // Y CENTER +{ + int iT,iO=PreviousPSXDisplay.Range.y0; + int iOldYOffset=PreviousPSXDisplay.DisplayModeNew.y; + +// new + + if((PreviousPSXDisplay.DisplayModeNew.x+PSXDisplay.DisplayModeNew.y)>iGPUHeight) + { + int dy1=iGPUHeight-PreviousPSXDisplay.DisplayModeNew.x; + int dy2=(PreviousPSXDisplay.DisplayModeNew.x+PSXDisplay.DisplayModeNew.y)-iGPUHeight; + + if(dy1>=dy2) + { + PreviousPSXDisplay.DisplayModeNew.y=-dy2; + } + else + { + PSXDisplay.DisplayPosition.y=0; + PreviousPSXDisplay.DisplayModeNew.y=-dy1; + } + } + else PreviousPSXDisplay.DisplayModeNew.y=0; + +// eon + + if(PreviousPSXDisplay.DisplayModeNew.y!=iOldYOffset) // if old offset!=new offset: recalc height + { + PSXDisplay.Height = PSXDisplay.Range.y1 - + PSXDisplay.Range.y0 + + PreviousPSXDisplay.DisplayModeNew.y; + PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double; + } + +// + + if(PSXDisplay.PAL) iT=48; else iT=28; + + if(PSXDisplay.Range.y0>=iT) + { + PreviousPSXDisplay.Range.y0= + (short)((PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double); + if(PreviousPSXDisplay.Range.y0<0) + PreviousPSXDisplay.Range.y0=0; + PSXDisplay.DisplayModeNew.y+= + PreviousPSXDisplay.Range.y0; + } + else + PreviousPSXDisplay.Range.y0=0; + + if(iO!=PreviousPSXDisplay.Range.y0) + { + DoClearScreenBuffer(); + } +} + +//////////////////////////////////////////////////////////////////////// +// check if update needed +//////////////////////////////////////////////////////////////////////// + +void updateDisplayIfChanged(void) // UPDATE DISPLAY IF CHANGED +{ + if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) && + (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x)) + { + if((PSXDisplay.RGB24 == PSXDisplay.RGB24New) && + (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew)) return; + } + + PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos + + PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y; + PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x; + PreviousPSXDisplay.DisplayMode.x= // previous will hold + min(640,PSXDisplay.DisplayMode.x); // max 640x512... that's + PreviousPSXDisplay.DisplayMode.y= // the size of my + min(512,PSXDisplay.DisplayMode.y); // back buffer surface + PSXDisplay.Interlaced = PSXDisplay.InterlacedNew; + + PSXDisplay.DisplayEnd.x= // calc end of display + PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PSXDisplay.DisplayEnd.y= + PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + PreviousPSXDisplay.DisplayEnd.x= + PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PreviousPSXDisplay.DisplayEnd.y= + PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + + ChangeDispOffsetsX(); + + if(iFrameLimit==2) SetAutoFrameCap(); // -> set it + + if(UseFrameSkip) updateDisplay(); // stupid stuff when frame skipping enabled +} + +//////////////////////////////////////////////////////////////////////// + +#if defined(_WINDOWS) + +void ChangeWindowMode(void) // TOGGLE FULLSCREEN - WINDOW +{ + GPUclose(); + iWindowMode=!iWindowMode; + GPUopen(hWGPU); + bChangeWinMode=FALSE; + bDoVSyncUpdate=TRUE; +} + +#elif !defined (_MACGL) + +#include "draw.h" + +void ChangeWindowMode(void) // TOGGLE FULLSCREEN - WINDOW +{ + 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=FALSE; + bDoVSyncUpdate=TRUE; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// gun cursor func: player=0-7, x=0-511, y=0-255 +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUcursor(int iPlayer,int x,int y) +{ + if(iPlayer<0) return; + if(iPlayer>7) return; + + usCursorActive|=(1<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 +{ + //if(!(dwActFixes&1)) + //lGPUstatusRet^=0x80000000; // odd/even bit + + if(!(dwActFixes&32)) // std fps limitation? + CheckFrameRate(); + + if(PSXDisplay.Interlaced) // interlaced mode? + { + lGPUstatusRet^=0x80000000; + if(bDoVSyncUpdate && PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0) + { + updateDisplay(); + } + } + else // non-interlaced? + { + if(dwActFixes&64) // lazy screen update fix + { + if(bDoLazyUpdate && !UseFrameSkip) + updateDisplay(); + bDoLazyUpdate=FALSE; + } + else + { + if(bDoVSyncUpdate && !UseFrameSkip) // some primitives drawn? + updateDisplay(); // -> update display + } + } + +#ifdef _WINDOWS + if(RECORD_RECORDING) + if(RECORD_WriteFrame()==FALSE) + {RECORD_RECORDING=FALSE;RECORD_Stop();} +#endif + +#ifndef _MACGL + if(bChangeWinMode) ChangeWindowMode(); // toggle full - window mode +#endif + + bDoVSyncUpdate=FALSE; // vsync done +} + +//////////////////////////////////////////////////////////////////////// +// process read request from GPU status register +//////////////////////////////////////////////////////////////////////// + + +uint32_t CALLBACK GPUreadStatus(void) // READ STATUS +{ + if(dwActFixes&1) + { + static int iNumRead=0; // odd/even hack + if((iNumRead++)==2) + { + iNumRead=0; + lGPUstatusRet^=0x80000000; // interlaced bit toggle... we do it on every 3 read status... needed by some games (like ChronoCross) with old epsxe versions (1.5.2 and older) + } + } + + if(iFakePrimBusy) // 27.10.2007 - PETE : emulating some 'busy' while drawing... pfff + { + iFakePrimBusy--; + + if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims + { + GPUIsBusy; + GPUIsNotReadyForCommands; + } + else + { + GPUIsIdle; + GPUIsReadyForCommands; + } + } + return lGPUstatusRet | (vBlank ? 0x80000000 : 0 ); +} + +//////////////////////////////////////////////////////////////////////// +// processes data send to GPU status register +// these are always single packet commands. +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUwriteStatus(uint32_t gdata) // WRITE STATUS +{ + uint32_t lCommand=(gdata>>24)&0xff; + + ulStatusControl[lCommand]=gdata; // store command for freezing + + switch(lCommand) + { + //--------------------------------------------------// + // reset gpu + case 0x00: + memset(lGPUInfoVals,0x00,16*sizeof(uint32_t)); + lGPUstatusRet=0x14802000; + PSXDisplay.Disabled=1; + DataWriteMode=DataReadMode=DR_NORMAL; + PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0; + drawX=drawY=0;drawW=drawH=0; + sSetMask=0;lSetMask=0;bCheckMask=FALSE; + usMirror=0; + GlobalTextAddrX=0;GlobalTextAddrY=0; + GlobalTextTP=0;GlobalTextABR=0; + PSXDisplay.RGB24=FALSE; + PSXDisplay.Interlaced=FALSE; + bUsingTWin = FALSE; + return; + //--------------------------------------------------// + // dis/enable display + case 0x03: + + PreviousPSXDisplay.Disabled = PSXDisplay.Disabled; + PSXDisplay.Disabled = (gdata & 1); + + if(PSXDisplay.Disabled) + lGPUstatusRet|=GPUSTATUS_DISPLAYDISABLED; + else lGPUstatusRet&=~GPUSTATUS_DISPLAYDISABLED; + return; + + //--------------------------------------------------// + // setting transfer mode + case 0x04: + gdata &= 0x03; // Only want the lower two bits + + DataWriteMode=DataReadMode=DR_NORMAL; + if(gdata==0x02) DataWriteMode=DR_VRAMTRANSFER; + if(gdata==0x03) DataReadMode =DR_VRAMTRANSFER; + lGPUstatusRet&=~GPUSTATUS_DMABITS; // Clear the current settings of the DMA bits + lGPUstatusRet|=(gdata << 29); // Set the DMA bits according to the received data + + return; + //--------------------------------------------------// + // setting display position + case 0x05: + { + PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; + +//////// +/* + PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x3ff); + if (PSXDisplay.DisplayPosition.y & 0x200) + PSXDisplay.DisplayPosition.y |= 0xfffffc00; + if(PSXDisplay.DisplayPosition.y<0) + { + PreviousPSXDisplay.DisplayModeNew.y=PSXDisplay.DisplayPosition.y/PSXDisplay.Double; + PSXDisplay.DisplayPosition.y=0; + } + else PreviousPSXDisplay.DisplayModeNew.y=0; +*/ + +// new + if(iGPUHeight==1024) + { + if(dwGPUVersion==2) + PSXDisplay.DisplayPosition.y = (short)((gdata>>12)&0x3ff); + else PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x3ff); + } + else PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x1ff); + + // store the same val in some helper var, we need it on later compares + PreviousPSXDisplay.DisplayModeNew.x=PSXDisplay.DisplayPosition.y; + + if((PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayMode.y)>iGPUHeight) + { + int dy1=iGPUHeight-PSXDisplay.DisplayPosition.y; + int dy2=(PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayMode.y)-iGPUHeight; + + if(dy1>=dy2) + { + PreviousPSXDisplay.DisplayModeNew.y=-dy2; + } + else + { + PSXDisplay.DisplayPosition.y=0; + PreviousPSXDisplay.DisplayModeNew.y=-dy1; + } + } + else PreviousPSXDisplay.DisplayModeNew.y=0; +// eon + + PSXDisplay.DisplayPosition.x = (short)(gdata & 0x3ff); + PSXDisplay.DisplayEnd.x= + PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PSXDisplay.DisplayEnd.y= + PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y + PreviousPSXDisplay.DisplayModeNew.y; + PreviousPSXDisplay.DisplayEnd.x= + PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PreviousPSXDisplay.DisplayEnd.y= + PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y + PreviousPSXDisplay.DisplayModeNew.y; + + bDoVSyncUpdate=TRUE; + + if (!(PSXDisplay.Interlaced)) // stupid frame skipping option + { + if(UseFrameSkip) updateDisplay(); + if(dwActFixes&64) bDoLazyUpdate=TRUE; + } + }return; + //--------------------------------------------------// + // setting width + case 0x06: + + PSXDisplay.Range.x0=(short)(gdata & 0x7ff); + PSXDisplay.Range.x1=(short)((gdata>>12) & 0xfff); + + PSXDisplay.Range.x1-=PSXDisplay.Range.x0; + + ChangeDispOffsetsX(); + + return; + //--------------------------------------------------// + // setting height + case 0x07: + { + + PSXDisplay.Range.y0=(short)(gdata & 0x3ff); + PSXDisplay.Range.y1=(short)((gdata>>10) & 0x3ff); + + PreviousPSXDisplay.Height = PSXDisplay.Height; + + PSXDisplay.Height = PSXDisplay.Range.y1 - + PSXDisplay.Range.y0 + + PreviousPSXDisplay.DisplayModeNew.y; + + if(PreviousPSXDisplay.Height!=PSXDisplay.Height) + { + PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double; + + ChangeDispOffsetsY(); + + updateDisplayIfChanged(); + } + return; + } + //--------------------------------------------------// + // setting display infos + case 0x08: + + PSXDisplay.DisplayModeNew.x = + sDispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)]; + + if (gdata&0x04) PSXDisplay.Double=2; + else PSXDisplay.Double=1; + + PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double; + + ChangeDispOffsetsY(); + + PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC + PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor + PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace + + lGPUstatusRet&=~GPUSTATUS_WIDTHBITS; // Clear the width bits + lGPUstatusRet|= + (((gdata & 0x03) << 17) | + ((gdata & 0x40) << 10)); // Set the width bits + + if(PSXDisplay.InterlacedNew) + { + if(!PSXDisplay.Interlaced) + { + PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; + } + lGPUstatusRet|=GPUSTATUS_INTERLACED; + } + else lGPUstatusRet&=~GPUSTATUS_INTERLACED; + + if (PSXDisplay.PAL) + lGPUstatusRet|=GPUSTATUS_PAL; + else lGPUstatusRet&=~GPUSTATUS_PAL; + + if (PSXDisplay.Double==2) + lGPUstatusRet|=GPUSTATUS_DOUBLEHEIGHT; + else lGPUstatusRet&=~GPUSTATUS_DOUBLEHEIGHT; + + if (PSXDisplay.RGB24New) + lGPUstatusRet|=GPUSTATUS_RGB24; + else lGPUstatusRet&=~GPUSTATUS_RGB24; + + updateDisplayIfChanged(); + + return; + //--------------------------------------------------// + // ask about GPU version and other stuff + case 0x10: + + gdata&=0xff; + + switch(gdata) + { + case 0x02: + lGPUdataRet=lGPUInfoVals[INFO_TW]; // tw infos + return; + case 0x03: + lGPUdataRet=lGPUInfoVals[INFO_DRAWSTART]; // draw start + return; + case 0x04: + lGPUdataRet=lGPUInfoVals[INFO_DRAWEND]; // draw end + return; + case 0x05: + case 0x06: + lGPUdataRet=lGPUInfoVals[INFO_DRAWOFF]; // draw offset + return; + case 0x07: + if(dwGPUVersion==2) + lGPUdataRet=0x01; + else lGPUdataRet=0x02; // gpu type + return; + case 0x08: + case 0x0F: // some bios addr? + lGPUdataRet=0xBFC03720; + return; + } + return; + //--------------------------------------------------// + } +} + +//////////////////////////////////////////////////////////////////////// +// vram read/write helpers, needed by LEWPY's optimized vram read/write :) +//////////////////////////////////////////////////////////////////////// + +__inline void FinishedVRAMWrite(void) +{ +/* +// NEWX + if(!PSXDisplay.Interlaced && UseFrameSkip) // stupid frame skipping + { + VRAMWrite.Width +=VRAMWrite.x; + VRAMWrite.Height+=VRAMWrite.y; + if(VRAMWrite.x=PSXDisplay.DisplayPosition.x && + VRAMWrite.y=PSXDisplay.DisplayPosition.y) + updateDisplay(); + } +*/ + + // Set register to NORMAL operation + DataWriteMode = DR_NORMAL; + // Reset transfer values, to prevent mis-transfer of data + VRAMWrite.x = 0; + VRAMWrite.y = 0; + VRAMWrite.Width = 0; + VRAMWrite.Height = 0; + VRAMWrite.ColsRemaining = 0; + VRAMWrite.RowsRemaining = 0; +} + +__inline void FinishedVRAMRead(void) +{ + // Set register to NORMAL operation + DataReadMode = DR_NORMAL; + // Reset transfer values, to prevent mis-transfer of data + VRAMRead.x = 0; + VRAMRead.y = 0; + VRAMRead.Width = 0; + VRAMRead.Height = 0; + VRAMRead.ColsRemaining = 0; + VRAMRead.RowsRemaining = 0; + + // Indicate GPU is no longer ready for VRAM data in the STATUS REGISTER + lGPUstatusRet&=~GPUSTATUS_READYFORVRAM; +} + +//////////////////////////////////////////////////////////////////////// +// core read from vram +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUreadDataMem(uint32_t * pMem, int iSize) +{ + int i; + + if(DataReadMode!=DR_VRAMTRANSFER) return; + + GPUIsBusy; + + // adjust read ptr, if necessary + while(VRAMRead.ImagePtr>=psxVuw_eom) + VRAMRead.ImagePtr-=iGPUHeight*1024; + while(VRAMRead.ImagePtr 0) && (VRAMRead.RowsRemaining > 0)) + { + // lower 16 bit + lGPUdataRet=(uint32_t)GETLE16(VRAMRead.ImagePtr); + + VRAMRead.ImagePtr++; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + VRAMRead.RowsRemaining --; + + if(VRAMRead.RowsRemaining<=0) + { + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining--; + VRAMRead.ImagePtr += 1024 - VRAMRead.Width; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + } + + // higher 16 bit (always, even if it's an odd width) + lGPUdataRet|=(uint32_t)GETLE16(VRAMRead.ImagePtr)<<16; + PUTLE32(pMem, lGPUdataRet); pMem++; + + if(VRAMRead.ColsRemaining <= 0) + {FinishedVRAMRead();goto ENDREAD;} + + VRAMRead.ImagePtr++; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + VRAMRead.RowsRemaining--; + if(VRAMRead.RowsRemaining<=0) + { + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining--; + VRAMRead.ImagePtr += 1024 - VRAMRead.Width; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + } + if(VRAMRead.ColsRemaining <= 0) + {FinishedVRAMRead();goto ENDREAD;} + } + else {FinishedVRAMRead();goto ENDREAD;} + } + +ENDREAD: + GPUIsIdle; +} + + +//////////////////////////////////////////////////////////////////////// + +uint32_t CALLBACK GPUreadData(void) +{ + uint32_t l; + GPUreadDataMem(&l,1); + return 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; + GPUIsBusy; + GPUIsNotReadyForCommands; + +STARTVRAM: + + if(DataWriteMode==DR_VRAMTRANSFER) + { + BOOL bFinished=FALSE; + + // make sure we are in vram + while(VRAMWrite.ImagePtr>=psxVuw_eom) + VRAMWrite.ImagePtr-=iGPUHeight*1024; + while(VRAMWrite.ImagePtr0) + { + while(VRAMWrite.RowsRemaining>0) + { + if(i>=iSize) {goto ENDVRAM;} + i++; + + gdata=GETLE32(pMem); pMem++; + + PUTLE16(VRAMWrite.ImagePtr, (unsigned short)gdata); VRAMWrite.ImagePtr++; + if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; + VRAMWrite.RowsRemaining --; + + if(VRAMWrite.RowsRemaining <= 0) + { + VRAMWrite.ColsRemaining--; + if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width + { + gdata=(gdata&0xFFFF)|(((uint32_t)GETLE16(VRAMWrite.ImagePtr))<<16); + FinishedVRAMWrite(); + bDoVSyncUpdate=TRUE; + goto ENDVRAM; + } + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; + } + + PUTLE16(VRAMWrite.ImagePtr, (unsigned short)(gdata>>16)); VRAMWrite.ImagePtr++; + if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; + VRAMWrite.RowsRemaining --; + } + + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ColsRemaining--; + VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; + bFinished=TRUE; + } + + FinishedVRAMWrite(); + if(bFinished) bDoVSyncUpdate=TRUE; + } + +ENDVRAM: + + if(DataWriteMode==DR_NORMAL) + { + void (* *primFunc)(unsigned char *); + if(bSkipNextFrame) primFunc=primTableSkip; + else primFunc=primTableJ; + + for(;i>24) & 0xff); + +//if(command>=0xb0 && command<0xc0) auxprintf("b0 %x!!!!!!!!!\n",command); + + if(primTableCX[command]) + { + gpuDataC = primTableCX[command]; + gpuCommand = command; + PUTLE32(&gpuDataM[0], gdata); + gpuDataP = 1; + } + else continue; + } + else + { + PUTLE32(&gpuDataM[gpuDataP], gdata); + if(gpuDataC>128) + { + if((gpuDataC==254 && gpuDataP>=3) || + (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1))) + { + if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000) + gpuDataP=gpuDataC-1; + } + } + gpuDataP++; + } + + if(gpuDataP == gpuDataC) + { + gpuDataC=gpuDataP=0; + primFunc[gpuCommand]((unsigned char *)gpuDataM); + if(dwEmuFixes&0x0001 || dwActFixes&0x0400) // hack for emulating "gpu busy" in some games + iFakePrimBusy=4; + } + } + } + + lGPUdataRet=gdata; + + GPUIsReadyForCommands; + GPUIsIdle; +} + +//////////////////////////////////////////////////////////////////////// + +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(DataWriteMode==DR_VRAMTRANSFER) iT|=0x1; + if(DataReadMode ==DR_VRAMTRANSFER) iT|=0x2; + return iT; +} + +//////////////////////////////////////////////////////////////////////// +// call config dlg +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUconfigure(void) +{ +#ifdef _WINDOWS + HWND hWP=GetActiveWindow(); + + DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGSOFT), + hWP,(DLGPROC)SoftDlgProc); +#else + SoftDlgProc(); +#endif + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// sets all kind of act fixes +//////////////////////////////////////////////////////////////////////// + +void SetFixes(void) + { +#ifdef _WINDOWS + BOOL bOldPerformanceCounter=IsPerformanceCounter; // store curr timer mode + + if(dwActFixes&0x10) // check fix 0x10 + IsPerformanceCounter=FALSE; + else SetFPSHandler(); + + if(bOldPerformanceCounter!=IsPerformanceCounter) // we have change it? + InitFPS(); // -> init fps again +#endif + + if(dwActFixes&0x02) sDispWidths[4]=384; + else sDispWidths[4]=368; + } + +//////////////////////////////////////////////////////////////////////// +// process gpu commands +//////////////////////////////////////////////////////////////////////// + +unsigned long lUsedAddr[3]; + +__inline BOOL CheckForEndlessLoop(unsigned long laddr) +{ + if(laddr==lUsedAddr[1]) return TRUE; + if(laddr==lUsedAddr[2]) return TRUE; + + if(laddr 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); + + GPUIsIdle; + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// show about dlg +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_COMMAND: + { + switch(LOWORD(wParam)) + {case IDOK: EndDialog(hW,TRUE);return TRUE;} + } + } + return FALSE; +} +#endif + +void CALLBACK GPUabout(void) // ABOUT +{ +#ifdef _WINDOWS + HWND hWP=GetActiveWindow(); // to be sure + DialogBox(hInst,MAKEINTRESOURCE(IDD_ABOUT), + hWP,(DLGPROC)AboutDlgProc); +#else + AboutDlgProc(); +#endif + + 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; + 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=lGPUstatusRet; + memcpy(pF->ulControl,ulStatusControl,256*sizeof(uint32_t)); + memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2); + + return 1; + } + + if(ulGetFreezeData!=0) return 0; // 0: set data + + lGPUstatusRet=pF->ulStatus; + memcpy(ulStatusControl,pF->ulControl,256*sizeof(uint32_t)); + memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2); + +// RESET TEXTURE STORE HERE, IF YOU USE SOMETHING LIKE THAT + + GPUwriteStatus(ulStatusControl[0]); + GPUwriteStatus(ulStatusControl[1]); + GPUwriteStatus(ulStatusControl[2]); + GPUwriteStatus(ulStatusControl[3]); + GPUwriteStatus(ulStatusControl[8]); // try to repair things + GPUwriteStatus(ulStatusControl[6]); + GPUwriteStatus(ulStatusControl[7]); + GPUwriteStatus(ulStatusControl[5]); + GPUwriteStatus(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 + +#ifdef _WINDOWS + +void CALLBACK GPUgetScreenPic(unsigned char * pMem) +{ + HRESULT ddrval;DDSURFACEDESC xddsd;unsigned char * pf; + int x,y,c,v;RECT r; + float XS,YS; + + memset(&xddsd, 0, sizeof(DDSURFACEDESC)); + xddsd.dwSize = sizeof(DDSURFACEDESC); + xddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; + xddsd.dwWidth = iResX; + xddsd.dwHeight = iResY; + + r.left=0; r.right =iResX; + r.top=0; r.bottom=iResY; + + if(iWindowMode) + { + POINT Point={0,0}; + ClientToScreen(DX.hWnd,&Point); + r.left+=Point.x;r.right+=Point.x; + r.top+=Point.y;r.bottom+=Point.y; + } + + XS=(float)iResX/128; + YS=(float)iResY/96; + + ddrval=IDirectDrawSurface_Lock(DX.DDSPrimary,NULL, &xddsd, DDLOCK_WAIT|DDLOCK_READONLY, NULL); + + if(ddrval==DDERR_SURFACELOST) IDirectDrawSurface_Restore(DX.DDSPrimary); + + pf=pMem; + + if(ddrval==DD_OK) + { + unsigned char * ps=(unsigned char *)xddsd.lpSurface; + + if(iDesktopCol==16) + { + unsigned short sx; + for(y=0;y<96;y++) + { + for(x=0;x<128;x++) + { + sx=*((unsigned short *)((ps)+ + r.top*xddsd.lPitch+ + (((int)((float)y*YS))*xddsd.lPitch)+ + r.left*2+ + ((int)((float)x*XS))*2)); + *(pf+0)=(sx&0x1f)<<3; + *(pf+1)=(sx&0x7e0)>>3; + *(pf+2)=(sx&0xf800)>>8; + pf+=3; + } + } + } + else + if(iDesktopCol==15) + { + unsigned short sx; + for(y=0;y<96;y++) + { + for(x=0;x<128;x++) + { + sx=*((unsigned short *)((ps)+ + r.top*xddsd.lPitch+ + (((int)((float)y*YS))*xddsd.lPitch)+ + r.left*2+ + ((int)((float)x*XS))*2)); + *(pf+0)=(sx&0x1f)<<3; + *(pf+1)=(sx&0x3e0)>>2; + *(pf+2)=(sx&0x7c00)>>7; + pf+=3; + } + } + } + else + { + unsigned long sx; + for(y=0;y<96;y++) + { + for(x=0;x<128;x++) + { + sx=*((unsigned long *)((ps)+ + r.top*xddsd.lPitch+ + (((int)((float)y*YS))*xddsd.lPitch)+ + r.left*4+ + ((int)((float)x*XS))*4)); + *(pf+0)=(unsigned char)((sx&0xff)); + *(pf+1)=(unsigned char)((sx&0xff00)>>8); + *(pf+2)=(unsigned char)((sx&0xff0000)>>16); + pf+=3; + } + } + } + } + + IDirectDrawSurface_Unlock(DX.DDSPrimary,&xddsd); + + ///////////////////////////////////////////////////////////////////// + // 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) + v=(c&0xc0)>>6; + PaintPicDot(pf,(unsigned char)v);pf+=3; // paint the dots into the rect + v=(c&0x30)>>4; + PaintPicDot(pf,(unsigned char)v);pf+=3; + v=(c&0x0c)>>2; + PaintPicDot(pf,(unsigned char)v);pf+=3; + v=c&0x03; + PaintPicDot(pf,(unsigned char)v);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 + } +} + +#else + +// 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 + } +*/ +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// 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) +{ + dwEmuFixes=dwFixBits; +} + +void CALLBACK GPUvBlank( int val ) +{ + vBlank = val; +} + +void CALLBACK GPUvisualVibration(uint32_t iSmall, uint32_t iBig) +{ + int iVibVal; + + if(PreviousPSXDisplay.DisplayMode.x) // calc min "shake pixel" from screen width + iVibVal=max(1,iResX/PreviousPSXDisplay.DisplayMode.x); + else iVibVal=1; + // big rumble: 4...15 sp ; small rumble 1...3 sp + if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig *iVibVal)/10)); + else iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10)); + + iRumbleTime=15; // let the rumble last 16 buffer swaps +} diff --git a/plugins/dfxvideo/gpucfg-0.1df/main.c b/plugins/dfxvideo/gpucfg-0.1df/main.c index e5062757..07d362e3 100644 --- a/plugins/dfxvideo/gpucfg-0.1df/main.c +++ b/plugins/dfxvideo/gpucfg-0.1df/main.c @@ -1,465 +1,464 @@ -#include -#include - -#include "config.h" - -#ifdef ENABLE_NLS -#include -#include -#endif - -#include -#include -#include -#include -#include - -void SaveConfig(GtkWidget *widget, gpointer user_datal); - -#define READBINARY "rb" -#define WRITEBINARY "wb" -#define CONFIG_FILENAME "dfxvideo.cfg" - -enum { - VIDMODE_320x200 = 0, - VIDMODE_640x480, - VIDMODE_800x600, - VIDMODE_1024x768, - VIDMODE_1152x864, - VIDMODE_1280x1024, - VIDMODE_1600x1200 -}; /* Video_modes */ - -/*ADB static GtkWidget * wndMain=0;*/ - -/* This function checks for the value being outside the accepted range, - and returns the appropriate boundary value */ -static 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; -} - -static void on_about_clicked(GtkWidget *widget, gpointer user_data) -{ - gtk_widget_destroy (widget); - exit (0); -} - -static void set_widget_sensitive(GtkWidget *widget, gpointer user_data) -{ - gtk_widget_set_sensitive (widget, (int)(long)user_data); -} - -static void on_fullscreen_toggled(GtkWidget *widget, gpointer user_data) -{ - GtkWidget *check, *resCombo2; - GladeXML *xml; - xml = (GladeXML*) user_data; - - check = glade_xml_get_widget(xml, "checkFullscreen"); - resCombo2 = glade_xml_get_widget(xml, "resCombo2"); - - gtk_widget_set_sensitive(resCombo2, !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))); -} - -static void on_use_fixes_toggled(GtkWidget *widget, gpointer user_data) -{ - GtkWidget *check, *table_fixes; - GladeXML *xml; - xml = (GladeXML*) user_data; - check = glade_xml_get_widget (xml, "checkUseFixes"); - - table_fixes = glade_xml_get_widget (xml, "table_fixes"); - - /* Set the state of each of the fixes to the value of the use fixes toggle */ - gtk_container_foreach (GTK_CONTAINER (table_fixes), (GtkCallback) set_widget_sensitive, - (gpointer)(long)gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(check))); -} - -static void on_fps_toggled(GtkWidget *widget, gpointer user_data) -{ - GtkWidget *entryFPS, *checkAutoFPSLimit; - GtkToggleButton *checkSetFPS; - GladeXML *xml; - - xml = (GladeXML*) user_data; - checkSetFPS = GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "checkSetFPS")); - checkAutoFPSLimit = glade_xml_get_widget(xml, "checkAutoFPSLimit"); - entryFPS = glade_xml_get_widget(xml, "entryFPS"); - - gtk_widget_set_sensitive(entryFPS, - gtk_toggle_button_get_active(checkSetFPS) && !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkAutoFPSLimit))); - gtk_widget_set_sensitive(checkAutoFPSLimit, gtk_toggle_button_get_active(checkSetFPS)); -} - -static void OnConfigClose(GtkWidget *widget, gpointer user_data) -{ - GladeXML *xml = (GladeXML *)user_data; - - gtk_widget_destroy(glade_xml_get_widget(xml, "CfgWnd")); - gtk_exit(0); -} - -int -main (int argc, char *argv[]) -{ - GtkWidget *widget; - GladeXML *xml; - FILE *in;char t[256];int len = 0,val; - float valf; - char * pB, * p; - char cfg[255]; - int i; - 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: cfgDFXVideo {ABOUT | CFG}\n"); - return 0; - } - if(strcmp(argv[1],"CFG")!=0 && strcmp(argv[1],"ABOUT")!=0) { - printf("Usage: cfgDFXVideo {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", - G_CALLBACK(on_about_clicked), NULL, NULL, G_CONNECT_AFTER); - - gtk_widget_show (widget); - gtk_main(); - - return 0; - } - - xml = glade_xml_new(DATADIR "dfxvideo.glade2", "CfgWnd", NULL); - if (!xml) { - g_warning("We could not load the interface!"); - return -1; - } - - /*ADB wndMain = glade_xml_get_widget(xml, "CfgWnd");*/ - - strcpy(cfg, CONFIG_FILENAME); - - in = fopen(cfg,READBINARY); - /* ADB TODO This is bad - asking for problems; need to read in line by line */ - if(in) - { - pB=(char *)malloc(32767); - memset(pB,0,32767); - len = fread(pB, 1, 32767, in); - fclose(in); - } - else{ pB=0;printf("Couldn't find config file %s\n", cfg);} -/* ADB TODO Parse this like we parse the config file in PCSX - use common functions! */ - val=1; - if(pB) - { - strcpy(t,"\nResX");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - val = set_limit (p, len, 0, 1600); - } - - if (val == 1600) val = VIDMODE_1600x1200; - else if (val == 1280) val = VIDMODE_1280x1024; - else if (val == 1152) val = VIDMODE_1152x864; - else if (val == 1024) val = VIDMODE_1024x768; - else if (val == 800) val = VIDMODE_800x600; - else if (val == 640) val = VIDMODE_640x480; - else if (val == 320) val = VIDMODE_320x200; - - gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "resCombo2")), val); - - val=0; - if(pB) - { - strcpy(t,"\nNoStretch");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - - val = set_limit (p, len, 0, 9); - } - - gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "stretchCombo2")), val); - - val=0; - if(pB) - { - strcpy(t,"\nDithering");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - - val = set_limit (p, len, 0, 2); - } - - gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "ditherCombo2")), val); - - val=0; - if(pB) - { - strcpy(t,"\nMaintain43");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - - val = set_limit (p, len, 0, 1); - } - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "maintain43")), val); - - val=0; //ADB Leave - these are default values - if(pB) - { - strcpy(t,"\nFullScreen");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - - val = set_limit (p, len, 0, 1); - } - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkFullscreen")), val); - - val=0; - if(pB) - { - strcpy(t,"\nShowFPS");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - - val = set_limit (p, len, 0, 1); - } - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkShowFPS")), val); - - val=1; - if(pB) - { - strcpy(t,"\nUseFrameLimit");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - - val = set_limit (p, len, 0, 1); - } - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkSetFPS")), val); - - val=0; - if(pB) - { - strcpy(t,"\nFPSDetection");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - - val = set_limit (p, len, 1, 2); - } - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkAutoFPSLimit")), (val-1)); - - val=0; - if(pB) - { - strcpy(t,"\nUseFrameSkip");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - val = set_limit (p, len, 0, 1); - } - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkFrameSkip")), val); - - valf=200; - if(pB) - { - strcpy(t,"\nFrameRate");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - if(p) valf=(float)atoi(p+len) / 10; - if(valf<1) valf=1; - if(valf>500) valf=500; - } - sprintf(tempstr,"%.1f",valf); - gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entryFPS")),tempstr); - - val=0; - if(pB) - { - strcpy(t,"\nUseFixes");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - - val = set_limit (p, len, 0, 1); - } - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkUseFixes")), val); - - - if(pB) - { - strcpy(t,"\nCfgFixes");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} - if (p) - val = atoi(p + len); - } - - for (i=0; i<11; i++) - { - sprintf(tempstr, "checkFix%d", i+1); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, tempstr)), (val>>i)&1 ); - } - - - if(pB) free(pB); - - widget = glade_xml_get_widget(xml, "CfgWnd"); - g_signal_connect_data(GTK_OBJECT(widget), "destroy", - G_CALLBACK(SaveConfig), xml, NULL, 0); - - widget = glade_xml_get_widget(xml, "btn_close"); - g_signal_connect_data(GTK_OBJECT(widget), "clicked", - G_CALLBACK(OnConfigClose), xml, NULL, G_CONNECT_AFTER); - - widget = glade_xml_get_widget(xml, "checkFullscreen"); - g_signal_connect_data(GTK_OBJECT(widget), "clicked", - G_CALLBACK(on_fullscreen_toggled), xml, NULL, G_CONNECT_AFTER); - - widget = glade_xml_get_widget(xml, "checkUseFixes"); - g_signal_connect_data(GTK_OBJECT(widget), "clicked", - G_CALLBACK(on_use_fixes_toggled), xml, NULL, G_CONNECT_AFTER); - - widget = glade_xml_get_widget(xml, "checkSetFPS"); - g_signal_connect_data(GTK_OBJECT(widget), "clicked", - G_CALLBACK(on_fps_toggled), xml, NULL, G_CONNECT_AFTER); - - widget = glade_xml_get_widget(xml, "checkAutoFPSLimit"); - g_signal_connect_data(GTK_OBJECT(widget), "clicked", - G_CALLBACK(on_fps_toggled), xml, NULL, G_CONNECT_AFTER); - - on_fullscreen_toggled(widget, (gpointer) xml); - on_fps_toggled(widget, (gpointer) xml); - on_use_fixes_toggled(widget, (gpointer) xml); - - gtk_main (); - return 0; -} - - -static void SetCfgVal(char * pB,char * pE,int val) -{ - char * p, *ps, *pC;char t[32]; - - sprintf(t,"%d",val); - - p=strstr(pB,pE); - if(p) - { - p=strstr(p,"="); - if(!p) return; - p++; - while(*p && *p!='\n' && (*p<'0' || *p>'9')) p++; - if(*p==0 || *p=='\n') return; - ps=p; - while(*p>='0' && *p<='9') p++; - pC=(char *)malloc(32767); - strcpy(pC,p); - strcpy(ps,t); - strcat(pB,pC); - free(pC); - } - else - { - strcat(pB,pE); - strcat(pB," = "); - strcat(pB,t); - strcat(pB,"\n"); - } -} - -void SaveConfig(GtkWidget *widget, gpointer user_data) -{ - FILE *in;int len,val;char * pB; - GladeXML *xml; - char cfg[255]; - char tempstr[50]; - int i; - - pB=(char *)malloc(32767); - memset(pB,0,32767); - - strcpy(cfg, CONFIG_FILENAME); - - /* ADB TODO Why do we read this in just to replace it again? */ - in = fopen(cfg,READBINARY); - if(in) - { - len = fread(pB, 1, 32767, in); - fclose(in); - } - xml = (GladeXML*) user_data; - - val = gtk_combo_box_get_active (GTK_COMBO_BOX (glade_xml_get_widget (xml, "resCombo2"))); - - if (val == VIDMODE_320x200) { SetCfgVal(pB,"\nResX",320); SetCfgVal(pB,"\nResY",240); } - else if (val == VIDMODE_640x480) { SetCfgVal(pB,"\nResX",640); SetCfgVal(pB,"\nResY",480); } - else if (val == VIDMODE_800x600) { SetCfgVal(pB,"\nResX",800); SetCfgVal(pB,"\nResY",600); } - else if (val == VIDMODE_1024x768) { SetCfgVal(pB,"\nResX",1024); SetCfgVal(pB,"\nResY",768); } - else if (val == VIDMODE_1152x864) { SetCfgVal(pB,"\nResX",1152); SetCfgVal(pB,"\nResY",864); } - else if (val == VIDMODE_1280x1024) { SetCfgVal(pB,"\nResX",1280); SetCfgVal(pB,"\nResY",1024); } - else if (val == VIDMODE_1600x1200) { SetCfgVal(pB,"\nResX",1600); SetCfgVal(pB,"\nResY",1200); } - - val = gtk_combo_box_get_active (GTK_COMBO_BOX (glade_xml_get_widget (xml, "stretchCombo2"))); - SetCfgVal(pB,"\nNoStretch",val); - - val = gtk_combo_box_get_active (GTK_COMBO_BOX (glade_xml_get_widget (xml, "ditherCombo2"))); - SetCfgVal(pB,"\nDithering",val); - - val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "maintain43"))); - SetCfgVal(pB,"\nMaintain43",val); - - val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkFullscreen"))); - SetCfgVal(pB,"\nFullScreen",val); - - val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkShowFPS"))); - SetCfgVal(pB,"\nShowFPS",val); - - val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkSetFPS"))); - SetCfgVal(pB,"\nUseFrameLimit",val); - - val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkAutoFPSLimit"))); - SetCfgVal(pB,"\nFPSDetection",val+1); - - val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkFrameSkip"))); - SetCfgVal(pB,"\nUseFrameSkip",val); - - //Framerate stored *10 - val = atof(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entryFPS")))) * 10; - SetCfgVal(pB,"\nFrameRate",val); - - val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkUseFixes"))); - SetCfgVal(pB,"\nUseFixes",val); - - - val = 0; - for (i=0; i<11; i++) - { - sprintf(tempstr, "checkFix%d", i+1); - if( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, tempstr))) ) - val |= 1 << i; - } - - SetCfgVal(pB,"\nCfgFixes",val); - - - - if((in=fopen(cfg, WRITEBINARY))!=NULL) - { - if(fwrite(pB,strlen(pB),1,in) != 1) - perror(cfg); - fclose(in); - } - - free(pB); - - // Close the window and exit control from the plugin - gtk_exit (0); -} +#include +#include + +#include "config.h" + +#ifdef ENABLE_NLS +#include +#include +#endif + +#include +#include +#include +#include +#include + +void SaveConfig(GtkWidget *widget, gpointer user_datal); + +#define READBINARY "rb" +#define WRITEBINARY "wb" +#define CONFIG_FILENAME "dfxvideo.cfg" + +enum { + VIDMODE_320x200 = 0, + VIDMODE_640x480, + VIDMODE_800x600, + VIDMODE_1024x768, + VIDMODE_1152x864, + VIDMODE_1280x1024, + VIDMODE_1600x1200 +}; /* Video_modes */ + +/*ADB static GtkWidget * wndMain=0;*/ + +/* 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, gpointer user_data) +{ + gtk_widget_set_sensitive (widget, (int)user_data); +} + +void on_fullscreen_toggled(GtkWidget *widget, gpointer user_data) +{ + GtkWidget *check, *resCombo2; + GladeXML *xml; + xml = (GladeXML*) user_data; + + check = glade_xml_get_widget(xml, "checkFullscreen"); + resCombo2 = glade_xml_get_widget(xml, "resCombo2"); + + set_widget_sensitive(resCombo2, !gtk_toggle_button_get_active(check)); +} + +void on_use_fixes_toggled(GtkWidget *widget, gpointer user_data) +{ + GtkWidget *check, *table_fixes; + GladeXML *xml; + xml = (GladeXML*) user_data; + check = glade_xml_get_widget (xml, "checkUseFixes"); + + table_fixes = glade_xml_get_widget (xml, "table_fixes"); + + /* Set the state of each of the fixes to the value of the use fixes toggle */ + gtk_container_foreach (GTK_CONTAINER (table_fixes), (GtkCallback) set_widget_sensitive, + (void *)gtk_toggle_button_get_active (check)); +} + +void on_fps_toggled(GtkWidget *widget, gpointer user_data) +{ + GtkWidget *checkSetFPS, *checkAutoFPSLimit, *entryFPS; + GladeXML *xml; + + xml = (GladeXML*) user_data; + checkSetFPS = glade_xml_get_widget(xml, "checkSetFPS"); + checkAutoFPSLimit = glade_xml_get_widget(xml, "checkAutoFPSLimit"); + entryFPS = glade_xml_get_widget(xml, "entryFPS"); + + set_widget_sensitive(entryFPS, + gtk_toggle_button_get_active(checkSetFPS) && !gtk_toggle_button_get_active(checkAutoFPSLimit)); + set_widget_sensitive(checkAutoFPSLimit, gtk_toggle_button_get_active(checkSetFPS)); +} + +void OnConfigClose(GtkWidget *widget, gpointer user_data) +{ + GladeXML *xml = (GladeXML *)user_data; + + gtk_widget_destroy(glade_xml_get_widget(xml, "CfgWnd")); + gtk_exit(0); +} + +int +main (int argc, char *argv[]) +{ + GtkWidget *CfgWnd, *widget; + GladeXML *xml; + FILE *in;char t[256];int len,val; + float valf; + char * pB, * p; + char cfg[255]; + int i; + 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: cfgDFXVideo {ABOUT | CFG}\n"); + return 0; + } + if(strcmp(argv[1],"CFG")!=0 && strcmp(argv[1],"ABOUT")!=0) { + printf("Usage: cfgDFXVideo {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", + G_CALLBACK(on_about_clicked), NULL, NULL, G_CONNECT_AFTER); + + gtk_widget_show (widget); + gtk_main(); + + return 0; + } + + xml = glade_xml_new(DATADIR "dfxvideo.glade2", "CfgWnd", NULL); + if (!xml) { + g_warning("We could not load the interface!"); + return -1; + } + + /*ADB wndMain = glade_xml_get_widget(xml, "CfgWnd");*/ + + strcpy(cfg, CONFIG_FILENAME); + + in = fopen(cfg,READBINARY); + /* ADB TODO This is bad - asking for problems; need to read in line by line */ + if(in) + { + pB=(char *)malloc(32767); + memset(pB,0,32767); + len = fread(pB, 1, 32767, in); + fclose(in); + } + else{ pB=0;printf("Couldn't find config file %s\n", cfg);} +/* ADB TODO Parse this like we parse the config file in PCSX - use common functions! */ + val=1; + if(pB) + { + strcpy(t,"\nResX");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + val = set_limit (p, len, 0, 1600); + } + + if (val == 1600) val = VIDMODE_1600x1200; + else if (val == 1280) val = VIDMODE_1280x1024; + else if (val == 1152) val = VIDMODE_1152x864; + else if (val == 1024) val = VIDMODE_1024x768; + else if (val == 800) val = VIDMODE_800x600; + else if (val == 640) val = VIDMODE_640x480; + else if (val == 320) val = VIDMODE_320x200; + + gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "resCombo2")), val); + + val=0; + if(pB) + { + strcpy(t,"\nNoStretch");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 0, 9); + } + + gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "stretchCombo2")), val); + + val=0; + if(pB) + { + strcpy(t,"\nDithering");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 0, 2); + } + + gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "ditherCombo2")), val); + + val=0; + if(pB) + { + strcpy(t,"\nMaintain43");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 0, 1); + } + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "maintain43")), val); + + val=0; //ADB Leave - these are default values + if(pB) + { + strcpy(t,"\nFullScreen");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 0, 1); + } + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkFullscreen")), val); + + val=0; + if(pB) + { + strcpy(t,"\nShowFPS");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 0, 1); + } + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkShowFPS")), val); + + val=1; + if(pB) + { + strcpy(t,"\nUseFrameLimit");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 0, 1); + } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkSetFPS")), val); + + val=0; + if(pB) + { + strcpy(t,"\nFPSDetection");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 1, 2); + } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkAutoFPSLimit")), (val-1)); + + val=0; + if(pB) + { + strcpy(t,"\nUseFrameSkip");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + val = set_limit (p, len, 0, 1); + } + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkFrameSkip")), val); + + valf=200; + if(pB) + { + strcpy(t,"\nFrameRate");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) valf=(float)atoi(p+len) / 10; + if(valf<1) valf=1; + if(valf>500) valf=500; + } + sprintf(tempstr,"%.1f",valf); + gtk_entry_set_text(glade_xml_get_widget(xml, "entryFPS"),tempstr); + + val=0; + if(pB) + { + strcpy(t,"\nUseFixes");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + + val = set_limit (p, len, 0, 1); + } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "checkUseFixes")), val); + + + if(pB) + { + strcpy(t,"\nCfgFixes");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if (p) + val = atoi(p + len); + } + + for (i=0; i<11; i++) + { + sprintf(tempstr, "checkFix%d", i+1); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, tempstr)), (val>>i)&1 ); + } + + + if(pB) free(pB); + + widget = glade_xml_get_widget(xml, "CfgWnd"); + g_signal_connect_data(GTK_OBJECT(widget), "destroy", + G_CALLBACK(SaveConfig), xml, NULL, 0); + + widget = glade_xml_get_widget(xml, "btn_close"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + G_CALLBACK(OnConfigClose), xml, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "checkFullscreen"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + G_CALLBACK(on_fullscreen_toggled), xml, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "checkUseFixes"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + G_CALLBACK(on_use_fixes_toggled), xml, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "checkSetFPS"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + G_CALLBACK(on_fps_toggled), xml, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "checkAutoFPSLimit"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + G_CALLBACK(on_fps_toggled), xml, NULL, G_CONNECT_AFTER); + + on_fullscreen_toggled(widget, (gpointer) xml); + on_fps_toggled(widget, (gpointer) xml); + on_use_fixes_toggled(widget, (gpointer) xml); + + gtk_main (); + return 0; +} + + +void SetCfgVal(char * pB,char * pE,int val) +{ + char * p, *ps, *pC;char t[32]; + + sprintf(t,"%d",val); + + p=strstr(pB,pE); + if(p) + { + p=strstr(p,"="); + if(!p) return; + p++; + while(*p && *p!='\n' && (*p<'0' || *p>'9')) p++; + if(*p==0 || *p=='\n') return; + ps=p; + while(*p>='0' && *p<='9') p++; + pC=(char *)malloc(32767); + strcpy(pC,p); + strcpy(ps,t); + strcat(pB,pC); + free(pC); + } + else + { + strcat(pB,pE); + strcat(pB," = "); + strcat(pB,t); + strcat(pB,"\n"); + } +} + +void SaveConfig(GtkWidget *widget, gpointer user_data) +{ + FILE *in;int len,val;char * pB; + GladeXML *xml; + char cfg[255]; + char tempstr[50]; + int i; + struct stat buf; + + pB=(char *)malloc(32767); + memset(pB,0,32767); + + strcpy(cfg, CONFIG_FILENAME); + + /* ADB TODO Why do we read this in just to replace it again? */ + in = fopen(cfg,READBINARY); + if(in) + { + len = fread(pB, 1, 32767, in); + fclose(in); + } + xml = (GladeXML*) user_data; + + val = gtk_combo_box_get_active (GTK_COMBO_BOX (glade_xml_get_widget (xml, "resCombo2"))); + + if (val == VIDMODE_320x200) { SetCfgVal(pB,"\nResX",320); SetCfgVal(pB,"\nResY",240); } + else if (val == VIDMODE_640x480) { SetCfgVal(pB,"\nResX",640); SetCfgVal(pB,"\nResY",480); } + else if (val == VIDMODE_800x600) { SetCfgVal(pB,"\nResX",800); SetCfgVal(pB,"\nResY",600); } + else if (val == VIDMODE_1024x768) { SetCfgVal(pB,"\nResX",1024); SetCfgVal(pB,"\nResY",768); } + else if (val == VIDMODE_1152x864) { SetCfgVal(pB,"\nResX",1152); SetCfgVal(pB,"\nResY",864); } + else if (val == VIDMODE_1280x1024) { SetCfgVal(pB,"\nResX",1280); SetCfgVal(pB,"\nResY",1024); } + else if (val == VIDMODE_1600x1200) { SetCfgVal(pB,"\nResX",1600); SetCfgVal(pB,"\nResY",1200); } + + val = gtk_combo_box_get_active (GTK_COMBO_BOX (glade_xml_get_widget (xml, "stretchCombo2"))); + SetCfgVal(pB,"\nNoStretch",val); + + val = gtk_combo_box_get_active (GTK_COMBO_BOX (glade_xml_get_widget (xml, "ditherCombo2"))); + SetCfgVal(pB,"\nDithering",val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "maintain43"))); + SetCfgVal(pB,"\nMaintain43",val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkFullscreen"))); + SetCfgVal(pB,"\nFullScreen",val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkShowFPS"))); + SetCfgVal(pB,"\nShowFPS",val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkSetFPS"))); + SetCfgVal(pB,"\nUseFrameLimit",val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkAutoFPSLimit"))); + SetCfgVal(pB,"\nFPSDetection",val+1); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkFrameSkip"))); + SetCfgVal(pB,"\nUseFrameSkip",val); + + //Framerate stored *10 + val = atof(gtk_entry_get_text(glade_xml_get_widget(xml, "entryFPS"))) * 10; + SetCfgVal(pB,"\nFrameRate",val); + + val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "checkUseFixes"))); + SetCfgVal(pB,"\nUseFixes",val); + + + val = 0; + for (i=0; i<11; i++) + { + sprintf(tempstr, "checkFix%d", i+1); + if( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, tempstr))) ) + val |= 1 << i; + } + + SetCfgVal(pB,"\nCfgFixes",val); + + + + if((in=fopen(cfg, WRITEBINARY))!=NULL) + { + fwrite(pB,strlen(pB),1,in); + fclose(in); + } + + free(pB); + + // Close the window and exit control from the plugin + gtk_exit (0); +} diff --git a/plugins/dfxvideo/key.c b/plugins/dfxvideo/key.c index 17311ef8..35f7ba2b 100644 --- a/plugins/dfxvideo/key.c +++ b/plugins/dfxvideo/key.c @@ -1,93 +1,92 @@ -/*************************************************************************** - 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. * - * * - ***************************************************************************/ - -#define _IN_KEY - -#include "externals.h" -#include "menu.h" -#include "gpu.h" -#include "draw.h" -#include "key.h" -#include "psemu_plugin_defs.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) -{ - switch(keycode) - { - case 0xFFC9: //X11 key: F12 - case ((1<<29) | 0xFF0D): //special keycode from pcsx-df: alt-enter - bChangeWinMode=TRUE; - break; - case VK_F5: - GPUmakeSnapshot(); - break; - - case VK_INSERT: - if(iUseFixes) {iUseFixes=0;dwActFixes=0;} - else {iUseFixes=1;dwActFixes=dwCfgFixes;} - SetFixes(); - if(iFrameLimit==2) SetAutoFrameCap(); - break; - - case VK_DEL: - if(ulKeybits&KEY_SHOWFPS) - ulKeybits&=~KEY_SHOWFPS; - else - { - ulKeybits|=KEY_SHOWFPS; - szDispBuf[0]=0; - BuildDispMenu(0); - } - break; - - case VK_PRIOR: BuildDispMenu(-1); break; - case VK_NEXT: BuildDispMenu( 1); break; - case VK_END: SwitchDispMenu(1); break; - case VK_HOME: SwitchDispMenu(-1); break; - case 0x60: - { - iFastFwd = 1 - iFastFwd; - bSkipNextFrame = FALSE; - UseFrameSkip = iFastFwd; - BuildDispMenu(0); - break; - } -#ifdef _MACGL - default: { void HandleKey(int keycode); HandleKey(keycode); } -#endif - } -} - -void SetKeyHandler(void) -{ -} - -void ReleaseKeyHandler(void) -{ -} +/*************************************************************************** + 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. * + * * + ***************************************************************************/ + +#define _IN_KEY + +#include "externals.h" +#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) +{ + switch(keycode) + { + case 0xFFC9: //X11 key: F12 + case ((1<<29) | 0xFF0D): //special keycode from pcsx-df: alt-enter + bChangeWinMode=TRUE; + break; + case VK_F5: + GPUmakeSnapshot(); + break; + + case VK_INSERT: + if(iUseFixes) {iUseFixes=0;dwActFixes=0;} + else {iUseFixes=1;dwActFixes=dwCfgFixes;} + SetFixes(); + if(iFrameLimit==2) SetAutoFrameCap(); + break; + + case VK_DEL: + if(ulKeybits&KEY_SHOWFPS) + ulKeybits&=~KEY_SHOWFPS; + else + { + ulKeybits|=KEY_SHOWFPS; + szDispBuf[0]=0; + BuildDispMenu(0); + } + break; + + case VK_PRIOR: BuildDispMenu(-1); break; + case VK_NEXT: BuildDispMenu( 1); break; + case VK_END: SwitchDispMenu(1); break; + case VK_HOME: SwitchDispMenu(-1); break; + case 0x60: + { + iFastFwd = 1 - iFastFwd; + bSkipNextFrame = FALSE; + UseFrameSkip = iFastFwd; + BuildDispMenu(0); + break; + } +#ifdef _MACGL + default: { void HandleKey(int keycode); HandleKey(keycode); } +#endif + } +} + +void SetKeyHandler(void) +{ +} + +void ReleaseKeyHandler(void) +{ +} diff --git a/plugins/dfxvideo/menu.c b/plugins/dfxvideo/menu.c index 4867ca0b..1c742668 100644 --- a/plugins/dfxvideo/menu.c +++ b/plugins/dfxvideo/menu.c @@ -1,242 +1,245 @@ -/*************************************************************************** - 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. * - * * - ***************************************************************************/ - -#define _IN_MENU - -#include "externals.h" -#include "draw.h" -#include "menu.h" -#include "gpu.h" - -#ifdef _WINDOWS - -#include "record.h" - -HFONT hGFont=NULL; -BOOL bTransparent=FALSE; - -#endif - -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) -{ -#ifdef _WINDOWS - hGFont=CreateFont(//-8, - 13,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE, - ANSI_CHARSET,OUT_DEFAULT_PRECIS, - CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, - DEFAULT_PITCH, - //"Courier New"); - //"MS Sans Serif"); - "Arial"); -#endif -} - -// kill existing lists/fonts -void CloseMenu(void) -{ -#ifdef _WINDOWS - if(hGFont) DeleteObject(hGFont); - hGFont=NULL; -#else - DestroyPic(); -#endif -} - -// DISPLAY FPS/MENU TEXT - -int iMPos=0; // menu arrow pos - -void DisplayText(void) // DISPLAY TEXT -{ -#ifdef _WINDOWS - HDC hdc;HFONT hFO; - - IDirectDrawSurface_GetDC(DX.DDSRender,&hdc); - hFO=(HFONT)SelectObject(hdc,hGFont); - - SetTextColor(hdc,RGB(0,255,0)); - if(bTransparent) - SetBkMode(hdc,TRANSPARENT); - else SetBkColor(hdc,RGB(0,0,0)); - - if(szDebugText[0] && ((time(NULL) - tStart) < 2)) // special debug text? show it - { - RECT r={0,0,1024,1024}; - DrawText(hdc,szDebugText,lstrlen(szDebugText),&r,DT_LEFT|DT_NOCLIP); - } - else // else standard gpu menu - { - szDebugText[0]=0; - lstrcat(szDispBuf,szMenuBuf); - ExtTextOut(hdc,0,0,0,NULL,szDispBuf,lstrlen(szDispBuf),NULL); - } - - SelectObject(hdc,hFO); - IDirectDrawSurface_ReleaseDC(DX.DDSRender,hdc); -#endif -} - -// Build Menu buffer (== Dispbuffer without FPS)... -void BuildDispMenu(int iInc) -{ - if(!(ulKeybits&KEY_SHOWFPS)) return; // mmm, cheater ;) - - iMPos+=iInc; // up or down - if(iMPos<0) iMPos=3; // wrap around - if(iMPos>3) iMPos=0; - - strcpy(szMenuBuf," FL FS DI GF "); // main menu items - - if(UseFrameLimit) // set marks - { - if(iFrameLimit==1) szMenuBuf[2] = '+'; - else szMenuBuf[2] = '*'; - } - if(iFastFwd) szMenuBuf[7] = '~'; - else - if(UseFrameSkip) szMenuBuf[7] = '*'; - - if(iUseDither) // set marks - { - if(iUseDither==1) szMenuBuf[12] = '+'; - else szMenuBuf[12] = '*'; - } - - if(dwActFixes) szMenuBuf[17] = '*'; - - if(dwCoreFlags&1) szMenuBuf[23] = 'A'; - if(dwCoreFlags&2) szMenuBuf[23] = 'M'; - - if(dwCoreFlags&0xff00) //A/M/G/D - { - if((dwCoreFlags&0x0f00)==0x0000) // D - szMenuBuf[23] = 'D'; - else - if((dwCoreFlags&0x0f00)==0x0100) // A - szMenuBuf[23] = 'A'; - else - if((dwCoreFlags&0x0f00)==0x0200) // M - szMenuBuf[23] = 'M'; - else - if((dwCoreFlags&0x0f00)==0x0300) // G - szMenuBuf[23] = 'G'; - - szMenuBuf[24]='0'+(char)((dwCoreFlags&0xf000)>>12); // number - } - -#ifdef _WINDOWS - if(bVsync_Key) szMenuBuf[25] = 'V'; -#endif - - if(lSelectedSlot) szMenuBuf[26] = '0'+(char)lSelectedSlot; - - szMenuBuf[(iMPos+1)*5]='<'; // set arrow - -#ifdef _WINDOWS - if(RECORD_RECORDING) - { - szMenuBuf[27] = ' '; - szMenuBuf[28] = ' '; - szMenuBuf[29] = ' '; - szMenuBuf[30] = 'R'; - szMenuBuf[31] = 'e'; - szMenuBuf[32] = 'c'; - szMenuBuf[33] = 0; - } - - if(DX.DDSScreenPic) ShowTextGpuPic(); -#endif -} - -// Some menu action... -void SwitchDispMenu(int iStep) // SWITCH DISP MENU -{ - if(!(ulKeybits&KEY_SHOWFPS)) return; // tststs - - switch(iMPos) - { - case 0: // frame limit - { - int iType=0; - bInitCap = TRUE; - -#ifdef _WINDOWS - if(iFrameLimit==1 && UseFrameLimit && - GetAsyncKeyState(VK_SHIFT)&32768) - { - fFrameRate+=iStep; - if(fFrameRate<3.0f) fFrameRate=3.0f; - SetAutoFrameCap(); - break; - } -#endif - - if(UseFrameLimit) iType=iFrameLimit; - iType+=iStep; - if(iType<0) iType=2; - if(iType>2) iType=0; - if(iType==0) UseFrameLimit=0; - else - { - UseFrameLimit=1; - iFrameLimit=iType; - SetAutoFrameCap(); - } - } break; - - case 1: // frame skip - bInitCap = TRUE; - if(iStep>0) - { - if(!UseFrameSkip) {UseFrameSkip=1;iFastFwd = 0;} - else - { - if(!iFastFwd) iFastFwd=1; - else {UseFrameSkip=0;iFastFwd = 0;} - } - } - else - { - if(!UseFrameSkip) {UseFrameSkip=1;iFastFwd = 1;} - else - { - if(iFastFwd) iFastFwd=0; - else {UseFrameSkip=0;iFastFwd = 0;} - } - } - bSkipNextFrame=FALSE; - break; - - case 2: // dithering - iUseDither+=iStep; - if(iUseDither<0) iUseDither=2; - if(iUseDither>2) iUseDither=0; - break; - - case 3: // special fixes - if(iUseFixes) {iUseFixes=0;dwActFixes=0;} - else {iUseFixes=1;dwActFixes=dwCfgFixes;} - SetFixes(); - if(iFrameLimit==2) SetAutoFrameCap(); - break; - } - - BuildDispMenu(0); // update info -} +/*************************************************************************** + 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. * + * * + ***************************************************************************/ + +#define _IN_MENU + +#include "externals.h" +#include "draw.h" +#include "menu.h" +#include "gpu.h" + +#ifdef _WINDOWS + +#include "record.h" + +HFONT hGFont=NULL; +BOOL bTransparent=FALSE; + +#endif + +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) +{ +#ifdef _WINDOWS + hGFont=CreateFont(//-8, + 13,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE, + ANSI_CHARSET,OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + DEFAULT_PITCH, + //"Courier New"); + //"MS Sans Serif"); + "Arial"); +#endif +} + +// kill existing lists/fonts +void CloseMenu(void) +{ +#ifdef _WINDOWS + if(hGFont) DeleteObject(hGFont); + hGFont=NULL; +#else + DestroyPic(); +#endif +} + +// DISPLAY FPS/MENU TEXT + +#include +extern time_t tStart; + +int iMPos=0; // menu arrow pos + +void DisplayText(void) // DISPLAY TEXT +{ +#ifdef _WINDOWS + HDC hdc;HFONT hFO; + + IDirectDrawSurface_GetDC(DX.DDSRender,&hdc); + hFO=(HFONT)SelectObject(hdc,hGFont); + + SetTextColor(hdc,RGB(0,255,0)); + if(bTransparent) + SetBkMode(hdc,TRANSPARENT); + else SetBkColor(hdc,RGB(0,0,0)); + + if(szDebugText[0] && ((time(NULL) - tStart) < 2)) // special debug text? show it + { + RECT r={0,0,1024,1024}; + DrawText(hdc,szDebugText,lstrlen(szDebugText),&r,DT_LEFT|DT_NOCLIP); + } + else // else standard gpu menu + { + szDebugText[0]=0; + lstrcat(szDispBuf,szMenuBuf); + ExtTextOut(hdc,0,0,0,NULL,szDispBuf,lstrlen(szDispBuf),NULL); + } + + SelectObject(hdc,hFO); + IDirectDrawSurface_ReleaseDC(DX.DDSRender,hdc); +#endif +} + +// Build Menu buffer (== Dispbuffer without FPS)... +void BuildDispMenu(int iInc) +{ + if(!(ulKeybits&KEY_SHOWFPS)) return; // mmm, cheater ;) + + iMPos+=iInc; // up or down + if(iMPos<0) iMPos=3; // wrap around + if(iMPos>3) iMPos=0; + + strcpy(szMenuBuf," FL FS DI GF "); // main menu items + + if(UseFrameLimit) // set marks + { + if(iFrameLimit==1) szMenuBuf[2] = '+'; + else szMenuBuf[2] = '*'; + } + if(iFastFwd) szMenuBuf[7] = '~'; + else + if(UseFrameSkip) szMenuBuf[7] = '*'; + + if(iUseDither) // set marks + { + if(iUseDither==1) szMenuBuf[12] = '+'; + else szMenuBuf[12] = '*'; + } + + if(dwActFixes) szMenuBuf[17] = '*'; + + if(dwCoreFlags&1) szMenuBuf[23] = 'A'; + if(dwCoreFlags&2) szMenuBuf[23] = 'M'; + + if(dwCoreFlags&0xff00) //A/M/G/D + { + if((dwCoreFlags&0x0f00)==0x0000) // D + szMenuBuf[23] = 'D'; + else + if((dwCoreFlags&0x0f00)==0x0100) // A + szMenuBuf[23] = 'A'; + else + if((dwCoreFlags&0x0f00)==0x0200) // M + szMenuBuf[23] = 'M'; + else + if((dwCoreFlags&0x0f00)==0x0300) // G + szMenuBuf[23] = 'G'; + + szMenuBuf[24]='0'+(char)((dwCoreFlags&0xf000)>>12); // number + } + +#ifdef _WINDOWS + if(bVsync_Key) szMenuBuf[25] = 'V'; +#endif + + if(lSelectedSlot) szMenuBuf[26] = '0'+(char)lSelectedSlot; + + szMenuBuf[(iMPos+1)*5]='<'; // set arrow + +#ifdef _WINDOWS + if(RECORD_RECORDING) + { + szMenuBuf[27] = ' '; + szMenuBuf[28] = ' '; + szMenuBuf[29] = ' '; + szMenuBuf[30] = 'R'; + szMenuBuf[31] = 'e'; + szMenuBuf[32] = 'c'; + szMenuBuf[33] = 0; + } + + if(DX.DDSScreenPic) ShowTextGpuPic(); +#endif +} + +// Some menu action... +void SwitchDispMenu(int iStep) // SWITCH DISP MENU +{ + if(!(ulKeybits&KEY_SHOWFPS)) return; // tststs + + switch(iMPos) + { + case 0: // frame limit + { + int iType=0; + bInitCap = TRUE; + +#ifdef _WINDOWS + if(iFrameLimit==1 && UseFrameLimit && + GetAsyncKeyState(VK_SHIFT)&32768) + { + fFrameRate+=iStep; + if(fFrameRate<3.0f) fFrameRate=3.0f; + SetAutoFrameCap(); + break; + } +#endif + + if(UseFrameLimit) iType=iFrameLimit; + iType+=iStep; + if(iType<0) iType=2; + if(iType>2) iType=0; + if(iType==0) UseFrameLimit=0; + else + { + UseFrameLimit=1; + iFrameLimit=iType; + SetAutoFrameCap(); + } + } break; + + case 1: // frame skip + bInitCap = TRUE; + if(iStep>0) + { + if(!UseFrameSkip) {UseFrameSkip=1;iFastFwd = 0;} + else + { + if(!iFastFwd) iFastFwd=1; + else {UseFrameSkip=0;iFastFwd = 0;} + } + } + else + { + if(!UseFrameSkip) {UseFrameSkip=1;iFastFwd = 1;} + else + { + if(iFastFwd) iFastFwd=0; + else {UseFrameSkip=0;iFastFwd = 0;} + } + } + bSkipNextFrame=FALSE; + break; + + case 2: // dithering + iUseDither+=iStep; + if(iUseDither<0) iUseDither=2; + if(iUseDither>2) iUseDither=0; + break; + + case 3: // special fixes + if(iUseFixes) {iUseFixes=0;dwActFixes=0;} + else {iUseFixes=1;dwActFixes=dwCfgFixes;} + SetFixes(); + if(iFrameLimit==2) SetAutoFrameCap(); + break; + } + + BuildDispMenu(0); // update info +} diff --git a/plugins/dfxvideo/prim.c b/plugins/dfxvideo/prim.c index 8729170a..e797dbec 100644 --- a/plugins/dfxvideo/prim.c +++ b/plugins/dfxvideo/prim.c @@ -1,1663 +1,1661 @@ -/*************************************************************************** - 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. * - * * - ***************************************************************************/ - -#define _IN_PRIMDRAW - -#include "externals.h" -#include "gpu.h" -#include "draw.h" -#include "soft.h" -#include "swap.h" - -//////////////////////////////////////////////////////////////////////// -// globals -//////////////////////////////////////////////////////////////////////// - -BOOL bUsingTWin=FALSE; -TWin_t TWin; -//unsigned long clutid; // global clut -unsigned short usMirror=0; // sprite mirror -int iDither=0; -int32_t drawX; -int32_t drawY; -int32_t drawW; -int32_t drawH; -uint32_t dwCfgFixes; -uint32_t dwActFixes=0; -uint32_t dwEmuFixes=0; -int iUseFixes; -int iUseDither=0; -BOOL bDoVSyncUpdate=FALSE; - -//////////////////////////////////////////////////////////////////////// -// Some ASM color convertion by LEWPY -//////////////////////////////////////////////////////////////////////// - -#ifdef USE_NASM - -#define BGR24to16 i386_BGR24to16 -__inline unsigned short BGR24to16 (uint32_t BGR); - -#else - -static __inline unsigned short BGR24to16 (uint32_t BGR) -{ - return (unsigned short)(((BGR>>3)&0x1f)|((BGR&0xf80000)>>9)|((BGR&0xf800)>>6)); -} - -#endif - -//////////////////////////////////////////////////////////////////////// -// Update global TP infos -//////////////////////////////////////////////////////////////////////// - -static __inline void UpdateGlobalTP(unsigned short gdata) -{ - GlobalTextAddrX = (gdata << 6) & 0x3c0; // texture addr - - if(iGPUHeight==1024) - { - if(dwGPUVersion==2) - { - GlobalTextAddrY =((gdata & 0x60 ) << 3); - GlobalTextIL =(gdata & 0x2000) >> 13; - GlobalTextABR = (unsigned short)((gdata >> 7) & 0x3); - GlobalTextTP = (gdata >> 9) & 0x3; - if(GlobalTextTP==3) GlobalTextTP=2; - usMirror =0; - lGPUstatusRet = (lGPUstatusRet & 0xffffe000 ) | (gdata & 0x1fff ); - - // tekken dithering? right now only if dithering is forced by user - if(iUseDither==2) iDither=2; else iDither=0; - - return; - } - else - { - GlobalTextAddrY = (unsigned short)(((gdata << 4) & 0x100) | ((gdata >> 2) & 0x200)); - } - } - else GlobalTextAddrY = (gdata << 4) & 0x100; - - GlobalTextTP = (gdata >> 7) & 0x3; // tex mode (4,8,15) - - if(GlobalTextTP==3) GlobalTextTP=2; // seen in Wild9 :( - - GlobalTextABR = (gdata >> 5) & 0x3; // blend mode - - lGPUstatusRet&=~0x000001ff; // Clear the necessary bits - lGPUstatusRet|=(gdata & 0x01ff); // set the necessary bits - - switch(iUseDither) - { - case 0: - iDither=0; - break; - case 1: - if(lGPUstatusRet&0x0200) iDither=2; - else iDither=0; - break; - case 2: - iDither=2; - break; - } -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void SetRenderMode(uint32_t DrawAttributes) -{ - DrawSemiTrans = (SEMITRANSBIT(DrawAttributes)) ? TRUE : FALSE; - - if(SHADETEXBIT(DrawAttributes)) - {g_m1=g_m2=g_m3=128;} - else - { - if((dwActFixes&4) && ((DrawAttributes&0x00ffffff)==0)) - DrawAttributes|=0x007f7f7f; - - g_m1=(short)(DrawAttributes&0xff); - g_m2=(short)((DrawAttributes>>8)&0xff); - 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 - -static void AdjustCoord4() -{ - lx0=(short)(((int)lx0<>SIGNSHIFT); - lx1=(short)(((int)lx1<>SIGNSHIFT); - lx2=(short)(((int)lx2<>SIGNSHIFT); - lx3=(short)(((int)lx3<>SIGNSHIFT); - ly0=(short)(((int)ly0<>SIGNSHIFT); - ly1=(short)(((int)ly1<>SIGNSHIFT); - ly2=(short)(((int)ly2<>SIGNSHIFT); - ly3=(short)(((int)ly3<>SIGNSHIFT); -} - -static void AdjustCoord3() -{ - lx0=(short)(((int)lx0<>SIGNSHIFT); - lx1=(short)(((int)lx1<>SIGNSHIFT); - lx2=(short)(((int)lx2<>SIGNSHIFT); - ly0=(short)(((int)ly0<>SIGNSHIFT); - ly1=(short)(((int)ly1<>SIGNSHIFT); - ly2=(short)(((int)ly2<>SIGNSHIFT); -} - -static void AdjustCoord2() -{ - lx0=(short)(((int)lx0<>SIGNSHIFT); - lx1=(short)(((int)lx1<>SIGNSHIFT); - ly0=(short)(((int)ly0<>SIGNSHIFT); - ly1=(short)(((int)ly1<>SIGNSHIFT); -} - -static void AdjustCoord1() -{ - lx0=(short)(((int)lx0<>SIGNSHIFT); - ly0=(short)(((int)ly0<>SIGNSHIFT); - - if(lx0<-512 && PSXDisplay.DrawOffset.x<=-512) - lx0+=2048; - - if(ly0<-512 && PSXDisplay.DrawOffset.y<=-512) - 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 -*/ - -static __inline BOOL CheckCoord4() -{ - if(lx0<0) - { - if(((lx1-lx0)>CHKMAX_X) || - ((lx2-lx0)>CHKMAX_X)) - { - if(lx3<0) - { - if((lx1-lx3)>CHKMAX_X) return TRUE; - if((lx2-lx3)>CHKMAX_X) return TRUE; - } - } - } - if(lx1<0) - { - if((lx0-lx1)>CHKMAX_X) return TRUE; - if((lx2-lx1)>CHKMAX_X) return TRUE; - if((lx3-lx1)>CHKMAX_X) return TRUE; - } - if(lx2<0) - { - if((lx0-lx2)>CHKMAX_X) return TRUE; - if((lx1-lx2)>CHKMAX_X) return TRUE; - if((lx3-lx2)>CHKMAX_X) return TRUE; - } - if(lx3<0) - { - if(((lx1-lx3)>CHKMAX_X) || - ((lx2-lx3)>CHKMAX_X)) - { - if(lx0<0) - { - if((lx1-lx0)>CHKMAX_X) return TRUE; - if((lx2-lx0)>CHKMAX_X) return TRUE; - } - } - } - - - if(ly0<0) - { - if((ly1-ly0)>CHKMAX_Y) return TRUE; - if((ly2-ly0)>CHKMAX_Y) return TRUE; - } - if(ly1<0) - { - if((ly0-ly1)>CHKMAX_Y) return TRUE; - if((ly2-ly1)>CHKMAX_Y) return TRUE; - if((ly3-ly1)>CHKMAX_Y) return TRUE; - } - if(ly2<0) - { - if((ly0-ly2)>CHKMAX_Y) return TRUE; - if((ly1-ly2)>CHKMAX_Y) return TRUE; - if((ly3-ly2)>CHKMAX_Y) return TRUE; - } - if(ly3<0) - { - if((ly1-ly3)>CHKMAX_Y) return TRUE; - if((ly2-ly3)>CHKMAX_Y) return TRUE; - } - - return FALSE; -} - -static __inline BOOL CheckCoord3() -{ - if(lx0<0) - { - if((lx1-lx0)>CHKMAX_X) return TRUE; - if((lx2-lx0)>CHKMAX_X) return TRUE; - } - if(lx1<0) - { - if((lx0-lx1)>CHKMAX_X) return TRUE; - if((lx2-lx1)>CHKMAX_X) return TRUE; - } - if(lx2<0) - { - if((lx0-lx2)>CHKMAX_X) return TRUE; - if((lx1-lx2)>CHKMAX_X) return TRUE; - } - if(ly0<0) - { - if((ly1-ly0)>CHKMAX_Y) return TRUE; - if((ly2-ly0)>CHKMAX_Y) return TRUE; - } - if(ly1<0) - { - if((ly0-ly1)>CHKMAX_Y) return TRUE; - if((ly2-ly1)>CHKMAX_Y) return TRUE; - } - if(ly2<0) - { - if((ly0-ly2)>CHKMAX_Y) return TRUE; - if((ly1-ly2)>CHKMAX_Y) return TRUE; - } - - return FALSE; -} - - -static __inline BOOL CheckCoord2() -{ - if(lx0<0) - { - if((lx1-lx0)>CHKMAX_X) return TRUE; - } - if(lx1<0) - { - if((lx0-lx1)>CHKMAX_X) return TRUE; - } - if(ly0<0) - { - if((ly1-ly0)>CHKMAX_Y) return TRUE; - } - if(ly1<0) - { - if((ly0-ly1)>CHKMAX_Y) return TRUE; - } - - return FALSE; -} - -static __inline BOOL CheckCoordL(short slx0,short sly0,short slx1,short sly1) -{ - if(slx0<0) - { - if((slx1-slx0)>CHKMAX_X) return TRUE; - } - if(slx1<0) - { - if((slx0-slx1)>CHKMAX_X) return TRUE; - } - if(sly0<0) - { - if((sly1-sly0)>CHKMAX_Y) return TRUE; - } - if(sly1<0) - { - if((sly0-sly1)>CHKMAX_Y) return TRUE; - } - - return FALSE; -} - - -//////////////////////////////////////////////////////////////////////// -// mask stuff... used in silent hill -//////////////////////////////////////////////////////////////////////// - -static void cmdSTP(unsigned char * baseAddr) -{ - uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); - - lGPUstatusRet&=~0x1800; // Clear the necessary bits - lGPUstatusRet|=((gdata & 0x03) << 11); // Set the necessary bits - - if(gdata&1) {sSetMask=0x8000;lSetMask=0x80008000;} - else {sSetMask=0; lSetMask=0; } - - if(gdata&2) bCheckMask=TRUE; - else bCheckMask=FALSE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: Set texture page infos -//////////////////////////////////////////////////////////////////////// - -static void cmdTexturePage(unsigned char * baseAddr) -{ - uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); - - lGPUstatusRet&=~0x000007ff; - lGPUstatusRet|=(gdata & 0x07ff); - - usMirror=(unsigned short)(gdata&0x3000); - - UpdateGlobalTP((unsigned short)gdata); - GlobalTextREST = (gdata&0x00ffffff)>>9; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: turn on/off texture window -//////////////////////////////////////////////////////////////////////// - -static void cmdTextureWindow(unsigned char *baseAddr) -{ - uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); - - uint32_t YAlign,XAlign; - - lGPUInfoVals[INFO_TW]=gdata&0xFFFFF; - - if(gdata & 0x020) - TWin.Position.y1 = 8; // xxxx1 - else if (gdata & 0x040) - TWin.Position.y1 = 16; // xxx10 - else if (gdata & 0x080) - TWin.Position.y1 = 32; // xx100 - else if (gdata & 0x100) - TWin.Position.y1 = 64; // x1000 - else if (gdata & 0x200) - TWin.Position.y1 = 128; // 10000 - else - TWin.Position.y1 = 256; // 00000 - - // Texture window size is determined by the least bit set of the relevant 5 bits - - if (gdata & 0x001) - TWin.Position.x1 = 8; // xxxx1 - else if (gdata & 0x002) - TWin.Position.x1 = 16; // xxx10 - else if (gdata & 0x004) - TWin.Position.x1 = 32; // xx100 - else if (gdata & 0x008) - TWin.Position.x1 = 64; // x1000 - else if (gdata & 0x010) - TWin.Position.x1 = 128; // 10000 - else - 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 - (TWin.Position.y1 >> 3)); - XAlign = (uint32_t)(32 - (TWin.Position.x1 >> 3)); - - // Absolute position of the start of the texture window - - TWin.Position.y0 = (short)(((gdata >> 15) & YAlign) << 3); - TWin.Position.x0 = (short)(((gdata >> 10) & XAlign) << 3); - - if((TWin.Position.x0 == 0 && // tw turned off - TWin.Position.y0 == 0 && - TWin.Position.x1 == 0 && - TWin.Position.y1 == 0) || - (TWin.Position.x1 == 256 && - TWin.Position.y1 == 256)) - { - bUsingTWin = FALSE; // -> just do it - } - else // otherwise - { - bUsingTWin = TRUE; // -> tw turned on - } -} - -//////////////////////////////////////////////////////////////////////// -// cmd: start of drawing area... primitives will be clipped inside -//////////////////////////////////////////////////////////////////////// - - - -static void cmdDrawAreaStart(unsigned char * baseAddr) -{ - uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); - - drawX = gdata & 0x3ff; // for soft drawing - - if(dwGPUVersion==2) - { - lGPUInfoVals[INFO_DRAWSTART]=gdata&0x3FFFFF; - drawY = (gdata>>12)&0x3ff; - if(drawY>=1024) drawY=1023; // some security - } - else - { - lGPUInfoVals[INFO_DRAWSTART]=gdata&0xFFFFF; - drawY = (gdata>>10)&0x3ff; - if(drawY>=512) drawY=511; // some security - } -} - -//////////////////////////////////////////////////////////////////////// -// cmd: end of drawing area... primitives will be clipped inside -//////////////////////////////////////////////////////////////////////// - -static void cmdDrawAreaEnd(unsigned char * baseAddr) -{ - uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); - - drawW = gdata & 0x3ff; // for soft drawing - - if(dwGPUVersion==2) - { - lGPUInfoVals[INFO_DRAWEND]=gdata&0x3FFFFF; - drawH = (gdata>>12)&0x3ff; - if(drawH>=1024) drawH=1023; // some security - } - else - { - lGPUInfoVals[INFO_DRAWEND]=gdata&0xFFFFF; - drawH = (gdata>>10)&0x3ff; - if(drawH>=512) drawH=511; // some security - } -} - -//////////////////////////////////////////////////////////////////////// -// cmd: draw offset... will be added to prim coords -//////////////////////////////////////////////////////////////////////// - -static void cmdDrawOffset(unsigned char * baseAddr) -{ - uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); - - PSXDisplay.DrawOffset.x = (short)(gdata & 0x7ff); - - if(dwGPUVersion==2) - { - lGPUInfoVals[INFO_DRAWOFF]=gdata&0x7FFFFF; - PSXDisplay.DrawOffset.y = (short)((gdata>>12) & 0x7ff); - } - else - { - lGPUInfoVals[INFO_DRAWOFF]=gdata&0x3FFFFF; - PSXDisplay.DrawOffset.y = (short)((gdata>>11) & 0x7ff); - } - - PSXDisplay.DrawOffset.y=(short)(((int)PSXDisplay.DrawOffset.y<<21)>>21); - PSXDisplay.DrawOffset.x=(short)(((int)PSXDisplay.DrawOffset.x<<21)>>21); -} - -//////////////////////////////////////////////////////////////////////// -// cmd: load image to vram -//////////////////////////////////////////////////////////////////////// - -static void primLoadImage(unsigned char * baseAddr) -{ - unsigned short *sgpuData = ((unsigned short *) baseAddr); - - VRAMWrite.x = GETLEs16(&sgpuData[2])&0x3ff; - VRAMWrite.y = GETLEs16(&sgpuData[3])&iGPUHeightMask; - VRAMWrite.Width = GETLEs16(&sgpuData[4]); - VRAMWrite.Height = GETLEs16(&sgpuData[5]); - - DataWriteMode = DR_VRAMTRANSFER; - - VRAMWrite.ImagePtr = psxVuw + (VRAMWrite.y<<10) + VRAMWrite.x; - VRAMWrite.RowsRemaining = VRAMWrite.Width; - VRAMWrite.ColsRemaining = VRAMWrite.Height; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: vram -> psx mem -//////////////////////////////////////////////////////////////////////// - -static void primStoreImage(unsigned char * baseAddr) -{ - unsigned short *sgpuData = ((unsigned short *) baseAddr); - - VRAMRead.x = GETLEs16(&sgpuData[2])&0x03ff; - VRAMRead.y = GETLEs16(&sgpuData[3])&iGPUHeightMask; - VRAMRead.Width = GETLEs16(&sgpuData[4]); - VRAMRead.Height = GETLEs16(&sgpuData[5]); - - VRAMRead.ImagePtr = psxVuw + (VRAMRead.y<<10) + VRAMRead.x; - VRAMRead.RowsRemaining = VRAMRead.Width; - VRAMRead.ColsRemaining = VRAMRead.Height; - - DataReadMode = DR_VRAMTRANSFER; - - lGPUstatusRet |= GPUSTATUS_READYFORVRAM; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: blkfill - NO primitive! Doesn't care about draw areas... -//////////////////////////////////////////////////////////////////////// - -static 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]))); - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: move image vram -> vram -//////////////////////////////////////////////////////////////////////// - -static 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])&iGPUHeightMask; - imageX1 = GETLEs16(&sgpuData[4])&0x03ff; - imageY1 = GETLEs16(&sgpuData[5])&iGPUHeightMask; - imageSX = GETLEs16(&sgpuData[6]); - imageSY = GETLEs16(&sgpuData[7]); - - if((imageX0 == imageX1) && (imageY0 == imageY1)) return; - if(imageSX<=0) return; - if(imageSY<=0) return; - - // ZN SF2: screwed moves - // - // move sgpuData[2],sgpuData[3],sgpuData[4],sgpuData[5],sgpuData[6],sgpuData[7] - // - // move 365 182 32723 -21846 17219 15427 - // move 127 160 147 -1 20817 13409 - // move 141 165 16275 -21862 -32126 13442 - // move 161 136 24620 -1 16962 13388 - // move 168 138 32556 -13090 -29556 15500 - // - // and here's the hack for it: - - if(iGPUHeight==1024 && GETLEs16(&sgpuData[7])>1024) return; - - if((imageY0+imageSY)>iGPUHeight || - (imageX0+imageSX)>1024 || - (imageY1+imageSY)>iGPUHeight || - (imageX1+imageSX)>1024) - { - int i,j; - for(j=0;j>1; - - SRCPtr = (uint32_t *)(psxVuw + (1024*imageY0) + imageX0); - DSTPtr = (uint32_t *)(psxVuw + (1024*imageY1) + imageX1); - - LineOffset = 512 - dx; - - for(j=0;j=PSXDisplay.DisplayPosition.x && - imageY1=PSXDisplay.DisplayPosition.y) - updateDisplay(); - } -*/ - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: draw free-size Tile -//////////////////////////////////////////////////////////////////////// - -//#define SMALLDEBUG -//#include - -static 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]) & iGPUHeightMask; // mmm... limit tiles to 0x1ff or height? - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - - if(!(dwActFixes&8)) AdjustCoord1(); - - // x and y of start - ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; - ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; - lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; - lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; - - DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; - - if(!(iTileCheat && sH==32 && GETLE32(&gpuData[0])==0x60ffffff)) // special cheat for certain ZiNc games - FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, - BGR24to16(GETLE32(&gpuData[0]))); - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: draw 1 dot Tile (point) -//////////////////////////////////////////////////////////////////////// - -static void primTile1(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t*)baseAddr); - short *sgpuData = ((short *) baseAddr); - short sH = 1; - short sW = 1; - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - - if(!(dwActFixes&8)) AdjustCoord1(); - - // x and y of start - ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; - ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; - lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; - lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; - - DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; - - FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, - BGR24to16(GETLE32(&gpuData[0]))); // Takes Start and Offset - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: draw 8 dot Tile (small rect) -//////////////////////////////////////////////////////////////////////// - -static void primTile8(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t*)baseAddr); - short *sgpuData = ((short *) baseAddr); - short sH = 8; - short sW = 8; - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - - if(!(dwActFixes&8)) AdjustCoord1(); - - // x and y of start - ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; - ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; - lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; - lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; - - DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; - - FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, - BGR24to16(GETLE32(&gpuData[0]))); // Takes Start and Offset - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: draw 16 dot Tile (medium rect) -//////////////////////////////////////////////////////////////////////// - -static void primTile16(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t*)baseAddr); - short *sgpuData = ((short *) baseAddr); - short sH = 16; - short sW = 16; - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - - if(!(dwActFixes&8)) AdjustCoord1(); - - // x and y of start - ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; - ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; - lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; - lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; - - DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; - - FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, - BGR24to16(GETLE32(&gpuData[0]))); // Takes Start and Offset - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: small sprite (textured rect) -//////////////////////////////////////////////////////////////////////// - -static void primSprt8(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - - if(!(dwActFixes&8)) AdjustCoord1(); - - SetRenderMode(GETLE32(&gpuData[0])); - - if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,8,8); - else - if(usMirror) DrawSoftwareSpriteMirror(baseAddr,8,8); - else DrawSoftwareSprite(baseAddr,8,8, - baseAddr[8], - baseAddr[9]); - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: medium sprite (textured rect) -//////////////////////////////////////////////////////////////////////// - -static void primSprt16(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - - if(!(dwActFixes&8)) AdjustCoord1(); - - SetRenderMode(GETLE32(&gpuData[0])); - - if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,16,16); - else - if(usMirror) DrawSoftwareSpriteMirror(baseAddr,16,16); - else DrawSoftwareSprite(baseAddr,16,16, - baseAddr[8], - baseAddr[9]); - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: free-size sprite (textured rect) -//////////////////////////////////////////////////////////////////////// - -// func used on texture coord wrap -static 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;} - - lx0 = sX; - ly0 = sY; - - if(!(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); - } - -} - -//////////////////////////////////////////////////////////////////////// - -static void primSprtS(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - short sW,sH; - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - - if(!(dwActFixes&8)) AdjustCoord1(); - - sW = GETLEs16(&sgpuData[6]) & 0x3ff; - sH = GETLEs16(&sgpuData[7]) & 0x1ff; - - SetRenderMode(GETLE32(&gpuData[0])); - - if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,sW,sH); - else - if(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); - } - - } - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: flat shaded Poly4 -//////////////////////////////////////////////////////////////////////// - -static void primPolyF4(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - lx1 = GETLEs16(&sgpuData[4]); - ly1 = GETLEs16(&sgpuData[5]); - lx2 = GETLEs16(&sgpuData[6]); - ly2 = GETLEs16(&sgpuData[7]); - lx3 = GETLEs16(&sgpuData[8]); - ly3 = GETLEs16(&sgpuData[9]); - - if(!(dwActFixes&8)) - { - AdjustCoord4(); - if(CheckCoord4()) return; - } - - offsetPSX4(); - DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; - - drawPoly4F(GETLE32(&gpuData[0])); - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: smooth shaded Poly4 -//////////////////////////////////////////////////////////////////////// - -static void primPolyG4(unsigned char * baseAddr) -{ - uint32_t *gpuData = (uint32_t *)baseAddr; - short *sgpuData = ((short *) baseAddr); - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - lx1 = GETLEs16(&sgpuData[6]); - ly1 = GETLEs16(&sgpuData[7]); - lx2 = GETLEs16(&sgpuData[10]); - ly2 = GETLEs16(&sgpuData[11]); - lx3 = GETLEs16(&sgpuData[14]); - ly3 = GETLEs16(&sgpuData[15]); - - if(!(dwActFixes&8)) - { - AdjustCoord4(); - if(CheckCoord4()) return; - } - - offsetPSX4(); - DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; - - drawPoly4G(GETLE32(&gpuData[0]), GETLE32(&gpuData[2]), - GETLE32(&gpuData[4]), GETLE32(&gpuData[6])); - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: flat shaded Texture3 -//////////////////////////////////////////////////////////////////////// - -static void primPolyFT3(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - lx1 = GETLEs16(&sgpuData[6]); - ly1 = GETLEs16(&sgpuData[7]); - lx2 = GETLEs16(&sgpuData[10]); - ly2 = GETLEs16(&sgpuData[11]); - - lLowerpart=GETLE32(&gpuData[4])>>16; - UpdateGlobalTP((unsigned short)lLowerpart); - - if(!(dwActFixes&8)) - { - AdjustCoord3(); - if(CheckCoord3()) return; - } - - offsetPSX3(); - SetRenderMode(GETLE32(&gpuData[0])); - - drawPoly3FT(baseAddr); - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: flat shaded Texture4 -//////////////////////////////////////////////////////////////////////// - -static void primPolyFT4(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - lx1 = GETLEs16(&sgpuData[6]); - ly1 = GETLEs16(&sgpuData[7]); - lx2 = GETLEs16(&sgpuData[10]); - ly2 = GETLEs16(&sgpuData[11]); - lx3 = GETLEs16(&sgpuData[14]); - ly3 = GETLEs16(&sgpuData[15]); - - lLowerpart=GETLE32(&gpuData[4])>>16; - UpdateGlobalTP((unsigned short)lLowerpart); - - if(!(dwActFixes&8)) - { - AdjustCoord4(); - if(CheckCoord4()) return; - } - - offsetPSX4(); - - SetRenderMode(GETLE32(&gpuData[0])); - - drawPoly4FT(baseAddr); - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: smooth shaded Texture3 -//////////////////////////////////////////////////////////////////////// - -static void primPolyGT3(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - lx1 = GETLEs16(&sgpuData[8]); - ly1 = GETLEs16(&sgpuData[9]); - lx2 = GETLEs16(&sgpuData[14]); - ly2 = GETLEs16(&sgpuData[15]); - - lLowerpart=GETLE32(&gpuData[5])>>16; - UpdateGlobalTP((unsigned short)lLowerpart); - - if(!(dwActFixes&8)) - { - AdjustCoord3(); - if(CheckCoord3()) return; - } - - offsetPSX3(); - DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; - - 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); - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: smooth shaded Poly3 -//////////////////////////////////////////////////////////////////////// - -static void primPolyG3(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - lx1 = GETLEs16(&sgpuData[6]); - ly1 = GETLEs16(&sgpuData[7]); - lx2 = GETLEs16(&sgpuData[10]); - ly2 = GETLEs16(&sgpuData[11]); - - if(!(dwActFixes&8)) - { - AdjustCoord3(); - if(CheckCoord3()) return; - } - - offsetPSX3(); - DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; - - drawPoly3G(GETLE32(&gpuData[0]), GETLE32(&gpuData[2]), GETLE32(&gpuData[4])); - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: smooth shaded Texture4 -//////////////////////////////////////////////////////////////////////// - -static void primPolyGT4(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - lx1 = GETLEs16(&sgpuData[8]); - ly1 = GETLEs16(&sgpuData[9]); - lx2 = GETLEs16(&sgpuData[14]); - ly2 = GETLEs16(&sgpuData[15]); - lx3 = GETLEs16(&sgpuData[20]); - ly3 = GETLEs16(&sgpuData[21]); - - lLowerpart=GETLE32(&gpuData[5])>>16; - UpdateGlobalTP((unsigned short)lLowerpart); - - if(!(dwActFixes&8)) - { - AdjustCoord4(); - if(CheckCoord4()) return; - } - - offsetPSX4(); - DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; - - 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); - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: smooth shaded Poly3 -//////////////////////////////////////////////////////////////////////// - -static void primPolyF3(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - lx1 = GETLEs16(&sgpuData[4]); - ly1 = GETLEs16(&sgpuData[5]); - lx2 = GETLEs16(&sgpuData[6]); - ly2 = GETLEs16(&sgpuData[7]); - - if(!(dwActFixes&8)) - { - AdjustCoord3(); - if(CheckCoord3()) return; - } - - offsetPSX3(); - SetRenderMode(GETLE32(&gpuData[0])); - - drawPoly3F(GETLE32(&gpuData[0])); - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: skipping shaded polylines -//////////////////////////////////////////////////////////////////////// - -static void primLineGSkip(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - int iMax=255; - int i=2; - - ly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); - lx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); - - while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=4)) - { - i++; - ly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff); - lx1 = (short)(GETLE32(&gpuData[i]) & 0xffff); - i++;if(i>iMax) break; - } -} - -//////////////////////////////////////////////////////////////////////// -// cmd: shaded polylines -//////////////////////////////////////////////////////////////////////// - -static 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;BOOL bDraw=TRUE; - - sly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); - slx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); - - if(!(dwActFixes&8)) - { - slx1=(short)(((int)slx1<>SIGNSHIFT); - sly1=(short)(((int)sly1<>SIGNSHIFT); - } - - lc1 = gpuData[0] & 0xffffff; - - DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; - - 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(!(dwActFixes&8)) - { - slx1=(short)(((int)slx1<>SIGNSHIFT); - sly1=(short)(((int)sly1<>SIGNSHIFT); - if(CheckCoordL(slx0,sly0,slx1,sly1)) bDraw=FALSE; else bDraw=TRUE; - } - - if ((lx0 != lx1) || (ly0 != ly1)) - { - ly0=sly0; - lx0=slx0; - ly1=sly1; - lx1=slx1; - - offsetPSX2(); - if(bDraw) DrawSoftwareLineShade(lc0, lc1); - } - i++; - if(i>iMax) break; - } - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: shaded polyline2 -//////////////////////////////////////////////////////////////////////// - -static void primLineG2(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - lx1 = GETLEs16(&sgpuData[6]); - ly1 = GETLEs16(&sgpuData[7]); - - if(!(dwActFixes&8)) - { - AdjustCoord2(); - if(CheckCoord2()) return; - } - - if((lx0 == lx1) && (ly0 == ly1)) {lx1++;ly1++;} - - DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; - offsetPSX2(); - DrawSoftwareLineShade(GETLE32(&gpuData[0]),GETLE32(&gpuData[2])); - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: skipping flat polylines -//////////////////////////////////////////////////////////////////////// - -static void primLineFSkip(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - int i=2,iMax=255; - - ly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); - lx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); - - while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=3)) - { - ly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff); - lx1 = (short)(GETLE32(&gpuData[i]) & 0xffff); - i++;if(i>iMax) break; - } -} - -//////////////////////////////////////////////////////////////////////// -// cmd: drawing flat polylines -//////////////////////////////////////////////////////////////////////// - -static void primLineFEx(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - int iMax; - short slx0,slx1,sly0,sly1;int i=2;BOOL bDraw=TRUE; - - iMax=255; - - sly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); - slx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); - if(!(dwActFixes&8)) - { - slx1=(short)(((int)slx1<>SIGNSHIFT); - sly1=(short)(((int)sly1<>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(!(dwActFixes&8)) - { - slx1=(short)(((int)slx1<>SIGNSHIFT); - sly1=(short)(((int)sly1<>SIGNSHIFT); - - if(CheckCoordL(slx0,sly0,slx1,sly1)) bDraw=FALSE; else bDraw=TRUE; - } - - ly0=sly0; - lx0=slx0; - ly1=sly1; - lx1=slx1; - - offsetPSX2(); - if(bDraw) DrawSoftwareLineFlat(GETLE32(&gpuData[0])); - - i++;if(i>iMax) break; - } - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: drawing flat polyline2 -//////////////////////////////////////////////////////////////////////// - -static void primLineF2(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = GETLEs16(&sgpuData[2]); - ly0 = GETLEs16(&sgpuData[3]); - lx1 = GETLEs16(&sgpuData[4]); - ly1 = GETLEs16(&sgpuData[5]); - - if(!(dwActFixes&8)) - { - AdjustCoord2(); - if(CheckCoord2()) return; - } - - if((lx0 == lx1) && (ly0 == ly1)) {lx1++;ly1++;} - - offsetPSX2(); - SetRenderMode(GETLE32(&gpuData[0])); - - DrawSoftwareLineFlat(GETLE32(&gpuData[0])); - - bDoVSyncUpdate=TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: well, easiest command... not implemented -//////////////////////////////////////////////////////////////////////// - -static void primNI(unsigned char *bA) -{ -} - -//////////////////////////////////////////////////////////////////////// -// cmd func ptr table -//////////////////////////////////////////////////////////////////////// - - -void (*primTableJ[256])(unsigned char *) = -{ - // 00 - primNI,primNI,primBlkFill,primNI,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 -}; - -//////////////////////////////////////////////////////////////////////// -// cmd func ptr table for skipping -//////////////////////////////////////////////////////////////////////// - -void (*primTableSkip[256])(unsigned char *) = -{ - // 00 - primNI,primNI,primBlkFill,primNI,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 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 28 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 30 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 38 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 40 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 48 - primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip, - // 50 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 58 - primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip, - // 60 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 68 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 70 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 78 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 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 -}; +/*************************************************************************** + 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. * + * * + ***************************************************************************/ + +#define _IN_PRIMDRAW + +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "soft.h" +#include "swap.h" + +//////////////////////////////////////////////////////////////////////// +// globals +//////////////////////////////////////////////////////////////////////// + +BOOL bUsingTWin=FALSE; +TWin_t TWin; +//unsigned long clutid; // global clut +unsigned short usMirror=0; // sprite mirror +int iDither=0; +int32_t drawX; +int32_t drawY; +int32_t drawW; +int32_t drawH; +uint32_t dwCfgFixes; +uint32_t dwActFixes=0; +uint32_t dwEmuFixes=0; +int iUseFixes; +int iUseDither=0; +BOOL bDoVSyncUpdate=FALSE; + +//////////////////////////////////////////////////////////////////////// +// 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) +{ + GlobalTextAddrX = (gdata << 6) & 0x3c0; // texture addr + + if(iGPUHeight==1024) + { + if(dwGPUVersion==2) + { + GlobalTextAddrY =((gdata & 0x60 ) << 3); + GlobalTextIL =(gdata & 0x2000) >> 13; + GlobalTextABR = (unsigned short)((gdata >> 7) & 0x3); + GlobalTextTP = (gdata >> 9) & 0x3; + if(GlobalTextTP==3) GlobalTextTP=2; + usMirror =0; + lGPUstatusRet = (lGPUstatusRet & 0xffffe000 ) | (gdata & 0x1fff ); + + // tekken dithering? right now only if dithering is forced by user + if(iUseDither==2) iDither=2; else iDither=0; + + return; + } + else + { + GlobalTextAddrY = (unsigned short)(((gdata << 4) & 0x100) | ((gdata >> 2) & 0x200)); + } + } + else GlobalTextAddrY = (gdata << 4) & 0x100; + + GlobalTextTP = (gdata >> 7) & 0x3; // tex mode (4,8,15) + + if(GlobalTextTP==3) GlobalTextTP=2; // seen in Wild9 :( + + GlobalTextABR = (gdata >> 5) & 0x3; // blend mode + + lGPUstatusRet&=~0x000001ff; // Clear the necessary bits + lGPUstatusRet|=(gdata & 0x01ff); // set the necessary bits + + switch(iUseDither) + { + case 0: + iDither=0; + break; + case 1: + if(lGPUstatusRet&0x0200) iDither=2; + else iDither=0; + break; + case 2: + iDither=2; + break; + } +} + +//////////////////////////////////////////////////////////////////////// + +__inline void SetRenderMode(uint32_t DrawAttributes) +{ + DrawSemiTrans = (SEMITRANSBIT(DrawAttributes)) ? TRUE : FALSE; + + if(SHADETEXBIT(DrawAttributes)) + {g_m1=g_m2=g_m3=128;} + else + { + if((dwActFixes&4) && ((DrawAttributes&0x00ffffff)==0)) + DrawAttributes|=0x007f7f7f; + + g_m1=(short)(DrawAttributes&0xff); + g_m2=(short)((DrawAttributes>>8)&0xff); + 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() +{ + lx0=(short)(((int)lx0<>SIGNSHIFT); + lx1=(short)(((int)lx1<>SIGNSHIFT); + lx2=(short)(((int)lx2<>SIGNSHIFT); + lx3=(short)(((int)lx3<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + ly1=(short)(((int)ly1<>SIGNSHIFT); + ly2=(short)(((int)ly2<>SIGNSHIFT); + ly3=(short)(((int)ly3<>SIGNSHIFT); +} + +void AdjustCoord3() +{ + lx0=(short)(((int)lx0<>SIGNSHIFT); + lx1=(short)(((int)lx1<>SIGNSHIFT); + lx2=(short)(((int)lx2<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + ly1=(short)(((int)ly1<>SIGNSHIFT); + ly2=(short)(((int)ly2<>SIGNSHIFT); +} + +void AdjustCoord2() +{ + lx0=(short)(((int)lx0<>SIGNSHIFT); + lx1=(short)(((int)lx1<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + ly1=(short)(((int)ly1<>SIGNSHIFT); +} + +void AdjustCoord1() +{ + lx0=(short)(((int)lx0<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + + if(lx0<-512 && PSXDisplay.DrawOffset.x<=-512) + lx0+=2048; + + if(ly0<-512 && PSXDisplay.DrawOffset.y<=-512) + 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 BOOL CheckCoord4() +{ + if(lx0<0) + { + if(((lx1-lx0)>CHKMAX_X) || + ((lx2-lx0)>CHKMAX_X)) + { + if(lx3<0) + { + if((lx1-lx3)>CHKMAX_X) return TRUE; + if((lx2-lx3)>CHKMAX_X) return TRUE; + } + } + } + if(lx1<0) + { + if((lx0-lx1)>CHKMAX_X) return TRUE; + if((lx2-lx1)>CHKMAX_X) return TRUE; + if((lx3-lx1)>CHKMAX_X) return TRUE; + } + if(lx2<0) + { + if((lx0-lx2)>CHKMAX_X) return TRUE; + if((lx1-lx2)>CHKMAX_X) return TRUE; + if((lx3-lx2)>CHKMAX_X) return TRUE; + } + if(lx3<0) + { + if(((lx1-lx3)>CHKMAX_X) || + ((lx2-lx3)>CHKMAX_X)) + { + if(lx0<0) + { + if((lx1-lx0)>CHKMAX_X) return TRUE; + if((lx2-lx0)>CHKMAX_X) return TRUE; + } + } + } + + + if(ly0<0) + { + if((ly1-ly0)>CHKMAX_Y) return TRUE; + if((ly2-ly0)>CHKMAX_Y) return TRUE; + } + if(ly1<0) + { + if((ly0-ly1)>CHKMAX_Y) return TRUE; + if((ly2-ly1)>CHKMAX_Y) return TRUE; + if((ly3-ly1)>CHKMAX_Y) return TRUE; + } + if(ly2<0) + { + if((ly0-ly2)>CHKMAX_Y) return TRUE; + if((ly1-ly2)>CHKMAX_Y) return TRUE; + if((ly3-ly2)>CHKMAX_Y) return TRUE; + } + if(ly3<0) + { + if((ly1-ly3)>CHKMAX_Y) return TRUE; + if((ly2-ly3)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + +__inline BOOL CheckCoord3() +{ + if(lx0<0) + { + if((lx1-lx0)>CHKMAX_X) return TRUE; + if((lx2-lx0)>CHKMAX_X) return TRUE; + } + if(lx1<0) + { + if((lx0-lx1)>CHKMAX_X) return TRUE; + if((lx2-lx1)>CHKMAX_X) return TRUE; + } + if(lx2<0) + { + if((lx0-lx2)>CHKMAX_X) return TRUE; + if((lx1-lx2)>CHKMAX_X) return TRUE; + } + if(ly0<0) + { + if((ly1-ly0)>CHKMAX_Y) return TRUE; + if((ly2-ly0)>CHKMAX_Y) return TRUE; + } + if(ly1<0) + { + if((ly0-ly1)>CHKMAX_Y) return TRUE; + if((ly2-ly1)>CHKMAX_Y) return TRUE; + } + if(ly2<0) + { + if((ly0-ly2)>CHKMAX_Y) return TRUE; + if((ly1-ly2)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + + +__inline BOOL CheckCoord2() +{ + if(lx0<0) + { + if((lx1-lx0)>CHKMAX_X) return TRUE; + } + if(lx1<0) + { + if((lx0-lx1)>CHKMAX_X) return TRUE; + } + if(ly0<0) + { + if((ly1-ly0)>CHKMAX_Y) return TRUE; + } + if(ly1<0) + { + if((ly0-ly1)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + +__inline BOOL CheckCoordL(short slx0,short sly0,short slx1,short sly1) +{ + if(slx0<0) + { + if((slx1-slx0)>CHKMAX_X) return TRUE; + } + if(slx1<0) + { + if((slx0-slx1)>CHKMAX_X) return TRUE; + } + if(sly0<0) + { + if((sly1-sly0)>CHKMAX_Y) return TRUE; + } + if(sly1<0) + { + if((sly0-sly1)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + + +//////////////////////////////////////////////////////////////////////// +// mask stuff... used in silent hill +//////////////////////////////////////////////////////////////////////// + +void cmdSTP(unsigned char * baseAddr) +{ + uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); + + lGPUstatusRet&=~0x1800; // Clear the necessary bits + lGPUstatusRet|=((gdata & 0x03) << 11); // Set the necessary bits + + if(gdata&1) {sSetMask=0x8000;lSetMask=0x80008000;} + else {sSetMask=0; lSetMask=0; } + + if(gdata&2) bCheckMask=TRUE; + else bCheckMask=FALSE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: Set texture page infos +//////////////////////////////////////////////////////////////////////// + +void cmdTexturePage(unsigned char * baseAddr) +{ + uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); + + lGPUstatusRet&=~0x000007ff; + lGPUstatusRet|=(gdata & 0x07ff); + + usMirror=(unsigned short)(gdata&0x3000); + + UpdateGlobalTP((unsigned short)gdata); + 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; + + lGPUInfoVals[INFO_TW]=gdata&0xFFFFF; + + if(gdata & 0x020) + TWin.Position.y1 = 8; // xxxx1 + else if (gdata & 0x040) + TWin.Position.y1 = 16; // xxx10 + else if (gdata & 0x080) + TWin.Position.y1 = 32; // xx100 + else if (gdata & 0x100) + TWin.Position.y1 = 64; // x1000 + else if (gdata & 0x200) + TWin.Position.y1 = 128; // 10000 + else + TWin.Position.y1 = 256; // 00000 + + // Texture window size is determined by the least bit set of the relevant 5 bits + + if (gdata & 0x001) + TWin.Position.x1 = 8; // xxxx1 + else if (gdata & 0x002) + TWin.Position.x1 = 16; // xxx10 + else if (gdata & 0x004) + TWin.Position.x1 = 32; // xx100 + else if (gdata & 0x008) + TWin.Position.x1 = 64; // x1000 + else if (gdata & 0x010) + TWin.Position.x1 = 128; // 10000 + else + 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 - (TWin.Position.y1 >> 3)); + XAlign = (uint32_t)(32 - (TWin.Position.x1 >> 3)); + + // Absolute position of the start of the texture window + + TWin.Position.y0 = (short)(((gdata >> 15) & YAlign) << 3); + TWin.Position.x0 = (short)(((gdata >> 10) & XAlign) << 3); + + if((TWin.Position.x0 == 0 && // tw turned off + TWin.Position.y0 == 0 && + TWin.Position.x1 == 0 && + TWin.Position.y1 == 0) || + (TWin.Position.x1 == 256 && + TWin.Position.y1 == 256)) + { + bUsingTWin = FALSE; // -> just do it + } + else // otherwise + { + bUsingTWin = TRUE; // -> 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]); + + drawX = gdata & 0x3ff; // for soft drawing + + if(dwGPUVersion==2) + { + lGPUInfoVals[INFO_DRAWSTART]=gdata&0x3FFFFF; + drawY = (gdata>>12)&0x3ff; + if(drawY>=1024) drawY=1023; // some security + } + else + { + lGPUInfoVals[INFO_DRAWSTART]=gdata&0xFFFFF; + drawY = (gdata>>10)&0x3ff; + if(drawY>=512) 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]); + + drawW = gdata & 0x3ff; // for soft drawing + + if(dwGPUVersion==2) + { + lGPUInfoVals[INFO_DRAWEND]=gdata&0x3FFFFF; + drawH = (gdata>>12)&0x3ff; + if(drawH>=1024) drawH=1023; // some security + } + else + { + lGPUInfoVals[INFO_DRAWEND]=gdata&0xFFFFF; + drawH = (gdata>>10)&0x3ff; + if(drawH>=512) 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]); + + PSXDisplay.DrawOffset.x = (short)(gdata & 0x7ff); + + if(dwGPUVersion==2) + { + lGPUInfoVals[INFO_DRAWOFF]=gdata&0x7FFFFF; + PSXDisplay.DrawOffset.y = (short)((gdata>>12) & 0x7ff); + } + else + { + lGPUInfoVals[INFO_DRAWOFF]=gdata&0x3FFFFF; + PSXDisplay.DrawOffset.y = (short)((gdata>>11) & 0x7ff); + } + + PSXDisplay.DrawOffset.y=(short)(((int)PSXDisplay.DrawOffset.y<<21)>>21); + PSXDisplay.DrawOffset.x=(short)(((int)PSXDisplay.DrawOffset.x<<21)>>21); +} + +//////////////////////////////////////////////////////////////////////// +// cmd: load image to vram +//////////////////////////////////////////////////////////////////////// + +void primLoadImage(unsigned char * baseAddr) +{ + unsigned short *sgpuData = ((unsigned short *) baseAddr); + + VRAMWrite.x = GETLEs16(&sgpuData[2])&0x3ff; + VRAMWrite.y = GETLEs16(&sgpuData[3])&iGPUHeightMask; + VRAMWrite.Width = GETLEs16(&sgpuData[4]); + VRAMWrite.Height = GETLEs16(&sgpuData[5]); + + DataWriteMode = DR_VRAMTRANSFER; + + VRAMWrite.ImagePtr = psxVuw + (VRAMWrite.y<<10) + VRAMWrite.x; + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ColsRemaining = VRAMWrite.Height; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: vram -> psx mem +//////////////////////////////////////////////////////////////////////// + +void primStoreImage(unsigned char * baseAddr) +{ + unsigned short *sgpuData = ((unsigned short *) baseAddr); + + VRAMRead.x = GETLEs16(&sgpuData[2])&0x03ff; + VRAMRead.y = GETLEs16(&sgpuData[3])&iGPUHeightMask; + VRAMRead.Width = GETLEs16(&sgpuData[4]); + VRAMRead.Height = GETLEs16(&sgpuData[5]); + + VRAMRead.ImagePtr = psxVuw + (VRAMRead.y<<10) + VRAMRead.x; + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining = VRAMRead.Height; + + DataReadMode = DR_VRAMTRANSFER; + + lGPUstatusRet |= GPUSTATUS_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]))); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// 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])&iGPUHeightMask; + imageX1 = GETLEs16(&sgpuData[4])&0x03ff; + imageY1 = GETLEs16(&sgpuData[5])&iGPUHeightMask; + imageSX = GETLEs16(&sgpuData[6]); + imageSY = GETLEs16(&sgpuData[7]); + + if((imageX0 == imageX1) && (imageY0 == imageY1)) return; + if(imageSX<=0) return; + if(imageSY<=0) return; + + // ZN SF2: screwed moves + // + // move sgpuData[2],sgpuData[3],sgpuData[4],sgpuData[5],sgpuData[6],sgpuData[7] + // + // move 365 182 32723 -21846 17219 15427 + // move 127 160 147 -1 20817 13409 + // move 141 165 16275 -21862 -32126 13442 + // move 161 136 24620 -1 16962 13388 + // move 168 138 32556 -13090 -29556 15500 + // + // and here's the hack for it: + + if(iGPUHeight==1024 && GETLEs16(&sgpuData[7])>1024) return; + + if((imageY0+imageSY)>iGPUHeight || + (imageX0+imageSX)>1024 || + (imageY1+imageSY)>iGPUHeight || + (imageX1+imageSX)>1024) + { + int i,j; + for(j=0;j>1; + + SRCPtr = (uint32_t *)(psxVuw + (1024*imageY0) + imageX0); + DSTPtr = (uint32_t *)(psxVuw + (1024*imageY1) + imageX1); + + LineOffset = 512 - dx; + + for(j=0;j=PSXDisplay.DisplayPosition.x && + imageY1=PSXDisplay.DisplayPosition.y) + updateDisplay(); + } +*/ + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: draw free-size Tile +//////////////////////////////////////////////////////////////////////// + +//#define SMALLDEBUG +//#include + +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]) & iGPUHeightMask; // mmm... limit tiles to 0x1ff or height? + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + + if(!(dwActFixes&8)) AdjustCoord1(); + + // x and y of start + ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; + ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; + lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; + lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; + + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + if(!(iTileCheat && sH==32 && GETLE32(&gpuData[0])==0x60ffffff)) // special cheat for certain ZiNc games + FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, + BGR24to16(GETLE32(&gpuData[0]))); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// 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; + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + + if(!(dwActFixes&8)) AdjustCoord1(); + + // x and y of start + ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; + ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; + lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; + lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; + + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, + BGR24to16(GETLE32(&gpuData[0]))); // Takes Start and Offset + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// 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; + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + + if(!(dwActFixes&8)) AdjustCoord1(); + + // x and y of start + ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; + ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; + lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; + lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; + + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, + BGR24to16(GETLE32(&gpuData[0]))); // Takes Start and Offset + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// 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; + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + + if(!(dwActFixes&8)) AdjustCoord1(); + + // x and y of start + ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; + ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; + lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; + lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; + + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, + BGR24to16(GETLE32(&gpuData[0]))); // Takes Start and Offset + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: small sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +void primSprt8(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + + if(!(dwActFixes&8)) AdjustCoord1(); + + SetRenderMode(GETLE32(&gpuData[0])); + + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,8,8); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,8,8); + else DrawSoftwareSprite(baseAddr,8,8, + baseAddr[8], + baseAddr[9]); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: medium sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +void primSprt16(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + + if(!(dwActFixes&8)) AdjustCoord1(); + + SetRenderMode(GETLE32(&gpuData[0])); + + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,16,16); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,16,16); + else DrawSoftwareSprite(baseAddr,16,16, + baseAddr[8], + baseAddr[9]); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// 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;} + + lx0 = sX; + ly0 = sY; + + if(!(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; + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + + if(!(dwActFixes&8)) AdjustCoord1(); + + sW = GETLEs16(&sgpuData[6]) & 0x3ff; + sH = GETLEs16(&sgpuData[7]) & 0x1ff; + + SetRenderMode(GETLE32(&gpuData[0])); + + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,sW,sH); + else + if(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); + } + + } + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Poly4 +//////////////////////////////////////////////////////////////////////// + +void primPolyF4(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[4]); + ly1 = GETLEs16(&sgpuData[5]); + lx2 = GETLEs16(&sgpuData[6]); + ly2 = GETLEs16(&sgpuData[7]); + lx3 = GETLEs16(&sgpuData[8]); + ly3 = GETLEs16(&sgpuData[9]); + + if(!(dwActFixes&8)) + { + AdjustCoord4(); + if(CheckCoord4()) return; + } + + offsetPSX4(); + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + drawPoly4F(GETLE32(&gpuData[0])); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly4 +//////////////////////////////////////////////////////////////////////// + +void primPolyG4(unsigned char * baseAddr) +{ + uint32_t *gpuData = (uint32_t *)baseAddr; + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[6]); + ly1 = GETLEs16(&sgpuData[7]); + lx2 = GETLEs16(&sgpuData[10]); + ly2 = GETLEs16(&sgpuData[11]); + lx3 = GETLEs16(&sgpuData[14]); + ly3 = GETLEs16(&sgpuData[15]); + + if(!(dwActFixes&8)) + { + AdjustCoord4(); + if(CheckCoord4()) return; + } + + offsetPSX4(); + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + drawPoly4G(GETLE32(&gpuData[0]), GETLE32(&gpuData[2]), + GETLE32(&gpuData[4]), GETLE32(&gpuData[6])); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Texture3 +//////////////////////////////////////////////////////////////////////// + +void primPolyFT3(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[6]); + ly1 = GETLEs16(&sgpuData[7]); + lx2 = GETLEs16(&sgpuData[10]); + ly2 = GETLEs16(&sgpuData[11]); + + lLowerpart=GETLE32(&gpuData[4])>>16; + UpdateGlobalTP((unsigned short)lLowerpart); + + if(!(dwActFixes&8)) + { + AdjustCoord3(); + if(CheckCoord3()) return; + } + + offsetPSX3(); + SetRenderMode(GETLE32(&gpuData[0])); + + drawPoly3FT(baseAddr); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Texture4 +//////////////////////////////////////////////////////////////////////// + +void primPolyFT4(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[6]); + ly1 = GETLEs16(&sgpuData[7]); + lx2 = GETLEs16(&sgpuData[10]); + ly2 = GETLEs16(&sgpuData[11]); + lx3 = GETLEs16(&sgpuData[14]); + ly3 = GETLEs16(&sgpuData[15]); + + lLowerpart=GETLE32(&gpuData[4])>>16; + UpdateGlobalTP((unsigned short)lLowerpart); + + if(!(dwActFixes&8)) + { + AdjustCoord4(); + if(CheckCoord4()) return; + } + + offsetPSX4(); + + SetRenderMode(GETLE32(&gpuData[0])); + + drawPoly4FT(baseAddr); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Texture3 +//////////////////////////////////////////////////////////////////////// + +void primPolyGT3(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[8]); + ly1 = GETLEs16(&sgpuData[9]); + lx2 = GETLEs16(&sgpuData[14]); + ly2 = GETLEs16(&sgpuData[15]); + + lLowerpart=GETLE32(&gpuData[5])>>16; + UpdateGlobalTP((unsigned short)lLowerpart); + + if(!(dwActFixes&8)) + { + AdjustCoord3(); + if(CheckCoord3()) return; + } + + offsetPSX3(); + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + 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); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly3 +//////////////////////////////////////////////////////////////////////// + +void primPolyG3(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[6]); + ly1 = GETLEs16(&sgpuData[7]); + lx2 = GETLEs16(&sgpuData[10]); + ly2 = GETLEs16(&sgpuData[11]); + + if(!(dwActFixes&8)) + { + AdjustCoord3(); + if(CheckCoord3()) return; + } + + offsetPSX3(); + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + drawPoly3G(GETLE32(&gpuData[0]), GETLE32(&gpuData[2]), GETLE32(&gpuData[4])); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Texture4 +//////////////////////////////////////////////////////////////////////// + +void primPolyGT4(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[8]); + ly1 = GETLEs16(&sgpuData[9]); + lx2 = GETLEs16(&sgpuData[14]); + ly2 = GETLEs16(&sgpuData[15]); + lx3 = GETLEs16(&sgpuData[20]); + ly3 = GETLEs16(&sgpuData[21]); + + lLowerpart=GETLE32(&gpuData[5])>>16; + UpdateGlobalTP((unsigned short)lLowerpart); + + if(!(dwActFixes&8)) + { + AdjustCoord4(); + if(CheckCoord4()) return; + } + + offsetPSX4(); + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + 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); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly3 +//////////////////////////////////////////////////////////////////////// + +void primPolyF3(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[4]); + ly1 = GETLEs16(&sgpuData[5]); + lx2 = GETLEs16(&sgpuData[6]); + ly2 = GETLEs16(&sgpuData[7]); + + if(!(dwActFixes&8)) + { + AdjustCoord3(); + if(CheckCoord3()) return; + } + + offsetPSX3(); + SetRenderMode(GETLE32(&gpuData[0])); + + drawPoly3F(GETLE32(&gpuData[0])); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: skipping shaded polylines +//////////////////////////////////////////////////////////////////////// + +void primLineGSkip(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + int iMax=255; + int i=2; + + ly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); + lx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); + + while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=4)) + { + i++; + ly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff); + 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;BOOL bDraw=TRUE; + + sly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); + slx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); + + if(!(dwActFixes&8)) + { + slx1=(short)(((int)slx1<>SIGNSHIFT); + sly1=(short)(((int)sly1<>SIGNSHIFT); + } + + lc1 = gpuData[0] & 0xffffff; + + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + + 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(!(dwActFixes&8)) + { + slx1=(short)(((int)slx1<>SIGNSHIFT); + sly1=(short)(((int)sly1<>SIGNSHIFT); + if(CheckCoordL(slx0,sly0,slx1,sly1)) bDraw=FALSE; else bDraw=TRUE; + } + + if ((lx0 != lx1) || (ly0 != ly1)) + { + ly0=sly0; + lx0=slx0; + ly1=sly1; + lx1=slx1; + + offsetPSX2(); + if(bDraw) DrawSoftwareLineShade(lc0, lc1); + } + i++; + if(i>iMax) break; + } + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: shaded polyline2 +//////////////////////////////////////////////////////////////////////// + +void primLineG2(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[6]); + ly1 = GETLEs16(&sgpuData[7]); + + if(!(dwActFixes&8)) + { + AdjustCoord2(); + if(CheckCoord2()) return; + } + + if((lx0 == lx1) && (ly0 == ly1)) {lx1++;ly1++;} + + DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; + offsetPSX2(); + DrawSoftwareLineShade(GETLE32(&gpuData[0]),GETLE32(&gpuData[2])); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: skipping flat polylines +//////////////////////////////////////////////////////////////////////// + +void primLineFSkip(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + int i=2,iMax=255; + + ly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); + lx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); + + while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=3)) + { + ly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff); + 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;BOOL bDraw=TRUE; + + iMax=255; + + sly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); + slx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); + if(!(dwActFixes&8)) + { + slx1=(short)(((int)slx1<>SIGNSHIFT); + sly1=(short)(((int)sly1<>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(!(dwActFixes&8)) + { + slx1=(short)(((int)slx1<>SIGNSHIFT); + sly1=(short)(((int)sly1<>SIGNSHIFT); + + if(CheckCoordL(slx0,sly0,slx1,sly1)) bDraw=FALSE; else bDraw=TRUE; + } + + ly0=sly0; + lx0=slx0; + ly1=sly1; + lx1=slx1; + + offsetPSX2(); + if(bDraw) DrawSoftwareLineFlat(GETLE32(&gpuData[0])); + + i++;if(i>iMax) break; + } + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: drawing flat polyline2 +//////////////////////////////////////////////////////////////////////// + +void primLineF2(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = GETLEs16(&sgpuData[2]); + ly0 = GETLEs16(&sgpuData[3]); + lx1 = GETLEs16(&sgpuData[4]); + ly1 = GETLEs16(&sgpuData[5]); + + if(!(dwActFixes&8)) + { + AdjustCoord2(); + if(CheckCoord2()) return; + } + + if((lx0 == lx1) && (ly0 == ly1)) {lx1++;ly1++;} + + offsetPSX2(); + SetRenderMode(GETLE32(&gpuData[0])); + + DrawSoftwareLineFlat(GETLE32(&gpuData[0])); + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: well, easiest command... not implemented +//////////////////////////////////////////////////////////////////////// + +void primNI(unsigned char *bA) +{ +} + +//////////////////////////////////////////////////////////////////////// +// cmd func ptr table +//////////////////////////////////////////////////////////////////////// + + +void (*primTableJ[256])(unsigned char *) = +{ + // 00 + primNI,primNI,primBlkFill,primNI,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 +}; + +//////////////////////////////////////////////////////////////////////// +// cmd func ptr table for skipping +//////////////////////////////////////////////////////////////////////// + +void (*primTableSkip[256])(unsigned char *) = +{ + // 00 + primNI,primNI,primBlkFill,primNI,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 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 28 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 30 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 38 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 40 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 48 + primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip, + // 50 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 58 + primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip, + // 60 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 68 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 70 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 78 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 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/dfxvideo/soft.c b/plugins/dfxvideo/soft.c index a0b2d25e..b0cbc290 100644 --- a/plugins/dfxvideo/soft.c +++ b/plugins/dfxvideo/soft.c @@ -1,8488 +1,8488 @@ -/*************************************************************************** - 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. * - * * - ***************************************************************************/ - -#define _IN_SOFT - -#include "externals.h" -#include "soft.h" - -//#define VC_INLINE -#include "gpu.h" -#include "prim.h" -#include "menu.h" -#include "swap.h" - -#ifdef _WINDOWS -#pragma warning (disable:4244) -#pragma warning (disable:4761) -#endif - -//////////////////////////////////////////////////////////////////////////////////// -// "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 -//////////////////////////////////////////////////////////////////////////////////// - -short g_m1=255,g_m2=255,g_m3=255; -short DrawSemiTrans=FALSE; -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; - -//////////////////////////////////////////////////////////////////////// -// POLYGON OFFSET FUNCS -//////////////////////////////////////////////////////////////////////// - -void offsetPSXLine(void) -{ - short x0,x1,y0,y1,dx,dy;float px,py; - - x0 = lx0+1+PSXDisplay.DrawOffset.x; - x1 = lx1+1+PSXDisplay.DrawOffset.x; - y0 = ly0+1+PSXDisplay.DrawOffset.y; - y1 = ly1+1+PSXDisplay.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(dxdy) px= 0.5f; - else if(dx=0) - { - py=0.5f; - dx=-dx; - if(dx>dy) px=-0.5f; - else if(dxdy) py=-0.5f; - else if(dx>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, ((unsigned short)b<<10) | - ((unsigned short)g<<5) | - (unsigned short)r | sM); -} - -///////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////// - -static __inline void GetShadeTransCol_Dither(unsigned short * pdest, int32_t m1, int32_t m2, int32_t m3) -{ - int32_t r,g,b; - - if(bCheckMask && (*pdest & HOST2LE16(0x8000))) return; - - if(DrawSemiTrans) - { - r=((XCOL1D(GETLE16(pdest)))<<3); - b=((XCOL2D(GETLE16(pdest)))<<3); - g=((XCOL3D(GETLE16(pdest)))<<3); - - if(GlobalTextABR==0) - { - r=(r>>1)+(m1>>1); - b=(b>>1)+(m2>>1); - g=(g>>1)+(m3>>1); - } - else - if(GlobalTextABR==1) - { - r+=m1; - b+=m2; - g+=m3; - } - else - if(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,sSetMask); -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetShadeTransCol(unsigned short * pdest,unsigned short color) -{ - if(bCheckMask && (*pdest & HOST2LE16(0x8000))) return; - - if(DrawSemiTrans) - { - int32_t r,g,b; - - if(GlobalTextABR==0) - { - PUTLE16(pdest, (((GETLE16(pdest)&0x7bde)>>1)+(((color)&0x7bde)>>1))|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(GlobalTextABR==1) - { - r=(XCOL1(GETLE16(pdest)))+((XCOL1(color))); - b=(XCOL2(GETLE16(pdest)))+((XCOL2(color))); - g=(XCOL3(GETLE16(pdest)))+((XCOL3(color))); - } - else - if(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))|sSetMask);//0x8000; - } - else PUTLE16(pdest, color|sSetMask); -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetShadeTransCol32(uint32_t * pdest,uint32_t color) -{ - if(DrawSemiTrans) - { - int32_t r,g,b; - - if(GlobalTextABR==0) - { - if(!bCheckMask) - { - PUTLE32(pdest, (((GETLE32(pdest)&0x7bde7bde)>>1)+(((color)&0x7bde7bde)>>1))|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(GlobalTextABR==1) - { - r=(X32COL1(GETLE32(pdest)))+((X32COL1(color))); - b=(X32COL2(GETLE32(pdest)))+((X32COL2(color))); - g=(X32COL3(GETLE32(pdest)))+((X32COL3(color))); - } - else - if(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(bCheckMask) - { - uint32_t ma=GETLE32(pdest); - PUTLE32(pdest, (X32PSXCOL(r,g,b))|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))|lSetMask);//0x80008000; - } - else - { - if(bCheckMask) - { - uint32_t ma=GETLE32(pdest); - PUTLE32(pdest, color|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|lSetMask);//0x80008000; - } -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColG(unsigned short * pdest,unsigned short color) -{ - int32_t r,g,b;unsigned short l; - - if(color==0) return; - - if(bCheckMask && (*pdest & HOST2LE16(0x8000))) return; - - l=sSetMask|(color&0x8000); - - if(DrawSemiTrans && (color&0x8000)) - { - if(GlobalTextABR==0) - { - unsigned short d; - d =(GETLE16(pdest)&0x7bde)>>1; - color =((color) &0x7bde)>>1; - r=(XCOL1(d))+((((XCOL1(color)))* g_m1)>>7); - b=(XCOL2(d))+((((XCOL2(color)))* g_m2)>>7); - g=(XCOL3(d))+((((XCOL3(color)))* g_m3)>>7); - -/* - r=(XCOL1(*pdest)>>1)+((((XCOL1(color))>>1)* g_m1)>>7); - b=(XCOL2(*pdest)>>1)+((((XCOL2(color))>>1)* g_m2)>>7); - g=(XCOL3(*pdest)>>1)+((((XCOL3(color))>>1)* g_m3)>>7); -*/ - } - else - if(GlobalTextABR==1) - { - r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color)))* g_m1)>>7); - b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color)))* g_m2)>>7); - g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color)))* g_m3)>>7); - } - else - if(GlobalTextABR==2) - { - r=(XCOL1(GETLE16(pdest)))-((((XCOL1(color)))* g_m1)>>7); - b=(XCOL2(GETLE16(pdest)))-((((XCOL2(color)))* g_m2)>>7); - g=(XCOL3(GETLE16(pdest)))-((((XCOL3(color)))* 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_m1)>>7); - b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>2)* g_m2)>>7); - g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>2)* g_m3)>>7); -#else - r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color))>>1)* g_m1)>>7); - b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>1)* g_m2)>>7); - g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>1)* g_m3)>>7); -#endif - } - } - else - { - r=((XCOL1(color))* g_m1)>>7; - b=((XCOL2(color))* g_m2)>>7; - g=((XCOL3(color))* 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); -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColG_S(unsigned short * pdest,unsigned short color) -{ - int32_t r,g,b;unsigned short l; - - if(color==0) return; - - l=sSetMask|(color&0x8000); - - r=((XCOL1(color))* g_m1)>>7; - b=((XCOL2(color))* g_m2)>>7; - g=((XCOL3(color))* 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); -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColG_SPR(unsigned short * pdest,unsigned short color) -{ - int32_t r,g,b;unsigned short l; - - if(color==0) return; - - if(bCheckMask && (GETLE16(pdest) & 0x8000)) return; - - l=sSetMask|(color&0x8000); - - if(DrawSemiTrans && (color&0x8000)) - { - if(GlobalTextABR==0) - { - unsigned short d; - d =(GETLE16(pdest)&0x7bde)>>1; - color =((color) &0x7bde)>>1; - r=(XCOL1(d))+((((XCOL1(color)))* g_m1)>>7); - b=(XCOL2(d))+((((XCOL2(color)))* g_m2)>>7); - g=(XCOL3(d))+((((XCOL3(color)))* g_m3)>>7); - -/* - r=(XCOL1(*pdest)>>1)+((((XCOL1(color))>>1)* g_m1)>>7); - b=(XCOL2(*pdest)>>1)+((((XCOL2(color))>>1)* g_m2)>>7); - g=(XCOL3(*pdest)>>1)+((((XCOL3(color))>>1)* g_m3)>>7); -*/ - } - else - if(GlobalTextABR==1) - { - r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color)))* g_m1)>>7); - b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color)))* g_m2)>>7); - g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color)))* g_m3)>>7); - } - else - if(GlobalTextABR==2) - { - r=(XCOL1(GETLE16(pdest)))-((((XCOL1(color)))* g_m1)>>7); - b=(XCOL2(GETLE16(pdest)))-((((XCOL2(color)))* g_m2)>>7); - g=(XCOL3(GETLE16(pdest)))-((((XCOL3(color)))* 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_m1)>>7); - b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>2)* g_m2)>>7); - g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>2)* g_m3)>>7); -#else - r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color))>>1)* g_m1)>>7); - b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>1)* g_m2)>>7); - g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>1)* g_m3)>>7); -#endif - } - } - else - { - r=((XCOL1(color))* g_m1)>>7; - b=((XCOL2(color))* g_m2)>>7; - g=((XCOL3(color))* 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); -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColG32(uint32_t * pdest,uint32_t color) -{ - int32_t r,g,b,l; - - if(color==0) return; - - l=lSetMask|(color&0x80008000); - - if(DrawSemiTrans && (color&0x80008000)) - { - if(GlobalTextABR==0) - { - r=((((X32TCOL1(GETLE32(pdest)))+((X32COL1(color)) * g_m1))&0xFF00FF00)>>8); - b=((((X32TCOL2(GETLE32(pdest)))+((X32COL2(color)) * g_m2))&0xFF00FF00)>>8); - g=((((X32TCOL3(GETLE32(pdest)))+((X32COL3(color)) * g_m3))&0xFF00FF00)>>8); - } - else - if(GlobalTextABR==1) - { - r=(X32COL1(GETLE32(pdest)))+(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); - b=(X32COL2(GETLE32(pdest)))+(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); - g=(X32COL3(GETLE32(pdest)))+(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); - } - else - if(GlobalTextABR==2) - { - int32_t t; - r=(((((X32COL1(color)))* 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_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_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_m1)&0xFF80FF80)>>7); - b=(X32COL2(GETLE32(pdest)))+(((((X32BCOL2(color))>>2)* g_m2)&0xFF80FF80)>>7); - g=(X32COL3(GETLE32(pdest)))+(((((X32BCOL3(color))>>2)* g_m3)&0xFF80FF80)>>7); -#else - r=(X32COL1(GETLE32(pdest)))+(((((X32ACOL1(color))>>1)* g_m1)&0xFF80FF80)>>7); - b=(X32COL2(GETLE32(pdest)))+(((((X32ACOL2(color))>>1)* g_m2)&0xFF80FF80)>>7); - g=(X32COL3(GETLE32(pdest)))+(((((X32ACOL3(color))>>1)* g_m3)&0xFF80FF80)>>7); -#endif - } - - if(!(color&0x8000)) - { - r=(r&0xffff0000)|((((X32COL1(color))* g_m1)&0x0000FF80)>>7); - b=(b&0xffff0000)|((((X32COL2(color))* g_m2)&0x0000FF80)>>7); - g=(g&0xffff0000)|((((X32COL3(color))* g_m3)&0x0000FF80)>>7); - } - if(!(color&0x80000000)) - { - r=(r&0xffff)|((((X32COL1(color))* g_m1)&0xFF800000)>>7); - b=(b&0xffff)|((((X32COL2(color))* g_m2)&0xFF800000)>>7); - g=(g&0xffff)|((((X32COL3(color))* g_m3)&0xFF800000)>>7); - } - - } - else - { - r=(((X32COL1(color))* g_m1)&0xFF80FF80)>>7; - b=(((X32COL2(color))* g_m2)&0xFF80FF80)>>7; - g=(((X32COL3(color))* 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(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); -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColG32_S(uint32_t * pdest,uint32_t color) -{ - int32_t r,g,b; - - if(color==0) return; - - r=(((X32COL1(color))* g_m1)&0xFF80FF80)>>7; - b=(((X32COL2(color))* g_m2)&0xFF80FF80)>>7; - g=(((X32COL3(color))* 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))|lSetMask|(color&0x80008000))&0xffff0000));return;} - if((color&0xffff0000)==0) {PUTLE32(pdest, (GETLE32(pdest)&0xffff0000)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff));return;} - - PUTLE32(pdest, (X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000)); -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColG32_SPR(uint32_t * pdest,uint32_t color) -{ - int32_t r,g,b; - - if(color==0) return; - - if(DrawSemiTrans && (color&0x80008000)) - { - if(GlobalTextABR==0) - { - r=((((X32TCOL1(GETLE32(pdest)))+((X32COL1(color)) * g_m1))&0xFF00FF00)>>8); - b=((((X32TCOL2(GETLE32(pdest)))+((X32COL2(color)) * g_m2))&0xFF00FF00)>>8); - g=((((X32TCOL3(GETLE32(pdest)))+((X32COL3(color)) * g_m3))&0xFF00FF00)>>8); - } - else - if(GlobalTextABR==1) - { - r=(X32COL1(GETLE32(pdest)))+(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); - b=(X32COL2(GETLE32(pdest)))+(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); - g=(X32COL3(GETLE32(pdest)))+(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); - } - else - if(GlobalTextABR==2) - { - int32_t t; - r=(((((X32COL1(color)))* 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_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_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_m1)&0xFF80FF80)>>7); - b=(X32COL2(GETLE32(pdest)))+(((((X32BCOL2(color))>>2)* g_m2)&0xFF80FF80)>>7); - g=(X32COL3(GETLE32(pdest)))+(((((X32BCOL3(color))>>2)* g_m3)&0xFF80FF80)>>7); -#else - r=(X32COL1(GETLE32(pdest)))+(((((X32ACOL1(color))>>1)* g_m1)&0xFF80FF80)>>7); - b=(X32COL2(GETLE32(pdest)))+(((((X32ACOL2(color))>>1)* g_m2)&0xFF80FF80)>>7); - g=(X32COL3(GETLE32(pdest)))+(((((X32ACOL3(color))>>1)* g_m3)&0xFF80FF80)>>7); -#endif - } - - if(!(color&0x8000)) - { - r=(r&0xffff0000)|((((X32COL1(color))* g_m1)&0x0000FF80)>>7); - b=(b&0xffff0000)|((((X32COL2(color))* g_m2)&0x0000FF80)>>7); - g=(g&0xffff0000)|((((X32COL3(color))* g_m3)&0x0000FF80)>>7); - } - if(!(color&0x80000000)) - { - r=(r&0xffff)|((((X32COL1(color))* g_m1)&0xFF800000)>>7); - b=(b&0xffff)|((((X32COL2(color))* g_m2)&0xFF800000)>>7); - g=(g&0xffff)|((((X32COL3(color))* g_m3)&0xFF800000)>>7); - } - - } - else - { - r=(((X32COL1(color))* g_m1)&0xFF80FF80)>>7; - b=(((X32COL2(color))* g_m2)&0xFF80FF80)>>7; - g=(((X32COL3(color))* 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(bCheckMask) - { - uint32_t ma=GETLE32(pdest); - - PUTLE32(pdest, (X32PSXCOL(r,g,b))|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))|lSetMask|(color&0x80008000))&0xffff0000));return;} - if((color&0xffff0000)==0) {PUTLE32(pdest, (GETLE32(pdest)&0xffff0000)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff));return;} - - PUTLE32(pdest, (X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000)); -} - -//////////////////////////////////////////////////////////////////////// - -static __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(bCheckMask && (*pdest & HOST2LE16(0x8000))) return; - - m1=(((XCOL1D(color)))*m1)>>4; - m2=(((XCOL2D(color)))*m2)>>4; - m3=(((XCOL3D(color)))*m3)>>4; - - if(DrawSemiTrans && (color&0x8000)) - { - r=((XCOL1D(GETLE16(pdest)))<<3); - b=((XCOL2D(GETLE16(pdest)))<<3); - g=((XCOL3D(GETLE16(pdest)))<<3); - - if(GlobalTextABR==0) - { - r=(r>>1)+(m1>>1); - b=(b>>1)+(m2>>1); - g=(g>>1)+(m3>>1); - } - else - if(GlobalTextABR==1) - { - r+=m1; - b+=m2; - g+=m3; - } - else - if(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,sSetMask|(color&0x8000)); - -} - -//////////////////////////////////////////////////////////////////////// - -static __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(bCheckMask && (*pdest & HOST2LE16(0x8000))) return; - - l=sSetMask|(color&0x8000); - - if(DrawSemiTrans && (color&0x8000)) - { - if(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(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(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); -} - -//////////////////////////////////////////////////////////////////////// - -static __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))|sSetMask|(color&0x8000)); -} - -//////////////////////////////////////////////////////////////////////// - -static __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))|lSetMask|(color&0x80008000))&0xffff0000));return;} - if((color&0xffff0000)==0) {PUTLE32(pdest, (GETLE32(pdest)&0xffff0000)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff));return;} - - PUTLE32(pdest, (X32PSXCOL(r,g,b))|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(x1drawW) return; - if(y0>drawH) return; - - x1=min(x1,drawW+1); - y1=min(y1,drawH+1); - x0=max(x0,drawX); - y0=max(y0,drawY); - - if(y0>=iGPUHeight) return; - if(x0>1023) return; - - if(y1>iGPUHeight) y1=iGPUHeight; - 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 = psxVuw + (1024*y0) + x0; - LineOffset = 1024 - dx; - for(i=0;i>=1; - DSTPtr = (uint32_t *)(psxVuw + (1024*y0) + x0); - LineOffset = 512 - dx; - - if(!bCheckMask && !DrawSemiTrans) - { - for(i=0;iy1) return; - if(x0>x1) return; - - if(y0>=iGPUHeight) return; - if(x0>1023) return; - - if(y1>iGPUHeight) y1=iGPUHeight; - if(x1>1024) x1=1024; - - dx=x1-x0;dy=y1-y0; - if(dx&1) - { - unsigned short *DSTPtr; - unsigned short LineOffset; - - DSTPtr = psxVuw + (1024*y0) + x0; - LineOffset = 1024 - dx; - - for(i=0;i>=1; - DSTPtr = (uint32_t *)(psxVuw + (1024*y0) + x0); - LineOffset = 512 - dx; - - for(i=0;iy - 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; -} - -//////////////////////////////////////////////////////////////////////// - -static __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; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline BOOL NextRow_F(void) -{ - if(--left_section_height<=0) - { - if(--left_section <= 0) {return TRUE;} - if(LeftSection_F() <= 0) {return TRUE;} - } - else - { - left_x += delta_left_x; - } - - if(--right_section_height<=0) - { - if(--right_section<=0) {return TRUE;} - if(RightSection_F() <=0) {return TRUE;} - } - else - { - right_x += delta_right_x; - } - return FALSE; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline BOOL 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 FALSE;} - longest = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x)>>16) + (v1->x - v2->x); - if(longest == 0) {return FALSE;} - - 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 FALSE; - if(RightSection_F() <= 0) - { - right_section--; - if(RightSection_F() <= 0) return FALSE; - } - } - 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 FALSE; - if(LeftSection_F() <= 0) - { - left_section--; - if(LeftSection_F() <= 0) return FALSE; - } - } - - Ymin=v1->y; - Ymax=min(v3->y-1,drawH); - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -static __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; -} - -//////////////////////////////////////////////////////////////////////// - -static __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; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline BOOL NextRow_G(void) -{ - if(--left_section_height<=0) - { - if(--left_section <= 0) {return TRUE;} - if(LeftSection_G() <= 0) {return TRUE;} - } - 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 TRUE;} - if(RightSection_G() <=0) {return TRUE;} - } - else - { - right_x += delta_right_x; - } - return FALSE; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline BOOL 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 FALSE;} - temp=(((v2->y - v1->y) << 16) / height); - longest = temp * ((v3->x - v1->x)>>16) + (v1->x - v2->x); - if(longest == 0) {return FALSE;} - - 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 FALSE; - if(RightSection_G() <= 0) - { - right_section--; - if(RightSection_G() <= 0) return FALSE; - } - 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 FALSE; - if(LeftSection_G() <= 0) - { - left_section--; - if(LeftSection_G() <= 0) return FALSE; - } - if(longest < 0x1000) longest = 0x1000; - } - - Ymin=v1->y; - Ymax=min(v3->y-1,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 TRUE; -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -static __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; -} - -//////////////////////////////////////////////////////////////////////// - -static __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; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline BOOL NextRow_FT(void) -{ - if(--left_section_height<=0) - { - if(--left_section <= 0) {return TRUE;} - if(LeftSection_FT() <= 0) {return TRUE;} - } - 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 TRUE;} - if(RightSection_FT() <=0) {return TRUE;} - } - else - { - right_x += delta_right_x; - } - return FALSE; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline BOOL 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 FALSE;} - - temp=(((v2->y - v1->y) << 16) / height); - longest = temp * ((v3->x - v1->x)>>16) + (v1->x - v2->x); - - if(longest == 0) {return FALSE;} - - 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 FALSE; - if(RightSection_FT() <= 0) - { - right_section--; - if(RightSection_FT() <= 0) return FALSE; - } - 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 FALSE; - if(LeftSection_FT() <= 0) - { - left_section--; - if(LeftSection_FT() <= 0) return FALSE; - } - if(longest < 0x1000) longest = 0x1000; - } - - Ymin=v1->y; - Ymax=min(v3->y-1,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 TRUE; -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -static __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; -} - -//////////////////////////////////////////////////////////////////////// - -static __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; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline BOOL NextRow_GT(void) -{ - if(--left_section_height<=0) - { - if(--left_section <= 0) {return TRUE;} - if(LeftSection_GT() <= 0) {return TRUE;} - } - 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 TRUE;} - if(RightSection_GT() <=0) {return TRUE;} - } - else - { - right_x += delta_right_x; - } - return FALSE; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline BOOL 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 FALSE;} - - temp=(((v2->y - v1->y) << 16) / height); - longest = temp * ((v3->x - v1->x)>>16) + (v1->x - v2->x); - - if(longest == 0) {return FALSE;} - - 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 FALSE; - if(RightSection_GT() <= 0) - { - right_section--; - if(RightSection_GT() <= 0) return FALSE; - } - - 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 FALSE; - if(LeftSection_GT() <= 0) - { - left_section--; - if(LeftSection_GT() <= 0) return FALSE; - } - if(longest < 0x1000) longest = 0x1000; - } - - Ymin=v1->y; - Ymax=min(v3->y-1,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 TRUE; -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -static __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; -} - -//////////////////////////////////////////////////////////////////////// - -static __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; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline BOOL 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 FALSE; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline BOOL 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; - } - - Ymin=v1->y; - Ymax=min(v4->y-1,drawH); - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -static __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; -} - -//////////////////////////////////////////////////////////////////////// - -static __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; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline BOOL 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 FALSE; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline BOOL 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; - } - - Ymin=v1->y; - Ymax=min(v4->y-1,drawH); - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -static __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; -} - -//////////////////////////////////////////////////////////////////////// - -static __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; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline BOOL 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 FALSE; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline BOOL 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; - } - - Ymin=v1->y; - Ymax=min(v4->y-1,drawH); - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -// POLY FUNCS -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -// POLY 3/4 FLAT SHADED -//////////////////////////////////////////////////////////////////////// - -static __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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_F(x1,y1,x2,y2,x3,y3)) return; - - ymax=Ymax; - - color = ((rgb & 0x00f80000)>>9) | ((rgb & 0x0000f800)>>6) | ((rgb & 0x000000f8)>>3); - lcolor=lSetMask|(((uint32_t)(color))<<16)|color; - - for(ymin=Ymin;ymin> 16; if(drawX>xmin) xmin=drawX; - xmax=(right_x >> 16)-1; if(drawW> 16; if(drawX>xmin) xmin=drawX; - xmax=(right_x >> 16)-1; if(drawWdrawW && lx1>drawW && lx2>drawW && lx3>drawW) return; - if(ly0>drawH && ly1>drawH && ly2>drawH && ly3>drawH) return; - if(lx0=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_F4(lx0,ly0,lx1,ly1,lx2,ly2,lx3,ly3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin>9) | ((rgb & 0x0000f800)>>6) | ((rgb & 0x000000f8)>>3); - lcolor= lSetMask|(((uint32_t)(color))<<16)|color; - -#ifdef FASTSOLID - - if(!bCheckMask && !DrawSemiTrans) - { - color |=sSetMask; - for (i=ymin;i<=ymax;i++) - { - xmin=left_x >> 16; if(drawX>xmin) xmin=drawX; - xmax=(right_x >> 16)-1; if(drawW> 16; if(drawX>xmin) xmin=drawX; - xmax=(right_x >> 16)-1; if(drawWdrawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16); - tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16); - tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16); - tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT()) - { - return; - } - } - return; - } - -#endif - - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16); - tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16); - tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16); - tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16); - - TXV=posY>>16; - n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); - - tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT()) - { - return; - } - } - return; - } - -#endif - - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16); - - TXV=posY>>16; - n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); - - tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin>1); - - difX=delta_right_u;difX2=difX<<1; - difY=delta_right_v;difY2=difY<<1; - -#ifdef FASTSOLID - - if(!bCheckMask && !DrawSemiTrans) - { - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16);//-1; //!!!!!!!!!!!!!!!! - if(xmax>xmin) xmax--; - - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16)%TWin.Position.x1; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT()) - { - return; - } - } - return; - } - -#endif - - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16)%TWin.Position.x1; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -#ifdef POLYQUAD3 - -static 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: - -static 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>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16); - tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16); - tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16); - tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>16); - tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16); - tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16); - tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16); - - TXV=posY>>16; - n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); - - tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>16); - - TXV=posY>>16; - n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); - - tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin>1); - -#ifdef FASTSOLID - - if(!bCheckMask && !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>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16)%TWin.Position.x1; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16)%TWin.Position.x1; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin>1); - -#ifdef FASTSOLID - - if(!bCheckMask && !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>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16)%TWin.Position.x1; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16)%TWin.Position.x1; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32_SPR((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG_SPR(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT4()) return; - } -} -//////////////////////////////////////////////////////////////////////// -// POLY 3 F-SHADED TEX PAL 8 -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; - tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ - ((posX+difX)>>16)]; - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - - if(j==xmax) - { - tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT()) - { - return; - } - } - return; - } - -#endif - - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; - tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ - ((posX+difX)>>16)]; - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - - if(j==xmax) - { - tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; - GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - - } - if(NextRow_FT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16; - TXV=posY>>16; - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT()) - { - return; - } - } - return; - } - -#endif - - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16; - TXV=posY>>16; - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - - } - if(NextRow_FT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16);//-1; //!!!!!!!!!!!!!!!! - if(xmax>xmin) xmax--; - - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - - if(j==xmax) - { - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT()) - { - return; - } - } - return; - } - -#endif - - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - - if(j==xmax) - { - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - - } - if(NextRow_FT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -#ifdef POLYQUAD3 - -static 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: - -static 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>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; - tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ - ((posX+difX)>>16)]; - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; - tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ - ((posX+difX)>>16)]; - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; - GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16; - TXV=posY>>16; - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>16; - TXV=posY>>16; - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; - GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; - GetTextureTransColG32_SPR((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - GetTextureTransColG_SPR(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); - } - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// -// POLY 3 F-SHADED TEX 15 BIT -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| - GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX])); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG_S(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX])); - } - if(NextRow_FT()) - { - return; - } - } - return; - } - -#endif - - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| - GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX])); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX])); - } - if(NextRow_FT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| - GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG_S(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| - GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); - } - if(NextRow_FT()) - { - return; - } - } -} - - -//////////////////////////////////////////////////////////////////////// - -#ifdef POLYQUAD3 - -static 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: - -static 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>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| - GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX])); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG_S(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| - GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX])); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX])); - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| - GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY)<<10)+TWin.Position.y0+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG_S(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| - GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| - GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY)<<10)+TWin.Position.y0+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG_S(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| - GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG_SPR(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// -// POLY 3/4 G-SHADED -//////////////////////////////////////////////////////////////////////// - -static __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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_G(x1,y1,x2,y2,x3,y3,rgb1,rgb2,rgb3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1;if(drawW=xmin) - { - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>3)&0x001f0000)| - (((cR1) >> 9)&0x7c00)|(((cG1) >> 14)&0x03e0)|(((cB1) >> 19)&0x001f))|lSetMask); - - cR1+=difR2; - cG1+=difG2; - cB1+=difB2; - } - if(j==xmax) - PUTLE16(&psxVuw[(i<<10)+j], (((cR1 >> 9)&0x7c00)|((cG1 >> 14)&0x03e0)|((cB1 >> 19)&0x001f))|sSetMask); - } - if(NextRow_G()) return; - } - return; - } - -#endif - - if(iDither==2) - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1;if(drawW=xmin) - { - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>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(drawW=xmin) - { - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin> 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(lx0,ly0,lx1,ly1,lx2,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(lx1,ly1,lx3,ly3,lx2,ly2, - rgb2,rgb4,rgb3); - drawPoly3Gi(lx0,ly0,lx1,ly1,lx2,ly2, - rgb1,rgb2,rgb3); -} - -//////////////////////////////////////////////////////////////////////// -// POLY 3/4 G-SHADED TEX PAL4 -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=((right_x) >> 16)-1; //!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16); - tC1 = psxVub[((posY>>5)&0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16); - tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16); - tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1]), - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1]), - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=((right_x) >> 16)-1; //!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16); - - TXV=posY>>16; - n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); - - tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16); - - TXV=posY>>16; - n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); - - tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1]), - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1]), - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin>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(!bCheckMask && !DrawSemiTrans && !iDither) - { - for (i=ymin;i<=ymax;i++) - { - xmin=((left_x) >> 16); - xmax=((right_x) >> 16)-1; //!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16)%TWin.Position.x1; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1]), - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[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... - -static 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 - -static 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 - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=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=Ymax; - - for(ymin=Ymin;ymin> 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>16); - tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16); - tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[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>16); - tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1]), - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1]), - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; // !!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>5)&(int32_t)0xFFFFF800)+YAdjust+((posX>>16))]; - tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ - (((posX+difX)>>16))]; - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+((posX>>16))]; - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>5)&(int32_t)0xFFFFF800)+YAdjust+((posX>>16))]; - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1]), - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1]), - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; // !!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16; - TXV=posY>>16; - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16; - TXV=posY>>16; - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; - - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1]), - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1]), - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; // !!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; - - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1]), - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[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 - -static 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 - -static 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 - -static 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>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=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=Ymax; - - for(ymin=Ymin;ymin> 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>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; - tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ - ((posX+difX)>>16)]; - - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1])| - ((int32_t)GETLE16(&psxVuw[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 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[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>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1]), - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[clutP+tC1]), - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| - GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+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(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]), - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]), - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| - GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX)>>16)%TWin.Position.x1)+GlobalTextAddrX+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(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]), - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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 - -static 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 - -static 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>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=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=Ymax; - - for(ymin=Ymin;ymin> 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>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| - GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+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(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]), - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]), - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 BOOL IsNoRect(void) -{ - if(lx0==lx1 && lx2==lx3) return FALSE; - if(lx0==lx2 && lx1==lx3) return FALSE; - if(lx0==lx3 && lx1==lx2) return FALSE; - return TRUE; -} -*/ - -// real rect test -static __inline BOOL IsNoRect(void) -{ - if(!(dwActFixes&0x200)) return FALSE; - - if(ly0==ly1) - { - if(lx1==lx3 && ly3==ly2 && lx2==lx0) return FALSE; - if(lx1==lx2 && ly2==ly3 && lx3==lx0) return FALSE; - return TRUE; - } - - if(ly0==ly2) - { - if(lx2==lx3 && ly3==ly1 && lx1==lx0) return FALSE; - if(lx2==lx1 && ly1==ly3 && lx3==lx0) return FALSE; - return TRUE; - } - - if(ly0==ly3) - { - if(lx3==lx2 && ly2==ly1 && lx1==lx0) return FALSE; - if(lx3==lx1 && ly1==ly2 && lx2==lx0) return FALSE; - return TRUE; - } - return TRUE; -} - -//////////////////////////////////////////////////////////////////////// - -void drawPoly3FT(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - - if(GlobalTextIL && GlobalTextTP<2) - { - if(GlobalTextTP==0) - drawPoly3TEx4_IL(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask)); - else - drawPoly3TEx8_IL(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask)); - return; - } - - if(!bUsingTWin && !(dwActFixes&0x100)) - { - switch(GlobalTextTP) // depending on texture mode - { - case 0: - drawPoly3TEx4(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask)); - return; - case 1: - drawPoly3TEx8(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask)); - return; - case 2: - drawPoly3TD(lx0,ly0,lx1,ly1,lx2,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(GlobalTextTP) // depending on texture mode - { - case 0: - drawPoly3TEx4_TW(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask)); - return; - case 1: - drawPoly3TEx8_TW(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask)); - return; - case 2: - drawPoly3TD_TW(lx0,ly0,lx1,ly1,lx2,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(GlobalTextIL && GlobalTextTP<2) - { - if(GlobalTextTP==0) - drawPoly4TEx4_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); - else - drawPoly4TEx8_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); - return; - } - - if(!bUsingTWin) - { -#ifdef POLYQUAD3GT - if(IsNoRect()) - { - switch (GlobalTextTP) - { - case 0: - drawPoly4TEx4_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); - return; - case 1: - drawPoly4TEx8_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); - return; - case 2: - drawPoly4TD_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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 (GlobalTextTP) - { - case 0: // grandia investigations needed - drawPoly4TEx4(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); - return; - case 1: - drawPoly4TEx8(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); - return; - case 2: - drawPoly4TD(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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 (GlobalTextTP) - { - case 0: - drawPoly4TEx4_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); - return; - case 1: - drawPoly4TEx8_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); - return; - case 2: - drawPoly4TD_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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(GlobalTextIL && GlobalTextTP<2) - { - if(GlobalTextTP==0) - drawPoly3TGEx4_IL(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask), - GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); - else - drawPoly3TGEx8_IL(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask), - GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); - return; - } - - if(!bUsingTWin) - { - switch (GlobalTextTP) - { - case 0: - drawPoly3TGEx4(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask), - GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); - return; - case 1: - drawPoly3TGEx8(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask), - GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); - return; - case 2: - drawPoly3TGD(lx0,ly0,lx1,ly1,lx2,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(GlobalTextTP) - { - case 0: - drawPoly3TGEx4_TW(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask), - GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); - return; - case 1: - drawPoly3TGEx8_TW(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask), - GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); - return; - case 2: - drawPoly3TGD_TW(lx0,ly0,lx1,ly1,lx2,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(GlobalTextIL && GlobalTextTP<2) - { - if(GlobalTextTP==0) - drawPoly4TGEx4_TRI_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), - GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); - else - drawPoly4TGEx8_TRI_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), - GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); - return; - } - - if(!bUsingTWin) - { -#ifdef POLYQUAD3GT - if(IsNoRect()) - { - switch (GlobalTextTP) - { - case 0: - drawPoly4TGEx4_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), - GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); - - return; - case 1: - drawPoly4TGEx8_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), - GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); - return; - case 2: - drawPoly4TGD_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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 (GlobalTextTP) - { - case 0: - drawPoly4TGEx4(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), - GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); - - return; - case 1: - drawPoly4TGEx8(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), - GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); - return; - case 2: - drawPoly4TGD(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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 (GlobalTextTP) - { - case 0: - drawPoly4TGEx4_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), - GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); - return; - case 1: - drawPoly4TGEx8_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), - GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); - return; - case 2: - drawPoly4TGD_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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=lx0; - sy0=ly0; - - sx0=sx3=sx0+PSXDisplay.DrawOffset.x; - sx1=sx2=sx0+w; - sy0=sy1=sy0+PSXDisplay.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 (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) & iGPUHeightMask)); - 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) & iGPUHeightMask)); - 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 = ly0; - sprtX = lx0; - sprtH = h; - sprtW = w; - clutY0 = (GETLE32(&gpuData[2])>>22) & iGPUHeightMask; - clutX0 = (GETLE32(&gpuData[2])>>12) & 0x3f0; - clutP = (clutY0<<11) + (clutX0<<1); - textY0 = ((GETLE32(&gpuData[2])>>8) & 0x000000ff) + GlobalTextAddrY; - textX0 = (GETLE32(&gpuData[2]) & 0x000000ff); - - sprtX+=PSXDisplay.DrawOffset.x; - sprtY+=PSXDisplay.DrawOffset.y; - -// while (sprtX>1023) sprtX-=1024; -// while (sprtY>MAXYLINESMIN1) sprtY-=MAXYLINES; - - if(sprtX>drawW) - { -// if((sprtX+sprtW)>1023) sprtX-=1024; -// else return; - return; - } - - if(sprtY>drawH) - { -// if ((sprtY+sprtH)>MAXYLINESMIN1) sprtY-=MAXYLINES; -// else return; - return; - } - - if(sprtYdrawH) sprtH=drawH-sprtY+1; - if((sprtX+sprtW)>drawW) sprtW=drawW-sprtX+1; - - if(usMirror&0x1000) lXDir=-1; else lXDir=1; - if(usMirror&0x2000) lYDir=-1; else lYDir=1; - - switch (GlobalTextTP) - { - case 0: // texture is 4-bit - - sprtW=sprtW/2; - textX0=(GlobalTextAddrX<<1)+(textX0>>1); - sprtYa=(sprtY<<10); - clutP=(clutY0<<10)+clutX0; - for (sprCY=0;sprCY>4)&0xf)])); - GetTextureTransColG_SPR(&psxVuw[sprA+1],GETLE16(&psxVuw[clutP+(tC&0xf)])); - } - return; - - case 1: - - clutP>>=1; - for(sprCY=0;sprCYdrawW) return; - if(sprtY>drawH) return; - - tdx=tx+sprtW; - tdy=ty+sprtH; - - sprtW+=sprtX; - sprtH+=sprtY; - - // Pete is too lazy to make a faster version ;) - - if(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) & iGPUHeightMask)); - - - 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) & iGPUHeightMask)); -} - -//////////////////////////////////////////////////////////////////////// - -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; - BOOL bWT,bWS; - - if(GlobalTextIL && GlobalTextTP<2) - {DrawSoftwareSprite_IL(baseAddr,w,h,tx,ty);return;} - - sprtY = ly0; - sprtX = lx0; - sprtH = h; - sprtW = w; - clutY0 = (GETLE32(&gpuData[2])>>22) & iGPUHeightMask; - clutX0 = (GETLE32(&gpuData[2])>>12) & 0x3f0; - - clutP = (clutY0<<11) + (clutX0<<1); - - textY0 =ty+ GlobalTextAddrY; - textX0 =tx; - - sprtX+=PSXDisplay.DrawOffset.x; - sprtY+=PSXDisplay.DrawOffset.y; - - //while (sprtX>1023) sprtX-=1024; - //while (sprtY>MAXYLINESMIN1) sprtY-=MAXYLINES; - - if(sprtX>drawW) - { -// if((sprtX+sprtW)>1023) sprtX-=1024; -// else return; - return; - } - - if(sprtY>drawH) - { -// if ((sprtY+sprtH)>MAXYLINESMIN1) sprtY-=MAXYLINES; -// else return; - return; - } - - if(sprtYdrawH) sprtH=drawH-sprtY+1; - if((sprtX+sprtW)>drawW) sprtW=drawW-sprtX+1; - - - bWT=FALSE; - bWS=FALSE; - - switch (GlobalTextTP) - { - case 0: - - if(textX0&1) {bWS=TRUE;sprtW--;} - if(sprtW&1) bWT=TRUE; - - sprtW=sprtW>>1; - textX0=(GlobalTextAddrX<<1)+(textX0>>1)+(textY0<<11); - sprtYa=(sprtY<<10)+sprtX; - clutP=(clutY0<<10)+clutX0; - -#ifdef FASTSOLID - - if(!bCheckMask && !DrawSemiTrans) - { - for (sprCY=0;sprCY>4)&0xf)])); - } - - for (sprCX=0;sprCX>4)&0xf)]))<<16)| - GETLE16(&psxVuw[clutP+(tC&0x0f)])); - } - - if(bWT) - { - tC=*pV; - GetTextureTransColG_S(&psxVuw[sprA],GETLE16(&psxVuw[clutP+(tC&0x0f)])); - } - } - return; - } - -#endif - - for (sprCY=0;sprCY>4)&0xf)])); - } - - for (sprCX=0;sprCX>4)&0xf)])<<16))| - GETLE16(&psxVuw[clutP+(tC&0x0f)])); - } - - if(bWT) - { - tC=*pV; - GetTextureTransColG_SPR(&psxVuw[sprA],GETLE16(&psxVuw[clutP+(tC&0x0f)])); - } - } - return; - - case 1: - clutP>>=1;sprtW--; - textX0+=(GlobalTextAddrX<<1) + (textY0<<11); - -#ifdef FASTSOLID - - if(!bCheckMask && !DrawSemiTrans) - { - for(sprCY=0;sprCY 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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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 < drawY) - { - r0+=dr*(drawY - y0); - g0+=dg*(drawY - y0); - b0+=db*(drawY - y0); - y0 = drawY; - } - - if (y1 > drawH) - y1 = drawH; - - for (y = y0; y <= y1; y++) - { - GetShadeTransCol(&psxVuw[(y<<10)+x],(unsigned short)(((r0 >> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); - r0+=dr; - g0+=dg; - b0+=db; - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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 < drawX) - { - r0+=dr*(drawX - x0); - g0+=dg*(drawX - x0); - b0+=db*(drawX - x0); - x0 = drawX; - } - - if (x1 > drawW) - x1 = drawW; - - for (x = x0; x <= x1; x++) - { - GetShadeTransCol(&psxVuw[(y<<10)+x],(unsigned short)(((r0 >> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); - r0+=dr; - g0+=dg; - b0+=db; - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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>=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y y1) - { - if (d <= 0) - { - d = d + incrN; /* Choose N */ - y--; - } - else - { - d = d + incrNE; /* Choose NE */ - x++; - y--; - } - if ((x>=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y drawH) - y1 = drawH; - - for (y = y0; y <= y1; y++) - GetShadeTransCol(&psxVuw[(y<<10)+x], colour); -} - -/////////////////////////////////////////////////////////////////////// - -static void HorzLineFlat(int y, int x0, int x1, unsigned short colour) -{ - int x; - - if (x0 < drawX) - x0 = drawX; - - if (x1 > drawW) - x1 = drawW; - - for (x = x0; x <= x1; x++) - GetShadeTransCol(&psxVuw[(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 (lx0 > drawW && lx1 > drawW) return; - if (ly0 > drawH && ly1 > drawH) return; - if (lx0 < drawX && lx1 < drawX) return; - if (ly0 < drawY && ly1 < drawY) return; - if (drawY >= drawH) return; - if (drawX >= drawW) return; - - x0 = lx0; - y0 = ly0; - x1 = lx1; - y1 = 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 (lx0 > drawW && lx1 > drawW) return; - if (ly0 > drawH && ly1 > drawH) return; - if (lx0 < drawX && lx1 < drawX) return; - if (ly0 < drawY && ly1 < drawY) return; - if (drawY >= drawH) return; - if (drawX >= drawW) return; - - colour = ((rgb & 0x00f80000) >> 9) | ((rgb & 0x0000f800) >> 6) | ((rgb & 0x000000f8) >> 3); - - x0 = lx0; - y0 = ly0; - x1 = lx1; - y1 = 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); - } -} - -/////////////////////////////////////////////////////////////////////// +/*************************************************************************** + 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. * + * * + ***************************************************************************/ + +#define _IN_SOFT + +#include "externals.h" +#include "soft.h" + +//#define VC_INLINE +#include "gpu.h" +#include "prim.h" +#include "menu.h" +#include "swap.h" + +#ifdef _WINDOWS +#pragma warning (disable:4244) +#pragma warning (disable:4761) +#endif + +//////////////////////////////////////////////////////////////////////////////////// +// "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 +//////////////////////////////////////////////////////////////////////////////////// + +short g_m1=255,g_m2=255,g_m3=255; +short DrawSemiTrans=FALSE; +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; + +//////////////////////////////////////////////////////////////////////// +// POLYGON OFFSET FUNCS +//////////////////////////////////////////////////////////////////////// + +void offsetPSXLine(void) +{ + short x0,x1,y0,y1,dx,dy;float px,py; + + x0 = lx0+1+PSXDisplay.DrawOffset.x; + x1 = lx1+1+PSXDisplay.DrawOffset.x; + y0 = ly0+1+PSXDisplay.DrawOffset.y; + y1 = ly1+1+PSXDisplay.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(dxdy) px= 0.5f; + else if(dx=0) + { + py=0.5f; + dx=-dx; + if(dx>dy) px=-0.5f; + else if(dxdy) py=-0.5f; + else if(dx>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, ((unsigned short)b<<10) | + ((unsigned short)g<<5) | + (unsigned short)r | sM); +} + +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// + +__inline void GetShadeTransCol_Dither(unsigned short * pdest, int32_t m1, int32_t m2, int32_t m3) +{ + int32_t r,g,b; + + if(bCheckMask && (*pdest & HOST2LE16(0x8000))) return; + + if(DrawSemiTrans) + { + r=((XCOL1D(GETLE16(pdest)))<<3); + b=((XCOL2D(GETLE16(pdest)))<<3); + g=((XCOL3D(GETLE16(pdest)))<<3); + + if(GlobalTextABR==0) + { + r=(r>>1)+(m1>>1); + b=(b>>1)+(m2>>1); + g=(g>>1)+(m3>>1); + } + else + if(GlobalTextABR==1) + { + r+=m1; + b+=m2; + g+=m3; + } + else + if(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,sSetMask); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetShadeTransCol(unsigned short * pdest,unsigned short color) +{ + if(bCheckMask && (*pdest & HOST2LE16(0x8000))) return; + + if(DrawSemiTrans) + { + int32_t r,g,b; + + if(GlobalTextABR==0) + { + PUTLE16(pdest, (((GETLE16(pdest)&0x7bde)>>1)+(((color)&0x7bde)>>1))|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(GlobalTextABR==1) + { + r=(XCOL1(GETLE16(pdest)))+((XCOL1(color))); + b=(XCOL2(GETLE16(pdest)))+((XCOL2(color))); + g=(XCOL3(GETLE16(pdest)))+((XCOL3(color))); + } + else + if(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))|sSetMask);//0x8000; + } + else PUTLE16(pdest, color|sSetMask); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetShadeTransCol32(uint32_t * pdest,uint32_t color) +{ + if(DrawSemiTrans) + { + int32_t r,g,b; + + if(GlobalTextABR==0) + { + if(!bCheckMask) + { + PUTLE32(pdest, (((GETLE32(pdest)&0x7bde7bde)>>1)+(((color)&0x7bde7bde)>>1))|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(GlobalTextABR==1) + { + r=(X32COL1(GETLE32(pdest)))+((X32COL1(color))); + b=(X32COL2(GETLE32(pdest)))+((X32COL2(color))); + g=(X32COL3(GETLE32(pdest)))+((X32COL3(color))); + } + else + if(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(bCheckMask) + { + uint32_t ma=GETLE32(pdest); + PUTLE32(pdest, (X32PSXCOL(r,g,b))|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))|lSetMask);//0x80008000; + } + else + { + if(bCheckMask) + { + uint32_t ma=GETLE32(pdest); + PUTLE32(pdest, color|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|lSetMask);//0x80008000; + } +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColG(unsigned short * pdest,unsigned short color) +{ + int32_t r,g,b;unsigned short l; + + if(color==0) return; + + if(bCheckMask && (*pdest & HOST2LE16(0x8000))) return; + + l=sSetMask|(color&0x8000); + + if(DrawSemiTrans && (color&0x8000)) + { + if(GlobalTextABR==0) + { + unsigned short d; + d =(GETLE16(pdest)&0x7bde)>>1; + color =((color) &0x7bde)>>1; + r=(XCOL1(d))+((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(d))+((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(d))+((((XCOL3(color)))* g_m3)>>7); + +/* + r=(XCOL1(*pdest)>>1)+((((XCOL1(color))>>1)* g_m1)>>7); + b=(XCOL2(*pdest)>>1)+((((XCOL2(color))>>1)* g_m2)>>7); + g=(XCOL3(*pdest)>>1)+((((XCOL3(color))>>1)* g_m3)>>7); +*/ + } + else + if(GlobalTextABR==1) + { + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color)))* g_m3)>>7); + } + else + if(GlobalTextABR==2) + { + r=(XCOL1(GETLE16(pdest)))-((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))-((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))-((((XCOL3(color)))* 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_m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>2)* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>2)* g_m3)>>7); +#else + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color))>>1)* g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>1)* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>1)* g_m3)>>7); +#endif + } + } + else + { + r=((XCOL1(color))* g_m1)>>7; + b=((XCOL2(color))* g_m2)>>7; + g=((XCOL3(color))* 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=sSetMask|(color&0x8000); + + r=((XCOL1(color))* g_m1)>>7; + b=((XCOL2(color))* g_m2)>>7; + g=((XCOL3(color))* 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(bCheckMask && (GETLE16(pdest) & 0x8000)) return; + + l=sSetMask|(color&0x8000); + + if(DrawSemiTrans && (color&0x8000)) + { + if(GlobalTextABR==0) + { + unsigned short d; + d =(GETLE16(pdest)&0x7bde)>>1; + color =((color) &0x7bde)>>1; + r=(XCOL1(d))+((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(d))+((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(d))+((((XCOL3(color)))* g_m3)>>7); + +/* + r=(XCOL1(*pdest)>>1)+((((XCOL1(color))>>1)* g_m1)>>7); + b=(XCOL2(*pdest)>>1)+((((XCOL2(color))>>1)* g_m2)>>7); + g=(XCOL3(*pdest)>>1)+((((XCOL3(color))>>1)* g_m3)>>7); +*/ + } + else + if(GlobalTextABR==1) + { + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color)))* g_m3)>>7); + } + else + if(GlobalTextABR==2) + { + r=(XCOL1(GETLE16(pdest)))-((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))-((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))-((((XCOL3(color)))* 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_m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>2)* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>2)* g_m3)>>7); +#else + r=(XCOL1(GETLE16(pdest)))+((((XCOL1(color))>>1)* g_m1)>>7); + b=(XCOL2(GETLE16(pdest)))+((((XCOL2(color))>>1)* g_m2)>>7); + g=(XCOL3(GETLE16(pdest)))+((((XCOL3(color))>>1)* g_m3)>>7); +#endif + } + } + else + { + r=((XCOL1(color))* g_m1)>>7; + b=((XCOL2(color))* g_m2)>>7; + g=((XCOL3(color))* 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=lSetMask|(color&0x80008000); + + if(DrawSemiTrans && (color&0x80008000)) + { + if(GlobalTextABR==0) + { + r=((((X32TCOL1(GETLE32(pdest)))+((X32COL1(color)) * g_m1))&0xFF00FF00)>>8); + b=((((X32TCOL2(GETLE32(pdest)))+((X32COL2(color)) * g_m2))&0xFF00FF00)>>8); + g=((((X32TCOL3(GETLE32(pdest)))+((X32COL3(color)) * g_m3))&0xFF00FF00)>>8); + } + else + if(GlobalTextABR==1) + { + r=(X32COL1(GETLE32(pdest)))+(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(GETLE32(pdest)))+(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(GETLE32(pdest)))+(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); + } + else + if(GlobalTextABR==2) + { + int32_t t; + r=(((((X32COL1(color)))* 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_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_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_m1)&0xFF80FF80)>>7); + b=(X32COL2(GETLE32(pdest)))+(((((X32BCOL2(color))>>2)* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(GETLE32(pdest)))+(((((X32BCOL3(color))>>2)* g_m3)&0xFF80FF80)>>7); +#else + r=(X32COL1(GETLE32(pdest)))+(((((X32ACOL1(color))>>1)* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(GETLE32(pdest)))+(((((X32ACOL2(color))>>1)* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(GETLE32(pdest)))+(((((X32ACOL3(color))>>1)* g_m3)&0xFF80FF80)>>7); +#endif + } + + if(!(color&0x8000)) + { + r=(r&0xffff0000)|((((X32COL1(color))* g_m1)&0x0000FF80)>>7); + b=(b&0xffff0000)|((((X32COL2(color))* g_m2)&0x0000FF80)>>7); + g=(g&0xffff0000)|((((X32COL3(color))* g_m3)&0x0000FF80)>>7); + } + if(!(color&0x80000000)) + { + r=(r&0xffff)|((((X32COL1(color))* g_m1)&0xFF800000)>>7); + b=(b&0xffff)|((((X32COL2(color))* g_m2)&0xFF800000)>>7); + g=(g&0xffff)|((((X32COL3(color))* g_m3)&0xFF800000)>>7); + } + + } + else + { + r=(((X32COL1(color))* g_m1)&0xFF80FF80)>>7; + b=(((X32COL2(color))* g_m2)&0xFF80FF80)>>7; + g=(((X32COL3(color))* 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(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_m1)&0xFF80FF80)>>7; + b=(((X32COL2(color))* g_m2)&0xFF80FF80)>>7; + g=(((X32COL3(color))* 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))|lSetMask|(color&0x80008000))&0xffff0000));return;} + if((color&0xffff0000)==0) {PUTLE32(pdest, (GETLE32(pdest)&0xffff0000)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff));return;} + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000)); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColG32_SPR(uint32_t * pdest,uint32_t color) +{ + int32_t r,g,b; + + if(color==0) return; + + if(DrawSemiTrans && (color&0x80008000)) + { + if(GlobalTextABR==0) + { + r=((((X32TCOL1(GETLE32(pdest)))+((X32COL1(color)) * g_m1))&0xFF00FF00)>>8); + b=((((X32TCOL2(GETLE32(pdest)))+((X32COL2(color)) * g_m2))&0xFF00FF00)>>8); + g=((((X32TCOL3(GETLE32(pdest)))+((X32COL3(color)) * g_m3))&0xFF00FF00)>>8); + } + else + if(GlobalTextABR==1) + { + r=(X32COL1(GETLE32(pdest)))+(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(GETLE32(pdest)))+(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(GETLE32(pdest)))+(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); + } + else + if(GlobalTextABR==2) + { + int32_t t; + r=(((((X32COL1(color)))* 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_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_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_m1)&0xFF80FF80)>>7); + b=(X32COL2(GETLE32(pdest)))+(((((X32BCOL2(color))>>2)* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(GETLE32(pdest)))+(((((X32BCOL3(color))>>2)* g_m3)&0xFF80FF80)>>7); +#else + r=(X32COL1(GETLE32(pdest)))+(((((X32ACOL1(color))>>1)* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(GETLE32(pdest)))+(((((X32ACOL2(color))>>1)* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(GETLE32(pdest)))+(((((X32ACOL3(color))>>1)* g_m3)&0xFF80FF80)>>7); +#endif + } + + if(!(color&0x8000)) + { + r=(r&0xffff0000)|((((X32COL1(color))* g_m1)&0x0000FF80)>>7); + b=(b&0xffff0000)|((((X32COL2(color))* g_m2)&0x0000FF80)>>7); + g=(g&0xffff0000)|((((X32COL3(color))* g_m3)&0x0000FF80)>>7); + } + if(!(color&0x80000000)) + { + r=(r&0xffff)|((((X32COL1(color))* g_m1)&0xFF800000)>>7); + b=(b&0xffff)|((((X32COL2(color))* g_m2)&0xFF800000)>>7); + g=(g&0xffff)|((((X32COL3(color))* g_m3)&0xFF800000)>>7); + } + + } + else + { + r=(((X32COL1(color))* g_m1)&0xFF80FF80)>>7; + b=(((X32COL2(color))* g_m2)&0xFF80FF80)>>7; + g=(((X32COL3(color))* 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(bCheckMask) + { + uint32_t ma=GETLE32(pdest); + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|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))|lSetMask|(color&0x80008000))&0xffff0000));return;} + if((color&0xffff0000)==0) {PUTLE32(pdest, (GETLE32(pdest)&0xffff0000)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff));return;} + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|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(bCheckMask && (*pdest & HOST2LE16(0x8000))) return; + + m1=(((XCOL1D(color)))*m1)>>4; + m2=(((XCOL2D(color)))*m2)>>4; + m3=(((XCOL3D(color)))*m3)>>4; + + if(DrawSemiTrans && (color&0x8000)) + { + r=((XCOL1D(GETLE16(pdest)))<<3); + b=((XCOL2D(GETLE16(pdest)))<<3); + g=((XCOL3D(GETLE16(pdest)))<<3); + + if(GlobalTextABR==0) + { + r=(r>>1)+(m1>>1); + b=(b>>1)+(m2>>1); + g=(g>>1)+(m3>>1); + } + else + if(GlobalTextABR==1) + { + r+=m1; + b+=m2; + g+=m3; + } + else + if(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,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(bCheckMask && (*pdest & HOST2LE16(0x8000))) return; + + l=sSetMask|(color&0x8000); + + if(DrawSemiTrans && (color&0x8000)) + { + if(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(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(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))|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))|lSetMask|(color&0x80008000))&0xffff0000));return;} + if((color&0xffff0000)==0) {PUTLE32(pdest, (GETLE32(pdest)&0xffff0000)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff));return;} + + PUTLE32(pdest, (X32PSXCOL(r,g,b))|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(x1drawW) return; + if(y0>drawH) return; + + x1=min(x1,drawW+1); + y1=min(y1,drawH+1); + x0=max(x0,drawX); + y0=max(y0,drawY); + + if(y0>=iGPUHeight) return; + if(x0>1023) return; + + if(y1>iGPUHeight) y1=iGPUHeight; + 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 = psxVuw + (1024*y0) + x0; + LineOffset = 1024 - dx; + for(i=0;i>=1; + DSTPtr = (uint32_t *)(psxVuw + (1024*y0) + x0); + LineOffset = 512 - dx; + + if(!bCheckMask && !DrawSemiTrans) + { + for(i=0;iy1) return; + if(x0>x1) return; + + if(y0>=iGPUHeight) return; + if(x0>1023) return; + + if(y1>iGPUHeight) y1=iGPUHeight; + if(x1>1024) x1=1024; + + dx=x1-x0;dy=y1-y0; + if(dx&1) + { + unsigned short *DSTPtr; + unsigned short LineOffset; + + DSTPtr = psxVuw + (1024*y0) + x0; + LineOffset = 1024 - dx; + + for(i=0;i>=1; + DSTPtr = (uint32_t *)(psxVuw + (1024*y0) + x0); + LineOffset = 512 - dx; + + for(i=0;iy - 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 BOOL NextRow_F(void) +{ + if(--left_section_height<=0) + { + if(--left_section <= 0) {return TRUE;} + if(LeftSection_F() <= 0) {return TRUE;} + } + else + { + left_x += delta_left_x; + } + + if(--right_section_height<=0) + { + if(--right_section<=0) {return TRUE;} + if(RightSection_F() <=0) {return TRUE;} + } + else + { + right_x += delta_right_x; + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL 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 FALSE;} + longest = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + if(longest == 0) {return FALSE;} + + 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 FALSE; + if(RightSection_F() <= 0) + { + right_section--; + if(RightSection_F() <= 0) return FALSE; + } + } + 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 FALSE; + if(LeftSection_F() <= 0) + { + left_section--; + if(LeftSection_F() <= 0) return FALSE; + } + } + + Ymin=v1->y; + Ymax=min(v3->y-1,drawH); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +__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 BOOL NextRow_G(void) +{ + if(--left_section_height<=0) + { + if(--left_section <= 0) {return TRUE;} + if(LeftSection_G() <= 0) {return TRUE;} + } + 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 TRUE;} + if(RightSection_G() <=0) {return TRUE;} + } + else + { + right_x += delta_right_x; + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL 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 FALSE;} + temp=(((v2->y - v1->y) << 16) / height); + longest = temp * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + if(longest == 0) {return FALSE;} + + 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 FALSE; + if(RightSection_G() <= 0) + { + right_section--; + if(RightSection_G() <= 0) return FALSE; + } + 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 FALSE; + if(LeftSection_G() <= 0) + { + left_section--; + if(LeftSection_G() <= 0) return FALSE; + } + if(longest < 0x1000) longest = 0x1000; + } + + Ymin=v1->y; + Ymax=min(v3->y-1,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 TRUE; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +__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 BOOL NextRow_FT(void) +{ + if(--left_section_height<=0) + { + if(--left_section <= 0) {return TRUE;} + if(LeftSection_FT() <= 0) {return TRUE;} + } + 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 TRUE;} + if(RightSection_FT() <=0) {return TRUE;} + } + else + { + right_x += delta_right_x; + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL 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 FALSE;} + + temp=(((v2->y - v1->y) << 16) / height); + longest = temp * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + + if(longest == 0) {return FALSE;} + + 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 FALSE; + if(RightSection_FT() <= 0) + { + right_section--; + if(RightSection_FT() <= 0) return FALSE; + } + 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 FALSE; + if(LeftSection_FT() <= 0) + { + left_section--; + if(LeftSection_FT() <= 0) return FALSE; + } + if(longest < 0x1000) longest = 0x1000; + } + + Ymin=v1->y; + Ymax=min(v3->y-1,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 TRUE; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +__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 BOOL NextRow_GT(void) +{ + if(--left_section_height<=0) + { + if(--left_section <= 0) {return TRUE;} + if(LeftSection_GT() <= 0) {return TRUE;} + } + 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 TRUE;} + if(RightSection_GT() <=0) {return TRUE;} + } + else + { + right_x += delta_right_x; + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL 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 FALSE;} + + temp=(((v2->y - v1->y) << 16) / height); + longest = temp * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + + if(longest == 0) {return FALSE;} + + 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 FALSE; + if(RightSection_GT() <= 0) + { + right_section--; + if(RightSection_GT() <= 0) return FALSE; + } + + 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 FALSE; + if(LeftSection_GT() <= 0) + { + left_section--; + if(LeftSection_GT() <= 0) return FALSE; + } + if(longest < 0x1000) longest = 0x1000; + } + + Ymin=v1->y; + Ymax=min(v3->y-1,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 TRUE; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +__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 BOOL 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 FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL 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; + } + + Ymin=v1->y; + Ymax=min(v4->y-1,drawH); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +__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 BOOL 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 FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL 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; + } + + Ymin=v1->y; + Ymax=min(v4->y-1,drawH); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +__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 BOOL 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 FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline BOOL 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; + } + + Ymin=v1->y; + Ymax=min(v4->y-1,drawH); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// 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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_F(x1,y1,x2,y2,x3,y3)) return; + + ymax=Ymax; + + color = ((rgb & 0x00f80000)>>9) | ((rgb & 0x0000f800)>>6) | ((rgb & 0x000000f8)>>3); + lcolor=lSetMask|(((uint32_t)(color))<<16)|color; + + for(ymin=Ymin;ymin> 16; if(drawX>xmin) xmin=drawX; + xmax=(right_x >> 16)-1; if(drawW> 16; if(drawX>xmin) xmin=drawX; + xmax=(right_x >> 16)-1; if(drawWdrawW && lx1>drawW && lx2>drawW && lx3>drawW) return; + if(ly0>drawH && ly1>drawH && ly2>drawH && ly3>drawH) return; + if(lx0=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_F4(lx0,ly0,lx1,ly1,lx2,ly2,lx3,ly3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin>9) | ((rgb & 0x0000f800)>>6) | ((rgb & 0x000000f8)>>3); + lcolor= lSetMask|(((uint32_t)(color))<<16)|color; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + color |=sSetMask; + for (i=ymin;i<=ymax;i++) + { + xmin=left_x >> 16; if(drawX>xmin) xmin=drawX; + xmax=(right_x >> 16)-1; if(drawW> 16; if(drawX>xmin) xmin=drawX; + xmax=(right_x >> 16)-1; if(drawWdrawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin>1); + + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16);//-1; //!!!!!!!!!!!!!!!! + if(xmax>xmin) xmax--; + + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin>1); + +#ifdef FASTSOLID + + if(!bCheckMask && !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>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin>1); + +#ifdef FASTSOLID + + if(!bCheckMask && !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>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_SPR((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_SPR(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + ((posX+difX)>>16)]; + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + + if(j==xmax) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + ((posX+difX)>>16)]; + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + + if(j==xmax) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16);//-1; //!!!!!!!!!!!!!!!! + if(xmax>xmin) xmax--; + + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + + if(j==xmax) + { + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[clutP+tC1])); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + + if(j==xmax) + { + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + ((posX+difX)>>16)]; + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + ((posX+difX)>>16)]; + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32_SPR((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[clutP+tC2]))<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG_SPR(&psxVuw[(i<<10)+j],GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX])); + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY)<<10)+TWin.Position.y0+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY)<<10)+TWin.Position.y0+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_SPR(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_G(x1,y1,x2,y2,x3,y3,rgb1,rgb2,rgb3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1;if(drawW=xmin) + { + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>3)&0x001f0000)| + (((cR1) >> 9)&0x7c00)|(((cG1) >> 14)&0x03e0)|(((cB1) >> 19)&0x001f))|lSetMask); + + cR1+=difR2; + cG1+=difG2; + cB1+=difB2; + } + if(j==xmax) + PUTLE16(&psxVuw[(i<<10)+j], (((cR1 >> 9)&0x7c00)|((cG1 >> 14)&0x03e0)|((cB1 >> 19)&0x001f))|sSetMask); + } + if(NextRow_G()) return; + } + return; + } + +#endif + + if(iDither==2) + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1;if(drawW=xmin) + { + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>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(drawW=xmin) + { + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin> 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(lx0,ly0,lx1,ly1,lx2,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(lx1,ly1,lx3,ly3,lx2,ly2, + rgb2,rgb4,rgb3); + drawPoly3Gi(lx0,ly0,lx1,ly1,lx2,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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=((right_x) >> 16)-1; //!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16); + tC1 = psxVub[((posY>>5)&0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=((right_x) >> 16)-1; //!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin>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(!bCheckMask && !DrawSemiTrans && !iDither) + { + for (i=ymin;i<=ymax;i++) + { + xmin=((left_x) >> 16); + xmax=((right_x) >> 16)-1; //!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=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=Ymax; + + for(ymin=Ymin;ymin> 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>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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>16); + tC1 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; // !!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>5)&(int32_t)0xFFFFF800)+YAdjust+((posX>>16))]; + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + (((posX+difX)>>16))]; + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+((posX>>16))]; + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>5)&(int32_t)0xFFFFF800)+YAdjust+((posX>>16))]; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; // !!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (GETLE16(&psxVuw[(n_yi<<10)+YAdjust+n_xi]) >> ((TXU & 0x01)<<3)) & 0xff; + + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; // !!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=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=Ymax; + + for(ymin=Ymin;ymin> 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>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + tC2 = psxVub[(((posY+difY)>>5)&(int32_t)0xFFFFF800)+YAdjust+ + ((posX+difX)>>16)]; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1])| + ((int32_t)GETLE16(&psxVuw[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 = psxVub[((posY>>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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>5)&(int32_t)0xFFFFF800)+YAdjust+(posX>>16)]; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[clutP+tC1]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+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(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]))<<16)| + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX)>>16)%TWin.Position.x1)+GlobalTextAddrX+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(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=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=Ymax; + + for(ymin=Ymin;ymin> 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>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX]))<<16)| + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+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(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]), + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + GETLE16(&psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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 BOOL IsNoRect(void) +{ + if(lx0==lx1 && lx2==lx3) return FALSE; + if(lx0==lx2 && lx1==lx3) return FALSE; + if(lx0==lx3 && lx1==lx2) return FALSE; + return TRUE; +} +*/ + +// real rect test +__inline BOOL IsNoRect(void) +{ + if(!(dwActFixes&0x200)) return FALSE; + + if(ly0==ly1) + { + if(lx1==lx3 && ly3==ly2 && lx2==lx0) return FALSE; + if(lx1==lx2 && ly2==ly3 && lx3==lx0) return FALSE; + return TRUE; + } + + if(ly0==ly2) + { + if(lx2==lx3 && ly3==ly1 && lx1==lx0) return FALSE; + if(lx2==lx1 && ly1==ly3 && lx3==lx0) return FALSE; + return TRUE; + } + + if(ly0==ly3) + { + if(lx3==lx2 && ly2==ly1 && lx1==lx0) return FALSE; + if(lx3==lx1 && ly1==ly2 && lx2==lx0) return FALSE; + return TRUE; + } + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3FT(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + + if(GlobalTextIL && GlobalTextTP<2) + { + if(GlobalTextTP==0) + drawPoly3TEx4_IL(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask)); + else + drawPoly3TEx8_IL(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask)); + return; + } + + if(!bUsingTWin && !(dwActFixes&0x100)) + { + switch(GlobalTextTP) // depending on texture mode + { + case 0: + drawPoly3TEx4(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask)); + return; + case 1: + drawPoly3TEx8(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask)); + return; + case 2: + drawPoly3TD(lx0,ly0,lx1,ly1,lx2,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(GlobalTextTP) // depending on texture mode + { + case 0: + drawPoly3TEx4_TW(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask)); + return; + case 1: + drawPoly3TEx8_TW(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask)); + return; + case 2: + drawPoly3TD_TW(lx0,ly0,lx1,ly1,lx2,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(GlobalTextIL && GlobalTextTP<2) + { + if(GlobalTextTP==0) + drawPoly4TEx4_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); + else + drawPoly4TEx8_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); + return; + } + + if(!bUsingTWin) + { +#ifdef POLYQUAD3GT + if(IsNoRect()) + { + switch (GlobalTextTP) + { + case 0: + drawPoly4TEx4_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); + return; + case 1: + drawPoly4TEx8_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); + return; + case 2: + drawPoly4TD_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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 (GlobalTextTP) + { + case 0: // grandia investigations needed + drawPoly4TEx4(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); + return; + case 1: + drawPoly4TEx8(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); + return; + case 2: + drawPoly4TD(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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 (GlobalTextTP) + { + case 0: + drawPoly4TEx4_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); + return; + case 1: + drawPoly4TEx8_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask)); + return; + case 2: + drawPoly4TD_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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(GlobalTextIL && GlobalTextTP<2) + { + if(GlobalTextTP==0) + drawPoly3TGEx4_IL(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); + else + drawPoly3TGEx8_IL(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); + return; + } + + if(!bUsingTWin) + { + switch (GlobalTextTP) + { + case 0: + drawPoly3TGEx4(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); + return; + case 1: + drawPoly3TGEx8(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); + return; + case 2: + drawPoly3TGD(lx0,ly0,lx1,ly1,lx2,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(GlobalTextTP) + { + case 0: + drawPoly3TGEx4_TW(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); + return; + case 1: + drawPoly3TGEx8_TW(lx0,ly0,lx1,ly1,lx2,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) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6])); + return; + case 2: + drawPoly3TGD_TW(lx0,ly0,lx1,ly1,lx2,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(GlobalTextIL && GlobalTextTP<2) + { + if(GlobalTextTP==0) + drawPoly4TGEx4_TRI_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + else + drawPoly4TGEx8_TRI_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + return; + } + + if(!bUsingTWin) + { +#ifdef POLYQUAD3GT + if(IsNoRect()) + { + switch (GlobalTextTP) + { + case 0: + drawPoly4TGEx4_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + + return; + case 1: + drawPoly4TGEx8_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + return; + case 2: + drawPoly4TGD_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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 (GlobalTextTP) + { + case 0: + drawPoly4TGEx4(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + + return; + case 1: + drawPoly4TGEx8(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + return; + case 2: + drawPoly4TGD(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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 (GlobalTextTP) + { + case 0: + drawPoly4TGEx4_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + return; + case 1: + drawPoly4TGEx8_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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) & iGPUHeightMask), + GETLE32(&gpuData[0]),GETLE32(&gpuData[3]),GETLE32(&gpuData[6]),GETLE32(&gpuData[9])); + return; + case 2: + drawPoly4TGD_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,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=lx0; + sy0=ly0; + + sx0=sx3=sx0+PSXDisplay.DrawOffset.x; + sx1=sx2=sx0+w; + sy0=sy1=sy0+PSXDisplay.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 (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) & iGPUHeightMask)); + 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) & iGPUHeightMask)); + 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 = ly0; + sprtX = lx0; + sprtH = h; + sprtW = w; + clutY0 = (GETLE32(&gpuData[2])>>22) & iGPUHeightMask; + clutX0 = (GETLE32(&gpuData[2])>>12) & 0x3f0; + clutP = (clutY0<<11) + (clutX0<<1); + textY0 = ((GETLE32(&gpuData[2])>>8) & 0x000000ff) + GlobalTextAddrY; + textX0 = (GETLE32(&gpuData[2]) & 0x000000ff); + + sprtX+=PSXDisplay.DrawOffset.x; + sprtY+=PSXDisplay.DrawOffset.y; + +// while (sprtX>1023) sprtX-=1024; +// while (sprtY>MAXYLINESMIN1) sprtY-=MAXYLINES; + + if(sprtX>drawW) + { +// if((sprtX+sprtW)>1023) sprtX-=1024; +// else return; + return; + } + + if(sprtY>drawH) + { +// if ((sprtY+sprtH)>MAXYLINESMIN1) sprtY-=MAXYLINES; +// else return; + return; + } + + if(sprtYdrawH) sprtH=drawH-sprtY+1; + if((sprtX+sprtW)>drawW) sprtW=drawW-sprtX+1; + + if(usMirror&0x1000) lXDir=-1; else lXDir=1; + if(usMirror&0x2000) lYDir=-1; else lYDir=1; + + switch (GlobalTextTP) + { + case 0: // texture is 4-bit + + sprtW=sprtW/2; + textX0=(GlobalTextAddrX<<1)+(textX0>>1); + sprtYa=(sprtY<<10); + clutP=(clutY0<<10)+clutX0; + for (sprCY=0;sprCY>4)&0xf)])); + GetTextureTransColG_SPR(&psxVuw[sprA+1],GETLE16(&psxVuw[clutP+(tC&0xf)])); + } + return; + + case 1: + + clutP>>=1; + for(sprCY=0;sprCYdrawW) return; + if(sprtY>drawH) return; + + tdx=tx+sprtW; + tdy=ty+sprtH; + + sprtW+=sprtX; + sprtH+=sprtY; + + // Pete is too lazy to make a faster version ;) + + if(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) & iGPUHeightMask)); + + + 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) & iGPUHeightMask)); +} + +//////////////////////////////////////////////////////////////////////// + +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; + BOOL bWT,bWS; + + if(GlobalTextIL && GlobalTextTP<2) + {DrawSoftwareSprite_IL(baseAddr,w,h,tx,ty);return;} + + sprtY = ly0; + sprtX = lx0; + sprtH = h; + sprtW = w; + clutY0 = (GETLE32(&gpuData[2])>>22) & iGPUHeightMask; + clutX0 = (GETLE32(&gpuData[2])>>12) & 0x3f0; + + clutP = (clutY0<<11) + (clutX0<<1); + + textY0 =ty+ GlobalTextAddrY; + textX0 =tx; + + sprtX+=PSXDisplay.DrawOffset.x; + sprtY+=PSXDisplay.DrawOffset.y; + + //while (sprtX>1023) sprtX-=1024; + //while (sprtY>MAXYLINESMIN1) sprtY-=MAXYLINES; + + if(sprtX>drawW) + { +// if((sprtX+sprtW)>1023) sprtX-=1024; +// else return; + return; + } + + if(sprtY>drawH) + { +// if ((sprtY+sprtH)>MAXYLINESMIN1) sprtY-=MAXYLINES; +// else return; + return; + } + + if(sprtYdrawH) sprtH=drawH-sprtY+1; + if((sprtX+sprtW)>drawW) sprtW=drawW-sprtX+1; + + + bWT=FALSE; + bWS=FALSE; + + switch (GlobalTextTP) + { + case 0: + + if(textX0&1) {bWS=TRUE;sprtW--;} + if(sprtW&1) bWT=TRUE; + + sprtW=sprtW>>1; + textX0=(GlobalTextAddrX<<1)+(textX0>>1)+(textY0<<11); + sprtYa=(sprtY<<10)+sprtX; + clutP=(clutY0<<10)+clutX0; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (sprCY=0;sprCY>4)&0xf)])); + } + + for (sprCX=0;sprCX>4)&0xf)]))<<16)| + GETLE16(&psxVuw[clutP+(tC&0x0f)])); + } + + if(bWT) + { + tC=*pV; + GetTextureTransColG_S(&psxVuw[sprA],GETLE16(&psxVuw[clutP+(tC&0x0f)])); + } + } + return; + } + +#endif + + for (sprCY=0;sprCY>4)&0xf)])); + } + + for (sprCX=0;sprCX>4)&0xf)])<<16))| + GETLE16(&psxVuw[clutP+(tC&0x0f)])); + } + + if(bWT) + { + tC=*pV; + GetTextureTransColG_SPR(&psxVuw[sprA],GETLE16(&psxVuw[clutP+(tC&0x0f)])); + } + } + return; + + case 1: + clutP>>=1;sprtW--; + textX0+=(GlobalTextAddrX<<1) + (textY0<<11); + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for(sprCY=0;sprCY 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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 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 < drawY) + { + r0+=dr*(drawY - y0); + g0+=dg*(drawY - y0); + b0+=db*(drawY - y0); + y0 = drawY; + } + + if (y1 > drawH) + y1 = drawH; + + for (y = y0; y <= y1; y++) + { + GetShadeTransCol(&psxVuw[(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 < drawX) + { + r0+=dr*(drawX - x0); + g0+=dg*(drawX - x0); + b0+=db*(drawX - x0); + x0 = drawX; + } + + if (x1 > drawW) + x1 = drawW; + + for (x = x0; x <= x1; x++) + { + GetShadeTransCol(&psxVuw[(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>=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y y1) + { + if (d <= 0) + { + d = d + incrN; /* Choose N */ + y--; + } + else + { + d = d + incrNE; /* Choose NE */ + x++; + y--; + } + if ((x>=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y drawH) + y1 = drawH; + + for (y = y0; y <= y1; y++) + GetShadeTransCol(&psxVuw[(y<<10)+x], colour); +} + +/////////////////////////////////////////////////////////////////////// + +void HorzLineFlat(int y, int x0, int x1, unsigned short colour) +{ + int x; + + if (x0 < drawX) + x0 = drawX; + + if (x1 > drawW) + x1 = drawW; + + for (x = x0; x <= x1; x++) + GetShadeTransCol(&psxVuw[(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 (lx0 > drawW && lx1 > drawW) return; + if (ly0 > drawH && ly1 > drawH) return; + if (lx0 < drawX && lx1 < drawX) return; + if (ly0 < drawY && ly1 < drawY) return; + if (drawY >= drawH) return; + if (drawX >= drawW) return; + + x0 = lx0; + y0 = ly0; + x1 = lx1; + y1 = 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 (lx0 > drawW && lx1 > drawW) return; + if (ly0 > drawH && ly1 > drawH) return; + if (lx0 < drawX && lx1 < drawX) return; + if (ly0 < drawY && ly1 < drawY) return; + if (drawY >= drawH) return; + if (drawX >= drawW) return; + + colour = ((rgb & 0x00f80000) >> 9) | ((rgb & 0x0000f800) >> 6) | ((rgb & 0x000000f8) >> 3); + + x0 = lx0; + y0 = ly0; + x1 = lx1; + y1 = 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/dfxvideo/zn.c b/plugins/dfxvideo/zn.c index d3fe1c57..38b906ba 100644 --- a/plugins/dfxvideo/zn.c +++ b/plugins/dfxvideo/zn.c @@ -1,236 +1,264 @@ -/*************************************************************************** - zn.c - description - ------------------- - begin : Sat Jan 31 2004 - copyright : (C) 2004 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. * - * * - ***************************************************************************/ - -#define _IN_ZN - -#include "externals.h" - -// --------------------------------------------------- // -// - psx gpu plugin interface prototypes-------------- // -// --------------------------------------------------- // - -#include "psemu_plugin_defs.h" - -// --------------------------------------------------- // -// - zn gpu interface -------------------------------- // -// --------------------------------------------------- // - -uint32_t dwGPUVersion=0; -int iGPUHeight=512; -int iGPUHeightMask=511; -int GlobalTextIL=0; -int iTileCheat=0; - -// --------------------------------------------------- // -// --------------------------------------------------- // -// --------------------------------------------------- // - -typedef struct GPUOTAG - { - uint32_t Version; // Version of structure - currently 1 - long hWnd; // Window handle - uint32_t ScreenRotation; // 0 = 0CW, 1 = 90CW, 2 = 180CW, 3 = 270CW = 90CCW - uint32_t GPUVersion; // 0 = a, 1 = b, 2 = c - const char* GameName; // NULL terminated string - const char* CfgFile; // NULL terminated string - } GPUConfiguration_t; - -#if 0 // ZN_* functions: wtf? not supported by pcsx -// --------------------------------------------------- // -// --------------------------------------------------- // -// --------------------------------------------------- // - -void CALLBACK ZN_GPUdisplayFlags(uint32_t dwFlags) -{ - GPUdisplayFlags(dwFlags); -} - -// --------------------------------------------------- // - -void CALLBACK ZN_GPUmakeSnapshot(void) -{ - GPUmakeSnapshot(); -} - -// --------------------------------------------------- // - -long CALLBACK ZN_GPUinit() -{ // we always set the vram size to 2MB, if the ZN interface is used - iGPUHeight=1024; - iGPUHeightMask=1023; - - return GPUinit(); -} - -// --------------------------------------------------- // - -long CALLBACK ZN_GPUopen(void * vcfg) -{ - GPUConfiguration_t * cfg=(GPUConfiguration_t *)vcfg; - long lret; - - if(!cfg) return -1; - if(cfg->Version!=1) return -1; - -#ifdef _WINDOWS - lret=GPUopen((HWND)cfg->hWnd); -#else - lret = GPUopen(&cfg->hWnd, cfg->GameName, cfg->CfgFile); -#endif - -/* - if(!lstrcmp(cfg->GameName,"kikaioh") || - !lstrcmp(cfg->GameName,"sr2j") || - !lstrcmp(cfg->GameName,"rvschool_a")) - iTileCheat=1; -*/ - - // some ZN games seem to erase the cluts with a 'white' TileS... strange.. - // I've added a cheat to avoid this issue. We can set it globally (for - // all ZiNc games) without much risk - - iTileCheat=1; - - dwGPUVersion=cfg->GPUVersion; - - return lret; -} - -// --------------------------------------------------- // - -long CALLBACK ZN_GPUclose() -{ - return GPUclose(); -} - -// --------------------------------------------------- // - -long CALLBACK ZN_GPUshutdown() -{ - return GPUshutdown(); -} - -// --------------------------------------------------- // - -void CALLBACK ZN_GPUupdateLace(void) -{ - GPUupdateLace(); -} - -// --------------------------------------------------- // - -uint32_t CALLBACK ZN_GPUreadStatus(void) -{ - return GPUreadStatus(); -} - -// --------------------------------------------------- // - -void CALLBACK ZN_GPUwriteStatus(uint32_t gdata) -{ - GPUwriteStatus(gdata); -} - -// --------------------------------------------------- // - -long CALLBACK ZN_GPUdmaSliceOut(uint32_t *baseAddrL, uint32_t addr, uint32_t iSize) -{ - GPUreadDataMem(baseAddrL+addr,iSize); - return 0; -} - -// --------------------------------------------------- // - -uint32_t CALLBACK ZN_GPUreadData(void) -{ - return GPUreadData(); -} - -// --------------------------------------------------- // - -void CALLBACK ZN_GPUsetMode(uint32_t gdata) -{ - GPUsetMode(gdata); -} - -// --------------------------------------------------- // - -long CALLBACK ZN_GPUgetMode(void) -{ - return GPUgetMode(); -} - -// --------------------------------------------------- // - -long CALLBACK ZN_GPUdmaSliceIn(uint32_t *baseAddrL, uint32_t addr, uint32_t iSize) -{ - GPUwriteDataMem(baseAddrL+addr,iSize); - return 0; -} -// --------------------------------------------------- // - -void CALLBACK ZN_GPUwriteData(uint32_t gdata) -{ - GPUwriteDataMem(&gdata,1); -} - -// --------------------------------------------------- // - -long CALLBACK ZN_GPUdmaChain(uint32_t * baseAddrL, uint32_t addr) -{ - return GPUdmaChain(baseAddrL,addr); -} - -// --------------------------------------------------- // - -long CALLBACK ZN_GPUtest(void) -{ - return GPUtest(); -} - -// --------------------------------------------------- // - -long CALLBACK ZN_GPUfreeze(uint32_t ulGetFreezeData,void * pF) -{ - return GPUfreeze(ulGetFreezeData,pF); -} - -// --------------------------------------------------- // - -void CALLBACK ZN_GPUgetScreenPic(unsigned char * pMem) -{ - GPUgetScreenPic(pMem); -} - -// --------------------------------------------------- // - -void CALLBACK ZN_GPUshowScreenPic(unsigned char * pMem) -{ - GPUshowScreenPic(pMem); -} - -// --------------------------------------------------- // - -#ifndef _WINDOWS - -void CALLBACK ZN_GPUkeypressed(int keycode) -{ - GPUkeypressed(keycode); -} - -#endif -#endif +/*************************************************************************** + zn.c - description + ------------------- + begin : Sat Jan 31 2004 + copyright : (C) 2004 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. * + * * + ***************************************************************************/ + +#define _IN_ZN + +#include "externals.h" + +// --------------------------------------------------- // +// - psx gpu plugin interface prototypes-------------- // +// --------------------------------------------------- // + +#ifdef _WINDOWS +long CALLBACK GPUopen(HWND hwndGPU); +#else +long GPUopen(unsigned long * disp,const char * CapText,const char * CfgFile); +#endif +void CALLBACK GPUdisplayText(char * pText); +void CALLBACK GPUdisplayFlags(uint32_t dwFlags); +void CALLBACK GPUmakeSnapshot(void); +long CALLBACK GPUinit(); +long CALLBACK GPUclose(); +long CALLBACK GPUshutdown(); +void CALLBACK GPUcursor(int iPlayer,int x,int y); +void CALLBACK GPUupdateLace(void); +uint32_t CALLBACK GPUreadStatus(void); +void CALLBACK GPUwriteStatus(uint32_t gdata); +void CALLBACK GPUreadDataMem(uint32_t * pMem, int iSize); +uint32_t CALLBACK GPUreadData(void); +void CALLBACK GPUwriteDataMem(uint32_t * pMem, int iSize); +void CALLBACK GPUwriteData(uint32_t gdata); +void CALLBACK GPUsetMode(uint32_t gdata); +long CALLBACK GPUgetMode(void); +long CALLBACK GPUdmaChain(uint32_t * baseAddrL, uint32_t addr); +long CALLBACK GPUconfigure(void); +void CALLBACK GPUabout(void); +long CALLBACK GPUtest(void); +long CALLBACK GPUfreeze(uint32_t ulGetFreezeData,void * pF); +void CALLBACK GPUgetScreenPic(unsigned char * pMem); +void CALLBACK GPUshowScreenPic(unsigned char * pMem); +#ifndef _WINDOWS +void CALLBACK GPUkeypressed(int keycode); +#endif + +// --------------------------------------------------- // +// - zn gpu interface -------------------------------- // +// --------------------------------------------------- // + +uint32_t dwGPUVersion=0; +int iGPUHeight=512; +int iGPUHeightMask=511; +int GlobalTextIL=0; +int iTileCheat=0; + +// --------------------------------------------------- // +// --------------------------------------------------- // +// --------------------------------------------------- // + +typedef struct GPUOTAG + { + uint32_t Version; // Version of structure - currently 1 + long hWnd; // Window handle + uint32_t ScreenRotation; // 0 = 0CW, 1 = 90CW, 2 = 180CW, 3 = 270CW = 90CCW + uint32_t GPUVersion; // 0 = a, 1 = b, 2 = c + const char* GameName; // NULL terminated string + const char* CfgFile; // NULL terminated string + } GPUConfiguration_t; + +// --------------------------------------------------- // +// --------------------------------------------------- // +// --------------------------------------------------- // + +void CALLBACK ZN_GPUdisplayFlags(uint32_t dwFlags) +{ + GPUdisplayFlags(dwFlags); +} + +// --------------------------------------------------- // + +void CALLBACK ZN_GPUmakeSnapshot(void) +{ + GPUmakeSnapshot(); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUinit() +{ // we always set the vram size to 2MB, if the ZN interface is used + iGPUHeight=1024; + iGPUHeightMask=1023; + + return GPUinit(); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUopen(void * vcfg) +{ + GPUConfiguration_t * cfg=(GPUConfiguration_t *)vcfg; + long lret; + + if(!cfg) return -1; + if(cfg->Version!=1) return -1; + +#ifdef _WINDOWS + lret=GPUopen((HWND)cfg->hWnd); +#else + lret = GPUopen(&cfg->hWnd, cfg->GameName, cfg->CfgFile); +#endif + +/* + if(!lstrcmp(cfg->GameName,"kikaioh") || + !lstrcmp(cfg->GameName,"sr2j") || + !lstrcmp(cfg->GameName,"rvschool_a")) + iTileCheat=1; +*/ + + // some ZN games seem to erase the cluts with a 'white' TileS... strange.. + // I've added a cheat to avoid this issue. We can set it globally (for + // all ZiNc games) without much risk + + iTileCheat=1; + + dwGPUVersion=cfg->GPUVersion; + + return lret; +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUclose() +{ + return GPUclose(); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUshutdown() +{ + return GPUshutdown(); +} + +// --------------------------------------------------- // + +void CALLBACK ZN_GPUupdateLace(void) +{ + GPUupdateLace(); +} + +// --------------------------------------------------- // + +uint32_t CALLBACK ZN_GPUreadStatus(void) +{ + return GPUreadStatus(); +} + +// --------------------------------------------------- // + +void CALLBACK ZN_GPUwriteStatus(uint32_t gdata) +{ + GPUwriteStatus(gdata); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUdmaSliceOut(uint32_t *baseAddrL, uint32_t addr, uint32_t iSize) +{ + GPUreadDataMem(baseAddrL+addr,iSize); + return 0; +} + +// --------------------------------------------------- // + +uint32_t CALLBACK ZN_GPUreadData(void) +{ + return GPUreadData(); +} + +// --------------------------------------------------- // + +void CALLBACK ZN_GPUsetMode(uint32_t gdata) +{ + GPUsetMode(gdata); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUgetMode(void) +{ + return GPUgetMode(); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUdmaSliceIn(uint32_t *baseAddrL, uint32_t addr, uint32_t iSize) +{ + GPUwriteDataMem(baseAddrL+addr,iSize); + return 0; +} +// --------------------------------------------------- // + +void CALLBACK ZN_GPUwriteData(uint32_t gdata) +{ + GPUwriteDataMem(&gdata,1); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUdmaChain(uint32_t * baseAddrL, uint32_t addr) +{ + return GPUdmaChain(baseAddrL,addr); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUtest(void) +{ + return GPUtest(); +} + +// --------------------------------------------------- // + +long CALLBACK ZN_GPUfreeze(uint32_t ulGetFreezeData,void * pF) +{ + return GPUfreeze(ulGetFreezeData,pF); +} + +// --------------------------------------------------- // + +void CALLBACK ZN_GPUgetScreenPic(unsigned char * pMem) +{ + GPUgetScreenPic(pMem); +} + +// --------------------------------------------------- // + +void CALLBACK ZN_GPUshowScreenPic(unsigned char * pMem) +{ + GPUshowScreenPic(pMem); +} + +// --------------------------------------------------- // + +#ifndef _WINDOWS + +void CALLBACK ZN_GPUkeypressed(int keycode) +{ + GPUkeypressed(keycode); +} + +#endif diff --git a/plugins/gxvideo/cfg.c b/plugins/gxvideo/cfg.c index 2274c529..7b18327a 100644 --- a/plugins/gxvideo/cfg.c +++ b/plugins/gxvideo/cfg.c @@ -1,261 +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 -#include -#include -#include -#include - -#include "globals.h" -#include "cfg.h" - -#define DEFAULT_CFG_NAME "gxvideo.cfg" - -static 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; -} - -static 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; -} - -static void write_int_value (FILE * f, char const * name, int val) { - fprintf(f, "%s = %d\n", name, val); -} - -static void write_double_value (FILE * f, char const * name, double val) { - fprintf(f, "%s = %.1f\n", name, val); -} - -static 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); -} - -static 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); -} +/* + * 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 +#include +#include +#include +#include + +#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/draw.c b/plugins/gxvideo/draw.c index a83e429b..5e3b31ad 100644 --- a/plugins/gxvideo/draw.c +++ b/plugins/gxvideo/draw.c @@ -1,761 +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 -#include -#include -#include -#include -#include - -#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 */ -static 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; -} - -static 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 - -static 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 - -static 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; -} - -#if 0 -static 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; -} -#endif - -static 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; - } -} - -static 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; - } -} - -#if 0 -static 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; -} -#endif - -static 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; - } - } -} - -static 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 - */ -static 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); -} - -static 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) { -} +/* + * 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 +#include +#include +#include +#include +#include + +#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/fps.c b/plugins/gxvideo/fps.c index f53800ff..3603dad1 100644 --- a/plugins/gxvideo/fps.c +++ b/plugins/gxvideo/fps.c @@ -1,69 +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 -#include - -#include "globals.h" -#include "fps.h" -#include "gpu.h" - -#define TIMEBASE 100000 - -static 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; - } -} +/* + * 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 +#include + +#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/gpu.c b/plugins/gxvideo/gpu.c index 85b003bd..22544950 100644 --- a/plugins/gxvideo/gpu.c +++ b/plugins/gxvideo/gpu.c @@ -1,1549 +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 -#include -#include - -#include "globals.h" -#include "gpu.h" -#include "swap.h" -#include "psemu_plugin_defs.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)) - -//////////////////////////////////////////////////////////////////////// -// 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"); -#if 0 -static char const * libraryInfo = N_("GXvideo Driver v1.00"); -#endif -//static char const * PluginAuthor = -// N_("gschwind (rewrite from Pete Bernert and the P.E.Op.S. team)"); - -//////////////////////////////////////////////////////////////////////// -// some misc external display funcs -//////////////////////////////////////////////////////////////////////// - -#include - -//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; -} - -#if 0 -char * GPUgetLibInfos(void) { - return _(libraryInfo); -} -#endif - -//////////////////////////////////////////////////////////////////////// -// 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 :) -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -static 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 -//////////////////////////////////////////////////////////////////////// - -#if 0 -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; -} -#endif - -//////////////////////////////////////////////////////////////////////// -// call config dlg -//////////////////////////////////////////////////////////////////////// - -long CALLBACK GPUconfigure(void) { - SoftDlgProc(); - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// sets all kind of act fixes -//////////////////////////////////////////////////////////////////////// - -#if 0 -void SetFixes(void) { - -} -#endif - -//////////////////////////////////////////////////////////////////////// -// process gpu commands -//////////////////////////////////////////////////////////////////////// - -unsigned long lUsedAddr[3]; - -static 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 -//////////////////////////////////////////////////////////////////////// - -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 } }; - -//////////////////////////////////////////////////////////////////////// - -#if 0 -static 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 -} -#endif - -//////////////////////////////////////////////////////////////////////// -// 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: - -long 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 - } - */ - return -1; -} - -//////////////////////////////////////////////////////////////////////// -// 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 - -long CALLBACK GPUshowScreenPic(unsigned char * pMem) { - DestroyPic(); // destroy old pic data - if (pMem == 0) - return 0; // done - CreatePic(pMem); // create new pic... don't free pMem or something like that... just read from it - return 0; -} - -#if 0 -void CALLBACK GPUsetfix(uint32_t dwFixBits) { - g_prim.dwEmuFixes = dwFixBits; -} -#endif - -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; -} +/* + * 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 +#include +#include + +#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 +#include +#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 + +//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/gpucfg/main.c b/plugins/gxvideo/gpucfg/main.c index 326eb1d8..64691e56 100644 --- a/plugins/gxvideo/gpucfg/main.c +++ b/plugins/gxvideo/gpucfg/main.c @@ -1,347 +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 -#include - -#include "globals.h" -#include "config.h" - -#ifdef ENABLE_NLS -#include -#include -#endif - -#include -#include -#include -#include -#include - -#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 *); - -static void on_about_clicked(GtkWidget * widget, gpointer user_data) { - gtk_widget_destroy(widget); - exit(0); -} - -static 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))); -} - -static void update_fixes_stase(GtkWidget * ths, GtkWidget * w) { - gtk_widget_set_sensitive(ths, gtk_toggle_button_get_active( - GTK_TOGGLE_BUTTON(w))); -} - -static 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); -} - -static 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); -} - -static void on_destroy_window(GtkWidget * widget, cfg_window_t * w) { - free(w); -} - -static 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); -} - -static 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", - G_CALLBACK(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", - G_CALLBACK(on_destroy_window), w, NULL, 0); - g_signal_connect_data(GTK_OBJECT(w->save_button), "clicked", - G_CALLBACK(on_click_save_button), w, NULL, G_CONNECT_AFTER); - g_signal_connect_data(GTK_OBJECT(w->cancel_button), "clicked", - G_CALLBACK(on_click_cancel_button), w, NULL, G_CONNECT_AFTER); - - g_signal_connect_data(GTK_OBJECT(w->fullscreen_checkbutton), "clicked", - G_CALLBACK(on_fullscreen_toggled), w, NULL, G_CONNECT_AFTER); - - g_signal_connect_data(GTK_OBJECT(w->use_game_fixes_checkbutton), "clicked", - G_CALLBACK(on_use_fixes_toggled), w, NULL, G_CONNECT_AFTER); - g_signal_connect_data(GTK_OBJECT(w->set_fps_checkbutton), "clicked", - G_CALLBACK(on_fps_toggled), w, NULL, G_CONNECT_AFTER); - - g_signal_connect_data(GTK_OBJECT(w->auto_fps_limit_checkbutton), "clicked", - G_CALLBACK(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); -} +/* + * 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 +#include + +#include "globals.h" +#include "config.h" + +#ifdef ENABLE_NLS +#include +#include +#endif + +#include +#include +#include +#include +#include + +#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", + G_CALLBACK(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", + G_CALLBACK(on_destroy_window), w, NULL, 0); + g_signal_connect_data(GTK_OBJECT(w->save_button), "clicked", + G_CALLBACK(on_click_save_button), w, NULL, G_CONNECT_AFTER); + g_signal_connect_data(GTK_OBJECT(w->cancel_button), "clicked", + G_CALLBACK(on_click_cancel_button), w, NULL, G_CONNECT_AFTER); + + g_signal_connect_data(GTK_OBJECT(w->fullscreen_checkbutton), "clicked", + G_CALLBACK(on_fullscreen_toggled), w, NULL, G_CONNECT_AFTER); + + g_signal_connect_data(GTK_OBJECT(w->use_game_fixes_checkbutton), "clicked", + G_CALLBACK(on_use_fixes_toggled), w, NULL, G_CONNECT_AFTER); + g_signal_connect_data(GTK_OBJECT(w->set_fps_checkbutton), "clicked", + G_CALLBACK(on_fps_toggled), w, NULL, G_CONNECT_AFTER); + + g_signal_connect_data(GTK_OBJECT(w->auto_fps_limit_checkbutton), "clicked", + G_CALLBACK(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/key.c b/plugins/gxvideo/key.c index c8a9b288..2175cc9c 100644 --- a/plugins/gxvideo/key.c +++ b/plugins/gxvideo/key.c @@ -1,44 +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" -#include "psemu_plugin_defs.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) { -} +/*************************************************************************** + 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/menu.c b/plugins/gxvideo/menu.c index babe2446..0ced33ef 100644 --- a/plugins/gxvideo/menu.c +++ b/plugins/gxvideo/menu.c @@ -1,56 +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 - -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 -} +/*************************************************************************** + 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 +//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/prim.c b/plugins/gxvideo/prim.c index 6a8d8cba..368edcb4 100644 --- a/plugins/gxvideo/prim.c +++ b/plugins/gxvideo/prim.c @@ -1,1619 +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 - -#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 - -static inline unsigned short BGR24to16(uint32_t BGR) { - return (unsigned short) (((BGR >> 3) & 0x1f) | ((BGR & 0xf80000) >> 9) - | ((BGR & 0xf800) >> 6)); -} - -#endif - -//////////////////////////////////////////////////////////////////////// -// Update global TP infos -//////////////////////////////////////////////////////////////////////// - -static 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; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 - -static 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); -} - -static 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); -} - -static 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); -} - -static 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 - */ -static 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; -} - -static 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; -} - -static 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; -} - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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... -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// -static 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) -//////////////////////////////////////////////////////////////////////// - -static 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) -//////////////////////////////////////////////////////////////////////// - -static 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) -//////////////////////////////////////////////////////////////////////// - -static 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) -//////////////////////////////////////////////////////////////////////// - -static 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) -//////////////////////////////////////////////////////////////////////// - -static 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 -static 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); - } - -} - -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -#if 0 -static 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; - } -} -#endif - -//////////////////////////////////////////////////////////////////////// -// cmd: shaded polylines -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -#if 0 -static 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; - } -} -#endif - -//////////////////////////////////////////////////////////////////////// -// cmd: drawing flat polylines -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 }; - +/*************************************************************************** + 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 + +#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/soft.c b/plugins/gxvideo/soft.c index d7e3a5c7..023073d3 100644 --- a/plugins/gxvideo/soft.c +++ b/plugins/gxvideo/soft.c @@ -1,9931 +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 }; - -static 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); -} - -///////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////// - -static 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); -} - -//////////////////////////////////////////////////////////////////////// - -static 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); - } - - //////////////////////////////////////////////////////////////////////// - -static 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; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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); -} - -//////////////////////////////////////////////////////////////////////// - -static 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); -} - -//////////////////////////////////////////////////////////////////////// - -static 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); -} - -//////////////////////////////////////////////////////////////////////// - -static 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); -} - -//////////////////////////////////////////////////////////////////////// - -static 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)); -} - -//////////////////////////////////////////////////////////////////////// - -static 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)); -} - -//////////////////////////////////////////////////////////////////////// - -static 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)); - -} - -//////////////////////////////////////////////////////////////////////// - -static 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); -} - -//////////////////////////////////////////////////////////////////////// - -static 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)); -} - -//////////////////////////////////////////////////////////////////////// - -static 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 - -static inline int shl10idiv(int x, int y); - -#else - -static inline int shl10idiv(int x, int y) { - int64_t bi = x; - bi <<= 10; - return bi / y; -} - -#endif - -#if 0 - -// GNUC long long int version: - -static inline int shl10idiv(int x, int y) -{ - long long int bi=x; - bi<<=10; - return bi/y; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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; -} - -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 - -static 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: - -static 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; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 - -static 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: - -static 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; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 - -static 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: - -static 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; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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... - -static 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 - -static 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 - -//////////////////////////////////////////////////////////////////////// - -static 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; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 - -static 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 - -static 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 - -static 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; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// - -static 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; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 - -static 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 - -static 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; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 -static 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; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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 -//////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////////// - -static 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))); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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))); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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))); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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))); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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; - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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; - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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); -} - -/////////////////////////////////////////////////////////////////////// - -static 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); - } -} - -/////////////////////////////////////////////////////////////////////// +/*************************************************************************** + 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/peopsxgl/draw.c b/plugins/peopsxgl/draw.c index 36bcf360..748824a1 100644 --- a/plugins/peopsxgl/draw.c +++ b/plugins/peopsxgl/draw.c @@ -1,1658 +1,1658 @@ -/*************************************************************************** - draw.c - description - ------------------- - begin : Sun Mar 08 2009 - copyright : (C) 1999-2009 by Pete Bernert - web : www.pbernert.com - ***************************************************************************/ - -/*************************************************************************** - * * - * 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 "stdafx.h" - -#define _IN_DRAW - -#include "externals.h" -#include "gpu.h" -#include "draw.h" -#include "prim.h" -#include "texture.h" -#include "menu.h" - -#if defined(_MACGL) -// if you use it, you must include it -#include -#include -#endif -//////////////////////////////////////////////////////////////////////////////////// -// defines - -#define SIGNBIT 0x800 -#define S_MASK 0xf000 -#define L_MASK 0xfffff000 - -// ownscale: some ogl drivers have buggy texture matrix funcs, so it -// is safer to calc sow/tow ourselves - -#ifdef OWNSCALE - -#define ST_FACSPRITE 255.99f -#define ST_BFFACSPRITE 0.5f/256.0f -#define ST_BFFACSPRITESORT 0.333f/256.0f - -#define ST_OFFSET 0.5f/256.0f; - -#define ST_FAC 255.99f -#define ST_BFFAC 0.5f/256.0f -#define ST_BFFACSORT 0.333f/256.0f - -#define ST_FACTRI 255.99f -#define ST_BFFACTRI 0.5f/256.0f -#define ST_BFFACTRISORT 0.333f/256.0f - -#define ST_FACVRAMX 255.0f -#define ST_FACVRAM 256.0f - -/////////////////////////////////////////////////////////////// - -#else - -#define ST_BFFACSPRITE 0.5f -#define ST_BFFACSPRITESORT 0.333f - -#define ST_BFFAC 0.5f -#define ST_BFFACSORT 0.333f - -#define ST_BFFACTRI 0.5f -#define ST_BFFACTRISORT 0.333f - -#define ST_OFFSET 0.5f; - -#endif - -//////////////////////////////////////////////////////////////////////////////////// -// draw globals; most will be initialized again later (by config or checks) - -#ifdef _WINDOWS -HDC dcGlobal = NULL; -HWND hWWindow; -#endif - -BOOL bIsFirstFrame = TRUE; - -// resolution/ratio vars - -int iResX; -int iResY; -BOOL bKeepRatio = FALSE; -RECT rRatioRect; - -// psx mask related vars - -BOOL bCheckMask = FALSE; -int iUseMask = 0; -int iSetMask = 0; -unsigned short sSetMask = 0; -uint32_t lSetMask = 0; - -// drawing/coord vars - -OGLVertex vertex[4]; -GLubyte gl_ux[8]; -GLubyte gl_vy[8]; -short sprtY,sprtX,sprtH,sprtW; - -// drawing options - -BOOL bOpaquePass; -BOOL bAdvancedBlend; -BOOL bUseLines; -BOOL bUseAntiAlias; -int iTexQuality; -int iUsePalTextures=1; -BOOL bSnapShot=FALSE; -BOOL bSmallAlpha=FALSE; -int iShowFPS=0; - -// OGL extension support - -int iForceVSync=-1; -int iUseExts=0; -BOOL bGLExt; -BOOL bGLFastMovie=FALSE; -BOOL bGLSoft; -BOOL bGLBlend; -#if defined (_MACGL) // always supported on OSX > 10.4.3 -#define glBlendEquationEXTEx glBlendEquationEXT -#define glColorTableEXTEx glColorTableEXT -#else -PFNGLBLENDEQU glBlendEquationEXTEx=NULL; -PFNGLCOLORTABLEEXT glColorTableEXTEx=NULL; -#endif -// gfx card buffer infos - -int iDepthFunc=0; -int iZBufferDepth=0; -GLbitfield uiBufferBits=GL_COLOR_BUFFER_BIT; - -//////////////////////////////////////////////////////////////////////// -// Set OGL pixel format -//////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS -BOOL bSetupPixelFormat(HDC hDC) -{ - int pixelformat; - static PIXELFORMATDESCRIPTOR pfd = - { - sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd - 1, // version number - PFD_DRAW_TO_WINDOW | // support window - PFD_SUPPORT_OPENGL | // support OpenGL - PFD_DOUBLEBUFFER, // double buffered - PFD_TYPE_RGBA, // RGBA type - 16, // 16-bit color depth (adjusted later) - 0, 0, 0, 0, 0, 0, // color bits ignored - 0, // no alpha buffer - 0, // shift bit ignored - 0, // no accumulation buffer - 0, 0, 0, 0, // accum bits ignored - 0, // z-buffer - 0, - 0, // no auxiliary buffer - PFD_MAIN_PLANE, // main layer - 0, // reserved - 0, 0, 0 // layer masks ignored - }; - - pfd.cColorBits=iColDepth; // set user color depth - pfd.cDepthBits=iZBufferDepth; // set user zbuffer (by psx mask) - - if((pixelformat=ChoosePixelFormat(hDC,&pfd))==0) - { - MessageBox(NULL,"ChoosePixelFormat failed","Error",MB_OK); - return FALSE; - } - - if(SetPixelFormat(hDC,pixelformat, &pfd)==FALSE) - { - MessageBox(NULL,"SetPixelFormat failed","Error",MB_OK); - return FALSE; - } - - return TRUE; -} -#endif - -//////////////////////////////////////////////////////////////////////// -// Get extension infos (f.e. pal textures / packed pixels) -//////////////////////////////////////////////////////////////////////// - -static void GetExtInfos(void) -{ - BOOL bPacked=FALSE; // default: no packed pixel support - - bGLExt=FALSE; // default: no extensions - bGLFastMovie=FALSE; - - if(strstr((char *)glGetString(GL_EXTENSIONS), // packed pixels available? - "GL_EXT_packed_pixels")) - bPacked=TRUE; // -> ok - - if(bPacked && bUse15bitMdec) // packed available and 15bit mdec wanted? - bGLFastMovie=TRUE; // -> ok - - if(bPacked && (iTexQuality==1 || iTexQuality==2)) // packed available and 16 bit texture format? - { - bGLFastMovie=TRUE; // -> ok - bGLExt=TRUE; - } - - if(iUseExts && // extension support wanted? - (strstr((char *)glGetString(GL_EXTENSIONS), - "GL_EXT_texture_edge_clamp") || - strstr((char *)glGetString(GL_EXTENSIONS), // -> check clamp support, if yes: use it - "GL_SGIS_texture_edge_clamp"))) - iClampType=GL_TO_EDGE_CLAMP; - else iClampType=GL_CLAMP; - -#if !defined (_MACGL) // OSX > 10.4.3 defines this - glColorTableEXTEx=(PFNGLCOLORTABLEEXT)NULL; // init ogl palette func pointer -#endif - -#ifndef __sun - if(iGPUHeight!=1024 && // no pal textures in ZN mode (height=1024)! - strstr((char *)glGetString(GL_EXTENSIONS), // otherwise: check ogl support - "GL_EXT_paletted_texture")) - { - iUsePalTextures=1; // -> wow, supported, get func pointer - -#ifdef _WINDOWS - glColorTableEXTEx=(PFNGLCOLORTABLEEXT)wglGetProcAddress("glColorTableEXT"); -#elif defined (_MACGL) - // no prob, done already in OSX > 10.4.3 -#else - glColorTableEXTEx=(PFNGLCOLORTABLEEXT)glXGetProcAddress((GLubyte *)"glColorTableEXT"); -#endif - - if(glColorTableEXTEx==NULL) iUsePalTextures=0; // -> ha, cheater... no func, no support - - } - else iUsePalTextures=0; -#else - iUsePalTextures=0; -#endif -} - -//////////////////////////////////////////////////////////////////////// -// Setup some stuff depending on user settings or in-game toggle -//////////////////////////////////////////////////////////////////////// - -void SetExtGLFuncs(void) -{ - //----------------------------------------------------// - - SetFixes(); // update fix infos - - //----------------------------------------------------// - -#ifdef _WINDOWS - if((iForceVSync>=0) && // force vsync? - strstr((char *)glGetString(GL_EXTENSIONS), // and extension available? - "WGL_EXT_swap_control")) - { - PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT= - (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress("wglSwapIntervalEXT"); - - if(wglSwapIntervalEXT) wglSwapIntervalEXT(iForceVSync); - } -#endif -#ifdef _MACGL - SetVSync(iForceVSync); -#endif - if(iUseExts && !(dwActFixes&1024) && // extensions wanted? and not turned off by game fix? - strstr((char *)glGetString(GL_EXTENSIONS), // and blend_subtract available? - "GL_EXT_blend_subtract")) - { // -> get ogl blend function pointer -#ifdef _WINDOWS - glBlendEquationEXTEx=(PFNGLBLENDEQU)wglGetProcAddress("glBlendEquationEXT"); -#elif defined(_MACGL) - // no prob, OSX > 10.4.3 has this -#else - glBlendEquationEXTEx=(PFNGLBLENDEQU)glXGetProcAddress((GLubyte *)"glBlendEquationEXT"); -#endif - } - else // no subtract blending? - { - if(glBlendEquationEXTEx) // -> change to additive blending (if subract was active) - glBlendEquationEXTEx(FUNC_ADD_EXT); -#if !defined(_MACGL) // BTW, why set to null? strange... - glBlendEquationEXTEx=(PFNGLBLENDEQU)NULL; // -> no more blend function pointer -#endif - } - - //----------------------------------------------------// - - if(iUseExts && bAdvancedBlend && // advanced blending wanted ? - strstr((char *)glGetString(GL_EXTENSIONS), // and extension avail? - "GL_EXT_texture_env_combine")) - { - bUseMultiPass=FALSE;bGLBlend=TRUE; // -> no need for 2 passes, perfect - - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT); - glTexEnvf(GL_TEXTURE_ENV, COMBINE_RGB_EXT, GL_MODULATE); - glTexEnvf(GL_TEXTURE_ENV, COMBINE_ALPHA_EXT, GL_MODULATE); - glTexEnvf(GL_TEXTURE_ENV, RGB_SCALE_EXT, 2.0f); - } - else // no advanced blending wanted/available: - { - if(bAdvancedBlend) bUseMultiPass=TRUE; // -> pseudo-advanced with 2 passes - else bUseMultiPass=FALSE; // -> or simple 'bright color' mode - bGLBlend=FALSE; // -> no ext blending! - - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } - - //----------------------------------------------------// - // init standard tex quality 0-2, and big alpha mode 3 - - if(!(dwActFixes&0x4000) && iFilterType && iTexQuality>=3) - bSmallAlpha=TRUE; - else bSmallAlpha=FALSE; - - if(bOpaquePass) // opaque mode? - { - if(dwActFixes&32) - { - TCF[0]=CP8RGBA_0; - PalTexturedColourFn=CP8RGBA; // -> init col func - } - else - { - TCF[0]=XP8RGBA_0; - PalTexturedColourFn=XP8RGBA; // -> init col func - } - - TCF[1]=XP8RGBA_1; - glAlphaFunc(GL_GREATER,0.49f); - } - else // no opaque mode? - { - TCF[0]=TCF[1]=P8RGBA; - PalTexturedColourFn=P8RGBA; // -> init col func - glAlphaFunc(GL_NOTEQUAL,0); // --> set alpha func - } - - //----------------------------------------------------// - - LoadSubTexFn=LoadSubTexturePageSort; // init load tex ptr - - giWantedFMT=GL_RGBA; // init ogl tex format - - switch(iTexQuality) // -> quality: - { - //--------------------------------------------------// - case 0: // -> don't care - giWantedRGBA=4; - giWantedTYPE=GL_UNSIGNED_BYTE; - break; - //--------------------------------------------------// - case 1: // -> R4G4B4A4 - if(bGLExt) - { - giWantedRGBA=GL_RGBA4; - giWantedTYPE=GL_UNSIGNED_SHORT_4_4_4_4_EXT; - LoadSubTexFn=LoadPackedSubTexturePageSort; - if(bOpaquePass) - { - if(dwActFixes&32) PTCF[0]=CP4RGBA_0; - else PTCF[0]=XP4RGBA_0; - PTCF[1]=XP4RGBA_1; - } - else - { - PTCF[0]=PTCF[1]=P4RGBA; - } - } - else - { - giWantedRGBA=GL_RGBA4; - giWantedTYPE=GL_UNSIGNED_BYTE; - } - break; - //--------------------------------------------------// - case 2: // -> R5B5G5A1 - if(bGLExt) - { - giWantedRGBA=GL_RGB5_A1; - giWantedTYPE=GL_UNSIGNED_SHORT_5_5_5_1_EXT; - LoadSubTexFn=LoadPackedSubTexturePageSort; - if(bOpaquePass) - { - if(dwActFixes&32) PTCF[0]=CP5RGBA_0; - else PTCF[0]=XP5RGBA_0; - PTCF[1]=XP5RGBA_1; - } - else - { - PTCF[0]=PTCF[1]=P5RGBA; - } - } - else - { - giWantedRGBA=GL_RGB5_A1;giWantedTYPE=GL_UNSIGNED_BYTE; - } - break; - //--------------------------------------------------// - case 3: // -> R8G8B8A8 - giWantedRGBA=GL_RGBA8; - giWantedTYPE=GL_UNSIGNED_BYTE; - - if(bSmallAlpha) - { - if(bOpaquePass) // opaque mode? - { - if(dwActFixes&32) {TCF[0]=CP8RGBAEx_0;PalTexturedColourFn=CP8RGBAEx;} - else {TCF[0]=XP8RGBAEx_0;PalTexturedColourFn=XP8RGBAEx;} - TCF[1]=XP8RGBAEx_1; - } - } - - break; - //--------------------------------------------------// - case 4: // -> R8G8B8A8 - giWantedRGBA = GL_RGBA8; - giWantedTYPE = GL_UNSIGNED_BYTE; - - if(strstr((char *)glGetString(GL_EXTENSIONS), // and extension avail? - "GL_EXT_bgra")) - { - giWantedFMT = GL_BGRA_EXT; - - if(bOpaquePass) // opaque mode? - { - if(bSmallAlpha) - { - if(dwActFixes&32) {TCF[0]=CP8BGRAEx_0;PalTexturedColourFn=CP8RGBAEx;} - else {TCF[0]=XP8BGRAEx_0;PalTexturedColourFn=XP8RGBAEx;} - TCF[1]=XP8BGRAEx_1; - } - else - { - if(dwActFixes&32) {TCF[0]=CP8BGRA_0;PalTexturedColourFn=CP8RGBA;} - else {TCF[0]=XP8BGRA_0;PalTexturedColourFn=XP8RGBA;} - TCF[1]=XP8BGRA_1; - } - } - else // no opaque mode? - { - TCF[0]=TCF[1]=P8BGRA; // -> init col func - } - } - else - { - iTexQuality=3; - if(bSmallAlpha) - { - if(bOpaquePass) // opaque mode? - { - if(dwActFixes&32) {TCF[0]=CP8RGBAEx_0;PalTexturedColourFn=CP8RGBAEx;} - else {TCF[0]=XP8RGBAEx_0;PalTexturedColourFn=XP8RGBAEx;} - TCF[1]=XP8RGBAEx_1; - } - } - } - - break; - //--------------------------------------------------// - } - - bBlendEnable=FALSE; // init blending: off - glDisable(GL_BLEND); - - SetScanTrans(); // init scan lines (if wanted) -} - -//////////////////////////////////////////////////////////////////////// -// setup scan lines -//////////////////////////////////////////////////////////////////////// - -#define R_TSP 0x00,0x45,0x00,0xff -#define G_TSP 0x00,0x00,0x45,0xff -#define B_TSP 0x45,0x00,0x00,0xff -#define O_TSP 0x45,0x45,0x45,0xff -#define N_TSP 0x00,0x00,0x00,0xff - -GLuint gTexScanName=0; - -GLubyte texscan[4][16]= -{ -{R_TSP, G_TSP, B_TSP, N_TSP}, -{O_TSP, N_TSP, O_TSP, N_TSP}, -{B_TSP, N_TSP, R_TSP, G_TSP}, -{O_TSP, N_TSP, O_TSP, N_TSP} -}; - -static void CreateScanLines(void) -{ - if(iUseScanLines) - { - int y; - if(iScanBlend<0) // special scan mask mode - { - glGenTextures(1, &gTexScanName); - glBindTexture(GL_TEXTURE_2D, gTexScanName); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, 4, 4, 4, 0,GL_RGBA, GL_UNSIGNED_BYTE, texscan); - } - else // otherwise simple lines in a display list - { - uiScanLine=glGenLists(1); - glNewList(uiScanLine,GL_COMPILE); - #ifdef _MACGL - // not mac specific, just commenting out to be friendly - // use it if you like - // this draws anti-aliased lines with user-chosen color - glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT); - glEnable(GL_BLEND | GL_LINE_SMOOTH); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - glColor4f(iScanlineColor[0],iScanlineColor[1],iScanlineColor[2],iScanlineColor[3]); - glBegin(GL_LINES); - for(y=0;y ok, turn display on - szDispBuf[0]=0; - BuildDispMenu(0); - } - - bIsFirstFrame = FALSE; // we have survived the first frame :) - - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// clean up OGL stuff -//////////////////////////////////////////////////////////////////////// - -void GLcleanup() -{ - KillDisplayLists(); // bye display lists - - if(iUseScanLines) // scanlines used? - { - if(iScanBlend<0) - { - if(gTexScanName!=0) // some scanline tex? - glDeleteTextures(1, &gTexScanName); // -> delete it - gTexScanName=0; - } - else glDeleteLists(uiScanLine,1); // otherwise del scanline display list - } - - CleanupTextureStore(); // bye textures - -#ifdef _WINDOWS - wglMakeCurrent(NULL, NULL); // bye context - if(GLCONTEXT) wglDeleteContext(GLCONTEXT); - if(!bWindowMode && dcGlobal) - ReleaseDC(hWWindow,dcGlobal); -#endif -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -// Offset stuff -//////////////////////////////////////////////////////////////////////// - -// please note: it is hardly do-able in a hw/accel plugin to get the -// real psx polygon coord mapping right... the following -// works not to bad with many games, though - -static __inline BOOL CheckCoord4() -{ - if(lx0<0) - { - if(((lx1-lx0)>CHKMAX_X) || - ((lx2-lx0)>CHKMAX_X)) - { - if(lx3<0) - { - if((lx1-lx3)>CHKMAX_X) return TRUE; - if((lx2-lx3)>CHKMAX_X) return TRUE; - } - } - } - if(lx1<0) - { - if((lx0-lx1)>CHKMAX_X) return TRUE; - if((lx2-lx1)>CHKMAX_X) return TRUE; - if((lx3-lx1)>CHKMAX_X) return TRUE; - } - if(lx2<0) - { - if((lx0-lx2)>CHKMAX_X) return TRUE; - if((lx1-lx2)>CHKMAX_X) return TRUE; - if((lx3-lx2)>CHKMAX_X) return TRUE; - } - if(lx3<0) - { - if(((lx1-lx3)>CHKMAX_X) || - ((lx2-lx3)>CHKMAX_X)) - { - if(lx0<0) - { - if((lx1-lx0)>CHKMAX_X) return TRUE; - if((lx2-lx0)>CHKMAX_X) return TRUE; - } - } - } - - - if(ly0<0) - { - if((ly1-ly0)>CHKMAX_Y) return TRUE; - if((ly2-ly0)>CHKMAX_Y) return TRUE; - } - if(ly1<0) - { - if((ly0-ly1)>CHKMAX_Y) return TRUE; - if((ly2-ly1)>CHKMAX_Y) return TRUE; - if((ly3-ly1)>CHKMAX_Y) return TRUE; - } - if(ly2<0) - { - if((ly0-ly2)>CHKMAX_Y) return TRUE; - if((ly1-ly2)>CHKMAX_Y) return TRUE; - if((ly3-ly2)>CHKMAX_Y) return TRUE; - } - if(ly3<0) - { - if((ly1-ly3)>CHKMAX_Y) return TRUE; - if((ly2-ly3)>CHKMAX_Y) return TRUE; - } - - return FALSE; -} - -static __inline BOOL CheckCoord3() -{ - if(lx0<0) - { - if((lx1-lx0)>CHKMAX_X) return TRUE; - if((lx2-lx0)>CHKMAX_X) return TRUE; - } - if(lx1<0) - { - if((lx0-lx1)>CHKMAX_X) return TRUE; - if((lx2-lx1)>CHKMAX_X) return TRUE; - } - if(lx2<0) - { - if((lx0-lx2)>CHKMAX_X) return TRUE; - if((lx1-lx2)>CHKMAX_X) return TRUE; - } - if(ly0<0) - { - if((ly1-ly0)>CHKMAX_Y) return TRUE; - if((ly2-ly0)>CHKMAX_Y) return TRUE; - } - if(ly1<0) - { - if((ly0-ly1)>CHKMAX_Y) return TRUE; - if((ly2-ly1)>CHKMAX_Y) return TRUE; - } - if(ly2<0) - { - if((ly0-ly2)>CHKMAX_Y) return TRUE; - if((ly1-ly2)>CHKMAX_Y) return TRUE; - } - - return FALSE; -} - - -static __inline BOOL CheckCoord2() -{ - if(lx0<0) - { - if((lx1-lx0)>CHKMAX_X) return TRUE; - } - if(lx1<0) - { - if((lx0-lx1)>CHKMAX_X) return TRUE; - } - if(ly0<0) - { - if((ly1-ly0)>CHKMAX_Y) return TRUE; - } - if(ly1<0) - { - if((ly0-ly1)>CHKMAX_Y) return TRUE; - } - - return FALSE; -} - -/* -//Lewpys "offsetline" func: - -void offsetline(void) -{ - float x0, x1, y0, y1, oolength, xl, yl; - - if(bDisplayNotSet) - SetOGLDisplaySettings(1); - - if(!(dwActFixes&16)) - { - if((lx0 & SIGNBIT)) lx0|=S_MASK; - else lx0&=~S_MASK; - if((lx1 & SIGNBIT)) lx1|=S_MASK; - else lx1&=~S_MASK; - if((ly0 & SIGNBIT)) ly0|=S_MASK; - else ly0&=~S_MASK; - if((ly1 & SIGNBIT)) ly1|=S_MASK; - else ly1&=~S_MASK; - } - - x0 = (float)(lx0 + PSXDisplay.CumulOffset.x); - x1 = (float)(lx1 + PSXDisplay.CumulOffset.x); - y0 = (float)(ly0 + PSXDisplay.CumulOffset.y); - y1 = (float)(ly1 + PSXDisplay.CumulOffset.y); - - oolength = (float)1/((float)sqrt((y1 - y0)*(y1 - y0) + (x1 - x0)*(x1 - x0)) * (float)2); -// oolength = (float)1/((float)sqrt(((y1 - y0)*(y1 - y0) + (x1 - x0)*(x1 - x0)) * (float)2)); - - xl = (x1 - x0) * oolength; - yl = (y1 - y0) * oolength; - - x0 += 0.5f; - x1 += 0.5f; - - x0 -= xl - yl; - x1 += xl + yl; - y0 -= yl + xl; - y1 += yl - xl; - - vertex[0].x=x0; - vertex[1].x=x1; - vertex[0].y=y0; - vertex[1].y=y1; - - x0 -= yl * 2; - x1 -= yl * 2; - y0 += xl * 2; - y1 += xl * 2; - - vertex[2].x=x1; - vertex[3].x=x0; - vertex[2].y=y1; - vertex[3].y=y0; -} -*/ - - -// Pete's way: a very easy (and hopefully fast) approach for lines -// without sqrt... using a small float -> short cast trick :) - -#define VERTEX_OFFX 0.2f -#define VERTEX_OFFY 0.2f - -BOOL offsetline(void) -{ - short x0,x1,y0,y1,dx,dy;float px,py; - - if(bDisplayNotSet) - SetOGLDisplaySettings(1); - - if(!(dwActFixes&16)) - { - lx0=(short)(((int)lx0<>SIGNSHIFT); - lx1=(short)(((int)lx1<>SIGNSHIFT); - ly0=(short)(((int)ly0<>SIGNSHIFT); - ly1=(short)(((int)ly1<>SIGNSHIFT); - - if(CheckCoord2()) return TRUE; - } - - x0 = (lx0 + PSXDisplay.CumulOffset.x)+1; - x1 = (lx1 + PSXDisplay.CumulOffset.x)+1; - y0 = (ly0 + PSXDisplay.CumulOffset.y)+1; - y1 = (ly1 + PSXDisplay.CumulOffset.y)+1; - - dx=x1-x0; - dy=y1-y0; - - if(dx>=0) - { - if(dy>=0) - { - px=0.5f; - if(dx>dy) py=-0.5f; - else if(dxdy) px= 0.5f; - else if(dx=0) - { - py=0.5f; - dx=-dx; - if(dx>dy) px=-0.5f; - else if(dxdy) py=-0.5f; - else if(dx>SIGNSHIFT); - lx1=(short)(((int)lx1<>SIGNSHIFT); - ly0=(short)(((int)ly0<>SIGNSHIFT); - ly1=(short)(((int)ly1<>SIGNSHIFT); - - if(CheckCoord2()) return TRUE; - } - - vertex[0].x=lx0+PSXDisplay.CumulOffset.x; - vertex[1].x=lx1+PSXDisplay.CumulOffset.x; - vertex[0].y=ly0+PSXDisplay.CumulOffset.y; - vertex[1].y=ly1+PSXDisplay.CumulOffset.y; - - return FALSE; -} - -///////////////////////////////////////////////////////// - -BOOL offset3(void) -{ - if(bDisplayNotSet) - SetOGLDisplaySettings(1); - - if(!(dwActFixes&16)) - { - lx0=(short)(((int)lx0<>SIGNSHIFT); - lx1=(short)(((int)lx1<>SIGNSHIFT); - lx2=(short)(((int)lx2<>SIGNSHIFT); - ly0=(short)(((int)ly0<>SIGNSHIFT); - ly1=(short)(((int)ly1<>SIGNSHIFT); - ly2=(short)(((int)ly2<>SIGNSHIFT); - - if(CheckCoord3()) return TRUE; - } - - vertex[0].x=lx0+PSXDisplay.CumulOffset.x; - vertex[1].x=lx1+PSXDisplay.CumulOffset.x; - vertex[2].x=lx2+PSXDisplay.CumulOffset.x; - vertex[0].y=ly0+PSXDisplay.CumulOffset.y; - vertex[1].y=ly1+PSXDisplay.CumulOffset.y; - vertex[2].y=ly2+PSXDisplay.CumulOffset.y; - - return FALSE; -} - -///////////////////////////////////////////////////////// - -BOOL offset4(void) -{ - if(bDisplayNotSet) - SetOGLDisplaySettings(1); - - if(!(dwActFixes&16)) - { - lx0=(short)(((int)lx0<>SIGNSHIFT); - lx1=(short)(((int)lx1<>SIGNSHIFT); - lx2=(short)(((int)lx2<>SIGNSHIFT); - lx3=(short)(((int)lx3<>SIGNSHIFT); - ly0=(short)(((int)ly0<>SIGNSHIFT); - ly1=(short)(((int)ly1<>SIGNSHIFT); - ly2=(short)(((int)ly2<>SIGNSHIFT); - ly3=(short)(((int)ly3<>SIGNSHIFT); - - if(CheckCoord4()) return TRUE; - } - - vertex[0].x=lx0+PSXDisplay.CumulOffset.x; - vertex[1].x=lx1+PSXDisplay.CumulOffset.x; - vertex[2].x=lx2+PSXDisplay.CumulOffset.x; - vertex[3].x=lx3+PSXDisplay.CumulOffset.x; - vertex[0].y=ly0+PSXDisplay.CumulOffset.y; - vertex[1].y=ly1+PSXDisplay.CumulOffset.y; - vertex[2].y=ly2+PSXDisplay.CumulOffset.y; - vertex[3].y=ly3+PSXDisplay.CumulOffset.y; - - return FALSE; -} - -///////////////////////////////////////////////////////// - -void offsetST(void) -{ - if(bDisplayNotSet) - SetOGLDisplaySettings(1); - - if(!(dwActFixes&16)) - { - lx0=(short)(((int)lx0<>SIGNSHIFT); - ly0=(short)(((int)ly0<>SIGNSHIFT); - - if(lx0<-512 && PSXDisplay.DrawOffset.x<=-512) - lx0+=2048; - - if(ly0<-512 && PSXDisplay.DrawOffset.y<=-512) - ly0+=2048; - } - - ly1 = ly0; - ly2 = ly3 = ly0+sprtH; - lx3 = lx0; - lx1 = lx2 = lx0+sprtW; - - vertex[0].x=lx0+PSXDisplay.CumulOffset.x; - vertex[1].x=lx1+PSXDisplay.CumulOffset.x; - vertex[2].x=lx2+PSXDisplay.CumulOffset.x; - vertex[3].x=lx3+PSXDisplay.CumulOffset.x; - vertex[0].y=ly0+PSXDisplay.CumulOffset.y; - vertex[1].y=ly1+PSXDisplay.CumulOffset.y; - vertex[2].y=ly2+PSXDisplay.CumulOffset.y; - vertex[3].y=ly3+PSXDisplay.CumulOffset.y; -} - -///////////////////////////////////////////////////////// - -void offsetScreenUpload(int Position) -{ - if(bDisplayNotSet) - SetOGLDisplaySettings(1); - - if(Position==-1) - { - int lmdx,lmdy; - - lmdx=xrUploadArea.x0; - lmdy=xrUploadArea.y0; - - lx0-=lmdx; - ly0-=lmdy; - lx1-=lmdx; - ly1-=lmdy; - lx2-=lmdx; - ly2-=lmdy; - lx3-=lmdx; - ly3-=lmdy; - } - else - if(Position) - { - lx0-=PSXDisplay.DisplayPosition.x; - ly0-=PSXDisplay.DisplayPosition.y; - lx1-=PSXDisplay.DisplayPosition.x; - ly1-=PSXDisplay.DisplayPosition.y; - lx2-=PSXDisplay.DisplayPosition.x; - ly2-=PSXDisplay.DisplayPosition.y; - lx3-=PSXDisplay.DisplayPosition.x; - ly3-=PSXDisplay.DisplayPosition.y; - } - else - { - lx0-=PreviousPSXDisplay.DisplayPosition.x; - ly0-=PreviousPSXDisplay.DisplayPosition.y; - lx1-=PreviousPSXDisplay.DisplayPosition.x; - ly1-=PreviousPSXDisplay.DisplayPosition.y; - lx2-=PreviousPSXDisplay.DisplayPosition.x; - ly2-=PreviousPSXDisplay.DisplayPosition.y; - lx3-=PreviousPSXDisplay.DisplayPosition.x; - ly3-=PreviousPSXDisplay.DisplayPosition.y; - } - - vertex[0].x=lx0 + PreviousPSXDisplay.Range.x0; - vertex[1].x=lx1 + PreviousPSXDisplay.Range.x0; - vertex[2].x=lx2 + PreviousPSXDisplay.Range.x0; - vertex[3].x=lx3 + PreviousPSXDisplay.Range.x0; - vertex[0].y=ly0 + PreviousPSXDisplay.Range.y0; - vertex[1].y=ly1 + PreviousPSXDisplay.Range.y0; - vertex[2].y=ly2 + PreviousPSXDisplay.Range.y0; - vertex[3].y=ly3 + PreviousPSXDisplay.Range.y0; - - if(iUseMask) - { - vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; - gl_z+=0.00004f; - } -} - -///////////////////////////////////////////////////////// - -void offsetBlk(void) -{ - if(bDisplayNotSet) - SetOGLDisplaySettings(1); - - vertex[0].x=lx0-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; - vertex[1].x=lx1-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; - vertex[2].x=lx2-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; - vertex[3].x=lx3-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; - vertex[0].y=ly0-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; - vertex[1].y=ly1-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; - vertex[2].y=ly2-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; - vertex[3].y=ly3-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; - - if(iUseMask) - { - vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; - gl_z+=0.00004f; - } -} - -//////////////////////////////////////////////////////////////////////// -// texture sow/tow calculations -//////////////////////////////////////////////////////////////////////// - -void assignTextureVRAMWrite(void) -{ -#ifdef OWNSCALE - - vertex[0].sow=0.5f/ ST_FACVRAMX; - vertex[0].tow=0.5f/ ST_FACVRAM; - - vertex[1].sow=(float)gl_ux[1]/ ST_FACVRAMX; - vertex[1].tow=0.5f/ ST_FACVRAM; - - vertex[2].sow=(float)gl_ux[2]/ ST_FACVRAMX; - vertex[2].tow=(float)gl_vy[2]/ ST_FACVRAM; - - vertex[3].sow=0.5f/ ST_FACVRAMX; - vertex[3].tow=(float)gl_vy[3]/ ST_FACVRAM; - -#else - - if(gl_ux[1]==255) - { - vertex[0].sow=(gl_ux[0]*255.99f)/255.0f; - vertex[1].sow=(gl_ux[1]*255.99f)/255.0f; - vertex[2].sow=(gl_ux[2]*255.99f)/255.0f; - vertex[3].sow=(gl_ux[3]*255.99f)/255.0f; - } - else - { - vertex[0].sow=gl_ux[0]; - vertex[1].sow=gl_ux[1]; - vertex[2].sow=gl_ux[2]; - vertex[3].sow=gl_ux[3]; - } - - vertex[0].tow=gl_vy[0]; - vertex[1].tow=gl_vy[1]; - vertex[2].tow=gl_vy[2]; - vertex[3].tow=gl_vy[3]; - -#endif -} - -GLuint gLastTex=0; -GLuint gLastFMode=(GLuint)-1; - -///////////////////////////////////////////////////////// - -void assignTextureSprite(void) -{ - if(bUsingTWin) - { - vertex[0].sow=vertex[3].sow=(float)gl_ux[0]/TWin.UScaleFactor; - vertex[1].sow=vertex[2].sow=(float)sSprite_ux2/TWin.UScaleFactor; - vertex[0].tow=vertex[1].tow=(float)gl_vy[0]/TWin.VScaleFactor; - vertex[2].tow=vertex[3].tow=(float)sSprite_vy2/TWin.VScaleFactor; - gLastTex=gTexName; - - if(iFilterType>0 && iFilterType<3 && iHiResTextures!=2) - { - float fxmin=65536.0f,fxmax=0.0f,fymin=65536.0f,fymax=0.0f;int i; - - for(i=0;i<4;i++) - { - if(vertex[i].sowfxmax) fxmax=vertex[i].sow; - if(vertex[i].tow>fymax) fymax=vertex[i].tow; - } - - for(i=0;i<4;i++) - { -#ifdef OWNSCALE - if(vertex[i].sow==fxmin) vertex[i].sow+=0.375f/(float)TWin.Position.x1; - if(vertex[i].sow==fxmax) vertex[i].sow-=0.375f/(float)TWin.Position.x1; - if(vertex[i].tow==fymin) vertex[i].tow+=0.375f/(float)TWin.Position.y1; - if(vertex[i].tow==fymax) vertex[i].tow-=0.375f/(float)TWin.Position.y1; -#else - if(vertex[i].sow==fxmin) vertex[i].sow+=96.0f/(float)TWin.Position.x1; - if(vertex[i].sow==fxmax) vertex[i].sow-=96.0f/(float)TWin.Position.x1; - if(vertex[i].tow==fymin) vertex[i].tow+=96.0f/(float)TWin.Position.y1; - if(vertex[i].tow==fymax) vertex[i].tow-=96.0f/(float)TWin.Position.y1; -#endif - } - } - - } - else - { -#ifdef OWNSCALE - - vertex[0].sow=vertex[3].sow=(float)gl_ux[0] / ST_FACSPRITE; - vertex[1].sow=vertex[2].sow=(float)sSprite_ux2 / ST_FACSPRITE; - vertex[0].tow=vertex[1].tow=(float)gl_vy[0] / ST_FACSPRITE; - vertex[2].tow=vertex[3].tow=(float)sSprite_vy2 / ST_FACSPRITE; - -#else - - vertex[0].sow=vertex[3].sow=gl_ux[0]; - vertex[1].sow=vertex[2].sow=sSprite_ux2; - vertex[0].tow=vertex[1].tow=gl_vy[0]; - vertex[2].tow=vertex[3].tow=sSprite_vy2; - -#endif - - if(iFilterType>2) - { - if(gLastTex!=gTexName || gLastFMode!=0) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - gLastTex=gTexName;gLastFMode=0; - } - } - } - - if(usMirror & 0x1000) - { - vertex[0].sow=vertex[1].sow; - vertex[1].sow=vertex[2].sow=vertex[3].sow; - vertex[3].sow=vertex[0].sow; - } - - if(usMirror & 0x2000) - { - vertex[0].tow=vertex[3].tow; - vertex[2].tow=vertex[3].tow=vertex[1].tow; - vertex[1].tow=vertex[0].tow; - } - -} - -///////////////////////////////////////////////////////// - -void assignTexture3(void) -{ - if(bUsingTWin) - { - vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor; - vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor; - vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor; - vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor; - vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor; - vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor; - gLastTex=gTexName; - } - else - { -#ifdef OWNSCALE - vertex[0].sow=(float)gl_ux[0] / ST_FACTRI; - vertex[0].tow=(float)gl_vy[0] / ST_FACTRI; - vertex[1].sow=(float)gl_ux[1] / ST_FACTRI; - - vertex[1].tow=(float)gl_vy[1] / ST_FACTRI; - vertex[2].sow=(float)gl_ux[2] / ST_FACTRI; - vertex[2].tow=(float)gl_vy[2] / ST_FACTRI; -#else - vertex[0].sow=gl_ux[0]; - vertex[0].tow=gl_vy[0]; - vertex[1].sow=gl_ux[1]; - vertex[1].tow=gl_vy[1]; - vertex[2].sow=gl_ux[2]; - vertex[2].tow=gl_vy[2]; -#endif - - if(iFilterType>2) - { - if(gLastTex!=gTexName || gLastFMode!=1) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gLastTex=gTexName;gLastFMode=1; - } - } - - if(iFilterType) - { - float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i; - for(i=0;i<3;i++) - { - if(vertex[i].sowfxmax) fxmax=vertex[i].sow; - if(vertex[i].tow>fymax) fymax=vertex[i].tow; - } - - for(i=0;i<3;i++) - { - if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT; - if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT; - if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT; - if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT; - } - } - } -} - -///////////////////////////////////////////////////////// - -void assignTexture4(void) -{ - if(bUsingTWin) - { - vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor; - vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor; - vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor; - vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor; - vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor; - vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor; - vertex[3].sow=(float)gl_ux[3]/TWin.UScaleFactor; - vertex[3].tow=(float)gl_vy[3]/TWin.VScaleFactor; - gLastTex=gTexName; - } - else - { -#ifdef OWNSCALE - vertex[0].sow=(float)gl_ux[0] / ST_FAC; - vertex[0].tow=(float)gl_vy[0] / ST_FAC; - vertex[1].sow=(float)gl_ux[1] / ST_FAC; - vertex[1].tow=(float)gl_vy[1] / ST_FAC; - vertex[2].sow=(float)gl_ux[2] / ST_FAC; - vertex[2].tow=(float)gl_vy[2] / ST_FAC; - vertex[3].sow=(float)gl_ux[3] / ST_FAC; - vertex[3].tow=(float)gl_vy[3] / ST_FAC; -#else - vertex[0].sow=gl_ux[0]; - vertex[0].tow=gl_vy[0]; - vertex[1].sow=gl_ux[1]; - vertex[1].tow=gl_vy[1]; - vertex[2].sow=gl_ux[2]; - vertex[2].tow=gl_vy[2]; - vertex[3].sow=gl_ux[3]; - vertex[3].tow=gl_vy[3]; -#endif - - if(iFilterType>2) - { - if(gLastTex!=gTexName || gLastFMode!=1) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gLastTex=gTexName;gLastFMode=1; - } - } - - if(iFilterType) - { - float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i; - for(i=0;i<4;i++) - { - if(vertex[i].sowfxmax) fxmax=vertex[i].sow; - if(vertex[i].tow>fymax) fymax=vertex[i].tow; - } - - for(i=0;i<4;i++) - { - if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT; - if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT; - if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT; - if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT; - } - } - } -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -// render pos / buffers -//////////////////////////////////////////////////////////////////////// - -#ifndef _WINDOWS -#define EqualRect(pr1,pr2) ((pr1)->left==(pr2)->left && (pr1)->top==(pr2)->top && (pr1)->right==(pr2)->right && (pr1)->bottom==(pr2)->bottom) -#endif - -//////////////////////////////////////////////////////////////////////// -// SetDisplaySettings: "simply" calcs the new drawing area and updates -// the ogl clipping (scissor) - -BOOL bSetClip=FALSE; - -void SetOGLDisplaySettings(BOOL DisplaySet) -{ - static RECT rprev={0,0,0,0}; - static RECT rC ={0,0,0,0}; - static int iOldX=0; - static int iOldY=0; - RECT r;float XS,YS; - - bDisplayNotSet = FALSE; - - //----------------------------------------------------// that's a whole screen upload - if(!DisplaySet) - { - RECT rX; - PSXDisplay.GDrawOffset.x=0; - PSXDisplay.GDrawOffset.y=0; - - PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x+PreviousPSXDisplay.Range.x0; - PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y+PreviousPSXDisplay.Range.y0; - - rprev.left=rprev.left+1; - - rX=rRatioRect; - rX.top=iResY-(rRatioRect.top+rRatioRect.bottom); - - if(bSetClip || !EqualRect(&rC,&rX)) - { - rC=rX; - glScissor(rC.left,rC.top,rC.right,rC.bottom); - bSetClip=FALSE; - } - return; - } - //----------------------------------------------------// - - PSXDisplay.GDrawOffset.y = PreviousPSXDisplay.DisplayPosition.y; - PSXDisplay.GDrawOffset.x = PreviousPSXDisplay.DisplayPosition.x; - PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x - PSXDisplay.GDrawOffset.x+PreviousPSXDisplay.Range.x0; - PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y - PSXDisplay.GDrawOffset.y+PreviousPSXDisplay.Range.y0; - - r.top =PSXDisplay.DrawArea.y0 - PreviousPSXDisplay.DisplayPosition.y; - r.bottom=PSXDisplay.DrawArea.y1 - PreviousPSXDisplay.DisplayPosition.y; - - if(r.bottom<0 || r.top>=PSXDisplay.DisplayMode.y) - { - r.top =PSXDisplay.DrawArea.y0 - PSXDisplay.DisplayPosition.y; - r.bottom=PSXDisplay.DrawArea.y1 - PSXDisplay.DisplayPosition.y; - } - - r.left =PSXDisplay.DrawArea.x0 - PreviousPSXDisplay.DisplayPosition.x; - r.right =PSXDisplay.DrawArea.x1 - PreviousPSXDisplay.DisplayPosition.x; - - if(r.right<0 || r.left>=PSXDisplay.DisplayMode.x) - { - r.left =PSXDisplay.DrawArea.x0 - PSXDisplay.DisplayPosition.x; - r.right =PSXDisplay.DrawArea.x1 - PSXDisplay.DisplayPosition.x; - } - - if(!bSetClip && EqualRect(&r,&rprev) && - iOldX == PSXDisplay.DisplayMode.x && - iOldY == PSXDisplay.DisplayMode.y) - return; - - rprev = r; - iOldX = PSXDisplay.DisplayMode.x; - iOldY = PSXDisplay.DisplayMode.y; - - XS=(float)rRatioRect.right/(float)PSXDisplay.DisplayMode.x; - YS=(float)rRatioRect.bottom/(float)PSXDisplay.DisplayMode.y; - - if(PreviousPSXDisplay.Range.x0) - { - short s=PreviousPSXDisplay.Range.x0+PreviousPSXDisplay.Range.x1; - - r.left+=PreviousPSXDisplay.Range.x0+1; - - r.right+=PreviousPSXDisplay.Range.x0; - - if(r.left>s) r.left=s; - if(r.right>s) r.right=s; - } - - if(PreviousPSXDisplay.Range.y0) - { - short s=PreviousPSXDisplay.Range.y0+PreviousPSXDisplay.Range.y1; - - r.top+=PreviousPSXDisplay.Range.y0+1; - r.bottom+=PreviousPSXDisplay.Range.y0; - - if(r.top>s) r.top=s; - if(r.bottom>s) r.bottom=s; - } - - // Set the ClipArea variables to reflect the new screen, - // offset from zero (since it is a new display buffer) - r.left = (int)(((float)(r.left)) *XS); - r.top = (int)(((float)(r.top)) *YS); - r.right = (int)(((float)(r.right + 1))*XS); - r.bottom = (int)(((float)(r.bottom + 1))*YS); - - // Limit clip area to the screen size - if (r.left > iResX) r.left = iResX; - if (r.left < 0) r.left = 0; - if (r.top > iResY) r.top = iResY; - if (r.top < 0) r.top = 0; - if (r.right > iResX) r.right = iResX; - if (r.right < 0) r.right = 0; - if (r.bottom > iResY) r.bottom = iResY; - if (r.bottom < 0) r.bottom = 0; - - r.right -=r.left; - r.bottom-=r.top; - r.top=iResY-(r.top+r.bottom); - - r.left+=rRatioRect.left; - r.top -=rRatioRect.top; - - if(bSetClip || !EqualRect(&r,&rC)) - { - glScissor(r.left,r.top,r.right,r.bottom); - rC=r; - bSetClip=FALSE; - } -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - +/*************************************************************************** + draw.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "stdafx.h" + +#define _IN_DRAW + +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "prim.h" +#include "texture.h" +#include "menu.h" + +#if defined(_MACGL) +// if you use it, you must include it +#include +#include +#endif +//////////////////////////////////////////////////////////////////////////////////// +// defines + +#define SIGNBIT 0x800 +#define S_MASK 0xf000 +#define L_MASK 0xfffff000 + +// ownscale: some ogl drivers have buggy texture matrix funcs, so it +// is safer to calc sow/tow ourselves + +#ifdef OWNSCALE + +#define ST_FACSPRITE 255.99f +#define ST_BFFACSPRITE 0.5f/256.0f +#define ST_BFFACSPRITESORT 0.333f/256.0f + +#define ST_OFFSET 0.5f/256.0f; + +#define ST_FAC 255.99f +#define ST_BFFAC 0.5f/256.0f +#define ST_BFFACSORT 0.333f/256.0f + +#define ST_FACTRI 255.99f +#define ST_BFFACTRI 0.5f/256.0f +#define ST_BFFACTRISORT 0.333f/256.0f + +#define ST_FACVRAMX 255.0f +#define ST_FACVRAM 256.0f + +/////////////////////////////////////////////////////////////// + +#else + +#define ST_BFFACSPRITE 0.5f +#define ST_BFFACSPRITESORT 0.333f + +#define ST_BFFAC 0.5f +#define ST_BFFACSORT 0.333f + +#define ST_BFFACTRI 0.5f +#define ST_BFFACTRISORT 0.333f + +#define ST_OFFSET 0.5f; + +#endif + +//////////////////////////////////////////////////////////////////////////////////// +// draw globals; most will be initialized again later (by config or checks) + +#ifdef _WINDOWS +HDC dcGlobal = NULL; +HWND hWWindow; +#endif + +BOOL bIsFirstFrame = TRUE; + +// resolution/ratio vars + +int iResX; +int iResY; +BOOL bKeepRatio = FALSE; +RECT rRatioRect; + +// psx mask related vars + +BOOL bCheckMask = FALSE; +int iUseMask = 0; +int iSetMask = 0; +unsigned short sSetMask = 0; +uint32_t lSetMask = 0; + +// drawing/coord vars + +OGLVertex vertex[4]; +GLubyte gl_ux[8]; +GLubyte gl_vy[8]; +short sprtY,sprtX,sprtH,sprtW; + +// drawing options + +BOOL bOpaquePass; +BOOL bAdvancedBlend; +BOOL bUseLines; +BOOL bUseAntiAlias; +int iTexQuality; +int iUsePalTextures=1; +BOOL bSnapShot=FALSE; +BOOL bSmallAlpha=FALSE; +int iShowFPS=0; + +// OGL extension support + +int iForceVSync=-1; +int iUseExts=0; +BOOL bGLExt; +BOOL bGLFastMovie=FALSE; +BOOL bGLSoft; +BOOL bGLBlend; +#if defined (_MACGL) // always supported on OSX > 10.4.3 +#define glBlendEquationEXTEx glBlendEquationEXT +#define glColorTableEXTEx glColorTableEXT +#else +PFNGLBLENDEQU glBlendEquationEXTEx=NULL; +PFNGLCOLORTABLEEXT glColorTableEXTEx=NULL; +#endif +// gfx card buffer infos + +int iDepthFunc=0; +int iZBufferDepth=0; +GLbitfield uiBufferBits=GL_COLOR_BUFFER_BIT; + +//////////////////////////////////////////////////////////////////////// +// Set OGL pixel format +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +BOOL bSetupPixelFormat(HDC hDC) +{ + int pixelformat; + static PIXELFORMATDESCRIPTOR pfd = + { + sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd + 1, // version number + PFD_DRAW_TO_WINDOW | // support window + PFD_SUPPORT_OPENGL | // support OpenGL + PFD_DOUBLEBUFFER, // double buffered + PFD_TYPE_RGBA, // RGBA type + 16, // 16-bit color depth (adjusted later) + 0, 0, 0, 0, 0, 0, // color bits ignored + 0, // no alpha buffer + 0, // shift bit ignored + 0, // no accumulation buffer + 0, 0, 0, 0, // accum bits ignored + 0, // z-buffer + 0, + 0, // no auxiliary buffer + PFD_MAIN_PLANE, // main layer + 0, // reserved + 0, 0, 0 // layer masks ignored + }; + + pfd.cColorBits=iColDepth; // set user color depth + pfd.cDepthBits=iZBufferDepth; // set user zbuffer (by psx mask) + + if((pixelformat=ChoosePixelFormat(hDC,&pfd))==0) + { + MessageBox(NULL,"ChoosePixelFormat failed","Error",MB_OK); + return FALSE; + } + + if(SetPixelFormat(hDC,pixelformat, &pfd)==FALSE) + { + MessageBox(NULL,"SetPixelFormat failed","Error",MB_OK); + return FALSE; + } + + return TRUE; +} +#endif + +//////////////////////////////////////////////////////////////////////// +// Get extension infos (f.e. pal textures / packed pixels) +//////////////////////////////////////////////////////////////////////// + +void GetExtInfos(void) +{ + BOOL bPacked=FALSE; // default: no packed pixel support + + bGLExt=FALSE; // default: no extensions + bGLFastMovie=FALSE; + + if(strstr((char *)glGetString(GL_EXTENSIONS), // packed pixels available? + "GL_EXT_packed_pixels")) + bPacked=TRUE; // -> ok + + if(bPacked && bUse15bitMdec) // packed available and 15bit mdec wanted? + bGLFastMovie=TRUE; // -> ok + + if(bPacked && (iTexQuality==1 || iTexQuality==2)) // packed available and 16 bit texture format? + { + bGLFastMovie=TRUE; // -> ok + bGLExt=TRUE; + } + + if(iUseExts && // extension support wanted? + (strstr((char *)glGetString(GL_EXTENSIONS), + "GL_EXT_texture_edge_clamp") || + strstr((char *)glGetString(GL_EXTENSIONS), // -> check clamp support, if yes: use it + "GL_SGIS_texture_edge_clamp"))) + iClampType=GL_TO_EDGE_CLAMP; + else iClampType=GL_CLAMP; + +#if !defined (_MACGL) // OSX > 10.4.3 defines this + glColorTableEXTEx=(PFNGLCOLORTABLEEXT)NULL; // init ogl palette func pointer +#endif + +#ifndef __sun + if(iGPUHeight!=1024 && // no pal textures in ZN mode (height=1024)! + strstr((char *)glGetString(GL_EXTENSIONS), // otherwise: check ogl support + "GL_EXT_paletted_texture")) + { + iUsePalTextures=1; // -> wow, supported, get func pointer + +#ifdef _WINDOWS + glColorTableEXTEx=(PFNGLCOLORTABLEEXT)wglGetProcAddress("glColorTableEXT"); +#elif defined (_MACGL) + // no prob, done already in OSX > 10.4.3 +#else + glColorTableEXTEx=(PFNGLCOLORTABLEEXT)glXGetProcAddress("glColorTableEXT"); +#endif + + if(glColorTableEXTEx==NULL) iUsePalTextures=0; // -> ha, cheater... no func, no support + + } + else iUsePalTextures=0; +#else + iUsePalTextures=0; +#endif +} + +//////////////////////////////////////////////////////////////////////// +// Setup some stuff depending on user settings or in-game toggle +//////////////////////////////////////////////////////////////////////// + +void SetExtGLFuncs(void) +{ + //----------------------------------------------------// + + SetFixes(); // update fix infos + + //----------------------------------------------------// + +#ifdef _WINDOWS + if((iForceVSync>=0) && // force vsync? + strstr((char *)glGetString(GL_EXTENSIONS), // and extension available? + "WGL_EXT_swap_control")) + { + PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT= + (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress("wglSwapIntervalEXT"); + + if(wglSwapIntervalEXT) wglSwapIntervalEXT(iForceVSync); + } +#endif +#ifdef _MACGL + SetVSync(iForceVSync); +#endif + if(iUseExts && !(dwActFixes&1024) && // extensions wanted? and not turned off by game fix? + strstr((char *)glGetString(GL_EXTENSIONS), // and blend_subtract available? + "GL_EXT_blend_subtract")) + { // -> get ogl blend function pointer +#ifdef _WINDOWS + glBlendEquationEXTEx=(PFNGLBLENDEQU)wglGetProcAddress("glBlendEquationEXT"); +#elif defined(_MACGL) + // no prob, OSX > 10.4.3 has this +#else + glBlendEquationEXTEx=(PFNGLBLENDEQU)glXGetProcAddress("glBlendEquationEXT"); +#endif + } + else // no subtract blending? + { + if(glBlendEquationEXTEx) // -> change to additive blending (if subract was active) + glBlendEquationEXTEx(FUNC_ADD_EXT); +#if !defined(_MACGL) // BTW, why set to null? strange... + glBlendEquationEXTEx=(PFNGLBLENDEQU)NULL; // -> no more blend function pointer +#endif + } + + //----------------------------------------------------// + + if(iUseExts && bAdvancedBlend && // advanced blending wanted ? + strstr((char *)glGetString(GL_EXTENSIONS), // and extension avail? + "GL_EXT_texture_env_combine")) + { + bUseMultiPass=FALSE;bGLBlend=TRUE; // -> no need for 2 passes, perfect + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT); + glTexEnvf(GL_TEXTURE_ENV, COMBINE_RGB_EXT, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, COMBINE_ALPHA_EXT, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, RGB_SCALE_EXT, 2.0f); + } + else // no advanced blending wanted/available: + { + if(bAdvancedBlend) bUseMultiPass=TRUE; // -> pseudo-advanced with 2 passes + else bUseMultiPass=FALSE; // -> or simple 'bright color' mode + bGLBlend=FALSE; // -> no ext blending! + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } + + //----------------------------------------------------// + // init standard tex quality 0-2, and big alpha mode 3 + + if(!(dwActFixes&0x4000) && iFilterType && iTexQuality>=3) + bSmallAlpha=TRUE; + else bSmallAlpha=FALSE; + + if(bOpaquePass) // opaque mode? + { + if(dwActFixes&32) + { + TCF[0]=CP8RGBA_0; + PalTexturedColourFn=CP8RGBA; // -> init col func + } + else + { + TCF[0]=XP8RGBA_0; + PalTexturedColourFn=XP8RGBA; // -> init col func + } + + TCF[1]=XP8RGBA_1; + glAlphaFunc(GL_GREATER,0.49f); + } + else // no opaque mode? + { + TCF[0]=TCF[1]=P8RGBA; + PalTexturedColourFn=P8RGBA; // -> init col func + glAlphaFunc(GL_NOTEQUAL,0); // --> set alpha func + } + + //----------------------------------------------------// + + LoadSubTexFn=LoadSubTexturePageSort; // init load tex ptr + + giWantedFMT=GL_RGBA; // init ogl tex format + + switch(iTexQuality) // -> quality: + { + //--------------------------------------------------// + case 0: // -> don't care + giWantedRGBA=4; + giWantedTYPE=GL_UNSIGNED_BYTE; + break; + //--------------------------------------------------// + case 1: // -> R4G4B4A4 + if(bGLExt) + { + giWantedRGBA=GL_RGBA4; + giWantedTYPE=GL_UNSIGNED_SHORT_4_4_4_4_EXT; + LoadSubTexFn=LoadPackedSubTexturePageSort; + if(bOpaquePass) + { + if(dwActFixes&32) PTCF[0]=CP4RGBA_0; + else PTCF[0]=XP4RGBA_0; + PTCF[1]=XP4RGBA_1; + } + else + { + PTCF[0]=PTCF[1]=P4RGBA; + } + } + else + { + giWantedRGBA=GL_RGBA4; + giWantedTYPE=GL_UNSIGNED_BYTE; + } + break; + //--------------------------------------------------// + case 2: // -> R5B5G5A1 + if(bGLExt) + { + giWantedRGBA=GL_RGB5_A1; + giWantedTYPE=GL_UNSIGNED_SHORT_5_5_5_1_EXT; + LoadSubTexFn=LoadPackedSubTexturePageSort; + if(bOpaquePass) + { + if(dwActFixes&32) PTCF[0]=CP5RGBA_0; + else PTCF[0]=XP5RGBA_0; + PTCF[1]=XP5RGBA_1; + } + else + { + PTCF[0]=PTCF[1]=P5RGBA; + } + } + else + { + giWantedRGBA=GL_RGB5_A1;giWantedTYPE=GL_UNSIGNED_BYTE; + } + break; + //--------------------------------------------------// + case 3: // -> R8G8B8A8 + giWantedRGBA=GL_RGBA8; + giWantedTYPE=GL_UNSIGNED_BYTE; + + if(bSmallAlpha) + { + if(bOpaquePass) // opaque mode? + { + if(dwActFixes&32) {TCF[0]=CP8RGBAEx_0;PalTexturedColourFn=CP8RGBAEx;} + else {TCF[0]=XP8RGBAEx_0;PalTexturedColourFn=XP8RGBAEx;} + TCF[1]=XP8RGBAEx_1; + } + } + + break; + //--------------------------------------------------// + case 4: // -> R8G8B8A8 + giWantedRGBA = GL_RGBA8; + giWantedTYPE = GL_UNSIGNED_BYTE; + + if(strstr((char *)glGetString(GL_EXTENSIONS), // and extension avail? + "GL_EXT_bgra")) + { + giWantedFMT = GL_BGRA_EXT; + + if(bOpaquePass) // opaque mode? + { + if(bSmallAlpha) + { + if(dwActFixes&32) {TCF[0]=CP8BGRAEx_0;PalTexturedColourFn=CP8RGBAEx;} + else {TCF[0]=XP8BGRAEx_0;PalTexturedColourFn=XP8RGBAEx;} + TCF[1]=XP8BGRAEx_1; + } + else + { + if(dwActFixes&32) {TCF[0]=CP8BGRA_0;PalTexturedColourFn=CP8RGBA;} + else {TCF[0]=XP8BGRA_0;PalTexturedColourFn=XP8RGBA;} + TCF[1]=XP8BGRA_1; + } + } + else // no opaque mode? + { + TCF[0]=TCF[1]=P8BGRA; // -> init col func + } + } + else + { + iTexQuality=3; + if(bSmallAlpha) + { + if(bOpaquePass) // opaque mode? + { + if(dwActFixes&32) {TCF[0]=CP8RGBAEx_0;PalTexturedColourFn=CP8RGBAEx;} + else {TCF[0]=XP8RGBAEx_0;PalTexturedColourFn=XP8RGBAEx;} + TCF[1]=XP8RGBAEx_1; + } + } + } + + break; + //--------------------------------------------------// + } + + bBlendEnable=FALSE; // init blending: off + glDisable(GL_BLEND); + + SetScanTrans(); // init scan lines (if wanted) +} + +//////////////////////////////////////////////////////////////////////// +// setup scan lines +//////////////////////////////////////////////////////////////////////// + +#define R_TSP 0x00,0x45,0x00,0xff +#define G_TSP 0x00,0x00,0x45,0xff +#define B_TSP 0x45,0x00,0x00,0xff +#define O_TSP 0x45,0x45,0x45,0xff +#define N_TSP 0x00,0x00,0x00,0xff + +GLuint gTexScanName=0; + +GLubyte texscan[4][16]= +{ +{R_TSP, G_TSP, B_TSP, N_TSP}, +{O_TSP, N_TSP, O_TSP, N_TSP}, +{B_TSP, N_TSP, R_TSP, G_TSP}, +{O_TSP, N_TSP, O_TSP, N_TSP} +}; + +void CreateScanLines(void) +{ + if(iUseScanLines) + { + int y; + if(iScanBlend<0) // special scan mask mode + { + glGenTextures(1, &gTexScanName); + glBindTexture(GL_TEXTURE_2D, gTexScanName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, 4, 4, 4, 0,GL_RGBA, GL_UNSIGNED_BYTE, texscan); + } + else // otherwise simple lines in a display list + { + uiScanLine=glGenLists(1); + glNewList(uiScanLine,GL_COMPILE); + #ifdef _MACGL + // not mac specific, just commenting out to be friendly + // use it if you like + // this draws anti-aliased lines with user-chosen color + glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT); + glEnable(GL_BLEND | GL_LINE_SMOOTH); + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + glColor4f(iScanlineColor[0],iScanlineColor[1],iScanlineColor[2],iScanlineColor[3]); + glBegin(GL_LINES); + for(y=0;y ok, turn display on + szDispBuf[0]=0; + BuildDispMenu(0); + } + + bIsFirstFrame = FALSE; // we have survived the first frame :) + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// clean up OGL stuff +//////////////////////////////////////////////////////////////////////// + +void GLcleanup() +{ + KillDisplayLists(); // bye display lists + + if(iUseScanLines) // scanlines used? + { + if(iScanBlend<0) + { + if(gTexScanName!=0) // some scanline tex? + glDeleteTextures(1, &gTexScanName); // -> delete it + gTexScanName=0; + } + else glDeleteLists(uiScanLine,1); // otherwise del scanline display list + } + + CleanupTextureStore(); // bye textures + +#ifdef _WINDOWS + wglMakeCurrent(NULL, NULL); // bye context + if(GLCONTEXT) wglDeleteContext(GLCONTEXT); + if(!bWindowMode && dcGlobal) + ReleaseDC(hWWindow,dcGlobal); +#endif +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// Offset stuff +//////////////////////////////////////////////////////////////////////// + +// please note: it is hardly do-able in a hw/accel plugin to get the +// real psx polygon coord mapping right... the following +// works not to bad with many games, though + +__inline BOOL CheckCoord4() +{ + if(lx0<0) + { + if(((lx1-lx0)>CHKMAX_X) || + ((lx2-lx0)>CHKMAX_X)) + { + if(lx3<0) + { + if((lx1-lx3)>CHKMAX_X) return TRUE; + if((lx2-lx3)>CHKMAX_X) return TRUE; + } + } + } + if(lx1<0) + { + if((lx0-lx1)>CHKMAX_X) return TRUE; + if((lx2-lx1)>CHKMAX_X) return TRUE; + if((lx3-lx1)>CHKMAX_X) return TRUE; + } + if(lx2<0) + { + if((lx0-lx2)>CHKMAX_X) return TRUE; + if((lx1-lx2)>CHKMAX_X) return TRUE; + if((lx3-lx2)>CHKMAX_X) return TRUE; + } + if(lx3<0) + { + if(((lx1-lx3)>CHKMAX_X) || + ((lx2-lx3)>CHKMAX_X)) + { + if(lx0<0) + { + if((lx1-lx0)>CHKMAX_X) return TRUE; + if((lx2-lx0)>CHKMAX_X) return TRUE; + } + } + } + + + if(ly0<0) + { + if((ly1-ly0)>CHKMAX_Y) return TRUE; + if((ly2-ly0)>CHKMAX_Y) return TRUE; + } + if(ly1<0) + { + if((ly0-ly1)>CHKMAX_Y) return TRUE; + if((ly2-ly1)>CHKMAX_Y) return TRUE; + if((ly3-ly1)>CHKMAX_Y) return TRUE; + } + if(ly2<0) + { + if((ly0-ly2)>CHKMAX_Y) return TRUE; + if((ly1-ly2)>CHKMAX_Y) return TRUE; + if((ly3-ly2)>CHKMAX_Y) return TRUE; + } + if(ly3<0) + { + if((ly1-ly3)>CHKMAX_Y) return TRUE; + if((ly2-ly3)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + +__inline BOOL CheckCoord3() +{ + if(lx0<0) + { + if((lx1-lx0)>CHKMAX_X) return TRUE; + if((lx2-lx0)>CHKMAX_X) return TRUE; + } + if(lx1<0) + { + if((lx0-lx1)>CHKMAX_X) return TRUE; + if((lx2-lx1)>CHKMAX_X) return TRUE; + } + if(lx2<0) + { + if((lx0-lx2)>CHKMAX_X) return TRUE; + if((lx1-lx2)>CHKMAX_X) return TRUE; + } + if(ly0<0) + { + if((ly1-ly0)>CHKMAX_Y) return TRUE; + if((ly2-ly0)>CHKMAX_Y) return TRUE; + } + if(ly1<0) + { + if((ly0-ly1)>CHKMAX_Y) return TRUE; + if((ly2-ly1)>CHKMAX_Y) return TRUE; + } + if(ly2<0) + { + if((ly0-ly2)>CHKMAX_Y) return TRUE; + if((ly1-ly2)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + + +__inline BOOL CheckCoord2() +{ + if(lx0<0) + { + if((lx1-lx0)>CHKMAX_X) return TRUE; + } + if(lx1<0) + { + if((lx0-lx1)>CHKMAX_X) return TRUE; + } + if(ly0<0) + { + if((ly1-ly0)>CHKMAX_Y) return TRUE; + } + if(ly1<0) + { + if((ly0-ly1)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + +/* +//Lewpys "offsetline" func: + +void offsetline(void) +{ + float x0, x1, y0, y1, oolength, xl, yl; + + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(!(dwActFixes&16)) + { + if((lx0 & SIGNBIT)) lx0|=S_MASK; + else lx0&=~S_MASK; + if((lx1 & SIGNBIT)) lx1|=S_MASK; + else lx1&=~S_MASK; + if((ly0 & SIGNBIT)) ly0|=S_MASK; + else ly0&=~S_MASK; + if((ly1 & SIGNBIT)) ly1|=S_MASK; + else ly1&=~S_MASK; + } + + x0 = (float)(lx0 + PSXDisplay.CumulOffset.x); + x1 = (float)(lx1 + PSXDisplay.CumulOffset.x); + y0 = (float)(ly0 + PSXDisplay.CumulOffset.y); + y1 = (float)(ly1 + PSXDisplay.CumulOffset.y); + + oolength = (float)1/((float)sqrt((y1 - y0)*(y1 - y0) + (x1 - x0)*(x1 - x0)) * (float)2); +// oolength = (float)1/((float)sqrt(((y1 - y0)*(y1 - y0) + (x1 - x0)*(x1 - x0)) * (float)2)); + + xl = (x1 - x0) * oolength; + yl = (y1 - y0) * oolength; + + x0 += 0.5f; + x1 += 0.5f; + + x0 -= xl - yl; + x1 += xl + yl; + y0 -= yl + xl; + y1 += yl - xl; + + vertex[0].x=x0; + vertex[1].x=x1; + vertex[0].y=y0; + vertex[1].y=y1; + + x0 -= yl * 2; + x1 -= yl * 2; + y0 += xl * 2; + y1 += xl * 2; + + vertex[2].x=x1; + vertex[3].x=x0; + vertex[2].y=y1; + vertex[3].y=y0; +} +*/ + + +// Pete's way: a very easy (and hopefully fast) approach for lines +// without sqrt... using a small float -> short cast trick :) + +#define VERTEX_OFFX 0.2f +#define VERTEX_OFFY 0.2f + +BOOL offsetline(void) +{ + short x0,x1,y0,y1,dx,dy;float px,py; + + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(!(dwActFixes&16)) + { + lx0=(short)(((int)lx0<>SIGNSHIFT); + lx1=(short)(((int)lx1<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + ly1=(short)(((int)ly1<>SIGNSHIFT); + + if(CheckCoord2()) return TRUE; + } + + x0 = (lx0 + PSXDisplay.CumulOffset.x)+1; + x1 = (lx1 + PSXDisplay.CumulOffset.x)+1; + y0 = (ly0 + PSXDisplay.CumulOffset.y)+1; + y1 = (ly1 + PSXDisplay.CumulOffset.y)+1; + + dx=x1-x0; + dy=y1-y0; + + if(dx>=0) + { + if(dy>=0) + { + px=0.5f; + if(dx>dy) py=-0.5f; + else if(dxdy) px= 0.5f; + else if(dx=0) + { + py=0.5f; + dx=-dx; + if(dx>dy) px=-0.5f; + else if(dxdy) py=-0.5f; + else if(dx>SIGNSHIFT); + lx1=(short)(((int)lx1<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + ly1=(short)(((int)ly1<>SIGNSHIFT); + + if(CheckCoord2()) return TRUE; + } + + vertex[0].x=lx0+PSXDisplay.CumulOffset.x; + vertex[1].x=lx1+PSXDisplay.CumulOffset.x; + vertex[0].y=ly0+PSXDisplay.CumulOffset.y; + vertex[1].y=ly1+PSXDisplay.CumulOffset.y; + + return FALSE; +} + +///////////////////////////////////////////////////////// + +BOOL offset3(void) +{ + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(!(dwActFixes&16)) + { + lx0=(short)(((int)lx0<>SIGNSHIFT); + lx1=(short)(((int)lx1<>SIGNSHIFT); + lx2=(short)(((int)lx2<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + ly1=(short)(((int)ly1<>SIGNSHIFT); + ly2=(short)(((int)ly2<>SIGNSHIFT); + + if(CheckCoord3()) return TRUE; + } + + vertex[0].x=lx0+PSXDisplay.CumulOffset.x; + vertex[1].x=lx1+PSXDisplay.CumulOffset.x; + vertex[2].x=lx2+PSXDisplay.CumulOffset.x; + vertex[0].y=ly0+PSXDisplay.CumulOffset.y; + vertex[1].y=ly1+PSXDisplay.CumulOffset.y; + vertex[2].y=ly2+PSXDisplay.CumulOffset.y; + + return FALSE; +} + +///////////////////////////////////////////////////////// + +BOOL offset4(void) +{ + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(!(dwActFixes&16)) + { + lx0=(short)(((int)lx0<>SIGNSHIFT); + lx1=(short)(((int)lx1<>SIGNSHIFT); + lx2=(short)(((int)lx2<>SIGNSHIFT); + lx3=(short)(((int)lx3<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + ly1=(short)(((int)ly1<>SIGNSHIFT); + ly2=(short)(((int)ly2<>SIGNSHIFT); + ly3=(short)(((int)ly3<>SIGNSHIFT); + + if(CheckCoord4()) return TRUE; + } + + vertex[0].x=lx0+PSXDisplay.CumulOffset.x; + vertex[1].x=lx1+PSXDisplay.CumulOffset.x; + vertex[2].x=lx2+PSXDisplay.CumulOffset.x; + vertex[3].x=lx3+PSXDisplay.CumulOffset.x; + vertex[0].y=ly0+PSXDisplay.CumulOffset.y; + vertex[1].y=ly1+PSXDisplay.CumulOffset.y; + vertex[2].y=ly2+PSXDisplay.CumulOffset.y; + vertex[3].y=ly3+PSXDisplay.CumulOffset.y; + + return FALSE; +} + +///////////////////////////////////////////////////////// + +void offsetST(void) +{ + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(!(dwActFixes&16)) + { + lx0=(short)(((int)lx0<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + + if(lx0<-512 && PSXDisplay.DrawOffset.x<=-512) + lx0+=2048; + + if(ly0<-512 && PSXDisplay.DrawOffset.y<=-512) + ly0+=2048; + } + + ly1 = ly0; + ly2 = ly3 = ly0+sprtH; + lx3 = lx0; + lx1 = lx2 = lx0+sprtW; + + vertex[0].x=lx0+PSXDisplay.CumulOffset.x; + vertex[1].x=lx1+PSXDisplay.CumulOffset.x; + vertex[2].x=lx2+PSXDisplay.CumulOffset.x; + vertex[3].x=lx3+PSXDisplay.CumulOffset.x; + vertex[0].y=ly0+PSXDisplay.CumulOffset.y; + vertex[1].y=ly1+PSXDisplay.CumulOffset.y; + vertex[2].y=ly2+PSXDisplay.CumulOffset.y; + vertex[3].y=ly3+PSXDisplay.CumulOffset.y; +} + +///////////////////////////////////////////////////////// + +void offsetScreenUpload(int Position) +{ + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(Position==-1) + { + int lmdx,lmdy; + + lmdx=xrUploadArea.x0; + lmdy=xrUploadArea.y0; + + lx0-=lmdx; + ly0-=lmdy; + lx1-=lmdx; + ly1-=lmdy; + lx2-=lmdx; + ly2-=lmdy; + lx3-=lmdx; + ly3-=lmdy; + } + else + if(Position) + { + lx0-=PSXDisplay.DisplayPosition.x; + ly0-=PSXDisplay.DisplayPosition.y; + lx1-=PSXDisplay.DisplayPosition.x; + ly1-=PSXDisplay.DisplayPosition.y; + lx2-=PSXDisplay.DisplayPosition.x; + ly2-=PSXDisplay.DisplayPosition.y; + lx3-=PSXDisplay.DisplayPosition.x; + ly3-=PSXDisplay.DisplayPosition.y; + } + else + { + lx0-=PreviousPSXDisplay.DisplayPosition.x; + ly0-=PreviousPSXDisplay.DisplayPosition.y; + lx1-=PreviousPSXDisplay.DisplayPosition.x; + ly1-=PreviousPSXDisplay.DisplayPosition.y; + lx2-=PreviousPSXDisplay.DisplayPosition.x; + ly2-=PreviousPSXDisplay.DisplayPosition.y; + lx3-=PreviousPSXDisplay.DisplayPosition.x; + ly3-=PreviousPSXDisplay.DisplayPosition.y; + } + + vertex[0].x=lx0 + PreviousPSXDisplay.Range.x0; + vertex[1].x=lx1 + PreviousPSXDisplay.Range.x0; + vertex[2].x=lx2 + PreviousPSXDisplay.Range.x0; + vertex[3].x=lx3 + PreviousPSXDisplay.Range.x0; + vertex[0].y=ly0 + PreviousPSXDisplay.Range.y0; + vertex[1].y=ly1 + PreviousPSXDisplay.Range.y0; + vertex[2].y=ly2 + PreviousPSXDisplay.Range.y0; + vertex[3].y=ly3 + PreviousPSXDisplay.Range.y0; + + if(iUseMask) + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } +} + +///////////////////////////////////////////////////////// + +void offsetBlk(void) +{ + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + vertex[0].x=lx0-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; + vertex[1].x=lx1-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; + vertex[2].x=lx2-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; + vertex[3].x=lx3-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; + vertex[0].y=ly0-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; + vertex[1].y=ly1-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; + vertex[2].y=ly2-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; + vertex[3].y=ly3-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; + + if(iUseMask) + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } +} + +//////////////////////////////////////////////////////////////////////// +// texture sow/tow calculations +//////////////////////////////////////////////////////////////////////// + +void assignTextureVRAMWrite(void) +{ +#ifdef OWNSCALE + + vertex[0].sow=0.5f/ ST_FACVRAMX; + vertex[0].tow=0.5f/ ST_FACVRAM; + + vertex[1].sow=(float)gl_ux[1]/ ST_FACVRAMX; + vertex[1].tow=0.5f/ ST_FACVRAM; + + vertex[2].sow=(float)gl_ux[2]/ ST_FACVRAMX; + vertex[2].tow=(float)gl_vy[2]/ ST_FACVRAM; + + vertex[3].sow=0.5f/ ST_FACVRAMX; + vertex[3].tow=(float)gl_vy[3]/ ST_FACVRAM; + +#else + + if(gl_ux[1]==255) + { + vertex[0].sow=(gl_ux[0]*255.99f)/255.0f; + vertex[1].sow=(gl_ux[1]*255.99f)/255.0f; + vertex[2].sow=(gl_ux[2]*255.99f)/255.0f; + vertex[3].sow=(gl_ux[3]*255.99f)/255.0f; + } + else + { + vertex[0].sow=gl_ux[0]; + vertex[1].sow=gl_ux[1]; + vertex[2].sow=gl_ux[2]; + vertex[3].sow=gl_ux[3]; + } + + vertex[0].tow=gl_vy[0]; + vertex[1].tow=gl_vy[1]; + vertex[2].tow=gl_vy[2]; + vertex[3].tow=gl_vy[3]; + +#endif +} + +GLuint gLastTex=0; +GLuint gLastFMode=(GLuint)-1; + +///////////////////////////////////////////////////////// + +void assignTextureSprite(void) +{ + if(bUsingTWin) + { + vertex[0].sow=vertex[3].sow=(float)gl_ux[0]/TWin.UScaleFactor; + vertex[1].sow=vertex[2].sow=(float)sSprite_ux2/TWin.UScaleFactor; + vertex[0].tow=vertex[1].tow=(float)gl_vy[0]/TWin.VScaleFactor; + vertex[2].tow=vertex[3].tow=(float)sSprite_vy2/TWin.VScaleFactor; + gLastTex=gTexName; + + if(iFilterType>0 && iFilterType<3 && iHiResTextures!=2) + { + float fxmin=65536.0f,fxmax=0.0f,fymin=65536.0f,fymax=0.0f;int i; + + for(i=0;i<4;i++) + { + if(vertex[i].sowfxmax) fxmax=vertex[i].sow; + if(vertex[i].tow>fymax) fymax=vertex[i].tow; + } + + for(i=0;i<4;i++) + { +#ifdef OWNSCALE + if(vertex[i].sow==fxmin) vertex[i].sow+=0.375f/(float)TWin.Position.x1; + if(vertex[i].sow==fxmax) vertex[i].sow-=0.375f/(float)TWin.Position.x1; + if(vertex[i].tow==fymin) vertex[i].tow+=0.375f/(float)TWin.Position.y1; + if(vertex[i].tow==fymax) vertex[i].tow-=0.375f/(float)TWin.Position.y1; +#else + if(vertex[i].sow==fxmin) vertex[i].sow+=96.0f/(float)TWin.Position.x1; + if(vertex[i].sow==fxmax) vertex[i].sow-=96.0f/(float)TWin.Position.x1; + if(vertex[i].tow==fymin) vertex[i].tow+=96.0f/(float)TWin.Position.y1; + if(vertex[i].tow==fymax) vertex[i].tow-=96.0f/(float)TWin.Position.y1; +#endif + } + } + + } + else + { +#ifdef OWNSCALE + + vertex[0].sow=vertex[3].sow=(float)gl_ux[0] / ST_FACSPRITE; + vertex[1].sow=vertex[2].sow=(float)sSprite_ux2 / ST_FACSPRITE; + vertex[0].tow=vertex[1].tow=(float)gl_vy[0] / ST_FACSPRITE; + vertex[2].tow=vertex[3].tow=(float)sSprite_vy2 / ST_FACSPRITE; + +#else + + vertex[0].sow=vertex[3].sow=gl_ux[0]; + vertex[1].sow=vertex[2].sow=sSprite_ux2; + vertex[0].tow=vertex[1].tow=gl_vy[0]; + vertex[2].tow=vertex[3].tow=sSprite_vy2; + +#endif + + if(iFilterType>2) + { + if(gLastTex!=gTexName || gLastFMode!=0) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gLastTex=gTexName;gLastFMode=0; + } + } + } + + if(usMirror & 0x1000) + { + vertex[0].sow=vertex[1].sow; + vertex[1].sow=vertex[2].sow=vertex[3].sow; + vertex[3].sow=vertex[0].sow; + } + + if(usMirror & 0x2000) + { + vertex[0].tow=vertex[3].tow; + vertex[2].tow=vertex[3].tow=vertex[1].tow; + vertex[1].tow=vertex[0].tow; + } + +} + +///////////////////////////////////////////////////////// + +void assignTexture3(void) +{ + if(bUsingTWin) + { + vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor; + vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor; + vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor; + vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor; + vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor; + vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor; + gLastTex=gTexName; + } + else + { +#ifdef OWNSCALE + vertex[0].sow=(float)gl_ux[0] / ST_FACTRI; + vertex[0].tow=(float)gl_vy[0] / ST_FACTRI; + vertex[1].sow=(float)gl_ux[1] / ST_FACTRI; + + vertex[1].tow=(float)gl_vy[1] / ST_FACTRI; + vertex[2].sow=(float)gl_ux[2] / ST_FACTRI; + vertex[2].tow=(float)gl_vy[2] / ST_FACTRI; +#else + vertex[0].sow=gl_ux[0]; + vertex[0].tow=gl_vy[0]; + vertex[1].sow=gl_ux[1]; + vertex[1].tow=gl_vy[1]; + vertex[2].sow=gl_ux[2]; + vertex[2].tow=gl_vy[2]; +#endif + + if(iFilterType>2) + { + if(gLastTex!=gTexName || gLastFMode!=1) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gLastTex=gTexName;gLastFMode=1; + } + } + + if(iFilterType) + { + float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i; + for(i=0;i<3;i++) + { + if(vertex[i].sowfxmax) fxmax=vertex[i].sow; + if(vertex[i].tow>fymax) fymax=vertex[i].tow; + } + + for(i=0;i<3;i++) + { + if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT; + if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT; + if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT; + if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT; + } + } + } +} + +///////////////////////////////////////////////////////// + +void assignTexture4(void) +{ + if(bUsingTWin) + { + vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor; + vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor; + vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor; + vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor; + vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor; + vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor; + vertex[3].sow=(float)gl_ux[3]/TWin.UScaleFactor; + vertex[3].tow=(float)gl_vy[3]/TWin.VScaleFactor; + gLastTex=gTexName; + } + else + { +#ifdef OWNSCALE + vertex[0].sow=(float)gl_ux[0] / ST_FAC; + vertex[0].tow=(float)gl_vy[0] / ST_FAC; + vertex[1].sow=(float)gl_ux[1] / ST_FAC; + vertex[1].tow=(float)gl_vy[1] / ST_FAC; + vertex[2].sow=(float)gl_ux[2] / ST_FAC; + vertex[2].tow=(float)gl_vy[2] / ST_FAC; + vertex[3].sow=(float)gl_ux[3] / ST_FAC; + vertex[3].tow=(float)gl_vy[3] / ST_FAC; +#else + vertex[0].sow=gl_ux[0]; + vertex[0].tow=gl_vy[0]; + vertex[1].sow=gl_ux[1]; + vertex[1].tow=gl_vy[1]; + vertex[2].sow=gl_ux[2]; + vertex[2].tow=gl_vy[2]; + vertex[3].sow=gl_ux[3]; + vertex[3].tow=gl_vy[3]; +#endif + + if(iFilterType>2) + { + if(gLastTex!=gTexName || gLastFMode!=1) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gLastTex=gTexName;gLastFMode=1; + } + } + + if(iFilterType) + { + float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i; + for(i=0;i<4;i++) + { + if(vertex[i].sowfxmax) fxmax=vertex[i].sow; + if(vertex[i].tow>fymax) fymax=vertex[i].tow; + } + + for(i=0;i<4;i++) + { + if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT; + if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT; + if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT; + if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT; + } + } + } +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// render pos / buffers +//////////////////////////////////////////////////////////////////////// + +#ifndef _WINDOWS +#define EqualRect(pr1,pr2) ((pr1)->left==(pr2)->left && (pr1)->top==(pr2)->top && (pr1)->right==(pr2)->right && (pr1)->bottom==(pr2)->bottom) +#endif + +//////////////////////////////////////////////////////////////////////// +// SetDisplaySettings: "simply" calcs the new drawing area and updates +// the ogl clipping (scissor) + +BOOL bSetClip=FALSE; + +void SetOGLDisplaySettings(BOOL DisplaySet) +{ + static RECT rprev={0,0,0,0}; + static RECT rC ={0,0,0,0}; + static int iOldX=0; + static int iOldY=0; + RECT r;float XS,YS; + + bDisplayNotSet = FALSE; + + //----------------------------------------------------// that's a whole screen upload + if(!DisplaySet) + { + RECT rX; + PSXDisplay.GDrawOffset.x=0; + PSXDisplay.GDrawOffset.y=0; + + PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x+PreviousPSXDisplay.Range.x0; + PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y+PreviousPSXDisplay.Range.y0; + + rprev.left=rprev.left+1; + + rX=rRatioRect; + rX.top=iResY-(rRatioRect.top+rRatioRect.bottom); + + if(bSetClip || !EqualRect(&rC,&rX)) + { + rC=rX; + glScissor(rC.left,rC.top,rC.right,rC.bottom); + bSetClip=FALSE; + } + return; + } + //----------------------------------------------------// + + PSXDisplay.GDrawOffset.y = PreviousPSXDisplay.DisplayPosition.y; + PSXDisplay.GDrawOffset.x = PreviousPSXDisplay.DisplayPosition.x; + PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x - PSXDisplay.GDrawOffset.x+PreviousPSXDisplay.Range.x0; + PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y - PSXDisplay.GDrawOffset.y+PreviousPSXDisplay.Range.y0; + + r.top =PSXDisplay.DrawArea.y0 - PreviousPSXDisplay.DisplayPosition.y; + r.bottom=PSXDisplay.DrawArea.y1 - PreviousPSXDisplay.DisplayPosition.y; + + if(r.bottom<0 || r.top>=PSXDisplay.DisplayMode.y) + { + r.top =PSXDisplay.DrawArea.y0 - PSXDisplay.DisplayPosition.y; + r.bottom=PSXDisplay.DrawArea.y1 - PSXDisplay.DisplayPosition.y; + } + + r.left =PSXDisplay.DrawArea.x0 - PreviousPSXDisplay.DisplayPosition.x; + r.right =PSXDisplay.DrawArea.x1 - PreviousPSXDisplay.DisplayPosition.x; + + if(r.right<0 || r.left>=PSXDisplay.DisplayMode.x) + { + r.left =PSXDisplay.DrawArea.x0 - PSXDisplay.DisplayPosition.x; + r.right =PSXDisplay.DrawArea.x1 - PSXDisplay.DisplayPosition.x; + } + + if(!bSetClip && EqualRect(&r,&rprev) && + iOldX == PSXDisplay.DisplayMode.x && + iOldY == PSXDisplay.DisplayMode.y) + return; + + rprev = r; + iOldX = PSXDisplay.DisplayMode.x; + iOldY = PSXDisplay.DisplayMode.y; + + XS=(float)rRatioRect.right/(float)PSXDisplay.DisplayMode.x; + YS=(float)rRatioRect.bottom/(float)PSXDisplay.DisplayMode.y; + + if(PreviousPSXDisplay.Range.x0) + { + short s=PreviousPSXDisplay.Range.x0+PreviousPSXDisplay.Range.x1; + + r.left+=PreviousPSXDisplay.Range.x0+1; + + r.right+=PreviousPSXDisplay.Range.x0; + + if(r.left>s) r.left=s; + if(r.right>s) r.right=s; + } + + if(PreviousPSXDisplay.Range.y0) + { + short s=PreviousPSXDisplay.Range.y0+PreviousPSXDisplay.Range.y1; + + r.top+=PreviousPSXDisplay.Range.y0+1; + r.bottom+=PreviousPSXDisplay.Range.y0; + + if(r.top>s) r.top=s; + if(r.bottom>s) r.bottom=s; + } + + // Set the ClipArea variables to reflect the new screen, + // offset from zero (since it is a new display buffer) + r.left = (int)(((float)(r.left)) *XS); + r.top = (int)(((float)(r.top)) *YS); + r.right = (int)(((float)(r.right + 1))*XS); + r.bottom = (int)(((float)(r.bottom + 1))*YS); + + // Limit clip area to the screen size + if (r.left > iResX) r.left = iResX; + if (r.left < 0) r.left = 0; + if (r.top > iResY) r.top = iResY; + if (r.top < 0) r.top = 0; + if (r.right > iResX) r.right = iResX; + if (r.right < 0) r.right = 0; + if (r.bottom > iResY) r.bottom = iResY; + if (r.bottom < 0) r.bottom = 0; + + r.right -=r.left; + r.bottom-=r.top; + r.top=iResY-(r.top+r.bottom); + + r.left+=rRatioRect.left; + r.top -=rRatioRect.top; + + if(bSetClip || !EqualRect(&r,&rC)) + { + glScissor(r.left,r.top,r.right,r.bottom); + rC=r; + bSetClip=FALSE; + } +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + diff --git a/plugins/peopsxgl/fps.c b/plugins/peopsxgl/fps.c index e7e0b3fe..dc89600f 100644 --- a/plugins/peopsxgl/fps.c +++ b/plugins/peopsxgl/fps.c @@ -1,399 +1,396 @@ -/*************************************************************************** - fps.c - description - ------------------- - begin : Sun Mar 08 2009 - copyright : (C) 1999-2009 by Pete Bernert - web : www.pbernert.com - ***************************************************************************/ - -/*************************************************************************** - * * - * 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. * - * * - ***************************************************************************/ - -//*************************************************************************// -// History of changes: -// -// 2009/03/08 - Pete -// - generic cleanup for the Peops release -// -//*************************************************************************// - -#include "stdafx.h" - -#define _IN_FPS - -#include "externals.h" -#include "fps.h" - -//////////////////////////////////////////////////////////////////////// -// FPS stuff -//////////////////////////////////////////////////////////////////////// - -BOOL bIsPerformanceCounter=FALSE; -float fFrameRateHz=0; -DWORD dwFrameRateTicks=16; -float fFrameRate; -int iFrameLimit; -BOOL bUseFrameLimit=FALSE; -BOOL bUseFrameSkip=0; -DWORD dwLaceCnt=0; - -//////////////////////////////////////////////////////////////////////// -// FPS skipping / limit -//////////////////////////////////////////////////////////////////////// - -BOOL bInitCap = TRUE; -float fps_skip = 0; -float fps_cur = 0; - -#define TIMEBASE 100000 - -unsigned long timeGetTime() -{ - struct timeval tv; - gettimeofday(&tv, 0); // well, maybe there are better ways - return tv.tv_sec * 100000 + tv.tv_usec/10; // to do that in linux, but at least it works -} - -static void FrameCap(void) -{ - static unsigned long curticks, lastticks, _ticks_since_last_update; - static unsigned long TicksToWait = 0; - bool Waiting = TRUE; - - { - curticks = timeGetTime(); - _ticks_since_last_update = curticks - lastticks; - - if((_ticks_since_last_update > TicksToWait) || - (curticks dwFrameRateTicks) - TicksToWait=0; - else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait); - } - else - { - while (Waiting) - { - curticks = timeGetTime(); - _ticks_since_last_update = curticks - lastticks; - if ((_ticks_since_last_update > TicksToWait) || - (curticks < lastticks)) - { - Waiting = FALSE; - lastticks = curticks; - TicksToWait = dwFrameRateTicks; - } - } - } - } -} - -#define MAXSKIP 120 -#define MAXLACE 16 - -void FrameSkip(void) -{ - static int iNumSkips=0,iAdditionalSkip=0; // number of additional frames to skip - static DWORD dwLastLace=0; // helper var for frame limitation - static DWORD curticks, lastticks, _ticks_since_last_update; - - if(!dwLaceCnt) return; // important: if no updatelace happened, we ignore it completely - - if(iNumSkips) // we are in skipping mode? - { - dwLastLace+=dwLaceCnt; // -> calc frame limit helper (number of laces) - bSkipNextFrame = TRUE; // -> we skip next frame - iNumSkips--; // -> ok, one done - } - else // ok, no additional skipping has to be done... - { // we check now, if some limitation is needed, or a new skipping has to get started - DWORD dwWaitTime; - - if(bInitCap || bSkipNextFrame) // first time or we skipped before? - { - if(bUseFrameLimit && !bInitCap) // frame limit wanted and not first time called? - { - DWORD dwT=_ticks_since_last_update; // -> that's the time of the last drawn frame - dwLastLace+=dwLaceCnt; // -> and that's the number of updatelace since the start of the last drawn frame - - curticks = timeGetTime(); - _ticks_since_last_update= dwT+curticks - lastticks; - - dwWaitTime=dwLastLace*dwFrameRateTicks; // -> and now we calc the time the real psx would have needed - - if(_ticks_since_last_update we were too fast? - { - if((dwWaitTime-_ticks_since_last_update)> // -> some more security, to prevent - (60*dwFrameRateTicks)) // wrong waiting times - _ticks_since_last_update=dwWaitTime; - - while(_ticks_since_last_update loop until we have reached the real psx time - { // (that's the additional limitation, yup) - curticks = timeGetTime(); - _ticks_since_last_update = dwT+curticks - lastticks; - } - } - else // we were still too slow ?!!? - { - if(iAdditionalSkip well, somewhen we really have to stop skipping on very slow systems - { - iAdditionalSkip++; // -> inc our watchdog var - dwLaceCnt=0; // -> reset lace count - lastticks = timeGetTime(); - return; // -> done, we will skip next frame to get more speed - } - } - } - - bInitCap=FALSE; // -> ok, we have inited the frameskip func - iAdditionalSkip=0; // -> init additional skip - bSkipNextFrame=FALSE; // -> we don't skip the next frame - lastticks = timeGetTime(); - dwLaceCnt=0; // -> and we start to count the laces - dwLastLace=0; - _ticks_since_last_update=0; - return; // -> done, the next frame will get drawn - } - - bSkipNextFrame=FALSE; // init the frame skip signal to 'no skipping' first - - curticks = timeGetTime(); - _ticks_since_last_update = curticks - lastticks; - - dwLastLace=dwLaceCnt; // store curr count (frame limitation helper) - dwWaitTime=dwLaceCnt*dwFrameRateTicks; // calc the 'real psx lace time' - - if(_ticks_since_last_update>dwWaitTime) // hey, we needed way too long for that frame... - { - if(bUseFrameLimit) // if limitation, we skip just next frame, - { // and decide after, if we need to do more - iNumSkips=0; - } - else - { - iNumSkips=_ticks_since_last_update/dwWaitTime; // -> calc number of frames to skip to catch up - iNumSkips--; // -> since we already skip next frame, one down - if(iNumSkips>MAXSKIP) iNumSkips=MAXSKIP; // -> well, somewhere we have to draw a line - } - bSkipNextFrame = TRUE; // -> signal for skipping the next frame - } - else // we were faster than real psx? fine :) - if(bUseFrameLimit) // frame limit used? so we wait til the 'real psx time' has been reached - { - if(dwLaceCnt>MAXLACE) // -> security check - _ticks_since_last_update=dwWaitTime; - - while(_ticks_since_last_updatefFrameRateHz) // optical adjust ;) avoids flickering fps display - fps_cur=fFrameRateHz; - } -} - -void PCFrameCap (void) -{ - static unsigned long curticks, lastticks, _ticks_since_last_update; - static unsigned long TicksToWait = 0; - bool Waiting = TRUE; - - while (Waiting) - { - curticks = timeGetTime(); - _ticks_since_last_update = curticks - lastticks; - if ((_ticks_since_last_update > TicksToWait) || - (curticks < lastticks)) - { - Waiting = FALSE; - lastticks = curticks; - TicksToWait = (TIMEBASE / (unsigned long)fFrameRateHz); - } - } -} - -void PCcalcfps(void) -{ - static unsigned long curticks,_ticks_since_last_update,lastticks; - static long fps_cnt = 0; - static float fps_acc = 0; - float CurrentFPS=0; - - curticks = timeGetTime(); - _ticks_since_last_update=curticks-lastticks; - if(_ticks_since_last_update) - CurrentFPS=(float)TIMEBASE/(float)_ticks_since_last_update; - else CurrentFPS = 0; - lastticks = curticks; - - fps_acc += CurrentFPS; - - if(++fps_cnt==10) - { - fps_cur = fps_acc / 10; - fps_acc = 0; - fps_cnt = 0; - } - - fps_skip=CurrentFPS+1.0f; -} - -void SetAutoFrameCap(void) -{ - if(iFrameLimit==1) - { - fFrameRateHz = fFrameRate; - dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz); - return; - } - - if(dwActFixes&128) - { - if (PSXDisplay.Interlaced) - fFrameRateHz = PSXDisplay.PAL?50.0f:60.0f; - else fFrameRateHz = PSXDisplay.PAL?25.0f:30.0f; - } - else - { - //fFrameRateHz = PSXDisplay.PAL?50.0f:59.94f; - - if(PSXDisplay.PAL) - { - if (STATUSREG&GPUSTATUS_INTERLACED) - fFrameRateHz=33868800.0f/677343.75f; // 50.00238 - else fFrameRateHz=33868800.0f/680595.00f; // 49.76351 - } - else - { - if (STATUSREG&GPUSTATUS_INTERLACED) - fFrameRateHz=33868800.0f/565031.25f; // 59.94146 - else fFrameRateHz=33868800.0f/566107.50f; // 59.82750 - } - - dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz); - } -} - -void SetFrameRateConfig(void) -{ - if(!fFrameRate) fFrameRate=200.0f; - - if(fFrameRateHz==0) - { - if(iFrameLimit==2) fFrameRateHz=59.94f; // auto framerate? set some init val (no pal/ntsc known yet) - else fFrameRateHz=fFrameRate; // else set user framerate - } - - dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz); - - if(iFrameLimit==2) SetAutoFrameCap(); -} - -void InitFrameCap(void) -{ -} - -void ReInitFrameCap(void) -{ -} - -void CheckFrameRate(void) // called in updatelace (on every emulated psx vsync) -{ - if(bUseFrameSkip) - { - if(!(dwActFixes&0x100)) - { - dwLaceCnt++; // -> and store cnt of vsync between frames - if(dwLaceCnt>=MAXLACE && bUseFrameLimit) - { - if(dwLaceCnt==MAXLACE) bInitCap=TRUE; - FrameCap(); - } - } - else if(bUseFrameLimit) FrameCap(); - calcfps(); // -> calc fps display in skipping mode - } - else // -> non-skipping mode: - { - if(bUseFrameLimit) FrameCap(); - if(ulKeybits&KEY_SHOWFPS) calcfps(); - } -} - -#if 0 /* unused by pcsx */ -void CALLBACK GPUsetframelimit(unsigned long option) // new EPSXE interface func: main emu can enable/disable fps limitation this way -{ - bInitCap = TRUE; - - if(option==1) // emu says: limit - { - bUseFrameLimit=TRUE;bUseFrameSkip=FALSE;iFrameLimit=2; - SetAutoFrameCap(); - } - else // emu says: no limit - { - bUseFrameLimit=FALSE; - } -} -#endif +/*************************************************************************** + fps.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_FPS + +#include "externals.h" + +//////////////////////////////////////////////////////////////////////// +// FPS stuff +//////////////////////////////////////////////////////////////////////// + +BOOL bIsPerformanceCounter=FALSE; +float fFrameRateHz=0; +DWORD dwFrameRateTicks=16; +float fFrameRate; +int iFrameLimit; +BOOL bUseFrameLimit=FALSE; +BOOL bUseFrameSkip=0; +DWORD dwLaceCnt=0; + +//////////////////////////////////////////////////////////////////////// +// FPS skipping / limit +//////////////////////////////////////////////////////////////////////// + +BOOL bInitCap = TRUE; +float fps_skip = 0; +float fps_cur = 0; + +#define TIMEBASE 100000 + +unsigned long timeGetTime() +{ + struct timeval tv; + gettimeofday(&tv, 0); // well, maybe there are better ways + return tv.tv_sec * 100000 + tv.tv_usec/10; // to do that in linux, but at least it works +} + +void FrameCap(void) +{ + static unsigned long curticks, lastticks, _ticks_since_last_update; + static unsigned long TicksToWait = 0; + bool Waiting = TRUE; + + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + + if((_ticks_since_last_update > TicksToWait) || + (curticks dwFrameRateTicks) + TicksToWait=0; + else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait); + } + else + { + while (Waiting) + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + Waiting = FALSE; + lastticks = curticks; + TicksToWait = dwFrameRateTicks; + } + } + } + } +} + +#define MAXSKIP 120 +#define MAXLACE 16 + +void FrameSkip(void) +{ + static int iNumSkips=0,iAdditionalSkip=0; // number of additional frames to skip + static DWORD dwLastLace=0; // helper var for frame limitation + static DWORD curticks, lastticks, _ticks_since_last_update; + + if(!dwLaceCnt) return; // important: if no updatelace happened, we ignore it completely + + if(iNumSkips) // we are in skipping mode? + { + dwLastLace+=dwLaceCnt; // -> calc frame limit helper (number of laces) + bSkipNextFrame = TRUE; // -> we skip next frame + iNumSkips--; // -> ok, one done + } + else // ok, no additional skipping has to be done... + { // we check now, if some limitation is needed, or a new skipping has to get started + DWORD dwWaitTime; + + if(bInitCap || bSkipNextFrame) // first time or we skipped before? + { + if(bUseFrameLimit && !bInitCap) // frame limit wanted and not first time called? + { + DWORD dwT=_ticks_since_last_update; // -> that's the time of the last drawn frame + dwLastLace+=dwLaceCnt; // -> and that's the number of updatelace since the start of the last drawn frame + + curticks = timeGetTime(); + _ticks_since_last_update= dwT+curticks - lastticks; + + dwWaitTime=dwLastLace*dwFrameRateTicks; // -> and now we calc the time the real psx would have needed + + if(_ticks_since_last_update we were too fast? + { + if((dwWaitTime-_ticks_since_last_update)> // -> some more security, to prevent + (60*dwFrameRateTicks)) // wrong waiting times + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_update loop until we have reached the real psx time + { // (that's the additional limitation, yup) + curticks = timeGetTime(); + _ticks_since_last_update = dwT+curticks - lastticks; + } + } + else // we were still too slow ?!!? + { + if(iAdditionalSkip well, somewhen we really have to stop skipping on very slow systems + { + iAdditionalSkip++; // -> inc our watchdog var + dwLaceCnt=0; // -> reset lace count + lastticks = timeGetTime(); + return; // -> done, we will skip next frame to get more speed + } + } + } + + bInitCap=FALSE; // -> ok, we have inited the frameskip func + iAdditionalSkip=0; // -> init additional skip + bSkipNextFrame=FALSE; // -> we don't skip the next frame + lastticks = timeGetTime(); + dwLaceCnt=0; // -> and we start to count the laces + dwLastLace=0; + _ticks_since_last_update=0; + return; // -> done, the next frame will get drawn + } + + bSkipNextFrame=FALSE; // init the frame skip signal to 'no skipping' first + + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + + dwLastLace=dwLaceCnt; // store curr count (frame limitation helper) + dwWaitTime=dwLaceCnt*dwFrameRateTicks; // calc the 'real psx lace time' + + if(_ticks_since_last_update>dwWaitTime) // hey, we needed way too long for that frame... + { + if(bUseFrameLimit) // if limitation, we skip just next frame, + { // and decide after, if we need to do more + iNumSkips=0; + } + else + { + iNumSkips=_ticks_since_last_update/dwWaitTime; // -> calc number of frames to skip to catch up + iNumSkips--; // -> since we already skip next frame, one down + if(iNumSkips>MAXSKIP) iNumSkips=MAXSKIP; // -> well, somewhere we have to draw a line + } + bSkipNextFrame = TRUE; // -> signal for skipping the next frame + } + else // we were faster than real psx? fine :) + if(bUseFrameLimit) // frame limit used? so we wait til the 'real psx time' has been reached + { + if(dwLaceCnt>MAXLACE) // -> security check + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_updatefFrameRateHz) // optical adjust ;) avoids flickering fps display + fps_cur=fFrameRateHz; + } +} + +void PCFrameCap (void) +{ + static unsigned long curticks, lastticks, _ticks_since_last_update; + static unsigned long TicksToWait = 0; + bool Waiting = TRUE; + + while (Waiting) + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + Waiting = FALSE; + lastticks = curticks; + TicksToWait = (TIMEBASE / (unsigned long)fFrameRateHz); + } + } +} + +void PCcalcfps(void) +{ + static unsigned long curticks,_ticks_since_last_update,lastticks; + static long fps_cnt = 0; + static float fps_acc = 0; + float CurrentFPS=0; + + curticks = timeGetTime(); + _ticks_since_last_update=curticks-lastticks; + if(_ticks_since_last_update) + CurrentFPS=(float)TIMEBASE/(float)_ticks_since_last_update; + else CurrentFPS = 0; + lastticks = curticks; + + fps_acc += CurrentFPS; + + if(++fps_cnt==10) + { + fps_cur = fps_acc / 10; + fps_acc = 0; + fps_cnt = 0; + } + + fps_skip=CurrentFPS+1.0f; +} + +void SetAutoFrameCap(void) +{ + if(iFrameLimit==1) + { + fFrameRateHz = fFrameRate; + dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz); + return; + } + + if(dwActFixes&128) + { + if (PSXDisplay.Interlaced) + fFrameRateHz = PSXDisplay.PAL?50.0f:60.0f; + else fFrameRateHz = PSXDisplay.PAL?25.0f:30.0f; + } + else + { + //fFrameRateHz = PSXDisplay.PAL?50.0f:59.94f; + + if(PSXDisplay.PAL) + { + if (STATUSREG&GPUSTATUS_INTERLACED) + fFrameRateHz=33868800.0f/677343.75f; // 50.00238 + else fFrameRateHz=33868800.0f/680595.00f; // 49.76351 + } + else + { + if (STATUSREG&GPUSTATUS_INTERLACED) + fFrameRateHz=33868800.0f/565031.25f; // 59.94146 + else fFrameRateHz=33868800.0f/566107.50f; // 59.82750 + } + + dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz); + } +} + +void SetFrameRateConfig(void) +{ + if(!fFrameRate) fFrameRate=200.0f; + + if(fFrameRateHz==0) + { + if(iFrameLimit==2) fFrameRateHz=59.94f; // auto framerate? set some init val (no pal/ntsc known yet) + else fFrameRateHz=fFrameRate; // else set user framerate + } + + dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz); + + if(iFrameLimit==2) SetAutoFrameCap(); +} + +void InitFrameCap(void) +{ +} + +void ReInitFrameCap(void) +{ +} + +void CheckFrameRate(void) // called in updatelace (on every emulated psx vsync) +{ + if(bUseFrameSkip) + { + if(!(dwActFixes&0x100)) + { + dwLaceCnt++; // -> and store cnt of vsync between frames + if(dwLaceCnt>=MAXLACE && bUseFrameLimit) + { + if(dwLaceCnt==MAXLACE) bInitCap=TRUE; + FrameCap(); + } + } + else if(bUseFrameLimit) FrameCap(); + calcfps(); // -> calc fps display in skipping mode + } + else // -> non-skipping mode: + { + if(bUseFrameLimit) FrameCap(); + if(ulKeybits&KEY_SHOWFPS) calcfps(); + } +} + +void CALLBACK GPUsetframelimit(unsigned long option) // new EPSXE interface func: main emu can enable/disable fps limitation this way +{ + bInitCap = TRUE; + + if(option==1) // emu says: limit + { + bUseFrameLimit=TRUE;bUseFrameSkip=FALSE;iFrameLimit=2; + SetAutoFrameCap(); + } + else // emu says: no limit + { + bUseFrameLimit=FALSE; + } +} diff --git a/plugins/peopsxgl/gpu.c b/plugins/peopsxgl/gpu.c index 092d32a5..f379372b 100644 --- a/plugins/peopsxgl/gpu.c +++ b/plugins/peopsxgl/gpu.c @@ -1,3527 +1,3529 @@ -/*************************************************************************** - gpu.c - description - ------------------- - begin : Sun Mar 08 2009 - copyright : (C) 1999-2009 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. * - * * - ***************************************************************************/ - -// !!! enable this, if Linux XF86VidMode is not supported: -//#define NOVMODE - -#include "stdafx.h" - -#if !defined(_MACGL) && !defined(_WINDOWS) - -#include "config.h" - -#ifndef NOVMODE -#include -static XF86VidModeModeInfo **modes=0; -static int iOldMode=0; -#endif - -#endif - -#define _IN_GPU - -#include "externals.h" -#include "psemu_plugin_defs.h" -#include "gpu.h" -#include "draw.h" -#include "cfg.h" -#include "prim.h" -#include "psemu_plugin_defs.h" -#include "texture.h" -#include "menu.h" -#include "fps.h" -#include "key.h" -#ifdef _WINDOWS -#include "resource.h" -#include "ssave.h" -#endif - -//////////////////////////////////////////////////////////////////////// -// PPDK developer must change libraryName field and can change revision and build -//////////////////////////////////////////////////////////////////////// - -const unsigned char version = 1; // do not touch - library for PSEmu 1.x -const unsigned char revision = 1; -const unsigned char build = 78; - -static char *libraryName = N_("OpenGL Driver"); - -static char *PluginAuthor = N_("Pete Bernert"); -#if 0 -static char *libraryInfo = N_("Based on P.E.Op.S. MesaGL Driver V1.78\nCoded by Pete Bernert\n"); -#endif - -//////////////////////////////////////////////////////////////////////// -// memory image of the PSX vram -//////////////////////////////////////////////////////////////////////// - -unsigned char *psxVSecure; -unsigned char *psxVub; -signed char *psxVsb; -unsigned short *psxVuw; -unsigned short *psxVuw_eom; -signed short *psxVsw; -uint32_t *psxVul; -signed int *psxVsl; - -// macro for easy access to packet information -#define GPUCOMMAND(x) ((x>>24) & 0xff) - -GLfloat gl_z=0.0f; -BOOL bNeedInterlaceUpdate=FALSE; -BOOL bNeedRGB24Update=FALSE; -BOOL bChangeWinMode=FALSE; - -uint32_t ulStatusControl[256]; - -//////////////////////////////////////////////////////////////////////// -// global GPU vars -//////////////////////////////////////////////////////////////////////// - -static int GPUdataRet; -int lGPUstatusRet; -char szDispBuf[64]; - -uint32_t dwGPUVersion = 0; -int iGPUHeight = 512; -int iGPUHeightMask = 511; -int GlobalTextIL = 0; -int iTileCheat = 0; - -static uint32_t gpuDataM[256]; -static unsigned char gpuCommand = 0; -static int gpuDataC = 0; -static int gpuDataP = 0; - -VRAMLoad_t VRAMWrite; -VRAMLoad_t VRAMRead; -int iDataWriteMode; -int iDataReadMode; - -int lClearOnSwap; -int lClearOnSwapColor; -BOOL bSkipNextFrame = FALSE; -int iColDepth; -BOOL bChangeRes; -BOOL bWindowMode; -int iWinSize; - -// possible psx display widths -short dispWidths[8] = {256,320,512,640,368,384,512,640}; - -PSXDisplay_t PSXDisplay; -PSXDisplay_t PreviousPSXDisplay; -TWin_t TWin; -short imageX0,imageX1; -short imageY0,imageY1; -BOOL bDisplayNotSet = TRUE; -GLuint uiScanLine=0; -int iUseScanLines=0; -float iScanlineColor[] = {0,0,0, 0.3}; // easy on the eyes. -int lSelectedSlot=0; -unsigned char * pGfxCardScreen=0; -int iBlurBuffer=0; -int iScanBlend=0; -int iRenderFVR=0; -int iNoScreenSaver=0; -uint32_t ulGPUInfoVals[16]; -int iFakePrimBusy = 0; -int iRumbleVal = 0; -int iRumbleTime = 0; -uint32_t vBlank=0; - -//////////////////////////////////////////////////////////////////////// -// stuff to make this a true PDK module -//////////////////////////////////////////////////////////////////////// - -char * CALLBACK PSEgetLibName(void) -{ - return _(libraryName); -} - -unsigned long CALLBACK PSEgetLibType(void) -{ - return PSE_LT_GPU; -} - -unsigned long CALLBACK PSEgetLibVersion(void) -{ - return version<<16|revision<<8|build; -} - -#if 0 -char * GPUgetLibInfos(void) -{ - return _(libraryInfo); -} -#endif - -//////////////////////////////////////////////////////////////////////// -// snapshot funcs (saves screen to bitmap / text infos into file) -//////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS -static char * GetConfigInfos(HWND hW) -#else -static char * GetConfigInfos(int hW) -#endif -{ -#ifdef _WINDOWS - HDC hdc;HGLRC hglrc; -#endif - 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 (mod)\r\n",libraryName,version,revision,build); - strcat(pB,szTxt); - sprintf(szTxt,"Author: %s\r\n",PluginAuthor); - strcat(pB,szTxt); - -#ifdef _WINDOWS - if(hW) - { - hdc = GetDC(hW); - bSetupPixelFormat(hdc); - hglrc = wglCreateContext(hdc); - wglMakeCurrent(hdc, hglrc); - } -#endif - - sprintf(szTxt,"Card vendor: %s\r\n",(char *)glGetString(GL_VENDOR)); - strcat(pB,szTxt); - sprintf(szTxt,"GFX card: %s\r\n",(char *)glGetString(GL_RENDERER)); - strcat(pB,szTxt); - sprintf(szTxt,"OGL version: %s\r\n\r\n",(char *)glGetString(GL_VERSION)); - strcat(pB,szTxt); - //strcat(pB,(char *)glGetString(GL_EXTENSIONS)); - //strcat(pB,"\r\n\r\n"); - -#ifdef _WINDOWS - if(hW) - { - wglMakeCurrent(NULL, NULL); - wglDeleteContext(hglrc); - ReleaseDC(hW,hdc); - } - //----------------------------------------------------// -#endif - - if(hW && bWindowMode) - sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize)); - else - sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY); - strcat(pB,szTxt); - if(bWindowMode) sprintf(szTxt,"Window mode\r\n"); - else - { - sprintf(szTxt,"Fullscreen "); - strcat(pB,szTxt); - if(bChangeRes) sprintf(szTxt,"- Desktop changing [%d Bit]\r\n",iColDepth); - else sprintf(szTxt,"- NO desktop changing\r\n"); - } - strcat(pB,szTxt); - - if(iForceVSync>=0) sprintf(szTxt,"- V-Sync: %s\r\n",szO[iForceVSync]); - else strcpy(szTxt,"- V-Sync: Driver\r\n"); - strcat(pB,szTxt); - sprintf(szTxt,"- Keep psx aspect ratio: %s\r\n\r\n",szO[bKeepRatio]); - strcat(pB,szTxt); - //----------------------------------------------------// - strcpy(szTxt,"Textures:\r\n- "); - if(iTexQuality==0) strcat(szTxt,"Default"); - else if(iTexQuality==1) strcat(szTxt,"R4G4B4A4"); - else if(iTexQuality==2) strcat(szTxt,"R5G5B5A1"); - else if(iTexQuality==3) strcat(szTxt,"R8G8A8A8"); - else if(iTexQuality==4) strcat(szTxt,"B8G8R8A8"); - if(!hW && bGLExt) strcat(szTxt," (packed pixels)\r\n"); - else strcat(szTxt,"\r\n"); - strcat(pB,szTxt); - if(!hW) - { - sprintf(szTxt,"- Filtering: %d - edge clamping ",iFilterType); - if(iClampType==GL_TO_EDGE_CLAMP) strcat(szTxt,"supported\r\n"); - else strcat(szTxt,"NOT supported\r\n"); - } - else sprintf(szTxt,"- iFiltering: %d\r\n",iFilterType); - strcat(pB,szTxt); - sprintf(szTxt,"- Hi-Res textures: %d\r\n",iHiResTextures); - strcat(pB,szTxt); - if(!hW) - { - sprintf(szTxt,"- Palettized tex windows: %s\r\n",szO[iUsePalTextures]); - strcat(pB,szTxt); - } - sprintf(szTxt,"- VRam size: %d MBytes",iVRamSize); - if(!hW) - sprintf(szTxt+strlen(szTxt)," - %d textures usable\r\n\r\n",iSortTexCnt); - else strcat(szTxt,"\r\n\r\n"); - strcat(pB,szTxt); - //----------------------------------------------------// - sprintf(szTxt,"Framerate:\r\n- FPS limitation: %s\r\n",szO[bUseFrameLimit]); - strcat(pB,szTxt); - sprintf(szTxt,"- Frame skipping: %s\r\n",szO[bUseFrameSkip]); - strcat(pB,szTxt); - 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); - //----------------------------------------------------// - sprintf(szTxt,"Compatibility:\r\n- Offscreen drawing: %d\r\n",iOffscreenDrawing); - strcat(pB,szTxt); - sprintf(szTxt,"- Framebuffer texture: %d",iFrameTexType); - if(!hW && iFrameTexType==2) - { - if(gTexFrameName) strcat(szTxt," - texture created\r\n"); - else strcat(szTxt," - not used yet\r\n"); - } - else strcat(szTxt,"\r\n"); - strcat(pB,szTxt); - sprintf(szTxt,"- Framebuffer access: %d\r\n",iFrameReadType); - strcat(pB,szTxt); - sprintf(szTxt,"- Alpha multipass: %s\r\n",szO[bOpaquePass]); - strcat(pB,szTxt); - sprintf(szTxt,"- Mask bit: %s\r\n",szO[iUseMask]); - strcat(pB,szTxt); - sprintf(szTxt,"- Advanced blending: %s",szO[bAdvancedBlend]); - if(!hW && bAdvancedBlend) - { - if(bGLBlend) strcat(szTxt," (hardware)\r\n"); - else strcat(szTxt," (software)\r\n"); - } - else strcat(szTxt,"\r\n"); - strcat(pB,szTxt); - - if(!hW) - { - strcpy(szTxt,"- Subtractive blending: "); - if(glBlendEquationEXTEx) - { - if(bUseMultiPass) strcat(szTxt,"supported, but not used!"); - else strcat(szTxt,"activated"); - } - else strcat(szTxt," NOT supported!"); - strcat(szTxt,"\r\n\r\n"); - } - else strcpy(szTxt,"\r\n"); - - strcat(pB,szTxt); - //----------------------------------------------------// - sprintf(szTxt,"Misc:\r\n- Scanlines: %s",szO[iUseScanLines]); - strcat(pB,szTxt); - if(iUseScanLines) sprintf(szTxt," [%d]\r\n",iScanBlend); - else strcpy(szTxt,"\r\n"); - strcat(pB,szTxt); - sprintf(szTxt,"- Line mode: %s\r\n",szO[bUseLines]); - strcat(pB,szTxt); -// sprintf(szTxt,"- Line AA: %s\r\n",szO[bUseAntiAlias]); -// fwrite(szTxt,lstrlen(szTxt),1,txtfile); - sprintf(szTxt,"- Unfiltered FB: %s\r\n",szO[bUseFastMdec]); - strcat(pB,szTxt); - sprintf(szTxt,"- 15 bit FB: %s\r\n",szO[bUse15bitMdec]); - strcat(pB,szTxt); - sprintf(szTxt,"- Dithering: %s\r\n",szO[bDrawDither]); - strcat(pB,szTxt); - sprintf(szTxt,"- Screen smoothing: %s",szO[iBlurBuffer]); - strcat(pB,szTxt); - if(!hW && iBlurBuffer) - { - if(gTexBlurName) strcat(pB," - supported\r\n"); - else strcat(pB," - not supported\r\n"); - } - else strcat(pB,"\r\n"); - sprintf(szTxt,"- Game fixes: %s [%08x]\r\n",szO[bUseFixes],dwCfgFixes); - strcat(pB,szTxt); - //----------------------------------------------------// - return pB; -} - -//////////////////////////////////////////////////////////////////////// -// save text infos to file -//////////////////////////////////////////////////////////////////////// - -static void DoTextSnapShot(int iNum) -{ - FILE *txtfile;char szTxt[256];char * pB; - -#ifdef _WINDOWS - sprintf(szTxt,"snap\\pcsx%04d.txt",iNum); -#else - sprintf(szTxt,"%s/pcsx%04d.txt",getenv("HOME"),iNum); -#endif - - if((txtfile=fopen(szTxt,"wb"))==NULL) - return; - - pB=GetConfigInfos(0); - if(pB) - { - if(fwrite(pB,strlen(pB),1,txtfile) != 1) { - free(pB); - fclose(txtfile); - remove(szTxt); - return; - } - free(pB); - } - fclose(txtfile); -} - -//////////////////////////////////////////////////////////////////////// -// saves screen bitmap to file -//////////////////////////////////////////////////////////////////////// - -void DoSnapShot(void) -{ - unsigned char * snapshotdumpmem=NULL,* p,c; - FILE *bmpfile;char filename[256]; - unsigned char header[0x36];int size; - unsigned char empty[2]={0,0};int i; - unsigned int snapshotnr = 0; - short SnapWidth; - short SnapHeigth; - - bSnapShot=FALSE; - - SnapWidth = iResX; - SnapHeigth = iResY; - - size=SnapWidth * SnapHeigth * 3 + 0x38; - - if((snapshotdumpmem=(unsigned char *) - malloc(SnapWidth*SnapHeigth*3))==NULL) - return; - - // fill in proper values for BMP - for(i=0;i<0x36;i++) header[i]=0; - header[0]='B'; - header[1]='M'; - header[2]=(unsigned char)(size&0xff); - header[3]=(unsigned char)((size>>8)&0xff); - header[4]=(unsigned char)((size>>16)&0xff); - header[5]=(unsigned char)((size>>24)&0xff); - header[0x0a]=0x36; - header[0x0e]=0x28; - header[0x12]=(unsigned char)(SnapWidth%256); - header[0x13]=(unsigned char)(SnapWidth/256); - header[0x16]=(unsigned char)(SnapHeigth%256); - header[0x17]=(unsigned char)(SnapHeigth/256); - header[0x1a]=0x01; - header[0x1c]=0x18; - header[0x26]=0x12; - header[0x27]=0x0B; - header[0x2A]=0x12; - header[0x2B]=0x0B; - - // increment snapshot value - // get filename - do - { - snapshotnr++; -#ifdef _WINDOWS - sprintf(filename,"snap/pcsx%04d.bmp",snapshotnr); -#else - sprintf(filename,"%s/pcsx%04d.bmp",getenv("HOME"),snapshotnr); -#endif - bmpfile=fopen(filename,"rb"); - if(bmpfile==NULL)break; - fclose(bmpfile); - if(snapshotnr==9999) break; - } - while(TRUE); - - // try opening new snapshot file - if((bmpfile=fopen(filename,"wb"))==NULL) - {free(snapshotdumpmem);return;} - - if(fwrite(header,0x36,1,bmpfile) != 1) { - free(snapshotdumpmem); - fclose(bmpfile); - remove(filename); - return; - } - - glReadPixels(0,0,SnapWidth,SnapHeigth,GL_RGB, - GL_UNSIGNED_BYTE,snapshotdumpmem); - p=snapshotdumpmem; - size=SnapWidth * SnapHeigth; - - for(i=0;i get sizes again - } - else // first real startup - { - ReadConfig(); // -> read config from registry - - SetFrameRateConfig(); // -> setup frame rate stuff - } - - if(iNoScreenSaver) EnableScreenSaver(FALSE); // at least we can try - - - memset(&dv,0,sizeof(DEVMODE)); - dv.dmSize=sizeof(DEVMODE); - EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dv); - - bIsFirstFrame = TRUE; // flag: we have to init OGL later in windows! - - if(bWindowMode) // win mode? - { - DWORD dw=GetWindowLong(hWWindow, GWL_STYLE); // -> adjust wnd style (owndc needed by some stupid ogl drivers) - dw&=~WS_THICKFRAME; - dw|=WS_BORDER|WS_CAPTION|CS_OWNDC; - SetWindowLong(hWWindow, GWL_STYLE, dw); - - hPSEMenu=GetMenu(hWWindow); // -> hide emu menu (if any) - if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL); - - iResX=LOWORD(iWinSize);iResY=HIWORD(iWinSize); - ShowWindow(hWWindow,SW_SHOWNORMAL); - - MoveWindow(hWWindow, // -> center wnd - GetSystemMetrics(SM_CXFULLSCREEN)/2-iResX/2, - GetSystemMetrics(SM_CYFULLSCREEN)/2-iResY/2, - iResX+GetSystemMetrics(SM_CXFIXEDFRAME)+3, - iResY+GetSystemMetrics(SM_CYFIXEDFRAME)+GetSystemMetrics(SM_CYCAPTION)+3, - TRUE); - UpdateWindow(hWWindow); // -> let windows do some update - - if(dv.dmBitsPerPel==16 || dv.dmBitsPerPel==32) // -> overwrite user color info with desktop color info - iColDepth=dv.dmBitsPerPel; - } - else // fullscreen mode: - { - if(dv.dmBitsPerPel!=(unsigned int)iColDepth || // -> check, if we have to change resolution - dv.dmPelsWidth !=(unsigned int)iResX || - dv.dmPelsHeight!=(unsigned int)iResY) - bChangeRes=TRUE; else bChangeRes=FALSE; - - if(bChangeRes) ChangeDesktop(); // -> change the res (had to do an own func because of some MS 'optimizations') - - SetWindowLong(hWWindow, GWL_STYLE, CS_OWNDC); // -> adjust wnd style as well (to be sure) - - hPSEMenu=GetMenu(hWWindow); // -> hide menu - if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL); - ShowWindow(hWWindow,SW_SHOWMAXIMIZED); // -> max mode - } - - rRatioRect.left = rRatioRect.top=0; - rRatioRect.right = iResX; - rRatioRect.bottom = iResY; - - r.left=r.top=0;r.right=iResX;r.bottom=iResY; // hack for getting a clean black window until OGL gets initialized - hdc = GetDC(hWWindow); - FillRect(hdc,&r,(HBRUSH)GetStockObject(BLACK_BRUSH)); - bSetupPixelFormat(hdc); - ReleaseDC(hWWindow,hdc); - - bDisplayNotSet = TRUE; - bSetClip=TRUE; - - SetFixes(); // setup game fixes - - InitializeTextureStore(); // init texture mem - -// lGPUstatusRet = 0x74000000; - -// with some emus, we could do the OGL init right here... oh my -// if(bIsFirstFrame) GLinitialize(); - - return 0; -} - -#elif !defined (_MACGL) - -//////////////////////////////////////////////////////////////////////// -// LINUX GPU OPEN: func to open up the gpu display (X stuff) -// please note: in linux we are creating our own display, and we return -// the display ID to the main emu... that's cleaner -//////////////////////////////////////////////////////////////////////// - -char * pCaptionText=0; -int bFullScreen=0; -Display *display; - -static Cursor cursor; -static XVisualInfo *myvisual; -static Colormap colormap; -static Window window; - -static int bModeChanged=0; - -typedef struct -{ -#define MWM_HINTS_DECORATIONS 2 - long flags; - long functions; - long decorations; - long input_mode; -} MotifWmHints; - -static int dbdepat[]={GLX_RGBA,GLX_DOUBLEBUFFER,GLX_DEPTH_SIZE,16,None}; -static int dbnodepat[]={GLX_RGBA,GLX_DOUBLEBUFFER,None}; -static GLXContext cx; - -static int fx=0; - -//////////////////////////////////////////////////////////////////////// - -static void osd_close_display (void) // close display -{ - if(display) // display exists? - { - glXDestroyContext(display,cx); // -> kill context - XFreeColormap(display, colormap); // -> kill colormap - XSync(display,False); // -> sync events - -#ifndef NOVMODE - if(bModeChanged) // -> repair screen mode - { - int myscreen=DefaultScreen(display); - XF86VidModeSwitchToMode(display,myscreen, // --> switch mode back - modes[iOldMode]); - XF86VidModeSetViewPort(display,myscreen,0,0); // --> set viewport upperleft - free(modes); // --> finally kill mode infos - bModeChanged=0; // --> done - } -#endif - - XCloseDisplay(display); // -> close display - } -} - -//////////////////////////////////////////////////////////////////////// - -static void sysdep_create_display(void) // create display -{ - XSetWindowAttributes winattr;float fxgamma=2; - int myscreen;char gammastr[14]; - Screen * screen;XEvent event; - XSizeHints hints;XWMHints wm_hints; - MotifWmHints mwmhints;Atom mwmatom;Atom delwindow; - char *glxfx; - - glxfx=getenv("MESA_GLX_FX"); // 3dfx mesa fullscreen flag - if(glxfx) - { - if(glxfx[0]=='f') // -> yup, fullscreen needed - { - fx=1; // -> raise flag - putenv("FX_GLIDE_NO_SPLASH="); - sprintf(gammastr,"SST_GAMMA=%2.1f",fxgamma); // -> set gamma - putenv(gammastr); - } - } - - display=XOpenDisplay(NULL); // open display - if(!display) // no display? - { - fprintf (stderr,"Failed to open display!!!\n"); - osd_close_display(); - return; // -> bye - } - - myscreen=DefaultScreen(display); // get screen id - -#ifdef NOVMODE - if(bFullScreen) {fx=1;bModeChanged=0;} -#else - if(bFullScreen) - { - XF86VidModeModeLine mode; - int nmodes,iC; - fx=1; // raise flag - XF86VidModeGetModeLine(display,myscreen,&iC,&mode); // get actual mode info - if(mode.privsize) XFree(mode.private); // no need for private stuff - bModeChanged=0; // init mode change flag - if(iResX!=mode.hdisplay || iResY!=mode.vdisplay) // wanted mode is different? - { - XF86VidModeGetAllModeLines(display,myscreen, // -> enum all mode infos - &nmodes,&modes); - if(modes) // -> infos got? - { - for(iC=0;iC loop modes - { - if(mode.hdisplay==modes[iC]->hdisplay && // -> act mode found? - mode.vdisplay==modes[iC]->vdisplay) // if yes: store mode id - iOldMode=iC; - - if(iResX==modes[iC]->hdisplay && // -> wanted mode found? - iResY==modes[iC]->vdisplay) - { - XF86VidModeSwitchToMode(display,myscreen, // --> switch to mode - modes[iC]); - XF86VidModeSetViewPort(display,myscreen,0,0); - bModeChanged=1; // --> raise flag for repairing mode on close - } - } - - if(bModeChanged==0) // -> no mode found? - { - free(modes); // --> free infos - printf("No proper fullscreen mode found!\n"); // --> some info output - } - } - } - } -#endif - - screen=DefaultScreenOfDisplay(display); - - if(iZBufferDepth) // visual (with or without zbuffer) - myvisual=glXChooseVisual(display,myscreen,dbdepat); - else myvisual=glXChooseVisual(display,myscreen,dbnodepat); - - if(!myvisual) // no visual? - { - fprintf(stderr,"Failed to obtain visual!!!\n"); // -> bye - osd_close_display(); - return; - } - - cx=glXCreateContext(display,myvisual,0,GL_TRUE); // create rendering context - - if(!cx) // no context? - { - fprintf(stderr,"Failed to create OpenGL context!!!\n"); - osd_close_display(); // -> bxe - return; - } - - // pffff... much work for a simple blank cursor... oh, well... - if(!bFullScreen) cursor=XCreateFontCursor(display,XC_trek); - else - { - Pixmap p1,p2;XImage * img; - XColor b,w;unsigned char * idata; - XGCValues GCv; - GC GCc; - - memset(&b,0,sizeof(XColor)); - memset(&w,0,sizeof(XColor)); - idata=(unsigned char *)malloc(8); - memset(idata,0,8); - - p1=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1); - p2=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1); - - img = XCreateImage(display,myvisual->visual, - 1,XYBitmap,0,(char *)idata,8,8,8,1); - - GCv.function = GXcopy; - GCv.foreground = ~0; - GCv.background = 0; - GCv.plane_mask = AllPlanes; - GCc = XCreateGC(display,p1, - (GCFunction|GCForeground|GCBackground|GCPlaneMask),&GCv); - - XPutImage(display, p1,GCc,img,0,0,0,0,8,8); - XPutImage(display, p2,GCc,img,0,0,0,0,8,8); - XFreeGC(display, GCc); - - cursor = XCreatePixmapCursor(display,p1,p2,&b,&w,0,0); - - XFreePixmap(display,p1); - XFreePixmap(display,p2); - XDestroyImage(img); // will free idata as well - } - - colormap=XCreateColormap(display, // create colormap - RootWindow(display,myvisual->screen), - myvisual->visual,AllocNone); - - winattr.background_pixel=0; - 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=colormap; - winattr.cursor=None; - - window=XCreateWindow(display, // create own window - RootWindow(display,DefaultScreen(display)), - 0,0,iResX,iResY, - 0,myvisual->depth, - InputOutput,myvisual->visual, - CWBorderPixel | CWBackPixel | - CWEventMask | CWDontPropagate | - CWColormap | CWCursor, - &winattr); - - if(!window) // no window? - { - fprintf(stderr,"Failed in XCreateWindow()!!!\n"); - osd_close_display(); // -> bye - return; - } - - delwindow = XInternAtom(display,"WM_DELETE_WINDOW",0); - XSetWMProtocols(display, window, &delwindow, 1); - - hints.flags=PMinSize|PMaxSize; // hints - if(fx) hints.flags|=USPosition|USSize; - else hints.flags|=PSize; - - hints.min_width = hints.max_width = hints.base_width = iResX; - hints.min_height = hints.max_height = hints.base_height = iResY; - - wm_hints.input=1; - wm_hints.flags=InputHint; - - XSetWMHints(display,window,&wm_hints); - XSetWMNormalHints(display,window,&hints); - if(pCaptionText) // caption - XStoreName(display,window,pCaptionText); - else XStoreName(display,window,"Pete MesaGL PSX Gpu"); - - XDefineCursor(display,window,cursor); // cursor - - if(fx) // window title bar hack - { - mwmhints.flags=MWM_HINTS_DECORATIONS; - mwmhints.decorations=0; - mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0); - XChangeProperty(display,window,mwmatom,mwmatom,32, - PropModeReplace,(unsigned char *)&mwmhints,4); - } - - XSelectInput(display,window, // input setup - FocusChangeMask | ExposureMask | - KeyPressMask | KeyReleaseMask); - - XMapRaised(display,window); - XClearWindow(display,window); - XWindowEvent(display,window,ExposureMask,&event); - glXMakeCurrent(display,window,cx); - -/* - printf(glGetString(GL_VENDOR)); - printf("\n"); - printf(glGetString(GL_RENDERER)); - printf("\n"); -*/ - - if (fx) // after make current: fullscreen resize - { - 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); - - // 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(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, RootWindow(display, DefaultScreen(display)), 0, - SubstructureRedirectMask | SubstructureNotifyMask, &xev); - } - } -} - -#endif // !defined(_MACGL) - -#ifndef _WINDOWS - -#if defined(_MACGL) -extern char * pCaptionText; -#endif - -//////////////////////////////////////////////////////////////////////// - -long GPUopen(unsigned long * disp,char * CapText,char * CfgFile) -{ - pCaptionText=CapText; - pConfigFile=CfgFile; - - ReadConfig(); // read text file for config - - SetFrameRateConfig(); // setup frame rate stuff - - bIsFirstFrame = TRUE; // we have to init later (well, no really... in Linux we do all in GPUopen) - - #if defined (_MACGL) - unsigned long display = ulInitDisplay(); - #else - sysdep_create_display(); // create display - #endif - - InitializeTextureStore(); // init texture mem - - rRatioRect.left = rRatioRect.top=0; - rRatioRect.right = iResX; - rRatioRect.bottom = iResY; - - GLinitialize(); // init opengl - - if(disp) - { - *disp = display; - } - - if(display) return 0; - return -1; -} - -#endif // ndef _WINDOWS - - - -//////////////////////////////////////////////////////////////////////// -// close -//////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS - -long CALLBACK GPUclose() // WINDOWS CLOSE -{ - ExitKeyHandler(); - - GLcleanup(); // close OGL - - if(bChangeRes) // change res back - ChangeDisplaySettings(NULL,0); - - if(hPSEMenu) // set menu again - SetMenu(hWWindow,hPSEMenu); - - if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory - pGfxCardScreen=0; - - if(iNoScreenSaver) EnableScreenSaver(TRUE); // enable screen saver again - - return 0; -} - -#else - -long GPUclose() // LINUX CLOSE -{ - GLcleanup(); // close OGL - - if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory - pGfxCardScreen=0; - #if defined (_MACGL) - CloseDisplay(); - #else - osd_close_display(); // destroy display - #endif - return 0; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -// I shot the sheriff... last function called from emu -//////////////////////////////////////////////////////////////////////// - -long CALLBACK GPUshutdown() -{ - if(psxVSecure) free(psxVSecure); // kill emulated vram memory - psxVSecure=0; - - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// paint it black: simple func to clean up optical border garbage -//////////////////////////////////////////////////////////////////////// - -static void PaintBlackBorders(void) -{ - short s; - - glDisable(GL_SCISSOR_TEST); - if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;} - if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} - if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} - glDisable(GL_ALPHA_TEST); - - glBegin(GL_QUADS); - - vertex[0].c.lcol=0xff000000; - SETCOL(vertex[0]); - - if(PreviousPSXDisplay.Range.x0) - { - s=PreviousPSXDisplay.Range.x0+1; - glVertex3f(0,0,0.99996f); - glVertex3f(0,PSXDisplay.DisplayMode.y,0.99996f); - glVertex3f(s,PSXDisplay.DisplayMode.y,0.99996f); - glVertex3f(s,0,0.99996f); - - s+=PreviousPSXDisplay.Range.x1-2; - - glVertex3f(s,0,0.99996f); - glVertex3f(s,PSXDisplay.DisplayMode.y,0.99996f); - glVertex3f(PSXDisplay.DisplayMode.x,PSXDisplay.DisplayMode.y,0.99996f); - glVertex3f(PSXDisplay.DisplayMode.x,0,0.99996f); - } - - if(PreviousPSXDisplay.Range.y0) - { - s=PreviousPSXDisplay.Range.y0+1; - glVertex3f(0,0,0.99996f); - glVertex3f(0,s,0.99996f); - glVertex3f(PSXDisplay.DisplayMode.x,s,0.99996f); - glVertex3f(PSXDisplay.DisplayMode.x,0,0.99996f); - } - - glEnd(); - - glEnable(GL_ALPHA_TEST); - glEnable(GL_SCISSOR_TEST); -} - -//////////////////////////////////////////////////////////////////////// -// helper to draw scanlines -//////////////////////////////////////////////////////////////////////// - -static __inline void XPRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2, - OGLVertex* vertex3, OGLVertex* vertex4) -{ - - glBegin(GL_QUAD_STRIP); - glTexCoord2fv(&vertex1->sow); - glVertex3fv(&vertex1->x); - - glTexCoord2fv(&vertex2->sow); - glVertex3fv(&vertex2->x); - - glTexCoord2fv(&vertex4->sow); - glVertex3fv(&vertex4->x); - - glTexCoord2fv(&vertex3->sow); - glVertex3fv(&vertex3->x); - glEnd(); -} - -//////////////////////////////////////////////////////////////////////// -// scanlines -//////////////////////////////////////////////////////////////////////// - -static void SetScanLines(void) -{ - glLoadIdentity(); - glOrtho(0,iResX,iResY, 0, -1, 1); - - if(bKeepRatio) - glViewport(0,0,iResX,iResY); - - glDisable(GL_SCISSOR_TEST); - glDisable(GL_ALPHA_TEST); - if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} - - if(iScanBlend<0) // special texture mask scanline mode - { - if(!bTexEnabled) {glEnable(GL_TEXTURE_2D);bTexEnabled=TRUE;} - gTexName=gTexScanName; - glBindTexture(GL_TEXTURE_2D, gTexName); - if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - if(!bBlendEnable) {glEnable(GL_BLEND);bBlendEnable=TRUE;} - SetScanTexTrans(); - - vertex[0].x=0; - vertex[0].y=iResY; - vertex[0].z=0.99996f; - - vertex[1].x=iResX; - vertex[1].y=iResY; - vertex[1].z=0.99996f; - - vertex[2].x=iResX; - vertex[2].y=0; - vertex[2].z=0.99996f; - - vertex[3].x=0; - vertex[3].y=0; - vertex[3].z=0.99996f; - - vertex[0].sow=0; - vertex[0].tow=0; - vertex[1].sow=(float)iResX/4.0f; - vertex[1].tow=0; - vertex[2].sow=vertex[1].sow; - vertex[2].tow=(float)iResY/4.0f; - vertex[3].sow=0; - vertex[3].tow=vertex[2].tow; - - vertex[0].c.lcol=0xffffffff; - SETCOL(vertex[0]); - - XPRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - - if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT); - } - else // typical line mode - { - if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;} - - if(iScanBlend==0) - { - if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} - vertex[0].c.lcol=0xff000000; - } - else - { - if(!bBlendEnable) {glEnable(GL_BLEND);bBlendEnable=TRUE;} - SetScanTrans(); - vertex[0].c.lcol=iScanBlend<<24; - } - - SETCOL(vertex[0]); - - glCallList(uiScanLine); - } - - glLoadIdentity(); - glOrtho(0,PSXDisplay.DisplayMode.x, - PSXDisplay.DisplayMode.y, 0, -1, 1); - - if(bKeepRatio) - glViewport(rRatioRect.left, - iResY-(rRatioRect.top+rRatioRect.bottom), - rRatioRect.right, - rRatioRect.bottom); // init viewport - - glEnable(GL_ALPHA_TEST); - glEnable(GL_SCISSOR_TEST); -} - -//////////////////////////////////////////////////////////////////////// -// blur, babe, blur (heavy performance hit for a so-so fullscreen effect) -//////////////////////////////////////////////////////////////////////// - -static void BlurBackBuffer(void) -{ - if(!gTexBlurName) return; - - if(bKeepRatio) glViewport(0,0,iResX,iResY); - - glDisable(GL_SCISSOR_TEST); - glDisable(GL_ALPHA_TEST); - if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} - if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} - if(!bTexEnabled) {glEnable(GL_TEXTURE_2D);bTexEnabled=TRUE;} - if(iZBufferDepth) glDisable(GL_DEPTH_TEST); - if(bDrawDither) glDisable(GL_DITHER); - - gTexName=gTexBlurName; - glBindTexture(GL_TEXTURE_2D, gTexName); - - glCopyTexSubImage2D( GL_TEXTURE_2D, 0, // get back buffer in texture - 0, - 0, - 0, - 0, - iResX,iResY); - - vertex[0].x=0; - vertex[0].y=PSXDisplay.DisplayMode.y; - vertex[1].x=PSXDisplay.DisplayMode.x; - vertex[1].y=PSXDisplay.DisplayMode.y; - vertex[2].x=PSXDisplay.DisplayMode.x; - vertex[2].y=0; - vertex[3].x=0; - vertex[3].y=0; - vertex[0].sow=0; - vertex[0].tow=0; - -#ifdef OWNSCALE - vertex[1].sow=((GLfloat)iFTexA)/256.0f; - vertex[2].tow=((GLfloat)iFTexB)/256.0f; -#else - vertex[1].sow=iFTexA; - vertex[2].tow=iFTexB; -#endif - vertex[1].tow=0; - vertex[2].sow=vertex[1].sow; - vertex[3].sow=0; - vertex[3].tow=vertex[2].tow; - - if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - vertex[0].c.lcol=0x7fffffff; - SETCOL(vertex[0]); - - DrawMultiBlur(); // draw the backbuffer texture to create blur effect - - glEnable(GL_ALPHA_TEST); - glEnable(GL_SCISSOR_TEST); - if(iZBufferDepth) glEnable(GL_DEPTH_TEST); - if(bDrawDither) glEnable(GL_DITHER); - if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT); - - if(bKeepRatio) - glViewport(rRatioRect.left, // re-init viewport - iResY-(rRatioRect.top+rRatioRect.bottom), - rRatioRect.right, - rRatioRect.bottom); -} - -//////////////////////////////////////////////////////////////////////// -// "unblur" repairs the backbuffer after a blur - -static void UnBlurBackBuffer(void) -{ - if(!gTexBlurName) return; - - if(bKeepRatio) glViewport(0,0,iResX,iResY); - - glDisable(GL_SCISSOR_TEST); - glDisable(GL_ALPHA_TEST); - if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} - if(!bTexEnabled) {glEnable(GL_TEXTURE_2D);bTexEnabled=TRUE;} - if(iZBufferDepth) glDisable(GL_DEPTH_TEST); - if(bDrawDither) glDisable(GL_DITHER); - - gTexName=gTexBlurName; - glBindTexture(GL_TEXTURE_2D, gTexName); - - vertex[0].x=0; - vertex[0].y=PSXDisplay.DisplayMode.y; - vertex[1].x=PSXDisplay.DisplayMode.x; - vertex[1].y=PSXDisplay.DisplayMode.y; - vertex[2].x=PSXDisplay.DisplayMode.x; - vertex[2].y=0; - vertex[3].x=0; - vertex[3].y=0; - vertex[0].sow=0; - vertex[0].tow=0; -#ifdef OWNSCALE - vertex[1].sow=((GLfloat)iFTexA)/256.0f; - vertex[2].tow=((GLfloat)iFTexB)/256.0f; -#else - vertex[1].sow=iFTexA; - vertex[2].tow=iFTexB; -#endif - vertex[1].tow=0; - vertex[2].sow=vertex[1].sow; - vertex[3].sow=0; - vertex[3].tow=vertex[2].tow; - if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - vertex[0].c.lcol=0xffffffff; - SETCOL(vertex[0]); - - // simply draw the backbuffer texture (without blur) - XPRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - - glEnable(GL_ALPHA_TEST); - glEnable(GL_SCISSOR_TEST); - if(iZBufferDepth) glEnable(GL_DEPTH_TEST); - if(bDrawDither) glEnable(GL_DITHER); // dither mode - if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT); - - if(bKeepRatio) - glViewport(rRatioRect.left, - iResY-(rRatioRect.top+rRatioRect.bottom), - rRatioRect.right, - rRatioRect.bottom); // init viewport -} - -//////////////////////////////////////////////////////////////////////// -// Update display (swap buffers)... called in interlaced mode on -// every emulated vsync, otherwise whenever the displayed screen region -// has been changed -//////////////////////////////////////////////////////////////////////// - -int iLastRGB24=0; // special vars for checking when to skip two display updates -int iSkipTwo=0; - -void updateDisplay(void) // UPDATE DISPLAY -{ - BOOL bBlur=FALSE; - -#ifdef _WINDOWS - HDC hdc=GetDC(hWWindow); // windows: - wglMakeCurrent(hdc,GLCONTEXT); // -> make context current again -#endif -#if defined (_MACGL) - BringContextForward(); -#endif - bFakeFrontBuffer=FALSE; - bRenderFrontBuffer=FALSE; - - if(iRenderFVR) // frame buffer read fix mode still active? - { - iRenderFVR--; // -> if some frames in a row without read access: turn off mode - if(!iRenderFVR) bFullVRam=FALSE; - } - - if(iLastRGB24 && iLastRGB24!=PSXDisplay.RGB24+1) // (mdec) garbage check - { - iSkipTwo=2; // -> skip two frames to avoid garbage if color mode changes - } - iLastRGB24=0; - - if(PSXDisplay.RGB24)// && !bNeedUploadAfter) // (mdec) upload wanted? - { - PrepareFullScreenUpload(-1); - UploadScreen(PSXDisplay.Interlaced); // -> upload whole screen from psx vram - bNeedUploadTest=FALSE; - bNeedInterlaceUpdate=FALSE; - bNeedUploadAfter=FALSE; - bNeedRGB24Update=FALSE; - } - else - if(bNeedInterlaceUpdate) // smaller upload? - { - bNeedInterlaceUpdate=FALSE; - xrUploadArea=xrUploadAreaIL; // -> upload this rect - UploadScreen(TRUE); - } - - if(dwActFixes&512) bCheckFF9G4(NULL); // special game fix for FF9 - - if(PreviousPSXDisplay.Range.x0|| // paint black borders around display area, if needed - PreviousPSXDisplay.Range.y0) - PaintBlackBorders(); - - if(PSXDisplay.Disabled) // display disabled? - { - // moved here - glDisable(GL_SCISSOR_TEST); - glClearColor(0,0,0,128); // -> clear whole backbuffer - glClear(uiBufferBits); - glEnable(GL_SCISSOR_TEST); - gl_z=0.0f; - bDisplayNotSet = TRUE; - } - - if(iSkipTwo) // we are in skipping mood? - { - iSkipTwo--; - iDrawnSomething=0; // -> simply lie about something drawn - } - - if(iBlurBuffer && !bSkipNextFrame) // "blur display" activated? - {BlurBackBuffer();bBlur=TRUE;} // -> blur it - - if(iUseScanLines) SetScanLines(); // "scan lines" activated? do it - - if(usCursorActive) ShowGunCursor(); // "gun cursor" wanted? show 'em - - if(dwActFixes&128) // special FPS limitation mode? - { - if(bUseFrameLimit) PCFrameCap(); // -> ok, do it - if(bUseFrameSkip || ulKeybits&KEY_SHOWFPS) - PCcalcfps(); - } - - if(gTexPicName) DisplayPic(); // some gpu info picture active? display it - - if(bSnapShot) DoSnapShot(); // snapshot key pressed? cheeeese :) - - if(ulKeybits&KEY_SHOWFPS) // wanna see FPS? - { - sprintf(szDispBuf,"%06.1f",fps_cur); - DisplayText(); // -> show it - } - - //----------------------------------------------------// - // main buffer swapping (well, or skip it) - - if(bUseFrameSkip) // frame skipping active ? - { - if(!bSkipNextFrame) - { - if(iDrawnSomething) -#ifdef _WINDOWS - SwapBuffers(wglGetCurrentDC()); // -> to skip or not to skip -#elif defined(_MACGL) - DoBufferSwap(); -#else - glXSwapBuffers(display,window); -#endif - } - if(dwActFixes&0x180) // -> special old frame skipping: skip max one in a row - { - if((fps_skip < fFrameRateHz) && !(bSkipNextFrame)) - {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;} - else bSkipNextFrame = FALSE; - } - else FrameSkip(); - } - else // no skip ? - { - if(iDrawnSomething) -#ifdef _WINDOWS - SwapBuffers(wglGetCurrentDC()); // -> swap -#elif defined(_MACGL) - DoBufferSwap(); -#else - glXSwapBuffers(display,window); -#endif - } - - iDrawnSomething=0; - - //----------------------------------------------------// - - if(lClearOnSwap) // clear buffer after swap? - { - GLclampf g,b,r; - - if(bDisplayNotSet) // -> set new vals - SetOGLDisplaySettings(1); - - g=((GLclampf)GREEN(lClearOnSwapColor))/255.0f; // -> get col - b=((GLclampf)BLUE(lClearOnSwapColor))/255.0f; - r=((GLclampf)RED(lClearOnSwapColor))/255.0f; - - glDisable(GL_SCISSOR_TEST); - glClearColor(r,g,b,128); // -> clear - glClear(uiBufferBits); - glEnable(GL_SCISSOR_TEST); - lClearOnSwap=0; // -> done - } - else - { - if(bBlur) UnBlurBackBuffer(); // unblur buff, if blurred before - - if(iZBufferDepth) // clear zbuffer as well (if activated) - { - glDisable(GL_SCISSOR_TEST); - glClear(GL_DEPTH_BUFFER_BIT); - glEnable(GL_SCISSOR_TEST); - } - } - gl_z=0.0f; - - //----------------------------------------------------// - // additional uploads immediatly after swapping - - if(bNeedUploadAfter) // upload wanted? - { - bNeedUploadAfter=FALSE; - bNeedUploadTest=FALSE; - UploadScreen(-1); // -> upload - } - - if(bNeedUploadTest) - { - bNeedUploadTest=FALSE; - if(PSXDisplay.InterlacedTest && - //iOffscreenDrawing>2 && - PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x && - PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x && - PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y && - PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y) - { - PrepareFullScreenUpload(TRUE); - UploadScreen(TRUE); - } - } - - //----------------------------------------------------// - // rumbling (main emu pad effect) - - if(iRumbleTime) // shake screen by modifying view port - { - int i1=0,i2=0,i3=0,i4=0; - - iRumbleTime--; - if(iRumbleTime) - { - i1=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); - i2=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); - i3=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); - i4=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); - } - - glViewport(rRatioRect.left+i1, - iResY-(rRatioRect.top+rRatioRect.bottom)+i2, - rRatioRect.right+i3, - rRatioRect.bottom+i4); - } - -#ifdef _WINDOWS - ReleaseDC(hWWindow,hdc); // ! important ! -#endif - - if(ulKeybits&KEY_RESETTEXSTORE) ResetStuff(); // reset on gpu mode changes? do it before next frame is filled -} - -//////////////////////////////////////////////////////////////////////// -// update front display: smaller update func, if something has changed -// in the frontbuffer... dirty, but hey... real men know no pain -//////////////////////////////////////////////////////////////////////// - -void updateFrontDisplay(void) -{ - if(PreviousPSXDisplay.Range.x0|| - PreviousPSXDisplay.Range.y0) - PaintBlackBorders(); - - if(iBlurBuffer) BlurBackBuffer(); - - if(iUseScanLines) SetScanLines(); - - if(usCursorActive) ShowGunCursor(); - - bFakeFrontBuffer=FALSE; - bRenderFrontBuffer=FALSE; - - if(gTexPicName) DisplayPic(); - if(ulKeybits&KEY_SHOWFPS) DisplayText(); - -#ifdef _WINDOWS - { // windows: - HDC hdc=GetDC(hWWindow); - wglMakeCurrent(hdc,GLCONTEXT); // -> make current again - if(iDrawnSomething) - SwapBuffers(wglGetCurrentDC()); // -> swap - ReleaseDC(hWWindow,hdc); // -> ! important ! - } -#elif defined (_MACGL) -if (iDrawnSomething){ - DoBufferSwap(); - } -#else - if(iDrawnSomething) // linux: - glXSwapBuffers(display,window); -#endif - - if(iBlurBuffer) UnBlurBackBuffer(); -} - -//////////////////////////////////////////////////////////////////////// -// check if update needed -//////////////////////////////////////////////////////////////////////// - -static void ChangeDispOffsetsX(void) // CENTER X -{ - int lx,l;short sO; - - if(!PSXDisplay.Range.x1) return; // some range given? - - l=PSXDisplay.DisplayMode.x; - - l*=(int)PSXDisplay.Range.x1; // some funky calculation - l/=2560;lx=l;l&=0xfffffff8; - - if(l==PreviousPSXDisplay.Range.x1) return; // some change? - - sO=PreviousPSXDisplay.Range.x0; // store old - - if(lx>=PSXDisplay.DisplayMode.x) // range bigger? - { - PreviousPSXDisplay.Range.x1= // -> take display width - PSXDisplay.DisplayMode.x; - PreviousPSXDisplay.Range.x0=0; // -> start pos is 0 - } - else // range smaller? center it - { - PreviousPSXDisplay.Range.x1=l; // -> store width (8 pixel aligned) - PreviousPSXDisplay.Range.x0= // -> calc start pos - (PSXDisplay.Range.x0-500)/8; - if(PreviousPSXDisplay.Range.x0<0) // -> we don't support neg. values yet - PreviousPSXDisplay.Range.x0=0; - - if((PreviousPSXDisplay.Range.x0+lx)> // -> uhuu... that's too much - PSXDisplay.DisplayMode.x) - { - PreviousPSXDisplay.Range.x0= // -> adjust start - PSXDisplay.DisplayMode.x-lx; - PreviousPSXDisplay.Range.x1+=lx-l; // -> adjust width - } - } - - if(sO!=PreviousPSXDisplay.Range.x0) // something changed? - { - bDisplayNotSet=TRUE; // -> recalc display stuff - } -} - -//////////////////////////////////////////////////////////////////////// - -static void ChangeDispOffsetsY(void) // CENTER Y -{ - int iT;short sO; // store previous y size - - if(PSXDisplay.PAL) iT=48; else iT=28; // different offsets on PAL/NTSC - - if(PSXDisplay.Range.y0>=iT) // crossed the security line? :) - { - PreviousPSXDisplay.Range.y1= // -> store width - PSXDisplay.DisplayModeNew.y; - - sO=(PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double; // -> calc offset - if(sO<0) sO=0; - - PSXDisplay.DisplayModeNew.y+=sO; // -> add offset to y size, too - } - else sO=0; // else no offset - - if(sO!=PreviousPSXDisplay.Range.y0) // something changed? - { - PreviousPSXDisplay.Range.y0=sO; - bDisplayNotSet=TRUE; // -> recalc display stuff - } -} - -//////////////////////////////////////////////////////////////////////// -// Aspect ratio of ogl screen: simply adjusting ogl view port -//////////////////////////////////////////////////////////////////////// - -void SetAspectRatio(void) -{ - float xs,ys,s;RECT r; - - if(!PSXDisplay.DisplayModeNew.x) return; - if(!PSXDisplay.DisplayModeNew.y) return; - - xs=(float)iResX/(float)PSXDisplay.DisplayModeNew.x; - ys=(float)iResY/(float)PSXDisplay.DisplayModeNew.y; - - s=min(xs,ys); - r.right =(int)((float)PSXDisplay.DisplayModeNew.x*s); - r.bottom=(int)((float)PSXDisplay.DisplayModeNew.y*s); - if(r.right > iResX) r.right = iResX; - if(r.bottom > iResY) r.bottom = iResY; - if(r.right < 1) r.right = 1; - if(r.bottom < 1) r.bottom = 1; - - r.left = (iResX-r.right)/2; - r.top = (iResY-r.bottom)/2; - - if(r.bottom new psx resolution - PSXDisplay.DisplayModeNew.y, 0, -1, 1); - if(bKeepRatio) SetAspectRatio(); - } - - bDisplayNotSet = TRUE; // re-calc offsets/display area - - bUp=FALSE; - if(PSXDisplay.RGB24!=PSXDisplay.RGB24New) // clean up textures, if rgb mode change (usually mdec on/off) - { - PreviousPSXDisplay.RGB24=0; // no full 24 frame uploaded yet - ResetTextureArea(FALSE); - bUp=TRUE; - } - - PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos - PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y; - PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x; - PSXDisplay.Interlaced = PSXDisplay.InterlacedNew; - - PSXDisplay.DisplayEnd.x= // calc new ends - PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; - PSXDisplay.DisplayEnd.y= - PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; - PreviousPSXDisplay.DisplayEnd.x= - PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; - PreviousPSXDisplay.DisplayEnd.y= - PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; - - ChangeDispOffsetsX(); - - if(iFrameLimit==2) SetAutoFrameCap(); // set new fps limit vals (depends on interlace) - - if(bUp) updateDisplay(); // yeah, real update (swap buffer) -} - -//////////////////////////////////////////////////////////////////////// -// window mode <-> fullscreen mode (windows) -//////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS -void ChangeWindowMode(void) - { - GPUclose(); - bWindowMode=!bWindowMode; - GPUopen(hWWindow); - bChangeWinMode=FALSE; - } -#endif - -//////////////////////////////////////////////////////////////////////// -// swap update check (called by psx vsync function) -//////////////////////////////////////////////////////////////////////// - -static BOOL bSwapCheck(void) -{ - static int iPosCheck=0; - static PSXPoint_t pO; - static PSXPoint_t pD; - static int iDoAgain=0; - - if(PSXDisplay.DisplayPosition.x==pO.x && - PSXDisplay.DisplayPosition.y==pO.y && - PSXDisplay.DisplayEnd.x==pD.x && - PSXDisplay.DisplayEnd.y==pD.y) - iPosCheck++; - else iPosCheck=0; - - pO=PSXDisplay.DisplayPosition; - pD=PSXDisplay.DisplayEnd; - - if(iPosCheck<=4) return FALSE; - - iPosCheck=4; - - if(PSXDisplay.Interlaced) return FALSE; - - if (bNeedInterlaceUpdate|| - bNeedRGB24Update || - bNeedUploadAfter|| - bNeedUploadTest || - iDoAgain - ) - { - iDoAgain=0; - if(bNeedUploadAfter) - iDoAgain=1; - if(bNeedUploadTest && PSXDisplay.InterlacedTest) - iDoAgain=1; - - bDisplayNotSet = TRUE; - updateDisplay(); - - PreviousPSXDisplay.DisplayPosition.x=PSXDisplay.DisplayPosition.x; - PreviousPSXDisplay.DisplayPosition.y=PSXDisplay.DisplayPosition.y; - PreviousPSXDisplay.DisplayEnd.x=PSXDisplay.DisplayEnd.x; - PreviousPSXDisplay.DisplayEnd.y=PSXDisplay.DisplayEnd.y; - pO=PSXDisplay.DisplayPosition; - pD=PSXDisplay.DisplayEnd; - - return TRUE; - } - - return FALSE; -} - -//////////////////////////////////////////////////////////////////////// -// gun cursor func: player=0-7, x=0-511, y=0-255 -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUcursor(int iPlayer,int x,int y) -{ - if(iPlayer<0) return; - if(iPlayer>7) return; - - usCursorActive|=(1<iGPUHeightMask) x=iGPUHeightMask; - if(y<0) y=0; - if(y>255) y=255; - - ptCursorPoint[iPlayer].x=x; - ptCursorPoint[iPlayer].y=y; -} - -//////////////////////////////////////////////////////////////////////// -// update lace is called every VSync. Basically we limit frame rate -// here, and in interlaced mode we swap ogl display buffers. -//////////////////////////////////////////////////////////////////////// - -static unsigned short usFirstPos=2; - -void CALLBACK GPUupdateLace(void) -{ - //if(!(dwActFixes&0x1000)) - // STATUSREG^=0x80000000; // interlaced bit toggle, if the CC game fix is not active (see gpuReadStatus) - - if(!(dwActFixes&128)) // normal frame limit func - CheckFrameRate(); - - if(iOffscreenDrawing==4) // special check if high offscreen drawing is on - { - if(bSwapCheck()) return; - } - - if(PSXDisplay.Interlaced) // interlaced mode? - { - STATUSREG^=0x80000000; - if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0) - { - updateDisplay(); // -> swap buffers (new frame) - } - } - else if(bRenderFrontBuffer) // no interlace mode? and some stuff in front has changed? - { - updateFrontDisplay(); // -> update front buffer - } - else if(usFirstPos==1) // initial updates (after startup) - { - updateDisplay(); - } - -#if defined(_WINDOWS) || defined(_MACGL) - if(bChangeWinMode) ChangeWindowMode(); -#endif -} - -//////////////////////////////////////////////////////////////////////// -// process read request from GPU status register -//////////////////////////////////////////////////////////////////////// - -uint32_t CALLBACK GPUreadStatus(void) -{ - if(dwActFixes&0x1000) // CC game fix - { - static int iNumRead=0; - if((iNumRead++)==2) - { - iNumRead=0; - STATUSREG^=0x80000000; // interlaced bit toggle... we do it on every second read status... needed by some games (like ChronoCross) - } - } - - if(iFakePrimBusy) // 27.10.2007 - emulating some 'busy' while drawing... pfff... not perfect, but since our emulated dma is not done in an extra thread... - { - iFakePrimBusy--; - - if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims - { - GPUIsBusy; - GPUIsNotReadyForCommands; - } - else - { - GPUIsIdle; - GPUIsReadyForCommands; - } - } - - return STATUSREG | (vBlank ? 0x80000000 : 0 );; -} - -//////////////////////////////////////////////////////////////////////// -// 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; - -#ifdef _WINDOWS - if(bIsFirstFrame) GLinitialize(); // real ogl startup (needed by some emus) -#endif - - ulStatusControl[lCommand]=gdata; - - switch(lCommand) - { - //--------------------------------------------------// - // reset gpu - case 0x00: - memset(ulGPUInfoVals, 0x00, 16 * sizeof(uint32_t)); - lGPUstatusRet = 0x14802000; - PSXDisplay.Disabled=1; - iDataWriteMode=iDataReadMode=DR_NORMAL; - PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0; - drawX=drawY=0;drawW=drawH=0; - sSetMask=0;lSetMask=0;bCheckMask=FALSE;iSetMask=0; - usMirror=0; - GlobalTextAddrX=0;GlobalTextAddrY=0; - GlobalTextTP=0;GlobalTextABR=0; - PSXDisplay.RGB24=FALSE; - PSXDisplay.Interlaced=FALSE; - bUsingTWin = FALSE; - return; - - // dis/enable display - case 0x03: - PreviousPSXDisplay.Disabled = PSXDisplay.Disabled; - PSXDisplay.Disabled = (gdata & 1); - - if(PSXDisplay.Disabled) - STATUSREG|=GPUSTATUS_DISPLAYDISABLED; - else STATUSREG&=~GPUSTATUS_DISPLAYDISABLED; - - if (iOffscreenDrawing==4 && - PreviousPSXDisplay.Disabled && - !(PSXDisplay.Disabled)) - { - - if(!PSXDisplay.RGB24) - { - PrepareFullScreenUpload(TRUE); - UploadScreen(TRUE); - updateDisplay(); - } - } - - return; - - // setting transfer mode - case 0x04: - gdata &= 0x03; // only want the lower two bits - - iDataWriteMode=iDataReadMode=DR_NORMAL; - if(gdata==0x02) iDataWriteMode=DR_VRAMTRANSFER; - if(gdata==0x03) iDataReadMode =DR_VRAMTRANSFER; - - STATUSREG&=~GPUSTATUS_DMABITS; // clear the current settings of the DMA bits - STATUSREG|=(gdata << 29); // set the DMA bits according to the received data - - return; - - // setting display position - case 0x05: - { - short sx=(short)(gdata & 0x3ff); - short sy; - - if(iGPUHeight==1024) - { - if(dwGPUVersion==2) - sy = (short)((gdata>>12)&0x3ff); - else sy = (short)((gdata>>10)&0x3ff); - } - else sy = (short)((gdata>>10)&0x3ff); // really: 0x1ff, but we adjust it later - - if (sy & 0x200) - { - sy|=0xfc00; - PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double; - sy=0; - } - else PreviousPSXDisplay.DisplayModeNew.y=0; - - if(sx>1000) sx=0; - - if(usFirstPos) - { - usFirstPos--; - if(usFirstPos) - { - PreviousPSXDisplay.DisplayPosition.x = sx; - PreviousPSXDisplay.DisplayPosition.y = sy; - PSXDisplay.DisplayPosition.x = sx; - PSXDisplay.DisplayPosition.y = sy; - } - } - - if(dwActFixes&8) - { - if((!PSXDisplay.Interlaced) && - PreviousPSXDisplay.DisplayPosition.x == sx && - PreviousPSXDisplay.DisplayPosition.y == sy) - return; - - PSXDisplay.DisplayPosition.x = PreviousPSXDisplay.DisplayPosition.x; - PSXDisplay.DisplayPosition.y = PreviousPSXDisplay.DisplayPosition.y; - PreviousPSXDisplay.DisplayPosition.x = sx; - PreviousPSXDisplay.DisplayPosition.y = sy; - } - else - { - if((!PSXDisplay.Interlaced) && - PSXDisplay.DisplayPosition.x == sx && - PSXDisplay.DisplayPosition.y == sy) - return; - PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; - PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; - PSXDisplay.DisplayPosition.x = sx; - PSXDisplay.DisplayPosition.y = sy; - } - - PSXDisplay.DisplayEnd.x= - PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; - PSXDisplay.DisplayEnd.y= - PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; - - PreviousPSXDisplay.DisplayEnd.x= - PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; - PreviousPSXDisplay.DisplayEnd.y= - PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; - - bDisplayNotSet = TRUE; - - if (!(PSXDisplay.Interlaced)) - { - updateDisplay(); - } - else - if(PSXDisplay.InterlacedTest && - ((PreviousPSXDisplay.DisplayPosition.x != PSXDisplay.DisplayPosition.x)|| - (PreviousPSXDisplay.DisplayPosition.y != PSXDisplay.DisplayPosition.y))) - PSXDisplay.InterlacedTest--; - - return; - } - - // setting width - case 0x06: - - PSXDisplay.Range.x0=gdata & 0x7ff; //0x3ff; - PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff; - - PSXDisplay.Range.x1-=PSXDisplay.Range.x0; - - ChangeDispOffsetsX(); - - return; - - // setting height - case 0x07: - - PreviousPSXDisplay.Height = PSXDisplay.Height; - - PSXDisplay.Range.y0=gdata & 0x3ff; - PSXDisplay.Range.y1=(gdata>>10) & 0x3ff; - - PSXDisplay.Height = PSXDisplay.Range.y1 - - PSXDisplay.Range.y0 + - PreviousPSXDisplay.DisplayModeNew.y; - - if (PreviousPSXDisplay.Height != PSXDisplay.Height) - { - PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double; - ChangeDispOffsetsY(); - updateDisplayIfChanged(); - } - return; - - // setting display infos - case 0x08: - - PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)]; - - if (gdata&0x04) PSXDisplay.Double=2; - else PSXDisplay.Double=1; - PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double; - - ChangeDispOffsetsY(); - - PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC - PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor - PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace - - STATUSREG&=~GPUSTATUS_WIDTHBITS; // clear the width bits - - STATUSREG|= - (((gdata & 0x03) << 17) | - ((gdata & 0x40) << 10)); // set the width bits - - PreviousPSXDisplay.InterlacedNew=FALSE; - if (PSXDisplay.InterlacedNew) - { - if(!PSXDisplay.Interlaced) - { - PSXDisplay.InterlacedTest=2; - PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; - PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; - PreviousPSXDisplay.InterlacedNew=TRUE; - } - - STATUSREG|=GPUSTATUS_INTERLACED; - } - else - { - PSXDisplay.InterlacedTest=0; - STATUSREG&=~GPUSTATUS_INTERLACED; - } - - if (PSXDisplay.PAL) - STATUSREG|=GPUSTATUS_PAL; - else STATUSREG&=~GPUSTATUS_PAL; - - if (PSXDisplay.Double==2) - STATUSREG|=GPUSTATUS_DOUBLEHEIGHT; - else STATUSREG&=~GPUSTATUS_DOUBLEHEIGHT; - - if (PSXDisplay.RGB24New) - STATUSREG|=GPUSTATUS_RGB24; - else STATUSREG&=~GPUSTATUS_RGB24; - - updateDisplayIfChanged(); - - return; - - //--------------------------------------------------// - // ask about GPU version and other stuff - case 0x10: - - gdata&=0xff; - - switch(gdata) - { - case 0x02: - GPUdataRet=ulGPUInfoVals[INFO_TW]; // tw infos - return; - case 0x03: - GPUdataRet=ulGPUInfoVals[INFO_DRAWSTART]; // draw start - return; - case 0x04: - GPUdataRet=ulGPUInfoVals[INFO_DRAWEND]; // draw end - return; - case 0x05: - case 0x06: - GPUdataRet=ulGPUInfoVals[INFO_DRAWOFF]; // draw offset - return; - case 0x07: - if(dwGPUVersion==2) - GPUdataRet=0x01; - else GPUdataRet=0x02; // gpu type - return; - case 0x08: - case 0x0F: // some bios addr? - GPUdataRet=0xBFC03720; - return; - } - return; - //--------------------------------------------------// - } -} - -//////////////////////////////////////////////////////////////////////// -// vram read/write helpers -//////////////////////////////////////////////////////////////////////// - -BOOL bNeedWriteUpload=FALSE; - -static __inline void FinishedVRAMWrite(void) -{ - if(bNeedWriteUpload) - { - bNeedWriteUpload=FALSE; - CheckWriteUpdate(); - } - - // set register to NORMAL operation - iDataWriteMode = DR_NORMAL; - - // reset transfer values, to prevent mis-transfer of data - VRAMWrite.ColsRemaining = 0; - VRAMWrite.RowsRemaining = 0; -} - -static __inline void FinishedVRAMRead(void) -{ - // set register to NORMAL operation - iDataReadMode = DR_NORMAL; - // reset transfer values, to prevent mis-transfer of data - VRAMRead.x = 0; - VRAMRead.y = 0; - VRAMRead.Width = 0; - VRAMRead.Height = 0; - VRAMRead.ColsRemaining = 0; - VRAMRead.RowsRemaining = 0; - - // indicate GPU is no longer ready for VRAM data in the STATUS REGISTER - STATUSREG&=~GPUSTATUS_READYFORVRAM; -} - -//////////////////////////////////////////////////////////////////////// -// vram read check ex (reading from card's back/frontbuffer if needed... -// slow!) -//////////////////////////////////////////////////////////////////////// - -void CheckVRamReadEx(int x, int y, int dx, int dy) -{ - unsigned short sArea; - int ux,uy,udx,udy,wx,wy; - unsigned short * p1, *p2; - float XS,YS; - unsigned char * ps; - unsigned char * px; - unsigned short s,sx; - - if(STATUSREG&GPUSTATUS_RGB24) return; - - if(((dx > PSXDisplay.DisplayPosition.x) && - (x < PSXDisplay.DisplayEnd.x) && - (dy > PSXDisplay.DisplayPosition.y) && - (y < PSXDisplay.DisplayEnd.y))) - sArea=0; - else - if((!(PSXDisplay.InterlacedTest) && - (dx > PreviousPSXDisplay.DisplayPosition.x) && - (x < PreviousPSXDisplay.DisplayEnd.x) && - (dy > PreviousPSXDisplay.DisplayPosition.y) && - (y < PreviousPSXDisplay.DisplayEnd.y))) - sArea=1; - else - { - return; - } - - ////////////// - - if(iRenderFVR) - { - bFullVRam=TRUE;iRenderFVR=2;return; - } - bFullVRam=TRUE;iRenderFVR=2; - - ////////////// - - p2=0; - - if(sArea==0) - { - ux=PSXDisplay.DisplayPosition.x; - uy=PSXDisplay.DisplayPosition.y; - udx=PSXDisplay.DisplayEnd.x-ux; - udy=PSXDisplay.DisplayEnd.y-uy; - if((PreviousPSXDisplay.DisplayEnd.x- - PreviousPSXDisplay.DisplayPosition.x)==udx && - (PreviousPSXDisplay.DisplayEnd.y- - PreviousPSXDisplay.DisplayPosition.y)==udy) - p2=(psxVuw + (1024*PreviousPSXDisplay.DisplayPosition.y) + - PreviousPSXDisplay.DisplayPosition.x); - } - else - { - ux=PreviousPSXDisplay.DisplayPosition.x; - uy=PreviousPSXDisplay.DisplayPosition.y; - udx=PreviousPSXDisplay.DisplayEnd.x-ux; - udy=PreviousPSXDisplay.DisplayEnd.y-uy; - if((PSXDisplay.DisplayEnd.x- - PSXDisplay.DisplayPosition.x)==udx && - (PSXDisplay.DisplayEnd.y- - PSXDisplay.DisplayPosition.y)==udy) - p2=(psxVuw + (1024*PSXDisplay.DisplayPosition.y) + - PSXDisplay.DisplayPosition.x); - } - - p1=(psxVuw + (1024*uy) + ux); - if(p1==p2) p2=0; - - x=0;y=0; - wx=dx=udx;wy=dy=udy; - - if(udx<=0) return; - if(udy<=0) return; - if(dx<=0) return; - if(dy<=0) return; - if(wx<=0) return; - if(wy<=0) return; - - XS=(float)rRatioRect.right/(float)wx; - YS=(float)rRatioRect.bottom/(float)wy; - - dx=(int)((float)(dx)*XS); - dy=(int)((float)(dy)*YS); - - if(dx>iResX) dx=iResX; - if(dy>iResY) dy=iResY; - - if(dx<=0) return; - if(dy<=0) return; - - // ogl y adjust - y=iResY-y-dy; - - x+=rRatioRect.left; - y-=rRatioRect.top; - - if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y; - - if(!pGfxCardScreen) - { - glPixelStorei(GL_PACK_ALIGNMENT,1); - pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4); - } - - ps=pGfxCardScreen; - - if(!sArea) glReadBuffer(GL_FRONT); - - glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); - - if(!sArea) glReadBuffer(GL_BACK); - - s=0; - - XS=(float)dx/(float)(udx); - YS=(float)dy/(float)(udy+1); - - for(y=udy;y>0;y--) - { - for(x=0;x=psxVuw && p1>3;px++; - s=sx; - sx=(*px)>>3;px++; - s|=sx<<5; - sx=(*px)>>3; - s|=sx<<10; - s&=~0x8000; - *p1=s; - } - if(p2>=psxVuw && p2 PSXDisplay.DisplayPosition.x) && - (x < PSXDisplay.DisplayEnd.x) && - (dy > PSXDisplay.DisplayPosition.y) && - (y < PSXDisplay.DisplayEnd.y))) - sArea=0; - else - if((!(PSXDisplay.InterlacedTest) && - (dx > PreviousPSXDisplay.DisplayPosition.x) && - (x < PreviousPSXDisplay.DisplayEnd.x) && - (dy > PreviousPSXDisplay.DisplayPosition.y) && - (y < PreviousPSXDisplay.DisplayEnd.y))) - sArea=1; - else - { - return; - } - - if(dwActFixes&0x40) - { - if(iRenderFVR) - { - bFullVRam=TRUE;iRenderFVR=2;return; - } - bFullVRam=TRUE;iRenderFVR=2; - } - - ux=x;uy=y;udx=dx;udy=dy; - - if(sArea==0) - { - x -=PSXDisplay.DisplayPosition.x; - dx-=PSXDisplay.DisplayPosition.x; - y -=PSXDisplay.DisplayPosition.y; - dy-=PSXDisplay.DisplayPosition.y; - wx=PSXDisplay.DisplayEnd.x-PSXDisplay.DisplayPosition.x; - wy=PSXDisplay.DisplayEnd.y-PSXDisplay.DisplayPosition.y; - } - else - { - x -=PreviousPSXDisplay.DisplayPosition.x; - dx-=PreviousPSXDisplay.DisplayPosition.x; - y -=PreviousPSXDisplay.DisplayPosition.y; - dy-=PreviousPSXDisplay.DisplayPosition.y; - wx=PreviousPSXDisplay.DisplayEnd.x-PreviousPSXDisplay.DisplayPosition.x; - wy=PreviousPSXDisplay.DisplayEnd.y-PreviousPSXDisplay.DisplayPosition.y; - } - if(x<0) {ux-=x;x=0;} - if(y<0) {uy-=y;y=0;} - if(dx>wx) {udx-=(dx-wx);dx=wx;} - if(dy>wy) {udy-=(dy-wy);dy=wy;} - udx-=ux; - udy-=uy; - - p=(psxVuw + (1024*uy) + ux); - - if(udx<=0) return; - if(udy<=0) return; - if(dx<=0) return; - if(dy<=0) return; - if(wx<=0) return; - if(wy<=0) return; - - XS=(float)rRatioRect.right/(float)wx; - YS=(float)rRatioRect.bottom/(float)wy; - - dx=(int)((float)(dx)*XS); - dy=(int)((float)(dy)*YS); - x=(int)((float)x*XS); - y=(int)((float)y*YS); - - dx-=x; - dy-=y; - - if(dx>iResX) dx=iResX; - if(dy>iResY) dy=iResY; - - if(dx<=0) return; - if(dy<=0) return; - - // ogl y adjust - y=iResY-y-dy; - - x+=rRatioRect.left; - y-=rRatioRect.top; - - if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y; - - if(!pGfxCardScreen) - { - glPixelStorei(GL_PACK_ALIGNMENT,1); - pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4); - } - - ps=pGfxCardScreen; - - if(bFront) glReadBuffer(GL_FRONT); - - glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); - - if(bFront) glReadBuffer(GL_BACK); - - XS=(float)dx/(float)(udx); - YS=(float)dy/(float)(udy+1); - - for(y=udy;y>0;y--) - { - for(x=0;x=psxVuw && p>3;px++; - s=sx; - sx=(*px)>>3;px++; - s|=sx<<5; - sx=(*px)>>3; - s|=sx<<10; - s&=~0x8000; - *p=s; - } - p++; - } - p += 1024 - udx; - } -} - -//////////////////////////////////////////////////////////////////////// -// core read from vram -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUreadDataMem(uint32_t *pMem, int iSize) -{ - int i; - - if(iDataReadMode!=DR_VRAMTRANSFER) return; - - GPUIsBusy; - - // adjust read ptr, if necessary - while(VRAMRead.ImagePtr>=psxVuw_eom) - VRAMRead.ImagePtr-=iGPUHeight*1024; - while(VRAMRead.ImagePtr1) && - !(iDrawnSomething==2 && - VRAMRead.x == VRAMWrite.x && - VRAMRead.y == VRAMWrite.y && - VRAMRead.Width == VRAMWrite.Width && - VRAMRead.Height == VRAMWrite.Height)) - CheckVRamRead(VRAMRead.x,VRAMRead.y, - VRAMRead.x+VRAMRead.RowsRemaining, - VRAMRead.y+VRAMRead.ColsRemaining, - TRUE); - - for(i=0;i 0) && (VRAMRead.RowsRemaining > 0)) - { - // lower 16 bit - GPUdataRet=(uint32_t)*VRAMRead.ImagePtr; - - VRAMRead.ImagePtr++; - if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; - VRAMRead.RowsRemaining --; - - if(VRAMRead.RowsRemaining<=0) - { - VRAMRead.RowsRemaining = VRAMRead.Width; - VRAMRead.ColsRemaining--; - VRAMRead.ImagePtr += 1024 - VRAMRead.Width; - if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; - } - - // higher 16 bit (always, even if it's an odd width) - GPUdataRet|=(uint32_t)(*VRAMRead.ImagePtr)<<16; - *pMem++=GPUdataRet; - - if(VRAMRead.ColsRemaining <= 0) - {FinishedVRAMRead();goto ENDREAD;} - - VRAMRead.ImagePtr++; - if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; - VRAMRead.RowsRemaining--; - if(VRAMRead.RowsRemaining<=0) - { - VRAMRead.RowsRemaining = VRAMRead.Width; - VRAMRead.ColsRemaining--; - VRAMRead.ImagePtr += 1024 - VRAMRead.Width; - if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; - } - if(VRAMRead.ColsRemaining <= 0) - {FinishedVRAMRead();goto ENDREAD;} - } - else {FinishedVRAMRead();goto ENDREAD;} - } - -ENDREAD: - GPUIsIdle; -} - -uint32_t CALLBACK GPUreadData(void) -{ - uint32_t l; - GPUreadDataMem(&l,1); - return GPUdataRet; -} - -//////////////////////////////////////////////////////////////////////// -// helper table to know how much data is used by drawing commands -//////////////////////////////////////////////////////////////////////// - -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, // LINEG3 LINEG4 - 255,255,255,255,255,255,255,255, - // 60 - 3,3,3,3,4,4,4,4, // TILE SPRT - // 68 - 2,2,2,2,3,3,3,3, // TILE1 - // 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 -}; - -//////////////////////////////////////////////////////////////////////// -// processes data send to GPU data register -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUwriteDataMem(uint32_t *pMem, int iSize) -{ - unsigned char command; - uint32_t gdata=0; - int i=0; - GPUIsBusy; - GPUIsNotReadyForCommands; - -STARTVRAM: - - if(iDataWriteMode==DR_VRAMTRANSFER) - { - // make sure we are in vram - while(VRAMWrite.ImagePtr>=psxVuw_eom) - VRAMWrite.ImagePtr-=iGPUHeight*1024; - while(VRAMWrite.ImagePtr0) - { - while(VRAMWrite.RowsRemaining>0) - { - if(i>=iSize) {goto ENDVRAM;} - i++; - - gdata=*pMem++; - - *VRAMWrite.ImagePtr++ = (unsigned short)gdata; - if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; - VRAMWrite.RowsRemaining --; - - if(VRAMWrite.RowsRemaining <= 0) - { - VRAMWrite.ColsRemaining--; - if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width - { - gdata=(gdata&0xFFFF)|(((uint32_t)(*VRAMWrite.ImagePtr))<<16); - FinishedVRAMWrite(); - goto ENDVRAM; - } - VRAMWrite.RowsRemaining = VRAMWrite.Width; - VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; - } - - *VRAMWrite.ImagePtr++ = (unsigned short)(gdata>>16); - if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; - VRAMWrite.RowsRemaining --; - } - - VRAMWrite.RowsRemaining = VRAMWrite.Width; - VRAMWrite.ColsRemaining--; - VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; - } - - FinishedVRAMWrite(); - } - -ENDVRAM: - - if(iDataWriteMode==DR_NORMAL) - { - void (* *primFunc)(unsigned char *); - if(bSkipNextFrame) primFunc=primTableSkip; - else primFunc=primTableJ; - - for(;i>24) & 0xff); - - if(primTableCX[command]) - { - gpuDataC = primTableCX[command]; - gpuCommand = command; - gpuDataM[0] = gdata; - gpuDataP = 1; - } - else continue; - } - else - { - gpuDataM[gpuDataP] = gdata; - if(gpuDataC>128) - { - if((gpuDataC==254 && gpuDataP>=3) || - (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1))) - { - if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000) - gpuDataP=gpuDataC-1; - } - } - gpuDataP++; - } - - if(gpuDataP == gpuDataC) - { - gpuDataC=gpuDataP=0; - primFunc[gpuCommand]((unsigned char *)gpuDataM); - - if(dwEmuFixes&0x0001 || dwActFixes&0x20000) // hack for emulating "gpu busy" in some games - iFakePrimBusy=4; - } - } - } - - GPUdataRet=gdata; - - GPUIsReadyForCommands; - GPUIsIdle; -} - -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUwriteData(uint32_t gdata) -{ - GPUwriteDataMem(&gdata,1); -} - -//////////////////////////////////////////////////////////////////////// -// call config dlg -//////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS - -long CALLBACK GPUconfigure(void) -{ - HWND hWP=GetActiveWindow(); - DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG), - hWP,(DLGPROC)CfgDlgProc); - - return 0; -} - -#elif defined(_MACGL) -long CALLBACK GPUconfigure(void) -{ - DlgProc(); - return 0; -} -#else - -static void StartCfgTool(char *arg) // linux: start external cfg tool -{ - char cfg[256]; - struct stat buf; - - strcpy(cfg, "./cfgpeopsxgl"); - if (stat(cfg, &buf) != -1) { - if (fork() == 0) { - execl(cfg, "cfgpeopsxgl", arg, NULL); - exit(0); - } - return; - } - - strcpy(cfg, "./cfg/cfgpeopsxgl"); - if (stat(cfg, &buf) != -1) { - if (fork() == 0) { - execl(cfg, "cfgpeopsxgl", arg, NULL); - exit(0); - } - return; - } - - sprintf(cfg, "%s/.pcsx/plugins/cfg/cfgpeopsxgl", getenv("HOME")); - if (stat(cfg, &buf) != -1) { - if (fork() == 0) { - execl(cfg, "cfgpeopsxgl", arg, NULL); - exit(0); - } - return; - } - - printf("ERROR: cfgpeopsxgl file not found!\n"); -} - -long CALLBACK GPUconfigure(void) -{ - StartCfgTool("CFG"); - return 0; -} - -#endif // def _WINDOWS / _MACGL - -//////////////////////////////////////////////////////////////////////// -// sets all kind of act fixes -//////////////////////////////////////////////////////////////////////// - -void SetFixes(void) -{ - ReInitFrameCap(); - - if(dwActFixes & 0x2000) - dispWidths[4]=384; - else dispWidths[4]=368; -} - -//////////////////////////////////////////////////////////////////////// -// Pete Special: make an 'intelligent' dma chain check (<-Tekken3) -//////////////////////////////////////////////////////////////////////// - -uint32_t lUsedAddr[3]; - -static __inline BOOL CheckForEndlessLoop(uint32_t laddr) -{ - if(laddr==lUsedAddr[1]) return TRUE; - if(laddr==lUsedAddr[2]) return TRUE; - - if(laddr 2000000) break; - if(CheckForEndlessLoop(addr)) break; - - count = baseAddrB[addr+3]; - - dmaMem=addr+4; - - if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count); - - addr = baseAddrL[addr>>2]&0xffffff; - } - while (addr != 0xffffff); - - GPUIsIdle; - - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// show about dlg -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUabout(void) -{ -#ifdef _WINDOWS - HWND hWP=GetActiveWindow(); // to be sure - DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG_ABOUT), - hWP,(DLGPROC)AboutDlgProc); -#elif defined(_MACGL) - - AboutDlgProc(); -#else - - StartCfgTool("ABOUT"); - -#endif -} - -//////////////////////////////////////////////////////////////////////// -// 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; -} - -//////////////////////////////////////////////////////////////////////// -// save state funcs -//////////////////////////////////////////////////////////////////////// - -long CALLBACK GPUfreeze(uint32_t ulGetFreezeData,GPUFreeze_t * pF) -{ - if(ulGetFreezeData==2) - { - int lSlotNum=*((int *)pF); - if(lSlotNum<0) return 0; - if(lSlotNum>8) return 0; - lSelectedSlot=lSlotNum+1; - return 1; - } - - if(!pF) return 0; - if(pF->ulFreezeVersion!=1) return 0; - - if(ulGetFreezeData==1) - { - pF->ulStatus=STATUSREG; - memcpy(pF->ulControl,ulStatusControl,256*sizeof(uint32_t)); - memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2); - - return 1; - } - - if(ulGetFreezeData!=0) return 0; - - STATUSREG=pF->ulStatus; - memcpy(ulStatusControl,pF->ulControl,256*sizeof(uint32_t)); - memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2); - - ResetTextureArea(TRUE); - - GPUwriteStatus(ulStatusControl[0]); - GPUwriteStatus(ulStatusControl[1]); - GPUwriteStatus(ulStatusControl[2]); - GPUwriteStatus(ulStatusControl[3]); - GPUwriteStatus(ulStatusControl[8]); - GPUwriteStatus(ulStatusControl[6]); - GPUwriteStatus(ulStatusControl[7]); - GPUwriteStatus(ulStatusControl[5]); - GPUwriteStatus(ulStatusControl[4]); - - return 1; -} - -//////////////////////////////////////////////////////////////////////// -// special "emu infos" / "emu effects" functions -//////////////////////////////////////////////////////////////////////// - -//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 -} -}; - -//////////////////////////////////////////////////////////////////////// - -static void PaintPicDot(unsigned char * p,unsigned char c) -{ - if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;} - if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;} - if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;} -} - -//////////////////////////////////////////////////////////////////////// - -long CALLBACK GPUgetScreenPic(unsigned char * pMem) -{ - float XS,YS;int x,y,v; - unsigned char * ps, * px, * pf; - unsigned char c; - - if(!pGfxCardScreen) - { - glPixelStorei(GL_PACK_ALIGNMENT,1); - pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4); - } - - ps=pGfxCardScreen; - - glReadBuffer(GL_FRONT); - - glReadPixels(0,0,iResX,iResY,GL_RGB,GL_UNSIGNED_BYTE,ps); - - glReadBuffer(GL_BACK); - - XS=(float)iResX/128; - YS=(float)iResY/96; - pf=pMem; - - for(y=96;y>0;y--) - { - for(x=0;x<128;x++) - { - px=ps+(3*((int)((float)x * XS))+ - (3*iResX)*((int)((float)y*YS))); - *(pf+0)=*(px+2); - *(pf+1)=*(px+1); - *(pf+2)=*(px+0); - pf+=3; - } - } - - ///////////////////////////////////////////////////////////////////// - // generic number/border painter - - pf=pMem+(103*3); - - for(y=0;y<20;y++) - { - for(x=0;x<6;x++) - { - c=cFont[lSelectedSlot][x+y*6]; - v=(c&0xc0)>>6; - PaintPicDot(pf,(unsigned char)v);pf+=3; // paint the dots into the rect - v=(c&0x30)>>4; - PaintPicDot(pf,(unsigned char)v);pf+=3; - v=(c&0x0c)>>2; - PaintPicDot(pf,(unsigned char)v);pf+=3; - v=c&0x03; - PaintPicDot(pf,(unsigned char)v);pf+=3; - } - pf+=104*3; - } - - pf=pMem; - for(x=0;x<128;x++) - { - *(pf+(95*128*3))=0x00;*pf++=0x00; - *(pf+(95*128*3))=0x00;*pf++=0x00; - *(pf+(95*128*3))=0xff;*pf++=0xff; - } - pf=pMem; - for(y=0;y<96;y++) - { - *(pf+(127*3))=0x00;*pf++=0x00; - *(pf+(127*3))=0x00;*pf++=0x00; - *(pf+(127*3))=0xff;*pf++=0xff; - pf+=127*3; - } - return 0; -} - -//////////////////////////////////////////////////////////////////////// - -long CALLBACK GPUshowScreenPic(unsigned char * pMem) -{ - DestroyPic(); - if(pMem==0) return 0; - CreatePic(pMem); - return 0; -} - -//////////////////////////////////////////////////////////////////////// - -#if 0 -void CALLBACK GPUsetfix(uint32_t dwFixBits) -{ - dwEmuFixes=dwFixBits; -} -#endif - -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUvisualVibration(uint32_t iSmall, uint32_t iBig) -{ - int iVibVal; - - if(PSXDisplay.DisplayModeNew.x) // calc min "shake pixel" from screen width - iVibVal=max(1,iResX/PSXDisplay.DisplayModeNew.x); - else iVibVal=1; - // big rumble: 4...15 sp ; small rumble 1...3 sp - if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig *iVibVal)/10)); - else iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10)); - - srand(timeGetTime()); // init rand (will be used in BufferSwap) - - iRumbleTime=15; // let the rumble last 16 buffer swaps -} - -//////////////////////////////////////////////////////////////////////// -// main emu can set display infos (A/M/G/D) -//////////////////////////////////////////////////////////////////////// - -#if 0 -void CALLBACK GPUdisplayFlags(uint32_t dwFlags) -{ - dwCoreFlags=dwFlags; -} -#endif - -void CALLBACK GPUvBlank( int val ) -{ - vBlank = val; -} +/*************************************************************************** + gpu.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 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. * + * * + ***************************************************************************/ + +// !!! enable this, if Linux XF86VidMode is not supported: +//#define NOVMODE + +#include "stdafx.h" + +#if !defined(_MACGL) && !defined(_WINDOWS) + +#include "config.h" + +#ifndef NOVMODE +#include +static XF86VidModeModeInfo **modes=0; +static int iOldMode=0; +#endif + +#endif + +#define _IN_GPU + +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "cfg.h" +#include "prim.h" +#include "psemu_plugin_defs.h" +#include "texture.h" +#include "menu.h" +#include "fps.h" +#include "key.h" +#ifdef _WINDOWS +#include "resource.h" +#include "ssave.h" +#endif +#ifdef ENABLE_NLS +#include +#include +#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 +//////////////////////////////////////////////////////////////////////// + +const unsigned char version = 1; // do not touch - library for PSEmu 1.x +const unsigned char revision = 1; +const unsigned char build = 78; + +static char *libraryName = N_("OpenGL Driver"); + +static char *PluginAuthor = N_("Pete Bernert"); +static char *libraryInfo = N_("Based on P.E.Op.S. MesaGL Driver V1.78\nCoded by Pete Bernert\n"); + +//////////////////////////////////////////////////////////////////////// +// memory image of the PSX vram +//////////////////////////////////////////////////////////////////////// + +unsigned char *psxVSecure; +unsigned char *psxVub; +signed char *psxVsb; +unsigned short *psxVuw; +unsigned short *psxVuw_eom; +signed short *psxVsw; +uint32_t *psxVul; +signed int *psxVsl; + +// macro for easy access to packet information +#define GPUCOMMAND(x) ((x>>24) & 0xff) + +GLfloat gl_z=0.0f; +BOOL bNeedInterlaceUpdate=FALSE; +BOOL bNeedRGB24Update=FALSE; +BOOL bChangeWinMode=FALSE; + +#ifdef _WINDOWS +extern HGLRC GLCONTEXT; +#endif + +uint32_t ulStatusControl[256]; + +//////////////////////////////////////////////////////////////////////// +// global GPU vars +//////////////////////////////////////////////////////////////////////// + +static int GPUdataRet; +int lGPUstatusRet; +char szDispBuf[64]; + +uint32_t dwGPUVersion = 0; +int iGPUHeight = 512; +int iGPUHeightMask = 511; +int GlobalTextIL = 0; +int iTileCheat = 0; + +static uint32_t gpuDataM[256]; +static unsigned char gpuCommand = 0; +static int gpuDataC = 0; +static int gpuDataP = 0; + +VRAMLoad_t VRAMWrite; +VRAMLoad_t VRAMRead; +int iDataWriteMode; +int iDataReadMode; + +int lClearOnSwap; +int lClearOnSwapColor; +BOOL bSkipNextFrame = FALSE; +int iColDepth; +BOOL bChangeRes; +BOOL bWindowMode; +int iWinSize; + +// possible psx display widths +short dispWidths[8] = {256,320,512,640,368,384,512,640}; + +PSXDisplay_t PSXDisplay; +PSXDisplay_t PreviousPSXDisplay; +TWin_t TWin; +short imageX0,imageX1; +short imageY0,imageY1; +BOOL bDisplayNotSet = TRUE; +GLuint uiScanLine=0; +int iUseScanLines=0; +float iScanlineColor[] = {0,0,0, 0.3}; // easy on the eyes. +int lSelectedSlot=0; +unsigned char * pGfxCardScreen=0; +int iBlurBuffer=0; +int iScanBlend=0; +int iRenderFVR=0; +int iNoScreenSaver=0; +uint32_t ulGPUInfoVals[16]; +int iFakePrimBusy = 0; +int iRumbleVal = 0; +int iRumbleTime = 0; +uint32_t vBlank=0; + +//////////////////////////////////////////////////////////////////////// +// stuff to make this a true PDK module +//////////////////////////////////////////////////////////////////////// + +char * CALLBACK PSEgetLibName(void) +{ + return _(libraryName); +} + +unsigned long CALLBACK PSEgetLibType(void) +{ + return PSE_LT_GPU; +} + +unsigned long CALLBACK PSEgetLibVersion(void) +{ + return version<<16|revision<<8|build; +} + +char * GPUgetLibInfos(void) +{ + return _(libraryInfo); +} + +//////////////////////////////////////////////////////////////////////// +// snapshot funcs (saves screen to bitmap / text infos into file) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +char * GetConfigInfos(HWND hW) +#else +char * GetConfigInfos(int hW) +#endif +{ +#ifdef _WINDOWS + HDC hdc;HGLRC hglrc; +#endif + 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 (mod)\r\n",libraryName,version,revision,build); + strcat(pB,szTxt); + sprintf(szTxt,"Author: %s\r\n",PluginAuthor); + strcat(pB,szTxt); + +#ifdef _WINDOWS + if(hW) + { + hdc = GetDC(hW); + bSetupPixelFormat(hdc); + hglrc = wglCreateContext(hdc); + wglMakeCurrent(hdc, hglrc); + } +#endif + + sprintf(szTxt,"Card vendor: %s\r\n",(char *)glGetString(GL_VENDOR)); + strcat(pB,szTxt); + sprintf(szTxt,"GFX card: %s\r\n",(char *)glGetString(GL_RENDERER)); + strcat(pB,szTxt); + sprintf(szTxt,"OGL version: %s\r\n\r\n",(char *)glGetString(GL_VERSION)); + strcat(pB,szTxt); + //strcat(pB,(char *)glGetString(GL_EXTENSIONS)); + //strcat(pB,"\r\n\r\n"); + +#ifdef _WINDOWS + if(hW) + { + wglMakeCurrent(NULL, NULL); + wglDeleteContext(hglrc); + ReleaseDC(hW,hdc); + } + //----------------------------------------------------// +#endif + + if(hW && bWindowMode) + sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize)); + else + sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY); + strcat(pB,szTxt); + if(bWindowMode) sprintf(szTxt,"Window mode\r\n"); + else + { + sprintf(szTxt,"Fullscreen "); + strcat(pB,szTxt); + if(bChangeRes) sprintf(szTxt,"- Desktop changing [%d Bit]\r\n",iColDepth); + else sprintf(szTxt,"- NO desktop changing\r\n"); + } + strcat(pB,szTxt); + + if(iForceVSync>=0) sprintf(szTxt,"- V-Sync: %s\r\n",szO[iForceVSync]); + else strcpy(szTxt,"- V-Sync: Driver\r\n"); + strcat(pB,szTxt); + sprintf(szTxt,"- Keep psx aspect ratio: %s\r\n\r\n",szO[bKeepRatio]); + strcat(pB,szTxt); + //----------------------------------------------------// + strcpy(szTxt,"Textures:\r\n- "); + if(iTexQuality==0) strcat(szTxt,"Default"); + else if(iTexQuality==1) strcat(szTxt,"R4G4B4A4"); + else if(iTexQuality==2) strcat(szTxt,"R5G5B5A1"); + else if(iTexQuality==3) strcat(szTxt,"R8G8A8A8"); + else if(iTexQuality==4) strcat(szTxt,"B8G8R8A8"); + if(!hW && bGLExt) strcat(szTxt," (packed pixels)\r\n"); + else strcat(szTxt,"\r\n"); + strcat(pB,szTxt); + if(!hW) + { + sprintf(szTxt,"- Filtering: %d - edge clamping ",iFilterType); + if(iClampType==GL_TO_EDGE_CLAMP) strcat(szTxt,"supported\r\n"); + else strcat(szTxt,"NOT supported\r\n"); + } + else sprintf(szTxt,"- iFiltering: %d\r\n",iFilterType); + strcat(pB,szTxt); + sprintf(szTxt,"- Hi-Res textures: %d\r\n",iHiResTextures); + strcat(pB,szTxt); + if(!hW) + { + sprintf(szTxt,"- Palettized tex windows: %s\r\n",szO[iUsePalTextures]); + strcat(pB,szTxt); + } + sprintf(szTxt,"- VRam size: %d MBytes",iVRamSize); + if(!hW) + sprintf(szTxt+strlen(szTxt)," - %d textures usable\r\n\r\n",iSortTexCnt); + else strcat(szTxt,"\r\n\r\n"); + strcat(pB,szTxt); + //----------------------------------------------------// + sprintf(szTxt,"Framerate:\r\n- FPS limitation: %s\r\n",szO[bUseFrameLimit]); + strcat(pB,szTxt); + sprintf(szTxt,"- Frame skipping: %s\r\n",szO[bUseFrameSkip]); + strcat(pB,szTxt); + 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); + //----------------------------------------------------// + sprintf(szTxt,"Compatibility:\r\n- Offscreen drawing: %d\r\n",iOffscreenDrawing); + strcat(pB,szTxt); + sprintf(szTxt,"- Framebuffer texture: %d",iFrameTexType); + if(!hW && iFrameTexType==2) + { + if(gTexFrameName) strcat(szTxt," - texture created\r\n"); + else strcat(szTxt," - not used yet\r\n"); + } + else strcat(szTxt,"\r\n"); + strcat(pB,szTxt); + sprintf(szTxt,"- Framebuffer access: %d\r\n",iFrameReadType); + strcat(pB,szTxt); + sprintf(szTxt,"- Alpha multipass: %s\r\n",szO[bOpaquePass]); + strcat(pB,szTxt); + sprintf(szTxt,"- Mask bit: %s\r\n",szO[iUseMask]); + strcat(pB,szTxt); + sprintf(szTxt,"- Advanced blending: %s",szO[bAdvancedBlend]); + if(!hW && bAdvancedBlend) + { + if(bGLBlend) strcat(szTxt," (hardware)\r\n"); + else strcat(szTxt," (software)\r\n"); + } + else strcat(szTxt,"\r\n"); + strcat(pB,szTxt); + + if(!hW) + { + strcpy(szTxt,"- Subtractive blending: "); + if(glBlendEquationEXTEx) + { + if(bUseMultiPass) strcat(szTxt,"supported, but not used!"); + else strcat(szTxt,"activated"); + } + else strcat(szTxt," NOT supported!"); + strcat(szTxt,"\r\n\r\n"); + } + else strcpy(szTxt,"\r\n"); + + strcat(pB,szTxt); + //----------------------------------------------------// + sprintf(szTxt,"Misc:\r\n- Scanlines: %s",szO[iUseScanLines]); + strcat(pB,szTxt); + if(iUseScanLines) sprintf(szTxt," [%d]\r\n",iScanBlend); + else strcpy(szTxt,"\r\n"); + strcat(pB,szTxt); + sprintf(szTxt,"- Line mode: %s\r\n",szO[bUseLines]); + strcat(pB,szTxt); +// sprintf(szTxt,"- Line AA: %s\r\n",szO[bUseAntiAlias]); +// fwrite(szTxt,lstrlen(szTxt),1,txtfile); + sprintf(szTxt,"- Unfiltered FB: %s\r\n",szO[bUseFastMdec]); + strcat(pB,szTxt); + sprintf(szTxt,"- 15 bit FB: %s\r\n",szO[bUse15bitMdec]); + strcat(pB,szTxt); + sprintf(szTxt,"- Dithering: %s\r\n",szO[bDrawDither]); + strcat(pB,szTxt); + sprintf(szTxt,"- Screen smoothing: %s",szO[iBlurBuffer]); + strcat(pB,szTxt); + if(!hW && iBlurBuffer) + { + if(gTexBlurName) strcat(pB," - supported\r\n"); + else strcat(pB," - not supported\r\n"); + } + else strcat(pB,"\r\n"); + sprintf(szTxt,"- Game fixes: %s [%08x]\r\n",szO[bUseFixes],dwCfgFixes); + strcat(pB,szTxt); + //----------------------------------------------------// + return pB; +} + +//////////////////////////////////////////////////////////////////////// +// save text infos to file +//////////////////////////////////////////////////////////////////////// + +void DoTextSnapShot(int iNum) +{ + FILE *txtfile;char szTxt[256];char * pB; + +#ifdef _WINDOWS + sprintf(szTxt,"snap\\pcsx%04d.txt",iNum); +#else + sprintf(szTxt,"%s/pcsx%04d.txt",getenv("HOME"),iNum); +#endif + + if((txtfile=fopen(szTxt,"wb"))==NULL) + return; + + pB=GetConfigInfos(0); + if(pB) + { + fwrite(pB,strlen(pB),1,txtfile); + free(pB); + } + fclose(txtfile); +} + +//////////////////////////////////////////////////////////////////////// +// saves screen bitmap to file +//////////////////////////////////////////////////////////////////////// + +void DoSnapShot(void) +{ + unsigned char * snapshotdumpmem=NULL,* p,c; + FILE *bmpfile;char filename[256]; + unsigned char header[0x36];int size; + unsigned char empty[2]={0,0};int i; + unsigned int snapshotnr = 0; + short SnapWidth; + short SnapHeigth; + + bSnapShot=FALSE; + + SnapWidth = iResX; + SnapHeigth = iResY; + + size=SnapWidth * SnapHeigth * 3 + 0x38; + + if((snapshotdumpmem=(unsigned char *) + malloc(SnapWidth*SnapHeigth*3))==NULL) + return; + + // fill in proper values for BMP + for(i=0;i<0x36;i++) header[i]=0; + header[0]='B'; + header[1]='M'; + header[2]=(unsigned char)(size&0xff); + header[3]=(unsigned char)((size>>8)&0xff); + header[4]=(unsigned char)((size>>16)&0xff); + header[5]=(unsigned char)((size>>24)&0xff); + header[0x0a]=0x36; + header[0x0e]=0x28; + header[0x12]=(unsigned char)(SnapWidth%256); + header[0x13]=(unsigned char)(SnapWidth/256); + header[0x16]=(unsigned char)(SnapHeigth%256); + header[0x17]=(unsigned char)(SnapHeigth/256); + header[0x1a]=0x01; + header[0x1c]=0x18; + header[0x26]=0x12; + header[0x27]=0x0B; + header[0x2A]=0x12; + header[0x2B]=0x0B; + + // increment snapshot value + // get filename + do + { + snapshotnr++; +#ifdef _WINDOWS + sprintf(filename,"snap/pcsx%04d.bmp",snapshotnr); +#else + sprintf(filename,"%s/pcsx%04d.bmp",getenv("HOME"),snapshotnr); +#endif + bmpfile=fopen(filename,"rb"); + if(bmpfile==NULL)break; + fclose(bmpfile); + if(snapshotnr==9999) break; + } + while(TRUE); + + // try opening new snapshot file + if((bmpfile=fopen(filename,"wb"))==NULL) + {free(snapshotdumpmem);return;} + + fwrite(header,0x36,1,bmpfile); + + glReadPixels(0,0,SnapWidth,SnapHeigth,GL_RGB, + GL_UNSIGNED_BYTE,snapshotdumpmem); + p=snapshotdumpmem; + size=SnapWidth * SnapHeigth; + + for(i=0;i get sizes again + } + else // first real startup + { + ReadConfig(); // -> read config from registry + + SetFrameRateConfig(); // -> setup frame rate stuff + } + + if(iNoScreenSaver) EnableScreenSaver(FALSE); // at least we can try + + + memset(&dv,0,sizeof(DEVMODE)); + dv.dmSize=sizeof(DEVMODE); + EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dv); + + bIsFirstFrame = TRUE; // flag: we have to init OGL later in windows! + + if(bWindowMode) // win mode? + { + DWORD dw=GetWindowLong(hWWindow, GWL_STYLE); // -> adjust wnd style (owndc needed by some stupid ogl drivers) + dw&=~WS_THICKFRAME; + dw|=WS_BORDER|WS_CAPTION|CS_OWNDC; + SetWindowLong(hWWindow, GWL_STYLE, dw); + + hPSEMenu=GetMenu(hWWindow); // -> hide emu menu (if any) + if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL); + + iResX=LOWORD(iWinSize);iResY=HIWORD(iWinSize); + ShowWindow(hWWindow,SW_SHOWNORMAL); + + MoveWindow(hWWindow, // -> center wnd + GetSystemMetrics(SM_CXFULLSCREEN)/2-iResX/2, + GetSystemMetrics(SM_CYFULLSCREEN)/2-iResY/2, + iResX+GetSystemMetrics(SM_CXFIXEDFRAME)+3, + iResY+GetSystemMetrics(SM_CYFIXEDFRAME)+GetSystemMetrics(SM_CYCAPTION)+3, + TRUE); + UpdateWindow(hWWindow); // -> let windows do some update + + if(dv.dmBitsPerPel==16 || dv.dmBitsPerPel==32) // -> overwrite user color info with desktop color info + iColDepth=dv.dmBitsPerPel; + } + else // fullscreen mode: + { + if(dv.dmBitsPerPel!=(unsigned int)iColDepth || // -> check, if we have to change resolution + dv.dmPelsWidth !=(unsigned int)iResX || + dv.dmPelsHeight!=(unsigned int)iResY) + bChangeRes=TRUE; else bChangeRes=FALSE; + + if(bChangeRes) ChangeDesktop(); // -> change the res (had to do an own func because of some MS 'optimizations') + + SetWindowLong(hWWindow, GWL_STYLE, CS_OWNDC); // -> adjust wnd style as well (to be sure) + + hPSEMenu=GetMenu(hWWindow); // -> hide menu + if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL); + ShowWindow(hWWindow,SW_SHOWMAXIMIZED); // -> max mode + } + + rRatioRect.left = rRatioRect.top=0; + rRatioRect.right = iResX; + rRatioRect.bottom = iResY; + + r.left=r.top=0;r.right=iResX;r.bottom=iResY; // hack for getting a clean black window until OGL gets initialized + hdc = GetDC(hWWindow); + FillRect(hdc,&r,(HBRUSH)GetStockObject(BLACK_BRUSH)); + bSetupPixelFormat(hdc); + ReleaseDC(hWWindow,hdc); + + bDisplayNotSet = TRUE; + bSetClip=TRUE; + + SetFixes(); // setup game fixes + + InitializeTextureStore(); // init texture mem + +// lGPUstatusRet = 0x74000000; + +// with some emus, we could do the OGL init right here... oh my +// if(bIsFirstFrame) GLinitialize(); + + return 0; +} + +#elif !defined (_MACGL) + +//////////////////////////////////////////////////////////////////////// +// LINUX GPU OPEN: func to open up the gpu display (X stuff) +// please note: in linux we are creating our own display, and we return +// the display ID to the main emu... that's cleaner +//////////////////////////////////////////////////////////////////////// + +char * pCaptionText=0; +int bFullScreen=0; +Display *display; + +static Cursor cursor; +static XVisualInfo *myvisual; +static Colormap colormap; +static Window window; + +static int bModeChanged=0; + +typedef struct +{ +#define MWM_HINTS_DECORATIONS 2 + long flags; + long functions; + long decorations; + long input_mode; +} MotifWmHints; + +static int dbdepat[]={GLX_RGBA,GLX_DOUBLEBUFFER,GLX_DEPTH_SIZE,16,None}; +static int dbnodepat[]={GLX_RGBA,GLX_DOUBLEBUFFER,None}; +static GLXContext cx; + +static int fx=0; + +//////////////////////////////////////////////////////////////////////// + +void osd_close_display (void) // close display +{ + if(display) // display exists? + { + glXDestroyContext(display,cx); // -> kill context + XFreeColormap(display, colormap); // -> kill colormap + XSync(display,False); // -> sync events + +#ifndef NOVMODE + if(bModeChanged) // -> repair screen mode + { + int myscreen=DefaultScreen(display); + XF86VidModeSwitchToMode(display,myscreen, // --> switch mode back + modes[iOldMode]); + XF86VidModeSetViewPort(display,myscreen,0,0); // --> set viewport upperleft + free(modes); // --> finally kill mode infos + bModeChanged=0; // --> done + } +#endif + + XCloseDisplay(display); // -> close display + } +} + +//////////////////////////////////////////////////////////////////////// + +void sysdep_create_display(void) // create display +{ + XSetWindowAttributes winattr;float fxgamma=2; + int myscreen;char gammastr[14]; + Screen * screen;XEvent event; + XSizeHints hints;XWMHints wm_hints; + MotifWmHints mwmhints;Atom mwmatom;Atom delwindow; + char *glxfx; + + glxfx=getenv("MESA_GLX_FX"); // 3dfx mesa fullscreen flag + if(glxfx) + { + if(glxfx[0]=='f') // -> yup, fullscreen needed + { + fx=1; // -> raise flag + putenv("FX_GLIDE_NO_SPLASH="); + sprintf(gammastr,"SST_GAMMA=%2.1f",fxgamma); // -> set gamma + putenv(gammastr); + } + } + + display=XOpenDisplay(NULL); // open display + if(!display) // no display? + { + fprintf (stderr,"Failed to open display!!!\n"); + osd_close_display(); + return; // -> bye + } + + myscreen=DefaultScreen(display); // get screen id + +#ifdef NOVMODE + if(bFullScreen) {fx=1;bModeChanged=0;} +#else + if(bFullScreen) + { + XF86VidModeModeLine mode; + int nmodes,iC; + fx=1; // raise flag + XF86VidModeGetModeLine(display,myscreen,&iC,&mode); // get actual mode info + if(mode.privsize) XFree(mode.private); // no need for private stuff + bModeChanged=0; // init mode change flag + if(iResX!=mode.hdisplay || iResY!=mode.vdisplay) // wanted mode is different? + { + XF86VidModeGetAllModeLines(display,myscreen, // -> enum all mode infos + &nmodes,&modes); + if(modes) // -> infos got? + { + for(iC=0;iC loop modes + { + if(mode.hdisplay==modes[iC]->hdisplay && // -> act mode found? + mode.vdisplay==modes[iC]->vdisplay) // if yes: store mode id + iOldMode=iC; + + if(iResX==modes[iC]->hdisplay && // -> wanted mode found? + iResY==modes[iC]->vdisplay) + { + XF86VidModeSwitchToMode(display,myscreen, // --> switch to mode + modes[iC]); + XF86VidModeSetViewPort(display,myscreen,0,0); + bModeChanged=1; // --> raise flag for repairing mode on close + } + } + + if(bModeChanged==0) // -> no mode found? + { + free(modes); // --> free infos + printf("No proper fullscreen mode found!\n"); // --> some info output + } + } + } + } +#endif + + screen=DefaultScreenOfDisplay(display); + + if(iZBufferDepth) // visual (with or without zbuffer) + myvisual=glXChooseVisual(display,myscreen,dbdepat); + else myvisual=glXChooseVisual(display,myscreen,dbnodepat); + + if(!myvisual) // no visual? + { + fprintf(stderr,"Failed to obtain visual!!!\n"); // -> bye + osd_close_display(); + return; + } + + cx=glXCreateContext(display,myvisual,0,GL_TRUE); // create rendering context + + if(!cx) // no context? + { + fprintf(stderr,"Failed to create OpenGL context!!!\n"); + osd_close_display(); // -> bxe + return; + } + + // pffff... much work for a simple blank cursor... oh, well... + if(!bFullScreen) cursor=XCreateFontCursor(display,XC_trek); + else + { + Pixmap p1,p2;XImage * img; + XColor b,w;unsigned char * idata; + XGCValues GCv; + GC GCc; + + memset(&b,0,sizeof(XColor)); + memset(&w,0,sizeof(XColor)); + idata=(unsigned char *)malloc(8); + memset(idata,0,8); + + p1=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1); + p2=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1); + + img = XCreateImage(display,myvisual->visual, + 1,XYBitmap,0,idata,8,8,8,1); + + GCv.function = GXcopy; + GCv.foreground = ~0; + GCv.background = 0; + GCv.plane_mask = AllPlanes; + GCc = XCreateGC(display,p1, + (GCFunction|GCForeground|GCBackground|GCPlaneMask),&GCv); + + XPutImage(display, p1,GCc,img,0,0,0,0,8,8); + XPutImage(display, p2,GCc,img,0,0,0,0,8,8); + XFreeGC(display, GCc); + + cursor = XCreatePixmapCursor(display,p1,p2,&b,&w,0,0); + + XFreePixmap(display,p1); + XFreePixmap(display,p2); + XDestroyImage(img); // will free idata as well + } + + colormap=XCreateColormap(display, // create colormap + RootWindow(display,myvisual->screen), + myvisual->visual,AllocNone); + + winattr.background_pixel=0; + 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=colormap; + winattr.cursor=None; + + window=XCreateWindow(display, // create own window + RootWindow(display,DefaultScreen(display)), + 0,0,iResX,iResY, + 0,myvisual->depth, + InputOutput,myvisual->visual, + CWBorderPixel | CWBackPixel | + CWEventMask | CWDontPropagate | + CWColormap | CWCursor, + &winattr); + + if(!window) // no window? + { + fprintf(stderr,"Failed in XCreateWindow()!!!\n"); + osd_close_display(); // -> bye + return; + } + + delwindow = XInternAtom(display,"WM_DELETE_WINDOW",0); + XSetWMProtocols(display, window, &delwindow, 1); + + hints.flags=PMinSize|PMaxSize; // hints + if(fx) hints.flags|=USPosition|USSize; + else hints.flags|=PSize; + + hints.min_width = hints.max_width = hints.base_width = iResX; + hints.min_height = hints.max_height = hints.base_height = iResY; + + wm_hints.input=1; + wm_hints.flags=InputHint; + + XSetWMHints(display,window,&wm_hints); + XSetWMNormalHints(display,window,&hints); + if(pCaptionText) // caption + XStoreName(display,window,pCaptionText); + else XStoreName(display,window,"Pete MesaGL PSX Gpu"); + + XDefineCursor(display,window,cursor); // cursor + + if(fx) // window title bar hack + { + mwmhints.flags=MWM_HINTS_DECORATIONS; + mwmhints.decorations=0; + mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0); + XChangeProperty(display,window,mwmatom,mwmatom,32, + PropModeReplace,(unsigned char *)&mwmhints,4); + } + + XSelectInput(display,window, // input setup + FocusChangeMask | ExposureMask | + KeyPressMask | KeyReleaseMask); + + XMapRaised(display,window); + XClearWindow(display,window); + XWindowEvent(display,window,ExposureMask,&event); + glXMakeCurrent(display,window,cx); + +/* + printf(glGetString(GL_VENDOR)); + printf("\n"); + printf(glGetString(GL_RENDERER)); + printf("\n"); +*/ + + if (fx) // after make current: fullscreen resize + { + 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); + + // 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(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, RootWindow(display, DefaultScreen(display)), 0, + SubstructureRedirectMask | SubstructureNotifyMask, &xev); + } + } +} + +#endif // !defined(_MACGL) + +#ifndef _WINDOWS + +#if defined(_MACGL) +extern char * pCaptionText; +#endif + +//////////////////////////////////////////////////////////////////////// + +long GPUopen(unsigned long * disp,char * CapText,char * CfgFile) +{ + pCaptionText=CapText; + pConfigFile=CfgFile; + + ReadConfig(); // read text file for config + + SetFrameRateConfig(); // setup frame rate stuff + + bIsFirstFrame = TRUE; // we have to init later (well, no really... in Linux we do all in GPUopen) + + #if defined (_MACGL) + unsigned long display = ulInitDisplay(); + #else + sysdep_create_display(); // create display + #endif + + InitializeTextureStore(); // init texture mem + + rRatioRect.left = rRatioRect.top=0; + rRatioRect.right = iResX; + rRatioRect.bottom = iResY; + + GLinitialize(); // init opengl + + if(disp) + { + #if defined (_MACGL) + *disp = display; + #else + *disp=(unsigned long *)display; // return display ID to main emu + #endif + } + + if(display) return 0; + return -1; +} + +#endif // ndef _WINDOWS + + + +//////////////////////////////////////////////////////////////////////// +// close +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS + +long CALLBACK GPUclose() // WINDOWS CLOSE +{ + ExitKeyHandler(); + + GLcleanup(); // close OGL + + if(bChangeRes) // change res back + ChangeDisplaySettings(NULL,0); + + if(hPSEMenu) // set menu again + SetMenu(hWWindow,hPSEMenu); + + if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory + pGfxCardScreen=0; + + if(iNoScreenSaver) EnableScreenSaver(TRUE); // enable screen saver again + + return 0; +} + +#else + +long GPUclose() // LINUX CLOSE +{ + GLcleanup(); // close OGL + + if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory + pGfxCardScreen=0; + #if defined (_MACGL) + CloseDisplay(); + #else + osd_close_display(); // destroy display + #endif + return 0; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// I shot the sheriff... last function called from emu +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUshutdown() +{ + if(psxVSecure) free(psxVSecure); // kill emulated vram memory + psxVSecure=0; + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// paint it black: simple func to clean up optical border garbage +//////////////////////////////////////////////////////////////////////// + +void PaintBlackBorders(void) +{ + short s; + + glDisable(GL_SCISSOR_TEST); + if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;} + if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} + if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} + glDisable(GL_ALPHA_TEST); + + glBegin(GL_QUADS); + + vertex[0].c.lcol=0xff000000; + SETCOL(vertex[0]); + + if(PreviousPSXDisplay.Range.x0) + { + s=PreviousPSXDisplay.Range.x0+1; + glVertex3f(0,0,0.99996f); + glVertex3f(0,PSXDisplay.DisplayMode.y,0.99996f); + glVertex3f(s,PSXDisplay.DisplayMode.y,0.99996f); + glVertex3f(s,0,0.99996f); + + s+=PreviousPSXDisplay.Range.x1-2; + + glVertex3f(s,0,0.99996f); + glVertex3f(s,PSXDisplay.DisplayMode.y,0.99996f); + glVertex3f(PSXDisplay.DisplayMode.x,PSXDisplay.DisplayMode.y,0.99996f); + glVertex3f(PSXDisplay.DisplayMode.x,0,0.99996f); + } + + if(PreviousPSXDisplay.Range.y0) + { + s=PreviousPSXDisplay.Range.y0+1; + glVertex3f(0,0,0.99996f); + glVertex3f(0,s,0.99996f); + glVertex3f(PSXDisplay.DisplayMode.x,s,0.99996f); + glVertex3f(PSXDisplay.DisplayMode.x,0,0.99996f); + } + + glEnd(); + + glEnable(GL_ALPHA_TEST); + glEnable(GL_SCISSOR_TEST); +} + +//////////////////////////////////////////////////////////////////////// +// helper to draw scanlines +//////////////////////////////////////////////////////////////////////// + +__inline void XPRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ + + glBegin(GL_QUAD_STRIP); + glTexCoord2fv(&vertex1->sow); + glVertex3fv(&vertex1->x); + + glTexCoord2fv(&vertex2->sow); + glVertex3fv(&vertex2->x); + + glTexCoord2fv(&vertex4->sow); + glVertex3fv(&vertex4->x); + + glTexCoord2fv(&vertex3->sow); + glVertex3fv(&vertex3->x); + glEnd(); +} + +//////////////////////////////////////////////////////////////////////// +// scanlines +//////////////////////////////////////////////////////////////////////// + +void SetScanLines(void) +{ + glLoadIdentity(); + glOrtho(0,iResX,iResY, 0, -1, 1); + + if(bKeepRatio) + glViewport(0,0,iResX,iResY); + + glDisable(GL_SCISSOR_TEST); + glDisable(GL_ALPHA_TEST); + if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} + + if(iScanBlend<0) // special texture mask scanline mode + { + if(!bTexEnabled) {glEnable(GL_TEXTURE_2D);bTexEnabled=TRUE;} + gTexName=gTexScanName; + glBindTexture(GL_TEXTURE_2D, gTexName); + if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + if(!bBlendEnable) {glEnable(GL_BLEND);bBlendEnable=TRUE;} + SetScanTexTrans(); + + vertex[0].x=0; + vertex[0].y=iResY; + vertex[0].z=0.99996f; + + vertex[1].x=iResX; + vertex[1].y=iResY; + vertex[1].z=0.99996f; + + vertex[2].x=iResX; + vertex[2].y=0; + vertex[2].z=0.99996f; + + vertex[3].x=0; + vertex[3].y=0; + vertex[3].z=0.99996f; + + vertex[0].sow=0; + vertex[0].tow=0; + vertex[1].sow=(float)iResX/4.0f; + vertex[1].tow=0; + vertex[2].sow=vertex[1].sow; + vertex[2].tow=(float)iResY/4.0f; + vertex[3].sow=0; + vertex[3].tow=vertex[2].tow; + + vertex[0].c.lcol=0xffffffff; + SETCOL(vertex[0]); + + XPRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT); + } + else // typical line mode + { + if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;} + + if(iScanBlend==0) + { + if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} + vertex[0].c.lcol=0xff000000; + } + else + { + if(!bBlendEnable) {glEnable(GL_BLEND);bBlendEnable=TRUE;} + SetScanTrans(); + vertex[0].c.lcol=iScanBlend<<24; + } + + SETCOL(vertex[0]); + + glCallList(uiScanLine); + } + + glLoadIdentity(); + glOrtho(0,PSXDisplay.DisplayMode.x, + PSXDisplay.DisplayMode.y, 0, -1, 1); + + if(bKeepRatio) + glViewport(rRatioRect.left, + iResY-(rRatioRect.top+rRatioRect.bottom), + rRatioRect.right, + rRatioRect.bottom); // init viewport + + glEnable(GL_ALPHA_TEST); + glEnable(GL_SCISSOR_TEST); +} + +//////////////////////////////////////////////////////////////////////// +// blur, babe, blur (heavy performance hit for a so-so fullscreen effect) +//////////////////////////////////////////////////////////////////////// + +void BlurBackBuffer(void) +{ + if(!gTexBlurName) return; + + if(bKeepRatio) glViewport(0,0,iResX,iResY); + + glDisable(GL_SCISSOR_TEST); + glDisable(GL_ALPHA_TEST); + if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} + if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} + if(!bTexEnabled) {glEnable(GL_TEXTURE_2D);bTexEnabled=TRUE;} + if(iZBufferDepth) glDisable(GL_DEPTH_TEST); + if(bDrawDither) glDisable(GL_DITHER); + + gTexName=gTexBlurName; + glBindTexture(GL_TEXTURE_2D, gTexName); + + glCopyTexSubImage2D( GL_TEXTURE_2D, 0, // get back buffer in texture + 0, + 0, + 0, + 0, + iResX,iResY); + + vertex[0].x=0; + vertex[0].y=PSXDisplay.DisplayMode.y; + vertex[1].x=PSXDisplay.DisplayMode.x; + vertex[1].y=PSXDisplay.DisplayMode.y; + vertex[2].x=PSXDisplay.DisplayMode.x; + vertex[2].y=0; + vertex[3].x=0; + vertex[3].y=0; + vertex[0].sow=0; + vertex[0].tow=0; + +#ifdef OWNSCALE + vertex[1].sow=((GLfloat)iFTexA)/256.0f; + vertex[2].tow=((GLfloat)iFTexB)/256.0f; +#else + vertex[1].sow=iFTexA; + vertex[2].tow=iFTexB; +#endif + vertex[1].tow=0; + vertex[2].sow=vertex[1].sow; + vertex[3].sow=0; + vertex[3].tow=vertex[2].tow; + + if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + vertex[0].c.lcol=0x7fffffff; + SETCOL(vertex[0]); + + DrawMultiBlur(); // draw the backbuffer texture to create blur effect + + glEnable(GL_ALPHA_TEST); + glEnable(GL_SCISSOR_TEST); + if(iZBufferDepth) glEnable(GL_DEPTH_TEST); + if(bDrawDither) glEnable(GL_DITHER); + if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT); + + if(bKeepRatio) + glViewport(rRatioRect.left, // re-init viewport + iResY-(rRatioRect.top+rRatioRect.bottom), + rRatioRect.right, + rRatioRect.bottom); +} + +//////////////////////////////////////////////////////////////////////// +// "unblur" repairs the backbuffer after a blur + +void UnBlurBackBuffer(void) +{ + if(!gTexBlurName) return; + + if(bKeepRatio) glViewport(0,0,iResX,iResY); + + glDisable(GL_SCISSOR_TEST); + glDisable(GL_ALPHA_TEST); + if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} + if(!bTexEnabled) {glEnable(GL_TEXTURE_2D);bTexEnabled=TRUE;} + if(iZBufferDepth) glDisable(GL_DEPTH_TEST); + if(bDrawDither) glDisable(GL_DITHER); + + gTexName=gTexBlurName; + glBindTexture(GL_TEXTURE_2D, gTexName); + + vertex[0].x=0; + vertex[0].y=PSXDisplay.DisplayMode.y; + vertex[1].x=PSXDisplay.DisplayMode.x; + vertex[1].y=PSXDisplay.DisplayMode.y; + vertex[2].x=PSXDisplay.DisplayMode.x; + vertex[2].y=0; + vertex[3].x=0; + vertex[3].y=0; + vertex[0].sow=0; + vertex[0].tow=0; +#ifdef OWNSCALE + vertex[1].sow=((GLfloat)iFTexA)/256.0f; + vertex[2].tow=((GLfloat)iFTexB)/256.0f; +#else + vertex[1].sow=iFTexA; + vertex[2].tow=iFTexB; +#endif + vertex[1].tow=0; + vertex[2].sow=vertex[1].sow; + vertex[3].sow=0; + vertex[3].tow=vertex[2].tow; + if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + vertex[0].c.lcol=0xffffffff; + SETCOL(vertex[0]); + + // simply draw the backbuffer texture (without blur) + XPRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + glEnable(GL_ALPHA_TEST); + glEnable(GL_SCISSOR_TEST); + if(iZBufferDepth) glEnable(GL_DEPTH_TEST); + if(bDrawDither) glEnable(GL_DITHER); // dither mode + if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT); + + if(bKeepRatio) + glViewport(rRatioRect.left, + iResY-(rRatioRect.top+rRatioRect.bottom), + rRatioRect.right, + rRatioRect.bottom); // init viewport +} + +//////////////////////////////////////////////////////////////////////// +// Update display (swap buffers)... called in interlaced mode on +// every emulated vsync, otherwise whenever the displayed screen region +// has been changed +//////////////////////////////////////////////////////////////////////// + +int iLastRGB24=0; // special vars for checking when to skip two display updates +int iSkipTwo=0; + +void updateDisplay(void) // UPDATE DISPLAY +{ + BOOL bBlur=FALSE; + +#ifdef _WINDOWS + HDC hdc=GetDC(hWWindow); // windows: + wglMakeCurrent(hdc,GLCONTEXT); // -> make context current again +#endif +#if defined (_MACGL) + BringContextForward(); +#endif + bFakeFrontBuffer=FALSE; + bRenderFrontBuffer=FALSE; + + if(iRenderFVR) // frame buffer read fix mode still active? + { + iRenderFVR--; // -> if some frames in a row without read access: turn off mode + if(!iRenderFVR) bFullVRam=FALSE; + } + + if(iLastRGB24 && iLastRGB24!=PSXDisplay.RGB24+1) // (mdec) garbage check + { + iSkipTwo=2; // -> skip two frames to avoid garbage if color mode changes + } + iLastRGB24=0; + + if(PSXDisplay.RGB24)// && !bNeedUploadAfter) // (mdec) upload wanted? + { + PrepareFullScreenUpload(-1); + UploadScreen(PSXDisplay.Interlaced); // -> upload whole screen from psx vram + bNeedUploadTest=FALSE; + bNeedInterlaceUpdate=FALSE; + bNeedUploadAfter=FALSE; + bNeedRGB24Update=FALSE; + } + else + if(bNeedInterlaceUpdate) // smaller upload? + { + bNeedInterlaceUpdate=FALSE; + xrUploadArea=xrUploadAreaIL; // -> upload this rect + UploadScreen(TRUE); + } + + if(dwActFixes&512) bCheckFF9G4(NULL); // special game fix for FF9 + + if(PreviousPSXDisplay.Range.x0|| // paint black borders around display area, if needed + PreviousPSXDisplay.Range.y0) + PaintBlackBorders(); + + if(PSXDisplay.Disabled) // display disabled? + { + // moved here + glDisable(GL_SCISSOR_TEST); + glClearColor(0,0,0,128); // -> clear whole backbuffer + glClear(uiBufferBits); + glEnable(GL_SCISSOR_TEST); + gl_z=0.0f; + bDisplayNotSet = TRUE; + } + + if(iSkipTwo) // we are in skipping mood? + { + iSkipTwo--; + iDrawnSomething=0; // -> simply lie about something drawn + } + + if(iBlurBuffer && !bSkipNextFrame) // "blur display" activated? + {BlurBackBuffer();bBlur=TRUE;} // -> blur it + + if(iUseScanLines) SetScanLines(); // "scan lines" activated? do it + + if(usCursorActive) ShowGunCursor(); // "gun cursor" wanted? show 'em + + if(dwActFixes&128) // special FPS limitation mode? + { + if(bUseFrameLimit) PCFrameCap(); // -> ok, do it + if(bUseFrameSkip || ulKeybits&KEY_SHOWFPS) + PCcalcfps(); + } + + if(gTexPicName) DisplayPic(); // some gpu info picture active? display it + + if(bSnapShot) DoSnapShot(); // snapshot key pressed? cheeeese :) + + if(ulKeybits&KEY_SHOWFPS) // wanna see FPS? + { + sprintf(szDispBuf,"%06.1f",fps_cur); + DisplayText(); // -> show it + } + + //----------------------------------------------------// + // main buffer swapping (well, or skip it) + + if(bUseFrameSkip) // frame skipping active ? + { + if(!bSkipNextFrame) + { + if(iDrawnSomething) +#ifdef _WINDOWS + SwapBuffers(wglGetCurrentDC()); // -> to skip or not to skip +#elif defined(_MACGL) + DoBufferSwap(); +#else + glXSwapBuffers(display,window); +#endif + } + if(dwActFixes&0x180) // -> special old frame skipping: skip max one in a row + { + if((fps_skip < fFrameRateHz) && !(bSkipNextFrame)) + {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;} + else bSkipNextFrame = FALSE; + } + else FrameSkip(); + } + else // no skip ? + { + if(iDrawnSomething) +#ifdef _WINDOWS + SwapBuffers(wglGetCurrentDC()); // -> swap +#elif defined(_MACGL) + DoBufferSwap(); +#else + glXSwapBuffers(display,window); +#endif + } + + iDrawnSomething=0; + + //----------------------------------------------------// + + if(lClearOnSwap) // clear buffer after swap? + { + GLclampf g,b,r; + + if(bDisplayNotSet) // -> set new vals + SetOGLDisplaySettings(1); + + g=((GLclampf)GREEN(lClearOnSwapColor))/255.0f; // -> get col + b=((GLclampf)BLUE(lClearOnSwapColor))/255.0f; + r=((GLclampf)RED(lClearOnSwapColor))/255.0f; + + glDisable(GL_SCISSOR_TEST); + glClearColor(r,g,b,128); // -> clear + glClear(uiBufferBits); + glEnable(GL_SCISSOR_TEST); + lClearOnSwap=0; // -> done + } + else + { + if(bBlur) UnBlurBackBuffer(); // unblur buff, if blurred before + + if(iZBufferDepth) // clear zbuffer as well (if activated) + { + glDisable(GL_SCISSOR_TEST); + glClear(GL_DEPTH_BUFFER_BIT); + glEnable(GL_SCISSOR_TEST); + } + } + gl_z=0.0f; + + //----------------------------------------------------// + // additional uploads immediatly after swapping + + if(bNeedUploadAfter) // upload wanted? + { + bNeedUploadAfter=FALSE; + bNeedUploadTest=FALSE; + UploadScreen(-1); // -> upload + } + + if(bNeedUploadTest) + { + bNeedUploadTest=FALSE; + if(PSXDisplay.InterlacedTest && + //iOffscreenDrawing>2 && + PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x && + PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x && + PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y && + PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y) + { + PrepareFullScreenUpload(TRUE); + UploadScreen(TRUE); + } + } + + //----------------------------------------------------// + // rumbling (main emu pad effect) + + if(iRumbleTime) // shake screen by modifying view port + { + int i1=0,i2=0,i3=0,i4=0; + + iRumbleTime--; + if(iRumbleTime) + { + i1=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + i2=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + i3=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + i4=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + } + + glViewport(rRatioRect.left+i1, + iResY-(rRatioRect.top+rRatioRect.bottom)+i2, + rRatioRect.right+i3, + rRatioRect.bottom+i4); + } + +#ifdef _WINDOWS + ReleaseDC(hWWindow,hdc); // ! important ! +#endif + + if(ulKeybits&KEY_RESETTEXSTORE) ResetStuff(); // reset on gpu mode changes? do it before next frame is filled +} + +//////////////////////////////////////////////////////////////////////// +// update front display: smaller update func, if something has changed +// in the frontbuffer... dirty, but hey... real men know no pain +//////////////////////////////////////////////////////////////////////// + +void updateFrontDisplay(void) +{ + if(PreviousPSXDisplay.Range.x0|| + PreviousPSXDisplay.Range.y0) + PaintBlackBorders(); + + if(iBlurBuffer) BlurBackBuffer(); + + if(iUseScanLines) SetScanLines(); + + if(usCursorActive) ShowGunCursor(); + + bFakeFrontBuffer=FALSE; + bRenderFrontBuffer=FALSE; + + if(gTexPicName) DisplayPic(); + if(ulKeybits&KEY_SHOWFPS) DisplayText(); + +#ifdef _WINDOWS + { // windows: + HDC hdc=GetDC(hWWindow); + wglMakeCurrent(hdc,GLCONTEXT); // -> make current again + if(iDrawnSomething) + SwapBuffers(wglGetCurrentDC()); // -> swap + ReleaseDC(hWWindow,hdc); // -> ! important ! + } +#elif defined (_MACGL) +if (iDrawnSomething){ + DoBufferSwap(); + } +#else + if(iDrawnSomething) // linux: + glXSwapBuffers(display,window); +#endif + + if(iBlurBuffer) UnBlurBackBuffer(); +} + +//////////////////////////////////////////////////////////////////////// +// check if update needed +//////////////////////////////////////////////////////////////////////// + +void ChangeDispOffsetsX(void) // CENTER X +{ + int lx,l;short sO; + + if(!PSXDisplay.Range.x1) return; // some range given? + + l=PSXDisplay.DisplayMode.x; + + l*=(int)PSXDisplay.Range.x1; // some funky calculation + l/=2560;lx=l;l&=0xfffffff8; + + if(l==PreviousPSXDisplay.Range.x1) return; // some change? + + sO=PreviousPSXDisplay.Range.x0; // store old + + if(lx>=PSXDisplay.DisplayMode.x) // range bigger? + { + PreviousPSXDisplay.Range.x1= // -> take display width + PSXDisplay.DisplayMode.x; + PreviousPSXDisplay.Range.x0=0; // -> start pos is 0 + } + else // range smaller? center it + { + PreviousPSXDisplay.Range.x1=l; // -> store width (8 pixel aligned) + PreviousPSXDisplay.Range.x0= // -> calc start pos + (PSXDisplay.Range.x0-500)/8; + if(PreviousPSXDisplay.Range.x0<0) // -> we don't support neg. values yet + PreviousPSXDisplay.Range.x0=0; + + if((PreviousPSXDisplay.Range.x0+lx)> // -> uhuu... that's too much + PSXDisplay.DisplayMode.x) + { + PreviousPSXDisplay.Range.x0= // -> adjust start + PSXDisplay.DisplayMode.x-lx; + PreviousPSXDisplay.Range.x1+=lx-l; // -> adjust width + } + } + + if(sO!=PreviousPSXDisplay.Range.x0) // something changed? + { + bDisplayNotSet=TRUE; // -> recalc display stuff + } +} + +//////////////////////////////////////////////////////////////////////// + +void ChangeDispOffsetsY(void) // CENTER Y +{ + int iT;short sO; // store previous y size + + if(PSXDisplay.PAL) iT=48; else iT=28; // different offsets on PAL/NTSC + + if(PSXDisplay.Range.y0>=iT) // crossed the security line? :) + { + PreviousPSXDisplay.Range.y1= // -> store width + PSXDisplay.DisplayModeNew.y; + + sO=(PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double; // -> calc offset + if(sO<0) sO=0; + + PSXDisplay.DisplayModeNew.y+=sO; // -> add offset to y size, too + } + else sO=0; // else no offset + + if(sO!=PreviousPSXDisplay.Range.y0) // something changed? + { + PreviousPSXDisplay.Range.y0=sO; + bDisplayNotSet=TRUE; // -> recalc display stuff + } +} + +//////////////////////////////////////////////////////////////////////// +// Aspect ratio of ogl screen: simply adjusting ogl view port +//////////////////////////////////////////////////////////////////////// + +void SetAspectRatio(void) +{ + float xs,ys,s;RECT r; + + if(!PSXDisplay.DisplayModeNew.x) return; + if(!PSXDisplay.DisplayModeNew.y) return; + + xs=(float)iResX/(float)PSXDisplay.DisplayModeNew.x; + ys=(float)iResY/(float)PSXDisplay.DisplayModeNew.y; + + s=min(xs,ys); + r.right =(int)((float)PSXDisplay.DisplayModeNew.x*s); + r.bottom=(int)((float)PSXDisplay.DisplayModeNew.y*s); + if(r.right > iResX) r.right = iResX; + if(r.bottom > iResY) r.bottom = iResY; + if(r.right < 1) r.right = 1; + if(r.bottom < 1) r.bottom = 1; + + r.left = (iResX-r.right)/2; + r.top = (iResY-r.bottom)/2; + + if(r.bottom new psx resolution + PSXDisplay.DisplayModeNew.y, 0, -1, 1); + if(bKeepRatio) SetAspectRatio(); + } + + bDisplayNotSet = TRUE; // re-calc offsets/display area + + bUp=FALSE; + if(PSXDisplay.RGB24!=PSXDisplay.RGB24New) // clean up textures, if rgb mode change (usually mdec on/off) + { + PreviousPSXDisplay.RGB24=0; // no full 24 frame uploaded yet + ResetTextureArea(FALSE); + bUp=TRUE; + } + + PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos + PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y; + PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x; + PSXDisplay.Interlaced = PSXDisplay.InterlacedNew; + + PSXDisplay.DisplayEnd.x= // calc new ends + PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PSXDisplay.DisplayEnd.y= + PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + PreviousPSXDisplay.DisplayEnd.x= + PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PreviousPSXDisplay.DisplayEnd.y= + PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + + ChangeDispOffsetsX(); + + if(iFrameLimit==2) SetAutoFrameCap(); // set new fps limit vals (depends on interlace) + + if(bUp) updateDisplay(); // yeah, real update (swap buffer) +} + +//////////////////////////////////////////////////////////////////////// +// window mode <-> fullscreen mode (windows) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void ChangeWindowMode(void) + { + GPUclose(); + bWindowMode=!bWindowMode; + GPUopen(hWWindow); + bChangeWinMode=FALSE; + } +#endif + +//////////////////////////////////////////////////////////////////////// +// swap update check (called by psx vsync function) +//////////////////////////////////////////////////////////////////////// + +BOOL bSwapCheck(void) +{ + static int iPosCheck=0; + static PSXPoint_t pO; + static PSXPoint_t pD; + static int iDoAgain=0; + + if(PSXDisplay.DisplayPosition.x==pO.x && + PSXDisplay.DisplayPosition.y==pO.y && + PSXDisplay.DisplayEnd.x==pD.x && + PSXDisplay.DisplayEnd.y==pD.y) + iPosCheck++; + else iPosCheck=0; + + pO=PSXDisplay.DisplayPosition; + pD=PSXDisplay.DisplayEnd; + + if(iPosCheck<=4) return FALSE; + + iPosCheck=4; + + if(PSXDisplay.Interlaced) return FALSE; + + if (bNeedInterlaceUpdate|| + bNeedRGB24Update || + bNeedUploadAfter|| + bNeedUploadTest || + iDoAgain + ) + { + iDoAgain=0; + if(bNeedUploadAfter) + iDoAgain=1; + if(bNeedUploadTest && PSXDisplay.InterlacedTest) + iDoAgain=1; + + bDisplayNotSet = TRUE; + updateDisplay(); + + PreviousPSXDisplay.DisplayPosition.x=PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y=PSXDisplay.DisplayPosition.y; + PreviousPSXDisplay.DisplayEnd.x=PSXDisplay.DisplayEnd.x; + PreviousPSXDisplay.DisplayEnd.y=PSXDisplay.DisplayEnd.y; + pO=PSXDisplay.DisplayPosition; + pD=PSXDisplay.DisplayEnd; + + return TRUE; + } + + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// +// gun cursor func: player=0-7, x=0-511, y=0-255 +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUcursor(int iPlayer,int x,int y) +{ + if(iPlayer<0) return; + if(iPlayer>7) return; + + usCursorActive|=(1<iGPUHeightMask) x=iGPUHeightMask; + if(y<0) y=0; + if(y>255) y=255; + + ptCursorPoint[iPlayer].x=x; + ptCursorPoint[iPlayer].y=y; +} + +//////////////////////////////////////////////////////////////////////// +// update lace is called every VSync. Basically we limit frame rate +// here, and in interlaced mode we swap ogl display buffers. +//////////////////////////////////////////////////////////////////////// + +static unsigned short usFirstPos=2; + +void CALLBACK GPUupdateLace(void) +{ + //if(!(dwActFixes&0x1000)) + // STATUSREG^=0x80000000; // interlaced bit toggle, if the CC game fix is not active (see gpuReadStatus) + + if(!(dwActFixes&128)) // normal frame limit func + CheckFrameRate(); + + if(iOffscreenDrawing==4) // special check if high offscreen drawing is on + { + if(bSwapCheck()) return; + } + + if(PSXDisplay.Interlaced) // interlaced mode? + { + STATUSREG^=0x80000000; + if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0) + { + updateDisplay(); // -> swap buffers (new frame) + } + } + else if(bRenderFrontBuffer) // no interlace mode? and some stuff in front has changed? + { + updateFrontDisplay(); // -> update front buffer + } + else if(usFirstPos==1) // initial updates (after startup) + { + updateDisplay(); + } + +#if defined(_WINDOWS) || defined(_MACGL) + if(bChangeWinMode) ChangeWindowMode(); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// process read request from GPU status register +//////////////////////////////////////////////////////////////////////// + +uint32_t CALLBACK GPUreadStatus(void) +{ + if(dwActFixes&0x1000) // CC game fix + { + static int iNumRead=0; + if((iNumRead++)==2) + { + iNumRead=0; + STATUSREG^=0x80000000; // interlaced bit toggle... we do it on every second read status... needed by some games (like ChronoCross) + } + } + + if(iFakePrimBusy) // 27.10.2007 - emulating some 'busy' while drawing... pfff... not perfect, but since our emulated dma is not done in an extra thread... + { + iFakePrimBusy--; + + if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims + { + GPUIsBusy; + GPUIsNotReadyForCommands; + } + else + { + GPUIsIdle; + GPUIsReadyForCommands; + } + } + + return STATUSREG | (vBlank ? 0x80000000 : 0 );; +} + +//////////////////////////////////////////////////////////////////////// +// 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; + +#ifdef _WINDOWS + if(bIsFirstFrame) GLinitialize(); // real ogl startup (needed by some emus) +#endif + + ulStatusControl[lCommand]=gdata; + + switch(lCommand) + { + //--------------------------------------------------// + // reset gpu + case 0x00: + memset(ulGPUInfoVals, 0x00, 16 * sizeof(uint32_t)); + lGPUstatusRet = 0x14802000; + PSXDisplay.Disabled=1; + iDataWriteMode=iDataReadMode=DR_NORMAL; + PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0; + drawX=drawY=0;drawW=drawH=0; + sSetMask=0;lSetMask=0;bCheckMask=FALSE;iSetMask=0; + usMirror=0; + GlobalTextAddrX=0;GlobalTextAddrY=0; + GlobalTextTP=0;GlobalTextABR=0; + PSXDisplay.RGB24=FALSE; + PSXDisplay.Interlaced=FALSE; + bUsingTWin = FALSE; + return; + + // dis/enable display + case 0x03: + PreviousPSXDisplay.Disabled = PSXDisplay.Disabled; + PSXDisplay.Disabled = (gdata & 1); + + if(PSXDisplay.Disabled) + STATUSREG|=GPUSTATUS_DISPLAYDISABLED; + else STATUSREG&=~GPUSTATUS_DISPLAYDISABLED; + + if (iOffscreenDrawing==4 && + PreviousPSXDisplay.Disabled && + !(PSXDisplay.Disabled)) + { + + if(!PSXDisplay.RGB24) + { + PrepareFullScreenUpload(TRUE); + UploadScreen(TRUE); + updateDisplay(); + } + } + + return; + + // setting transfer mode + case 0x04: + gdata &= 0x03; // only want the lower two bits + + iDataWriteMode=iDataReadMode=DR_NORMAL; + if(gdata==0x02) iDataWriteMode=DR_VRAMTRANSFER; + if(gdata==0x03) iDataReadMode =DR_VRAMTRANSFER; + + STATUSREG&=~GPUSTATUS_DMABITS; // clear the current settings of the DMA bits + STATUSREG|=(gdata << 29); // set the DMA bits according to the received data + + return; + + // setting display position + case 0x05: + { + short sx=(short)(gdata & 0x3ff); + short sy; + + if(iGPUHeight==1024) + { + if(dwGPUVersion==2) + sy = (short)((gdata>>12)&0x3ff); + else sy = (short)((gdata>>10)&0x3ff); + } + else sy = (short)((gdata>>10)&0x3ff); // really: 0x1ff, but we adjust it later + + if (sy & 0x200) + { + sy|=0xfc00; + PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double; + sy=0; + } + else PreviousPSXDisplay.DisplayModeNew.y=0; + + if(sx>1000) sx=0; + + if(usFirstPos) + { + usFirstPos--; + if(usFirstPos) + { + PreviousPSXDisplay.DisplayPosition.x = sx; + PreviousPSXDisplay.DisplayPosition.y = sy; + PSXDisplay.DisplayPosition.x = sx; + PSXDisplay.DisplayPosition.y = sy; + } + } + + if(dwActFixes&8) + { + if((!PSXDisplay.Interlaced) && + PreviousPSXDisplay.DisplayPosition.x == sx && + PreviousPSXDisplay.DisplayPosition.y == sy) + return; + + PSXDisplay.DisplayPosition.x = PreviousPSXDisplay.DisplayPosition.x; + PSXDisplay.DisplayPosition.y = PreviousPSXDisplay.DisplayPosition.y; + PreviousPSXDisplay.DisplayPosition.x = sx; + PreviousPSXDisplay.DisplayPosition.y = sy; + } + else + { + if((!PSXDisplay.Interlaced) && + PSXDisplay.DisplayPosition.x == sx && + PSXDisplay.DisplayPosition.y == sy) + return; + PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; + PSXDisplay.DisplayPosition.x = sx; + PSXDisplay.DisplayPosition.y = sy; + } + + PSXDisplay.DisplayEnd.x= + PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PSXDisplay.DisplayEnd.y= + PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + + PreviousPSXDisplay.DisplayEnd.x= + PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PreviousPSXDisplay.DisplayEnd.y= + PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + + bDisplayNotSet = TRUE; + + if (!(PSXDisplay.Interlaced)) + { + updateDisplay(); + } + else + if(PSXDisplay.InterlacedTest && + ((PreviousPSXDisplay.DisplayPosition.x != PSXDisplay.DisplayPosition.x)|| + (PreviousPSXDisplay.DisplayPosition.y != PSXDisplay.DisplayPosition.y))) + PSXDisplay.InterlacedTest--; + + return; + } + + // setting width + case 0x06: + + PSXDisplay.Range.x0=gdata & 0x7ff; //0x3ff; + PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff; + + PSXDisplay.Range.x1-=PSXDisplay.Range.x0; + + ChangeDispOffsetsX(); + + return; + + // setting height + case 0x07: + + PreviousPSXDisplay.Height = PSXDisplay.Height; + + PSXDisplay.Range.y0=gdata & 0x3ff; + PSXDisplay.Range.y1=(gdata>>10) & 0x3ff; + + PSXDisplay.Height = PSXDisplay.Range.y1 - + PSXDisplay.Range.y0 + + PreviousPSXDisplay.DisplayModeNew.y; + + if (PreviousPSXDisplay.Height != PSXDisplay.Height) + { + PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double; + ChangeDispOffsetsY(); + updateDisplayIfChanged(); + } + return; + + // setting display infos + case 0x08: + + PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)]; + + if (gdata&0x04) PSXDisplay.Double=2; + else PSXDisplay.Double=1; + PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double; + + ChangeDispOffsetsY(); + + PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC + PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor + PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace + + STATUSREG&=~GPUSTATUS_WIDTHBITS; // clear the width bits + + STATUSREG|= + (((gdata & 0x03) << 17) | + ((gdata & 0x40) << 10)); // set the width bits + + PreviousPSXDisplay.InterlacedNew=FALSE; + if (PSXDisplay.InterlacedNew) + { + if(!PSXDisplay.Interlaced) + { + PSXDisplay.InterlacedTest=2; + PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; + PreviousPSXDisplay.InterlacedNew=TRUE; + } + + STATUSREG|=GPUSTATUS_INTERLACED; + } + else + { + PSXDisplay.InterlacedTest=0; + STATUSREG&=~GPUSTATUS_INTERLACED; + } + + if (PSXDisplay.PAL) + STATUSREG|=GPUSTATUS_PAL; + else STATUSREG&=~GPUSTATUS_PAL; + + if (PSXDisplay.Double==2) + STATUSREG|=GPUSTATUS_DOUBLEHEIGHT; + else STATUSREG&=~GPUSTATUS_DOUBLEHEIGHT; + + if (PSXDisplay.RGB24New) + STATUSREG|=GPUSTATUS_RGB24; + else STATUSREG&=~GPUSTATUS_RGB24; + + updateDisplayIfChanged(); + + return; + + //--------------------------------------------------// + // ask about GPU version and other stuff + case 0x10: + + gdata&=0xff; + + switch(gdata) + { + case 0x02: + GPUdataRet=ulGPUInfoVals[INFO_TW]; // tw infos + return; + case 0x03: + GPUdataRet=ulGPUInfoVals[INFO_DRAWSTART]; // draw start + return; + case 0x04: + GPUdataRet=ulGPUInfoVals[INFO_DRAWEND]; // draw end + return; + case 0x05: + case 0x06: + GPUdataRet=ulGPUInfoVals[INFO_DRAWOFF]; // draw offset + return; + case 0x07: + if(dwGPUVersion==2) + GPUdataRet=0x01; + else GPUdataRet=0x02; // gpu type + return; + case 0x08: + case 0x0F: // some bios addr? + GPUdataRet=0xBFC03720; + return; + } + return; + //--------------------------------------------------// + } +} + +//////////////////////////////////////////////////////////////////////// +// vram read/write helpers +//////////////////////////////////////////////////////////////////////// + +BOOL bNeedWriteUpload=FALSE; + +__inline void FinishedVRAMWrite(void) +{ + if(bNeedWriteUpload) + { + bNeedWriteUpload=FALSE; + CheckWriteUpdate(); + } + + // set register to NORMAL operation + iDataWriteMode = DR_NORMAL; + + // reset transfer values, to prevent mis-transfer of data + VRAMWrite.ColsRemaining = 0; + VRAMWrite.RowsRemaining = 0; +} + +__inline void FinishedVRAMRead(void) +{ + // set register to NORMAL operation + iDataReadMode = DR_NORMAL; + // reset transfer values, to prevent mis-transfer of data + VRAMRead.x = 0; + VRAMRead.y = 0; + VRAMRead.Width = 0; + VRAMRead.Height = 0; + VRAMRead.ColsRemaining = 0; + VRAMRead.RowsRemaining = 0; + + // indicate GPU is no longer ready for VRAM data in the STATUS REGISTER + STATUSREG&=~GPUSTATUS_READYFORVRAM; +} + +//////////////////////////////////////////////////////////////////////// +// vram read check ex (reading from card's back/frontbuffer if needed... +// slow!) +//////////////////////////////////////////////////////////////////////// + +void CheckVRamReadEx(int x, int y, int dx, int dy) +{ + unsigned short sArea; + int ux,uy,udx,udy,wx,wy; + unsigned short * p1, *p2; + float XS,YS; + unsigned char * ps; + unsigned char * px; + unsigned short s,sx; + + if(STATUSREG&GPUSTATUS_RGB24) return; + + if(((dx > PSXDisplay.DisplayPosition.x) && + (x < PSXDisplay.DisplayEnd.x) && + (dy > PSXDisplay.DisplayPosition.y) && + (y < PSXDisplay.DisplayEnd.y))) + sArea=0; + else + if((!(PSXDisplay.InterlacedTest) && + (dx > PreviousPSXDisplay.DisplayPosition.x) && + (x < PreviousPSXDisplay.DisplayEnd.x) && + (dy > PreviousPSXDisplay.DisplayPosition.y) && + (y < PreviousPSXDisplay.DisplayEnd.y))) + sArea=1; + else + { + return; + } + + ////////////// + + if(iRenderFVR) + { + bFullVRam=TRUE;iRenderFVR=2;return; + } + bFullVRam=TRUE;iRenderFVR=2; + + ////////////// + + p2=0; + + if(sArea==0) + { + ux=PSXDisplay.DisplayPosition.x; + uy=PSXDisplay.DisplayPosition.y; + udx=PSXDisplay.DisplayEnd.x-ux; + udy=PSXDisplay.DisplayEnd.y-uy; + if((PreviousPSXDisplay.DisplayEnd.x- + PreviousPSXDisplay.DisplayPosition.x)==udx && + (PreviousPSXDisplay.DisplayEnd.y- + PreviousPSXDisplay.DisplayPosition.y)==udy) + p2=(psxVuw + (1024*PreviousPSXDisplay.DisplayPosition.y) + + PreviousPSXDisplay.DisplayPosition.x); + } + else + { + ux=PreviousPSXDisplay.DisplayPosition.x; + uy=PreviousPSXDisplay.DisplayPosition.y; + udx=PreviousPSXDisplay.DisplayEnd.x-ux; + udy=PreviousPSXDisplay.DisplayEnd.y-uy; + if((PSXDisplay.DisplayEnd.x- + PSXDisplay.DisplayPosition.x)==udx && + (PSXDisplay.DisplayEnd.y- + PSXDisplay.DisplayPosition.y)==udy) + p2=(psxVuw + (1024*PSXDisplay.DisplayPosition.y) + + PSXDisplay.DisplayPosition.x); + } + + p1=(psxVuw + (1024*uy) + ux); + if(p1==p2) p2=0; + + x=0;y=0; + wx=dx=udx;wy=dy=udy; + + if(udx<=0) return; + if(udy<=0) return; + if(dx<=0) return; + if(dy<=0) return; + if(wx<=0) return; + if(wy<=0) return; + + XS=(float)rRatioRect.right/(float)wx; + YS=(float)rRatioRect.bottom/(float)wy; + + dx=(int)((float)(dx)*XS); + dy=(int)((float)(dy)*YS); + + if(dx>iResX) dx=iResX; + if(dy>iResY) dy=iResY; + + if(dx<=0) return; + if(dy<=0) return; + + // ogl y adjust + y=iResY-y-dy; + + x+=rRatioRect.left; + y-=rRatioRect.top; + + if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y; + + if(!pGfxCardScreen) + { + glPixelStorei(GL_PACK_ALIGNMENT,1); + pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4); + } + + ps=pGfxCardScreen; + + if(!sArea) glReadBuffer(GL_FRONT); + + glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); + + if(!sArea) glReadBuffer(GL_BACK); + + s=0; + + XS=(float)dx/(float)(udx); + YS=(float)dy/(float)(udy+1); + + for(y=udy;y>0;y--) + { + for(x=0;x=psxVuw && p1>3;px++; + s=sx; + sx=(*px)>>3;px++; + s|=sx<<5; + sx=(*px)>>3; + s|=sx<<10; + s&=~0x8000; + *p1=s; + } + if(p2>=psxVuw && p2 PSXDisplay.DisplayPosition.x) && + (x < PSXDisplay.DisplayEnd.x) && + (dy > PSXDisplay.DisplayPosition.y) && + (y < PSXDisplay.DisplayEnd.y))) + sArea=0; + else + if((!(PSXDisplay.InterlacedTest) && + (dx > PreviousPSXDisplay.DisplayPosition.x) && + (x < PreviousPSXDisplay.DisplayEnd.x) && + (dy > PreviousPSXDisplay.DisplayPosition.y) && + (y < PreviousPSXDisplay.DisplayEnd.y))) + sArea=1; + else + { + return; + } + + if(dwActFixes&0x40) + { + if(iRenderFVR) + { + bFullVRam=TRUE;iRenderFVR=2;return; + } + bFullVRam=TRUE;iRenderFVR=2; + } + + ux=x;uy=y;udx=dx;udy=dy; + + if(sArea==0) + { + x -=PSXDisplay.DisplayPosition.x; + dx-=PSXDisplay.DisplayPosition.x; + y -=PSXDisplay.DisplayPosition.y; + dy-=PSXDisplay.DisplayPosition.y; + wx=PSXDisplay.DisplayEnd.x-PSXDisplay.DisplayPosition.x; + wy=PSXDisplay.DisplayEnd.y-PSXDisplay.DisplayPosition.y; + } + else + { + x -=PreviousPSXDisplay.DisplayPosition.x; + dx-=PreviousPSXDisplay.DisplayPosition.x; + y -=PreviousPSXDisplay.DisplayPosition.y; + dy-=PreviousPSXDisplay.DisplayPosition.y; + wx=PreviousPSXDisplay.DisplayEnd.x-PreviousPSXDisplay.DisplayPosition.x; + wy=PreviousPSXDisplay.DisplayEnd.y-PreviousPSXDisplay.DisplayPosition.y; + } + if(x<0) {ux-=x;x=0;} + if(y<0) {uy-=y;y=0;} + if(dx>wx) {udx-=(dx-wx);dx=wx;} + if(dy>wy) {udy-=(dy-wy);dy=wy;} + udx-=ux; + udy-=uy; + + p=(psxVuw + (1024*uy) + ux); + + if(udx<=0) return; + if(udy<=0) return; + if(dx<=0) return; + if(dy<=0) return; + if(wx<=0) return; + if(wy<=0) return; + + XS=(float)rRatioRect.right/(float)wx; + YS=(float)rRatioRect.bottom/(float)wy; + + dx=(int)((float)(dx)*XS); + dy=(int)((float)(dy)*YS); + x=(int)((float)x*XS); + y=(int)((float)y*YS); + + dx-=x; + dy-=y; + + if(dx>iResX) dx=iResX; + if(dy>iResY) dy=iResY; + + if(dx<=0) return; + if(dy<=0) return; + + // ogl y adjust + y=iResY-y-dy; + + x+=rRatioRect.left; + y-=rRatioRect.top; + + if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y; + + if(!pGfxCardScreen) + { + glPixelStorei(GL_PACK_ALIGNMENT,1); + pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4); + } + + ps=pGfxCardScreen; + + if(bFront) glReadBuffer(GL_FRONT); + + glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); + + if(bFront) glReadBuffer(GL_BACK); + + XS=(float)dx/(float)(udx); + YS=(float)dy/(float)(udy+1); + + for(y=udy;y>0;y--) + { + for(x=0;x=psxVuw && p>3;px++; + s=sx; + sx=(*px)>>3;px++; + s|=sx<<5; + sx=(*px)>>3; + s|=sx<<10; + s&=~0x8000; + *p=s; + } + p++; + } + p += 1024 - udx; + } +} + +//////////////////////////////////////////////////////////////////////// +// core read from vram +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUreadDataMem(uint32_t *pMem, int iSize) +{ + int i; + + if(iDataReadMode!=DR_VRAMTRANSFER) return; + + GPUIsBusy; + + // adjust read ptr, if necessary + while(VRAMRead.ImagePtr>=psxVuw_eom) + VRAMRead.ImagePtr-=iGPUHeight*1024; + while(VRAMRead.ImagePtr1) && + !(iDrawnSomething==2 && + VRAMRead.x == VRAMWrite.x && + VRAMRead.y == VRAMWrite.y && + VRAMRead.Width == VRAMWrite.Width && + VRAMRead.Height == VRAMWrite.Height)) + CheckVRamRead(VRAMRead.x,VRAMRead.y, + VRAMRead.x+VRAMRead.RowsRemaining, + VRAMRead.y+VRAMRead.ColsRemaining, + TRUE); + + for(i=0;i 0) && (VRAMRead.RowsRemaining > 0)) + { + // lower 16 bit + GPUdataRet=(uint32_t)*VRAMRead.ImagePtr; + + VRAMRead.ImagePtr++; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + VRAMRead.RowsRemaining --; + + if(VRAMRead.RowsRemaining<=0) + { + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining--; + VRAMRead.ImagePtr += 1024 - VRAMRead.Width; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + } + + // higher 16 bit (always, even if it's an odd width) + GPUdataRet|=(uint32_t)(*VRAMRead.ImagePtr)<<16; + *pMem++=GPUdataRet; + + if(VRAMRead.ColsRemaining <= 0) + {FinishedVRAMRead();goto ENDREAD;} + + VRAMRead.ImagePtr++; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + VRAMRead.RowsRemaining--; + if(VRAMRead.RowsRemaining<=0) + { + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining--; + VRAMRead.ImagePtr += 1024 - VRAMRead.Width; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + } + if(VRAMRead.ColsRemaining <= 0) + {FinishedVRAMRead();goto ENDREAD;} + } + else {FinishedVRAMRead();goto ENDREAD;} + } + +ENDREAD: + GPUIsIdle; +} + +uint32_t CALLBACK GPUreadData(void) +{ + uint32_t l; + GPUreadDataMem(&l,1); + return GPUdataRet; +} + +//////////////////////////////////////////////////////////////////////// +// helper table to know how much data is used by drawing commands +//////////////////////////////////////////////////////////////////////// + +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, // LINEG3 LINEG4 + 255,255,255,255,255,255,255,255, + // 60 + 3,3,3,3,4,4,4,4, // TILE SPRT + // 68 + 2,2,2,2,3,3,3,3, // TILE1 + // 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 +}; + +//////////////////////////////////////////////////////////////////////// +// processes data send to GPU data register +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUwriteDataMem(uint32_t *pMem, int iSize) +{ + unsigned char command; + uint32_t gdata=0; + int i=0; + GPUIsBusy; + GPUIsNotReadyForCommands; + +STARTVRAM: + + if(iDataWriteMode==DR_VRAMTRANSFER) + { + // make sure we are in vram + while(VRAMWrite.ImagePtr>=psxVuw_eom) + VRAMWrite.ImagePtr-=iGPUHeight*1024; + while(VRAMWrite.ImagePtr0) + { + while(VRAMWrite.RowsRemaining>0) + { + if(i>=iSize) {goto ENDVRAM;} + i++; + + gdata=*pMem++; + + *VRAMWrite.ImagePtr++ = (unsigned short)gdata; + if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; + VRAMWrite.RowsRemaining --; + + if(VRAMWrite.RowsRemaining <= 0) + { + VRAMWrite.ColsRemaining--; + if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width + { + gdata=(gdata&0xFFFF)|(((uint32_t)(*VRAMWrite.ImagePtr))<<16); + FinishedVRAMWrite(); + goto ENDVRAM; + } + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; + } + + *VRAMWrite.ImagePtr++ = (unsigned short)(gdata>>16); + if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; + VRAMWrite.RowsRemaining --; + } + + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ColsRemaining--; + VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; + } + + FinishedVRAMWrite(); + } + +ENDVRAM: + + if(iDataWriteMode==DR_NORMAL) + { + void (* *primFunc)(unsigned char *); + if(bSkipNextFrame) primFunc=primTableSkip; + else primFunc=primTableJ; + + for(;i>24) & 0xff); + + if(primTableCX[command]) + { + gpuDataC = primTableCX[command]; + gpuCommand = command; + gpuDataM[0] = gdata; + gpuDataP = 1; + } + else continue; + } + else + { + gpuDataM[gpuDataP] = gdata; + if(gpuDataC>128) + { + if((gpuDataC==254 && gpuDataP>=3) || + (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1))) + { + if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000) + gpuDataP=gpuDataC-1; + } + } + gpuDataP++; + } + + if(gpuDataP == gpuDataC) + { + gpuDataC=gpuDataP=0; + primFunc[gpuCommand]((unsigned char *)gpuDataM); + + if(dwEmuFixes&0x0001 || dwActFixes&0x20000) // hack for emulating "gpu busy" in some games + iFakePrimBusy=4; + } + } + } + + GPUdataRet=gdata; + + GPUIsReadyForCommands; + GPUIsIdle; +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUwriteData(uint32_t gdata) +{ + GPUwriteDataMem(&gdata,1); +} + +//////////////////////////////////////////////////////////////////////// +// call config dlg +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS + +long CALLBACK GPUconfigure(void) +{ + HWND hWP=GetActiveWindow(); + DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG), + hWP,(DLGPROC)CfgDlgProc); + + return 0; +} + +#elif defined(_MACGL) +long CALLBACK GPUconfigure(void) +{ + DlgProc(); + return 0; +} +#else + +void StartCfgTool(char *arg) // linux: start external cfg tool +{ + char cfg[256]; + struct stat buf; + + strcpy(cfg, "./cfgpeopsxgl"); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgpeopsxgl", arg, NULL); + exit(0); + } + return; + } + + strcpy(cfg, "./cfg/cfgpeopsxgl"); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgpeopsxgl", arg, NULL); + exit(0); + } + return; + } + + sprintf(cfg, "%s/.pcsx/plugins/cfg/cfgpeopsxgl", getenv("HOME")); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgpeopsxgl", arg, NULL); + exit(0); + } + return; + } + + printf("ERROR: cfgpeopsxgl file not found!\n"); +} + +long CALLBACK GPUconfigure(void) +{ + StartCfgTool("CFG"); + return 0; +} + +#endif // def _WINDOWS / _MACGL + +//////////////////////////////////////////////////////////////////////// +// sets all kind of act fixes +//////////////////////////////////////////////////////////////////////// + +void SetFixes(void) +{ + ReInitFrameCap(); + + if(dwActFixes & 0x2000) + dispWidths[4]=384; + else dispWidths[4]=368; +} + +//////////////////////////////////////////////////////////////////////// +// Pete Special: make an 'intelligent' dma chain check (<-Tekken3) +//////////////////////////////////////////////////////////////////////// + +uint32_t lUsedAddr[3]; + +__inline BOOL CheckForEndlessLoop(uint32_t laddr) +{ + if(laddr==lUsedAddr[1]) return TRUE; + if(laddr==lUsedAddr[2]) return TRUE; + + if(laddr 2000000) break; + if(CheckForEndlessLoop(addr)) break; + + count = baseAddrB[addr+3]; + + dmaMem=addr+4; + + if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count); + + addr = baseAddrL[addr>>2]&0xffffff; + } + while (addr != 0xffffff); + + GPUIsIdle; + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// show about dlg +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUabout(void) +{ +#ifdef _WINDOWS + HWND hWP=GetActiveWindow(); // to be sure + DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG_ABOUT), + hWP,(DLGPROC)AboutDlgProc); +#elif defined(_MACGL) + + AboutDlgProc(); +#else + + StartCfgTool("ABOUT"); + +#endif +} + +//////////////////////////////////////////////////////////////////////// +// 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; +} + +//////////////////////////////////////////////////////////////////////// +// save state funcs +//////////////////////////////////////////////////////////////////////// + +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) + { + int lSlotNum=*((int *)pF); + if(lSlotNum<0) return 0; + if(lSlotNum>8) return 0; + lSelectedSlot=lSlotNum+1; + return 1; + } + + if(!pF) return 0; + if(pF->ulFreezeVersion!=1) return 0; + + if(ulGetFreezeData==1) + { + pF->ulStatus=STATUSREG; + memcpy(pF->ulControl,ulStatusControl,256*sizeof(uint32_t)); + memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2); + + return 1; + } + + if(ulGetFreezeData!=0) return 0; + + STATUSREG=pF->ulStatus; + memcpy(ulStatusControl,pF->ulControl,256*sizeof(uint32_t)); + memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2); + + ResetTextureArea(TRUE); + + GPUwriteStatus(ulStatusControl[0]); + GPUwriteStatus(ulStatusControl[1]); + GPUwriteStatus(ulStatusControl[2]); + GPUwriteStatus(ulStatusControl[3]); + GPUwriteStatus(ulStatusControl[8]); + GPUwriteStatus(ulStatusControl[6]); + GPUwriteStatus(ulStatusControl[7]); + GPUwriteStatus(ulStatusControl[5]); + GPUwriteStatus(ulStatusControl[4]); + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +// special "emu infos" / "emu effects" functions +//////////////////////////////////////////////////////////////////////// + +//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;} + if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;} + if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;} +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUgetScreenPic(unsigned char * pMem) +{ + float XS,YS;int x,y,v; + unsigned char * ps, * px, * pf; + unsigned char c; + + if(!pGfxCardScreen) + { + glPixelStorei(GL_PACK_ALIGNMENT,1); + pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4); + } + + ps=pGfxCardScreen; + + glReadBuffer(GL_FRONT); + + glReadPixels(0,0,iResX,iResY,GL_RGB,GL_UNSIGNED_BYTE,ps); + + glReadBuffer(GL_BACK); + + XS=(float)iResX/128; + YS=(float)iResY/96; + pf=pMem; + + for(y=96;y>0;y--) + { + for(x=0;x<128;x++) + { + px=ps+(3*((int)((float)x * XS))+ + (3*iResX)*((int)((float)y*YS))); + *(pf+0)=*(px+2); + *(pf+1)=*(px+1); + *(pf+2)=*(px+0); + pf+=3; + } + } + + ///////////////////////////////////////////////////////////////////// + // generic number/border painter + + pf=pMem+(103*3); + + for(y=0;y<20;y++) + { + for(x=0;x<6;x++) + { + c=cFont[lSelectedSlot][x+y*6]; + v=(c&0xc0)>>6; + PaintPicDot(pf,(unsigned char)v);pf+=3; // paint the dots into the rect + v=(c&0x30)>>4; + PaintPicDot(pf,(unsigned char)v);pf+=3; + v=(c&0x0c)>>2; + PaintPicDot(pf,(unsigned char)v);pf+=3; + v=c&0x03; + PaintPicDot(pf,(unsigned char)v);pf+=3; + } + pf+=104*3; + } + + pf=pMem; + for(x=0;x<128;x++) + { + *(pf+(95*128*3))=0x00;*pf++=0x00; + *(pf+(95*128*3))=0x00;*pf++=0x00; + *(pf+(95*128*3))=0xff;*pf++=0xff; + } + pf=pMem; + for(y=0;y<96;y++) + { + *(pf+(127*3))=0x00;*pf++=0x00; + *(pf+(127*3))=0x00;*pf++=0x00; + *(pf+(127*3))=0xff;*pf++=0xff; + pf+=127*3; + } + +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUshowScreenPic(unsigned char * pMem) +{ + DestroyPic(); + if(pMem==0) return; + CreatePic(pMem); +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUsetfix(uint32_t dwFixBits) +{ + dwEmuFixes=dwFixBits; +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUvisualVibration(uint32_t iSmall, uint32_t iBig) +{ + int iVibVal; + + if(PSXDisplay.DisplayModeNew.x) // calc min "shake pixel" from screen width + iVibVal=max(1,iResX/PSXDisplay.DisplayModeNew.x); + else iVibVal=1; + // big rumble: 4...15 sp ; small rumble 1...3 sp + if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig *iVibVal)/10)); + else iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10)); + + srand(timeGetTime()); // init rand (will be used in BufferSwap) + + iRumbleTime=15; // let the rumble last 16 buffer swaps +} + +//////////////////////////////////////////////////////////////////////// +// main emu can set display infos (A/M/G/D) +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUdisplayFlags(uint32_t dwFlags) +{ + dwCoreFlags=dwFlags; +} + +void CALLBACK GPUvBlank( int val ) +{ + vBlank = val; +} diff --git a/plugins/peopsxgl/gpu.h b/plugins/peopsxgl/gpu.h index 19276781..f21433d9 100644 --- a/plugins/peopsxgl/gpu.h +++ b/plugins/peopsxgl/gpu.h @@ -1,43 +1,40 @@ -/*************************************************************************** - gpu.h - description - ------------------- - begin : Sun Mar 08 2009 - copyright : (C) 1999-2009 by Pete Bernert - web : www.pbernert.com - ***************************************************************************/ - -/*************************************************************************** - * * - * 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 - -#define PRED(x) ((x << 3) & 0xF8) -#define PBLUE(x) ((x >> 2) & 0xF8) -#define PGREEN(x) ((x >> 7) & 0xF8) - -#define RED(x) (x & 0xff) -#define BLUE(x) ((x>>16) & 0xff) -#define GREEN(x) ((x>>8) & 0xff) -#define COLOR(x) (x & 0xffffff) - -void DoSnapShot(void); -void updateDisplay(void); -void updateFrontDisplay(void); -void SetAutoFrameCap(void); -void SetAspectRatio(void); -void CheckVRamRead(int x, int y, int dx, int dy,BOOL bFront); -void CheckVRamReadEx(int x, int y, int dx, int dy); -void SetFixes(void); - -#ifdef _WINDOWS -extern HGLRC GLCONTEXT; -#endif -#endif // _GPU_INTERNALS_H +/*************************************************************************** + gpu.h - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 + +#define PRED(x) ((x << 3) & 0xF8) +#define PBLUE(x) ((x >> 2) & 0xF8) +#define PGREEN(x) ((x >> 7) & 0xF8) + +#define RED(x) (x & 0xff) +#define BLUE(x) ((x>>16) & 0xff) +#define GREEN(x) ((x>>8) & 0xff) +#define COLOR(x) (x & 0xffffff) + +void DoSnapShot(void); +void updateDisplay(void); +void updateFrontDisplay(void); +void SetAutoFrameCap(void); +void SetAspectRatio(void); +void CheckVRamRead(int x, int y, int dx, int dy,BOOL bFront); +void CheckVRamReadEx(int x, int y, int dx, int dy); +void SetFixes(void); + +#endif // _GPU_INTERNALS_H diff --git a/plugins/peopsxgl/gpucfg/main.c b/plugins/peopsxgl/gpucfg/main.c index 67258fee..3d7d9d68 100644 --- a/plugins/peopsxgl/gpucfg/main.c +++ b/plugins/peopsxgl/gpucfg/main.c @@ -1,735 +1,735 @@ -#include -#include -#include - -#include "config.h" - -#ifdef ENABLE_NLS -#include -#include -#endif - -// Widgets -GtkWidget *window, - *btnCancel, - *btnSave, - *spinXSize, - *spinYSize, - *chkKeepRatio, - *chkDithering, - *chkFullScreen, - *cbxTexQuality, - *cbxTexFiltering, - *cbxHiResTex, - *spinVRam, - *chkShowFPS, - *chkUseFPSLimit, - *vboxFPSLimit, - *radFPSLimitAuto, - *radFPSLimitManual, - *spinFPSLimit, - *chkUseFrameSkipping, - *cbxOffscreen, - *cbxFBTex, - *cbxFBAccess, - *chkMaskDetect, - *chkOpaquePass, - *chkAdvancedBlend, - *chkScanLines, - *spinScanLinesBlend, - *chkFastMdec, - *chk15bitMdec, - *chkLineMode, - *chkAntiAlias, - *chkOGLExtensions, - *chkScreenSmoothing, - *chkUseGameFixes, - *tblGameFixes, - *chkCfgFix1, - *chkCfgFix2, - *chkCfgFix4, - *chkCfgFix8, - *chkCfgFix16, - *chkCfgFix32, - *chkCfgFix64, - *chkCfgFix128, - *chkCfgFix256, - *chkCfgFix512, - *chkCfgFix1024, - *chkCfgFix2048, - *chkCfgFix4096, - *chkCfgFix8192, - *chkCfgFix16384, - *chkCfgFix32768, - *chkCfgFix65536, - *chkCfgFix131072, - *btnFast, - *btnBeautiful; - -// Save values to the config file -static void on_btnSave_clicked( GtkObject *object, gpointer user_data ) { - FILE *out; - out = fopen( "gpuPeopsMesaGL.cfg", "w+" ); - - if ( out != NULL ) { - - // Computes the 'fixes' bitfield - int cfgFixes = 0; - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix1 ) ) ) { cfgFixes |= (1 << 0); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix2 ) ) ) { cfgFixes |= (1 << 1); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix4 ) ) ) { cfgFixes |= (1 << 2); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix8 ) ) ) { cfgFixes |= (1 << 3); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix16 ) ) ) { cfgFixes |= (1 << 4); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix32 ) ) ) { cfgFixes |= (1 << 5); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix64 ) ) ) { cfgFixes |= (1 << 6); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix128 ) ) ) { cfgFixes |= (1 << 7); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix256 ) ) ) { cfgFixes |= (1 << 8); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix512 ) ) ) { cfgFixes |= (1 << 9); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix1024 ) ) ) { cfgFixes |= (1 << 10); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix2048 ) ) ) { cfgFixes |= (1 << 11); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix4096 ) ) ) { cfgFixes |= (1 << 12); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix8192 ) ) ) { cfgFixes |= (1 << 13); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix16384 ) ) ) { cfgFixes |= (1 << 14); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix32768 ) ) ) { cfgFixes |= (1 << 15); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix65536 ) ) ) { cfgFixes |= (1 << 16); } - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix131072 ) ) ) { cfgFixes |= (1 << 17); } - - // Print data to the config file - fprintf( out, "\nResX = %i", gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spinXSize ) ) ); - fprintf( out, "\nResY = %i", gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spinYSize ) ) ); - fprintf( out, "\nKeepRatio = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkKeepRatio ) ) ); - fprintf( out, "\nDithering = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkDithering ) ) ); - fprintf( out, "\nFullScreen = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkFullScreen ) ) ); - fprintf( out, "\nTexQuality = %i", gtk_combo_box_get_active( GTK_COMBO_BOX( cbxTexQuality ) ) ); - fprintf( out, "\nTexFilter = %i", gtk_combo_box_get_active( GTK_COMBO_BOX( cbxTexFiltering ) ) ); - fprintf( out, "\nHiResTextures = %i", gtk_combo_box_get_active( GTK_COMBO_BOX( cbxHiResTex ) ) ); - fprintf( out, "\nVRamSize = %i", gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spinVRam ) ) ); - fprintf( out, "\nShowFPS = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkShowFPS ) ) ); - fprintf( out, "\nUseFrameLimit = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkUseFPSLimit ) ) ); - fprintf( out, "\nFPSDetection = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( radFPSLimitAuto ) ) ); - fprintf( out, "\nFrameRate = %i", gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spinFPSLimit ) ) ); - fprintf( out, "\nUseFrameSkip = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkUseFrameSkipping ) ) ); - fprintf( out, "\nOffscreenDrawing = %i", gtk_combo_box_get_active( GTK_COMBO_BOX( cbxOffscreen ) ) ); - fprintf( out, "\nFrameTextures = %i", gtk_combo_box_get_active( GTK_COMBO_BOX( cbxFBTex ) ) ); - fprintf( out, "\nFrameAccess = %i", gtk_combo_box_get_active( GTK_COMBO_BOX( cbxFBAccess ) ) ); - fprintf( out, "\nMaskDetect = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkMaskDetect ) ) ); - fprintf( out, "\nOpaquePass = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkOpaquePass ) ) ); - fprintf( out, "\nAdvancedBlend = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkAdvancedBlend ) ) ); - fprintf( out, "\nScanLines = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkScanLines ) ) ); - fprintf( out, "\nScanLinesBlend = %i", gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spinScanLinesBlend ) ) ); - fprintf( out, "\nFastMdec = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkFastMdec ) ) ); - fprintf( out, "\n15bitMdec = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chk15bitMdec ) ) ); - fprintf( out, "\nLineMode = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkLineMode ) ) ); - fprintf( out, "\nAntiAlias = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkAntiAlias ) ) ); - fprintf( out, "\nOGLExtensions = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkOGLExtensions ) ) ); - fprintf( out, "\nScreenSmoothing = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkScreenSmoothing ) ) ); - fprintf( out, "\nUseFixes = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkUseGameFixes ) ) ); - fprintf( out, "\nCfgFixes = %i", cfgFixes ); - - fclose( out ); - } - - gtk_main_quit(); -} - -// Autoconfiguration callbacks - -static void on_btnFast_clicked( GtkObject *object, gpointer user_data ) { - gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinXSize ), 640 ); - gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinYSize ), 480 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkKeepRatio ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkDithering ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkFullScreen ), 0 ); - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxTexQuality ), 0 ); - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxTexFiltering ), 0 ); - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxHiResTex ), 0 ); - gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinVRam ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkShowFPS ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkUseFPSLimit ), 1 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( radFPSLimitAuto ), 1 ); - gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinFPSLimit ), 200 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkUseFrameSkipping ), 0 ); - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxOffscreen ), 1 ); - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxFBTex ), 1 ); - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxFBAccess ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkMaskDetect ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkOpaquePass ), 1 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkAdvancedBlend ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkScanLines ), 0 ); - gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinScanLinesBlend ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkFastMdec ), 1 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chk15bitMdec ), 1 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkLineMode ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkAntiAlias ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkOGLExtensions ), 1 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkScreenSmoothing ), 0 ); -} - -static void on_btnBeautiful_clicked( GtkObject *object, gpointer user_data ) { - gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinXSize ), 640 ); - gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinYSize ), 480 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkKeepRatio ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkDithering ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkFullScreen ), 0 ); - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxTexQuality ), 3 ); - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxTexFiltering ), 0 ); - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxHiResTex ), 0 ); - gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinVRam ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkShowFPS ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkUseFPSLimit ), 1 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( radFPSLimitAuto ), 1 ); - gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinFPSLimit ), 200 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkUseFrameSkipping ), 0 ); - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxOffscreen ), 3 ); - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxFBTex ), 2 ); - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxFBAccess ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkMaskDetect ), 1 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkOpaquePass ), 1 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkAdvancedBlend ), 1 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkScanLines ), 0 ); - gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinScanLinesBlend ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkFastMdec ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chk15bitMdec ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkLineMode ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkAntiAlias ), 0 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkOGLExtensions ), 1 ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkScreenSmoothing ), 0 ); -} - -// Callbacks used to toggle the sensitivity of some parts of the GUI - -static void on_chkUseGameFixes_toggled( GtkObject *object, gpointer user_data ) { - gtk_widget_set_sensitive( tblGameFixes, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkUseGameFixes ) ) ); -} - -static void on_chkUseFPSLimit_toggled( GtkObject *object, gpointer user_data ) { - gtk_widget_set_sensitive( vboxFPSLimit, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkUseFPSLimit ) ) ); -} - -static void on_radFPSLimitManual_toggled( GtkObject *object, gpointer user_data ) { - gtk_widget_set_sensitive( spinFPSLimit, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( radFPSLimitManual ) ) ); -} - -static void on_chkScanLines_toggled( GtkObject *object, gpointer user_data ) { - gtk_widget_set_sensitive( spinScanLinesBlend, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkScanLines ) ) ); -} - -/* Instanciates the GUI - Reads the config file - Sets widget states according to the config file - Connect callbacks to signals */ -int main( int argc, char **argv ) { - GtkBuilder *builder; - GError *error = NULL; - FILE *in; - char *pB, *p; - int len, val; - char t[256]; - -#ifdef ENABLE_NLS - setlocale (LC_ALL, ""); - bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); -#endif - - gtk_set_locale(); - gtk_init( &argc, &argv ); - - builder = gtk_builder_new(); - - // Load the glade file - if ( !gtk_builder_add_from_file( builder, DATADIR "peopsxgl.ui", &error ) ) { - g_warning( "%s", error->message ); - g_free( error ); - return( 1 ); - } - - // Display the About dialog when the emulator ask for it - if ( argv[1] && strcmp( argv[1], "ABOUT" ) == 0 ) { - GtkWidget *widget; - const char *authors[]= {"Adapted from P.E.Op.S OpenGL GPU by Pete Bernert", NULL}; - - widget = gtk_about_dialog_new(); - gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(widget), "OpenGL GPU Driver"); - gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(widget), "1.18"); - gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(widget), authors); - gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(widget), "http://pcsxr.codeplex.com/"); - - gtk_dialog_run(GTK_DIALOG(widget)); - gtk_widget_destroy(widget); - - return 0; - } - - // Get widgets from the glade file - window = GTK_WIDGET( gtk_builder_get_object( builder, "MainDialog" ) ); - btnCancel = GTK_WIDGET( gtk_builder_get_object( builder, "btnCancel" ) ); - btnSave = GTK_WIDGET( gtk_builder_get_object( builder, "btnSave" ) ); - spinXSize = GTK_WIDGET( gtk_builder_get_object( builder, "spinXSize" ) ); - spinYSize = GTK_WIDGET( gtk_builder_get_object( builder, "spinYSize" ) ); - chkKeepRatio = GTK_WIDGET( gtk_builder_get_object( builder, "chkKeepRatio" ) ); - chkDithering = GTK_WIDGET( gtk_builder_get_object( builder, "chkDithering" ) ); - chkFullScreen = GTK_WIDGET( gtk_builder_get_object( builder, "chkFullScreen" ) ); - cbxTexQuality = GTK_WIDGET( gtk_builder_get_object( builder, "cbxTexQuality" ) ); - cbxTexFiltering = GTK_WIDGET( gtk_builder_get_object( builder, "cbxTexFiltering" ) ); - cbxHiResTex = GTK_WIDGET( gtk_builder_get_object( builder, "cbxHiResTex" ) ); - spinVRam = GTK_WIDGET( gtk_builder_get_object( builder, "spinVRam" ) ); - chkShowFPS = GTK_WIDGET( gtk_builder_get_object( builder, "chkShowFPS" ) ); - chkUseFPSLimit = GTK_WIDGET( gtk_builder_get_object( builder, "chkUseFPSLimit" ) ); - vboxFPSLimit = GTK_WIDGET( gtk_builder_get_object( builder, "vboxFPSLimit" ) ); - radFPSLimitAuto = GTK_WIDGET( gtk_builder_get_object( builder, "radFPSLimitAuto" ) ); - radFPSLimitManual = GTK_WIDGET( gtk_builder_get_object( builder, "radFPSLimitManual" ) ); - spinFPSLimit = GTK_WIDGET( gtk_builder_get_object( builder, "spinFPSLimit" ) ); - chkUseFrameSkipping = GTK_WIDGET( gtk_builder_get_object( builder, "chkUseFrameSkipping" ) ); - cbxOffscreen = GTK_WIDGET( gtk_builder_get_object( builder, "cbxOffscreen" ) ); - cbxFBTex = GTK_WIDGET( gtk_builder_get_object( builder, "cbxFBTex" ) ); - cbxFBAccess = GTK_WIDGET( gtk_builder_get_object( builder, "cbxFBAccess" ) ); - chkMaskDetect = GTK_WIDGET( gtk_builder_get_object( builder, "chkMaskDetect" ) ); - chkOpaquePass = GTK_WIDGET( gtk_builder_get_object( builder, "chkOpaquePass" ) ); - chkAdvancedBlend = GTK_WIDGET( gtk_builder_get_object( builder, "chkAdvancedBlend" ) ); - chkScanLines = GTK_WIDGET( gtk_builder_get_object( builder, "chkScanLines" ) ); - spinScanLinesBlend = GTK_WIDGET( gtk_builder_get_object( builder, "spinScanLinesBlend" ) ); - chkFastMdec = GTK_WIDGET( gtk_builder_get_object( builder, "chkFastMdec" ) ); - chk15bitMdec = GTK_WIDGET( gtk_builder_get_object( builder, "chk15bitMdec" ) ); - chkLineMode = GTK_WIDGET( gtk_builder_get_object( builder, "chkLineMode" ) ); - chkAntiAlias = GTK_WIDGET( gtk_builder_get_object( builder, "chkAntiAlias" ) ); - chkOGLExtensions = GTK_WIDGET( gtk_builder_get_object( builder, "chkOGLExtensions" ) ); - chkScreenSmoothing = GTK_WIDGET( gtk_builder_get_object( builder, "chkScreenSmoothing" ) ); - chkUseGameFixes = GTK_WIDGET( gtk_builder_get_object( builder, "chkUseGameFixes" ) ); - tblGameFixes = GTK_WIDGET( gtk_builder_get_object( builder, "tblGameFixes" ) ); - chkCfgFix1 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix1" ) ); - chkCfgFix2 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix2" ) ); - chkCfgFix4 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix4" ) ); - chkCfgFix8 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix8" ) ); - chkCfgFix16 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix16" ) ); - chkCfgFix32 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix32" ) ); - chkCfgFix64 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix64" ) ); - chkCfgFix128 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix128" ) ); - chkCfgFix256 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix256" ) ); - chkCfgFix512 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix512" ) ); - chkCfgFix1024 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix1024" ) ); - chkCfgFix2048 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix2048" ) ); - chkCfgFix4096 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix4096" ) ); - chkCfgFix8192 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix8192" ) ); - chkCfgFix16384 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix16384" ) ); - chkCfgFix32768 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix32768" ) ); - chkCfgFix65536 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix65536" ) ); - chkCfgFix131072 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix131072" ) ); - btnFast = GTK_WIDGET( gtk_builder_get_object( builder, "btnFast" ) ); - btnBeautiful = GTK_WIDGET( gtk_builder_get_object( builder, "btnBeautiful" ) ); - - // Read the config file - in = fopen( "gpuPeopsMesaGL.cfg", "rb" ); - if ( in ) { - pB = (char *) malloc( 32767 ); - memset( pB, 0, 32767 ); - len = fread( pB, 1, 32767, in ); - fclose(in); - } - else pB = 0; - - val = 640; - if ( pB ) { - strcpy( t, "\nResX" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinXSize ), val ); - - val = 480; - if ( pB ) { - strcpy( t, "\nResY" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinYSize ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nKeepRatio" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkKeepRatio ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nDithering" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkDithering ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nFullScreen" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkFullScreen ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nTexQuality" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxTexQuality ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nTexFilter" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxTexFiltering ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nHiResTextures" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxHiResTex ), val ); - - val = 0; - if ( pB ) { - strcpy(t,"\nVRamSize"); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinVRam ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nShowFPS" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkShowFPS ), val ); - - val = 1; - if ( pB ) { - strcpy( t, "\nUseFrameLimit" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkUseFPSLimit ), val ); - - val = 1; - if ( pB ) { - strcpy( t, "\nFPSDetection" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( radFPSLimitAuto ), val ); - - val = 200; - if ( pB ) { - strcpy(t,"\nFrameRate"); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinFPSLimit ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nUseFrameSkip" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkUseFrameSkipping ), val ); - - val = 2; - if ( pB ) { - strcpy( t, "\nOffscreenDrawing" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxOffscreen ), val ); - - val = 1; - if ( pB ) { - strcpy( t, "\nFrameTextures" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxFBTex ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nFrameAccess" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_combo_box_set_active( GTK_COMBO_BOX( cbxFBAccess ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nMaskDetect" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkMaskDetect ), val ); - - val = 1; - if ( pB ) { - strcpy( t, "\nOpaquePass" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkOpaquePass ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nAdvancedBlend" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkAdvancedBlend ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nScanLines" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkScanLines ), val ); - - val = 0; - if ( pB ) { - strcpy(t,"\nScanLinesBlend"); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinScanLinesBlend ), val ); - - val = 1; - if ( pB ) { - strcpy( t, "\nFastMdec" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkFastMdec ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\n15bitMdec" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chk15bitMdec ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nLineMode" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkLineMode ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nAntiAlias" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkAntiAlias ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nOGLExtensions" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkOGLExtensions ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nScreenSmoothing" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkScreenSmoothing ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nUseFixes" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkUseGameFixes ), val ); - - val = 0; - if ( pB ) { - strcpy( t, "\nCfgFixes" ); - p = strstr( pB, t ); - if ( p ) { - p = strstr( p, "=" ); - len = 1; - val = atoi( p + len ); - } - } - if ( val & (1 << 17) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix131072 ), TRUE ); } - if ( val & (1 << 16) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix65536 ), TRUE ); } - if ( val & (1 << 15) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix32768 ), TRUE ); } - if ( val & (1 << 14) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix16384 ), TRUE ); } - if ( val & (1 << 13) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix8192 ), TRUE ); } - if ( val & (1 << 12) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix4096 ), TRUE ); } - if ( val & (1 << 11) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix2048 ), TRUE ); } - if ( val & (1 << 10) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix1024 ), TRUE ); } - if ( val & (1 << 9) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix512 ), TRUE ); } - if ( val & (1 << 8) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix256 ), TRUE ); } - if ( val & (1 << 7) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix128 ), TRUE ); } - if ( val & (1 << 6) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix64 ), TRUE ); } - if ( val & (1 << 5) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix32 ), TRUE ); } - if ( val & (1 << 4) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix16 ), TRUE ); } - if ( val & (1 << 3) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix8 ), TRUE ); } - if ( val & (1 << 2) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix4 ), TRUE ); } - if ( val & (1 << 1) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix2 ), TRUE ); } - if ( val & (1 << 0) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix1 ), TRUE ); } - - gtk_builder_connect_signals( builder, NULL ); - - g_object_unref( G_OBJECT( builder ) ); - - // Connect callbacks to signals - gtk_signal_connect( GTK_OBJECT( window ), "destroy", G_CALLBACK( gtk_main_quit ), NULL ); - gtk_signal_connect( GTK_OBJECT( btnCancel ), "clicked", G_CALLBACK( gtk_main_quit ), NULL ); - gtk_signal_connect( GTK_OBJECT( btnSave ), "clicked", G_CALLBACK( on_btnSave_clicked ), NULL ); - gtk_signal_connect( GTK_OBJECT( chkUseGameFixes ), "toggled", G_CALLBACK( on_chkUseGameFixes_toggled ), NULL ); - gtk_signal_connect( GTK_OBJECT( chkUseFPSLimit ), "toggled", G_CALLBACK( on_chkUseFPSLimit_toggled ), NULL ); - gtk_signal_connect( GTK_OBJECT( radFPSLimitManual ), "toggled", G_CALLBACK( on_radFPSLimitManual_toggled ), NULL ); - gtk_signal_connect( GTK_OBJECT( chkScanLines ), "toggled", G_CALLBACK( on_chkScanLines_toggled ), NULL ); - gtk_signal_connect( GTK_OBJECT( btnFast ), "clicked", G_CALLBACK( on_btnFast_clicked ), NULL ); - gtk_signal_connect( GTK_OBJECT( btnBeautiful ), "clicked", G_CALLBACK( on_btnBeautiful_clicked ), NULL ); - - // Call some callbacks to ensure widget state consistency - on_chkUseGameFixes_toggled( GTK_OBJECT( chkUseGameFixes ), NULL ); - on_chkUseFPSLimit_toggled( GTK_OBJECT( chkUseFPSLimit ), NULL ); - on_radFPSLimitManual_toggled( GTK_OBJECT( radFPSLimitManual ), NULL ); - on_chkScanLines_toggled( GTK_OBJECT( chkScanLines ), NULL ); - - gtk_widget_show( window ); - - gtk_main(); - - return 0; -} +#include +#include +#include + +#include "config.h" + +#ifdef ENABLE_NLS +#include +#include +#endif + +// Widgets +GtkWidget *window, + *btnCancel, + *btnSave, + *spinXSize, + *spinYSize, + *chkKeepRatio, + *chkDithering, + *chkFullScreen, + *cbxTexQuality, + *cbxTexFiltering, + *cbxHiResTex, + *spinVRam, + *chkShowFPS, + *chkUseFPSLimit, + *vboxFPSLimit, + *radFPSLimitAuto, + *radFPSLimitManual, + *spinFPSLimit, + *chkUseFrameSkipping, + *cbxOffscreen, + *cbxFBTex, + *cbxFBAccess, + *chkMaskDetect, + *chkOpaquePass, + *chkAdvancedBlend, + *chkScanLines, + *spinScanLinesBlend, + *chkFastMdec, + *chk15bitMdec, + *chkLineMode, + *chkAntiAlias, + *chkOGLExtensions, + *chkScreenSmoothing, + *chkUseGameFixes, + *tblGameFixes, + *chkCfgFix1, + *chkCfgFix2, + *chkCfgFix4, + *chkCfgFix8, + *chkCfgFix16, + *chkCfgFix32, + *chkCfgFix64, + *chkCfgFix128, + *chkCfgFix256, + *chkCfgFix512, + *chkCfgFix1024, + *chkCfgFix2048, + *chkCfgFix4096, + *chkCfgFix8192, + *chkCfgFix16384, + *chkCfgFix32768, + *chkCfgFix65536, + *chkCfgFix131072, + *btnFast, + *btnBeautiful; + +// Save values to the config file +void on_btnSave_clicked( GtkObject *object, gpointer user_data ) { + FILE *out; + out = fopen( "gpuPeopsMesaGL.cfg", "w+" ); + + if ( out != NULL ) { + + // Computes the 'fixes' bitfield + int cfgFixes = 0; + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix1 ) ) ) { cfgFixes |= (1 << 0); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix2 ) ) ) { cfgFixes |= (1 << 1); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix4 ) ) ) { cfgFixes |= (1 << 2); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix8 ) ) ) { cfgFixes |= (1 << 3); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix16 ) ) ) { cfgFixes |= (1 << 4); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix32 ) ) ) { cfgFixes |= (1 << 5); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix64 ) ) ) { cfgFixes |= (1 << 6); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix128 ) ) ) { cfgFixes |= (1 << 7); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix256 ) ) ) { cfgFixes |= (1 << 8); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix512 ) ) ) { cfgFixes |= (1 << 9); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix1024 ) ) ) { cfgFixes |= (1 << 10); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix2048 ) ) ) { cfgFixes |= (1 << 11); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix4096 ) ) ) { cfgFixes |= (1 << 12); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix8192 ) ) ) { cfgFixes |= (1 << 13); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix16384 ) ) ) { cfgFixes |= (1 << 14); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix32768 ) ) ) { cfgFixes |= (1 << 15); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix65536 ) ) ) { cfgFixes |= (1 << 16); } + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkCfgFix131072 ) ) ) { cfgFixes |= (1 << 17); } + + // Print data to the config file + fprintf( out, "\nResX = %i", gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spinXSize ) ) ); + fprintf( out, "\nResY = %i", gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spinYSize ) ) ); + fprintf( out, "\nKeepRatio = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkKeepRatio ) ) ); + fprintf( out, "\nDithering = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkDithering ) ) ); + fprintf( out, "\nFullScreen = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkFullScreen ) ) ); + fprintf( out, "\nTexQuality = %i", gtk_combo_box_get_active( GTK_COMBO_BOX( cbxTexQuality ) ) ); + fprintf( out, "\nTexFilter = %i", gtk_combo_box_get_active( GTK_COMBO_BOX( cbxTexFiltering ) ) ); + fprintf( out, "\nHiResTextures = %i", gtk_combo_box_get_active( GTK_COMBO_BOX( cbxHiResTex ) ) ); + fprintf( out, "\nVRamSize = %i", gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spinVRam ) ) ); + fprintf( out, "\nShowFPS = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkShowFPS ) ) ); + fprintf( out, "\nUseFrameLimit = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkUseFPSLimit ) ) ); + fprintf( out, "\nFPSDetection = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( radFPSLimitAuto ) ) ); + fprintf( out, "\nFrameRate = %i", gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spinFPSLimit ) ) ); + fprintf( out, "\nUseFrameSkip = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkUseFrameSkipping ) ) ); + fprintf( out, "\nOffscreenDrawing = %i", gtk_combo_box_get_active( GTK_COMBO_BOX( cbxOffscreen ) ) ); + fprintf( out, "\nFrameTextures = %i", gtk_combo_box_get_active( GTK_COMBO_BOX( cbxFBTex ) ) ); + fprintf( out, "\nFrameAccess = %i", gtk_combo_box_get_active( GTK_COMBO_BOX( cbxFBAccess ) ) ); + fprintf( out, "\nMaskDetect = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkMaskDetect ) ) ); + fprintf( out, "\nOpaquePass = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkOpaquePass ) ) ); + fprintf( out, "\nAdvancedBlend = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkAdvancedBlend ) ) ); + fprintf( out, "\nScanLines = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkScanLines ) ) ); + fprintf( out, "\nScanLinesBlend = %i", gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spinScanLinesBlend ) ) ); + fprintf( out, "\nFastMdec = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkFastMdec ) ) ); + fprintf( out, "\n15bitMdec = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chk15bitMdec ) ) ); + fprintf( out, "\nLineMode = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkLineMode ) ) ); + fprintf( out, "\nAntiAlias = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkAntiAlias ) ) ); + fprintf( out, "\nOGLExtensions = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkOGLExtensions ) ) ); + fprintf( out, "\nScreenSmoothing = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkScreenSmoothing ) ) ); + fprintf( out, "\nUseFixes = %i", gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkUseGameFixes ) ) ); + fprintf( out, "\nCfgFixes = %i", cfgFixes ); + + fclose( out ); + } + + gtk_main_quit(); +} + +// Autoconfiguration callbacks + +void on_btnFast_clicked( GtkObject *object, gpointer user_data ) { + gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinXSize ), 640 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinYSize ), 480 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkKeepRatio ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkDithering ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkFullScreen ), 0 ); + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxTexQuality ), 0 ); + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxTexFiltering ), 0 ); + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxHiResTex ), 0 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinVRam ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkShowFPS ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkUseFPSLimit ), 1 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( radFPSLimitAuto ), 1 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinFPSLimit ), 200 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkUseFrameSkipping ), 0 ); + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxOffscreen ), 1 ); + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxFBTex ), 1 ); + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxFBAccess ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkMaskDetect ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkOpaquePass ), 1 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkAdvancedBlend ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkScanLines ), 0 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinScanLinesBlend ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkFastMdec ), 1 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chk15bitMdec ), 1 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkLineMode ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkAntiAlias ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkOGLExtensions ), 1 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkScreenSmoothing ), 0 ); +} + +void on_btnBeautiful_clicked( GtkObject *object, gpointer user_data ) { + gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinXSize ), 640 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinYSize ), 480 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkKeepRatio ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkDithering ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkFullScreen ), 0 ); + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxTexQuality ), 3 ); + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxTexFiltering ), 0 ); + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxHiResTex ), 0 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinVRam ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkShowFPS ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkUseFPSLimit ), 1 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( radFPSLimitAuto ), 1 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinFPSLimit ), 200 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkUseFrameSkipping ), 0 ); + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxOffscreen ), 3 ); + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxFBTex ), 2 ); + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxFBAccess ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkMaskDetect ), 1 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkOpaquePass ), 1 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkAdvancedBlend ), 1 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkScanLines ), 0 ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinScanLinesBlend ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkFastMdec ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chk15bitMdec ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkLineMode ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkAntiAlias ), 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkOGLExtensions ), 1 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkScreenSmoothing ), 0 ); +} + +// Callbacks used to toggle the sensitivity of some parts of the GUI + +void on_chkUseGameFixes_toggled( GtkObject *object, gpointer user_data ) { + gtk_widget_set_sensitive( tblGameFixes, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkUseGameFixes ) ) ); +} + +void on_chkUseFPSLimit_toggled( GtkObject *object, gpointer user_data ) { + gtk_widget_set_sensitive( vboxFPSLimit, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkUseFPSLimit ) ) ); +} + +void on_radFPSLimitManual_toggled( GtkObject *object, gpointer user_data ) { + gtk_widget_set_sensitive( spinFPSLimit, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( radFPSLimitManual ) ) ); +} + +void on_chkScanLines_toggled( GtkObject *object, gpointer user_data ) { + gtk_widget_set_sensitive( spinScanLinesBlend, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkScanLines ) ) ); +} + +/* Instanciates the GUI + Reads the config file + Sets widget states according to the config file + Connect callbacks to signals */ +int main( int argc, char **argv ) { + GtkBuilder *builder; + GError *error = NULL; + FILE *in; + char *pB, *p; + int len, val; + char t[256]; + +#ifdef ENABLE_NLS + setlocale (LC_ALL, ""); + bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); +#endif + + gtk_set_locale(); + gtk_init( &argc, &argv ); + + builder = gtk_builder_new(); + + // Load the glade file + if ( !gtk_builder_add_from_file( builder, DATADIR "peopsxgl.ui", &error ) ) { + g_warning( "%s", error->message ); + g_free( error ); + return( 1 ); + } + + // Display the About dialog when the emulator ask for it + if ( argv[1] && strcmp( argv[1], "ABOUT" ) == 0 ) { + GtkWidget *widget; + const char *authors[]= {"Adapted from P.E.Op.S OpenGL GPU by Pete Bernert", NULL}; + + widget = gtk_about_dialog_new(); + gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(widget), "OpenGL GPU Driver"); + gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(widget), "1.18"); + gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(widget), authors); + gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(widget), "http://pcsxr.codeplex.com/"); + + gtk_dialog_run(GTK_DIALOG(widget)); + gtk_widget_destroy(widget); + + return 0; + } + + // Get widgets from the glade file + window = GTK_WIDGET( gtk_builder_get_object( builder, "MainDialog" ) ); + btnCancel = GTK_WIDGET( gtk_builder_get_object( builder, "btnCancel" ) ); + btnSave = GTK_WIDGET( gtk_builder_get_object( builder, "btnSave" ) ); + spinXSize = GTK_WIDGET( gtk_builder_get_object( builder, "spinXSize" ) ); + spinYSize = GTK_WIDGET( gtk_builder_get_object( builder, "spinYSize" ) ); + chkKeepRatio = GTK_WIDGET( gtk_builder_get_object( builder, "chkKeepRatio" ) ); + chkDithering = GTK_WIDGET( gtk_builder_get_object( builder, "chkDithering" ) ); + chkFullScreen = GTK_WIDGET( gtk_builder_get_object( builder, "chkFullScreen" ) ); + cbxTexQuality = GTK_WIDGET( gtk_builder_get_object( builder, "cbxTexQuality" ) ); + cbxTexFiltering = GTK_WIDGET( gtk_builder_get_object( builder, "cbxTexFiltering" ) ); + cbxHiResTex = GTK_WIDGET( gtk_builder_get_object( builder, "cbxHiResTex" ) ); + spinVRam = GTK_WIDGET( gtk_builder_get_object( builder, "spinVRam" ) ); + chkShowFPS = GTK_WIDGET( gtk_builder_get_object( builder, "chkShowFPS" ) ); + chkUseFPSLimit = GTK_WIDGET( gtk_builder_get_object( builder, "chkUseFPSLimit" ) ); + vboxFPSLimit = GTK_WIDGET( gtk_builder_get_object( builder, "vboxFPSLimit" ) ); + radFPSLimitAuto = GTK_WIDGET( gtk_builder_get_object( builder, "radFPSLimitAuto" ) ); + radFPSLimitManual = GTK_WIDGET( gtk_builder_get_object( builder, "radFPSLimitManual" ) ); + spinFPSLimit = GTK_WIDGET( gtk_builder_get_object( builder, "spinFPSLimit" ) ); + chkUseFrameSkipping = GTK_WIDGET( gtk_builder_get_object( builder, "chkUseFrameSkipping" ) ); + cbxOffscreen = GTK_WIDGET( gtk_builder_get_object( builder, "cbxOffscreen" ) ); + cbxFBTex = GTK_WIDGET( gtk_builder_get_object( builder, "cbxFBTex" ) ); + cbxFBAccess = GTK_WIDGET( gtk_builder_get_object( builder, "cbxFBAccess" ) ); + chkMaskDetect = GTK_WIDGET( gtk_builder_get_object( builder, "chkMaskDetect" ) ); + chkOpaquePass = GTK_WIDGET( gtk_builder_get_object( builder, "chkOpaquePass" ) ); + chkAdvancedBlend = GTK_WIDGET( gtk_builder_get_object( builder, "chkAdvancedBlend" ) ); + chkScanLines = GTK_WIDGET( gtk_builder_get_object( builder, "chkScanLines" ) ); + spinScanLinesBlend = GTK_WIDGET( gtk_builder_get_object( builder, "spinScanLinesBlend" ) ); + chkFastMdec = GTK_WIDGET( gtk_builder_get_object( builder, "chkFastMdec" ) ); + chk15bitMdec = GTK_WIDGET( gtk_builder_get_object( builder, "chk15bitMdec" ) ); + chkLineMode = GTK_WIDGET( gtk_builder_get_object( builder, "chkLineMode" ) ); + chkAntiAlias = GTK_WIDGET( gtk_builder_get_object( builder, "chkAntiAlias" ) ); + chkOGLExtensions = GTK_WIDGET( gtk_builder_get_object( builder, "chkOGLExtensions" ) ); + chkScreenSmoothing = GTK_WIDGET( gtk_builder_get_object( builder, "chkScreenSmoothing" ) ); + chkUseGameFixes = GTK_WIDGET( gtk_builder_get_object( builder, "chkUseGameFixes" ) ); + tblGameFixes = GTK_WIDGET( gtk_builder_get_object( builder, "tblGameFixes" ) ); + chkCfgFix1 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix1" ) ); + chkCfgFix2 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix2" ) ); + chkCfgFix4 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix4" ) ); + chkCfgFix8 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix8" ) ); + chkCfgFix16 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix16" ) ); + chkCfgFix32 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix32" ) ); + chkCfgFix64 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix64" ) ); + chkCfgFix128 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix128" ) ); + chkCfgFix256 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix256" ) ); + chkCfgFix512 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix512" ) ); + chkCfgFix1024 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix1024" ) ); + chkCfgFix2048 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix2048" ) ); + chkCfgFix4096 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix4096" ) ); + chkCfgFix8192 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix8192" ) ); + chkCfgFix16384 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix16384" ) ); + chkCfgFix32768 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix32768" ) ); + chkCfgFix65536 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix65536" ) ); + chkCfgFix131072 = GTK_WIDGET( gtk_builder_get_object( builder, "chkCfgFix131072" ) ); + btnFast = GTK_WIDGET( gtk_builder_get_object( builder, "btnFast" ) ); + btnBeautiful = GTK_WIDGET( gtk_builder_get_object( builder, "btnBeautiful" ) ); + + // Read the config file + in = fopen( "gpuPeopsMesaGL.cfg", "rb" ); + if ( in ) { + pB = (char *) malloc( 32767 ); + memset( pB, 0, 32767 ); + len = fread( pB, 1, 32767, in ); + fclose(in); + } + else pB = 0; + + val = 640; + if ( pB ) { + strcpy( t, "\nResX" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinXSize ), val ); + + val = 480; + if ( pB ) { + strcpy( t, "\nResY" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinYSize ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nKeepRatio" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkKeepRatio ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nDithering" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkDithering ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nFullScreen" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkFullScreen ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nTexQuality" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxTexQuality ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nTexFilter" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxTexFiltering ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nHiResTextures" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxHiResTex ), val ); + + val = 0; + if ( pB ) { + strcpy(t,"\nVRamSize"); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinVRam ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nShowFPS" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkShowFPS ), val ); + + val = 1; + if ( pB ) { + strcpy( t, "\nUseFrameLimit" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkUseFPSLimit ), val ); + + val = 1; + if ( pB ) { + strcpy( t, "\nFPSDetection" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( radFPSLimitAuto ), val ); + + val = 200; + if ( pB ) { + strcpy(t,"\nFrameRate"); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinFPSLimit ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nUseFrameSkip" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkUseFrameSkipping ), val ); + + val = 2; + if ( pB ) { + strcpy( t, "\nOffscreenDrawing" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxOffscreen ), val ); + + val = 1; + if ( pB ) { + strcpy( t, "\nFrameTextures" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxFBTex ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nFrameAccess" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_combo_box_set_active( GTK_COMBO_BOX( cbxFBAccess ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nMaskDetect" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkMaskDetect ), val ); + + val = 1; + if ( pB ) { + strcpy( t, "\nOpaquePass" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkOpaquePass ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nAdvancedBlend" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkAdvancedBlend ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nScanLines" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkScanLines ), val ); + + val = 0; + if ( pB ) { + strcpy(t,"\nScanLinesBlend"); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_spin_button_set_value( GTK_SPIN_BUTTON( spinScanLinesBlend ), val ); + + val = 1; + if ( pB ) { + strcpy( t, "\nFastMdec" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkFastMdec ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\n15bitMdec" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chk15bitMdec ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nLineMode" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkLineMode ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nAntiAlias" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkAntiAlias ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nOGLExtensions" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkOGLExtensions ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nScreenSmoothing" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkScreenSmoothing ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nUseFixes" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkUseGameFixes ), val ); + + val = 0; + if ( pB ) { + strcpy( t, "\nCfgFixes" ); + p = strstr( pB, t ); + if ( p ) { + p = strstr( p, "=" ); + len = 1; + val = atoi( p + len ); + } + } + if ( val & (1 << 17) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix131072 ), TRUE ); } + if ( val & (1 << 16) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix65536 ), TRUE ); } + if ( val & (1 << 15) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix32768 ), TRUE ); } + if ( val & (1 << 14) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix16384 ), TRUE ); } + if ( val & (1 << 13) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix8192 ), TRUE ); } + if ( val & (1 << 12) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix4096 ), TRUE ); } + if ( val & (1 << 11) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix2048 ), TRUE ); } + if ( val & (1 << 10) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix1024 ), TRUE ); } + if ( val & (1 << 9) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix512 ), TRUE ); } + if ( val & (1 << 8) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix256 ), TRUE ); } + if ( val & (1 << 7) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix128 ), TRUE ); } + if ( val & (1 << 6) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix64 ), TRUE ); } + if ( val & (1 << 5) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix32 ), TRUE ); } + if ( val & (1 << 4) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix16 ), TRUE ); } + if ( val & (1 << 3) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix8 ), TRUE ); } + if ( val & (1 << 2) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix4 ), TRUE ); } + if ( val & (1 << 1) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix2 ), TRUE ); } + if ( val & (1 << 0) ) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkCfgFix1 ), TRUE ); } + + gtk_builder_connect_signals( builder, NULL ); + + g_object_unref( G_OBJECT( builder ) ); + + // Connect callbacks to signals + gtk_signal_connect( GTK_OBJECT( window ), "destroy", G_CALLBACK( gtk_main_quit ), NULL ); + gtk_signal_connect( GTK_OBJECT( btnCancel ), "clicked", G_CALLBACK( gtk_main_quit ), NULL ); + gtk_signal_connect( GTK_OBJECT( btnSave ), "clicked", G_CALLBACK( on_btnSave_clicked ), NULL ); + gtk_signal_connect( GTK_OBJECT( chkUseGameFixes ), "toggled", G_CALLBACK( on_chkUseGameFixes_toggled ), NULL ); + gtk_signal_connect( GTK_OBJECT( chkUseFPSLimit ), "toggled", G_CALLBACK( on_chkUseFPSLimit_toggled ), NULL ); + gtk_signal_connect( GTK_OBJECT( radFPSLimitManual ), "toggled", G_CALLBACK( on_radFPSLimitManual_toggled ), NULL ); + gtk_signal_connect( GTK_OBJECT( chkScanLines ), "toggled", G_CALLBACK( on_chkScanLines_toggled ), NULL ); + gtk_signal_connect( GTK_OBJECT( btnFast ), "clicked", G_CALLBACK( on_btnFast_clicked ), NULL ); + gtk_signal_connect( GTK_OBJECT( btnBeautiful ), "clicked", G_CALLBACK( on_btnBeautiful_clicked ), NULL ); + + // Call some callbacks to ensure widget state consistency + on_chkUseGameFixes_toggled( GTK_OBJECT( chkUseGameFixes ), NULL ); + on_chkUseFPSLimit_toggled( GTK_OBJECT( chkUseFPSLimit ), NULL ); + on_radFPSLimitManual_toggled( GTK_OBJECT( radFPSLimitManual ), NULL ); + on_chkScanLines_toggled( GTK_OBJECT( chkScanLines ), NULL ); + + gtk_widget_show( window ); + + gtk_main(); + + return 0; +} diff --git a/plugins/peopsxgl/key.c b/plugins/peopsxgl/key.c index 200446a2..dba1c839 100644 --- a/plugins/peopsxgl/key.c +++ b/plugins/peopsxgl/key.c @@ -1,179 +1,177 @@ -/*************************************************************************** - key.c - description - ------------------- - begin : Sun Mar 08 2009 - copyright : (C) 1999-2009 by Pete Bernert - web : www.pbernert.com - ***************************************************************************/ - -/*************************************************************************** - * * - * 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 "stdafx.h" - -#define _IN_KEY - -#include "externals.h" -#include "menu.h" -#include "texture.h" -#include "draw.h" -#include "fps.h" -#include "key.h" -#include "psemu_plugin_defs.h" - -//////////////////////////////////////////////////////////////////////// -// KeyBoard handler stuff -//////////////////////////////////////////////////////////////////////// - -uint32_t ulKeybits = 0; - -//////////////////////////////////////////////////////////////////////// -// keyboard handler (LINUX) -//////////////////////////////////////////////////////////////////////// - -#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 GPUkeypressed(int keycode) -{ -/* arrives via the input plugin, so who knows what thread you're in */ - switch(keycode) - { - case VK_F5: - bSnapShot=1; - break; - - case VK_INSERT: - ulKeybits|=KEY_RESETTEXSTORE; - if(iBlurBuffer) iBlurBuffer=0; - else iBlurBuffer=1; - break; - - case VK_DEL: - if(ulKeybits&KEY_SHOWFPS) - { - ulKeybits&=~KEY_SHOWFPS; - HideText(); - DestroyPic(); - } - else - { - ulKeybits|=KEY_SHOWFPS; - szDispBuf[0]=0; - BuildDispMenu(0); - - } - break; - - case VK_PRIOR: BuildDispMenu(-1); break; - case VK_NEXT: BuildDispMenu( 1); break; - case VK_END: SwitchDispMenu( 1); break; - case VK_HOME: SwitchDispMenu(-1); break; -#if defined (_MACGL) - default: { void HandleKey(int keycode); HandleKey(keycode); }; -#endif - } - -} - -void InitKeyHandler(void) -{ -} - -void ExitKeyHandler(void) -{ -} - -//////////////////////////////////////////////////////////////////////// -// reset stuff on special keyboard commands -//////////////////////////////////////////////////////////////////////// - -void ResetStuff(void) -{ - ResetTextureArea(TRUE); - ulKeybits&=~KEY_RESETTEXSTORE; - - if(ulKeybits&KEY_BLACKWHITE) - { - if(bUseFixes) {bUseFixes=FALSE;dwActFixes=0;} - else {bUseFixes=TRUE; dwActFixes=dwCfgFixes;} - SetExtGLFuncs(); - if(iFrameLimit==2) SetAutoFrameCap(); - ulKeybits&=~KEY_BLACKWHITE; - } - - if(ulKeybits&KEY_RESETFILTER) - { - if(ulKeybits&KEY_STEPDOWN) - iFilterType--; - else iFilterType++; - if(iFilterType>6) iFilterType=0; - if(iFilterType<0) iFilterType=6; - SetExtGLFuncs(); - ulKeybits&=~(KEY_RESETFILTER|KEY_STEPDOWN); - BuildDispMenu(0); - } - - if(ulKeybits&KEY_RESETOPAQUE) - { - bOpaquePass=!bOpaquePass; - SetExtGLFuncs(); - ulKeybits&=~KEY_RESETOPAQUE; - BuildDispMenu(0); - } - - if(ulKeybits&KEY_RESETADVBLEND) - { - bAdvancedBlend=!bAdvancedBlend; - SetExtGLFuncs(); - ulKeybits&=~KEY_RESETADVBLEND; - BuildDispMenu(0); - } - - if(ulKeybits&KEY_RESETDITHER) - { - bDrawDither=!bDrawDither; - if(bDrawDither) glEnable(GL_DITHER); - else glDisable(GL_DITHER); - ulKeybits&=~KEY_RESETDITHER; - BuildDispMenu(0); - } - - if(ulKeybits & KEY_TOGGLEFBTEXTURE) - { - if(ulKeybits&KEY_STEPDOWN) - iFrameTexType--; - else iFrameTexType++; - if(iFrameTexType>3) iFrameTexType=0; - if(iFrameTexType<0) iFrameTexType=3; - if(gTexFrameName!=0) - glDeleteTextures(1, &gTexFrameName); - gTexFrameName=0; - ulKeybits&=~(KEY_TOGGLEFBTEXTURE|KEY_STEPDOWN); - } - - if(ulKeybits & KEY_TOGGLEFBREAD) - { - if(ulKeybits&KEY_STEPDOWN) - iFrameReadType--; - else iFrameReadType++; - if(iFrameReadType>4) iFrameReadType=0; - if(iFrameReadType<0) iFrameReadType=4; - if(iFrameReadType==4) bFullVRam=TRUE; - else bFullVRam=FALSE; - iRenderFVR=0; - ulKeybits&=~(KEY_TOGGLEFBREAD|KEY_STEPDOWN); - } -} +/*************************************************************************** + key.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "stdafx.h" + +#define _IN_KEY + +#include "externals.h" +#include "menu.h" +#include "texture.h" +#include "draw.h" +#include "fps.h" + +//////////////////////////////////////////////////////////////////////// +// KeyBoard handler stuff +//////////////////////////////////////////////////////////////////////// + +uint32_t ulKeybits = 0; + +//////////////////////////////////////////////////////////////////////// +// keyboard handler (LINUX) +//////////////////////////////////////////////////////////////////////// + +#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 GPUkeypressed(int keycode) +{ +/* arrives via the input plugin, so who knows what thread you're in */ + switch(keycode) + { + case VK_F5: + bSnapShot=1; + break; + + case VK_INSERT: + ulKeybits|=KEY_RESETTEXSTORE; + if(iBlurBuffer) iBlurBuffer=0; + else iBlurBuffer=1; + break; + + case VK_DEL: + if(ulKeybits&KEY_SHOWFPS) + { + ulKeybits&=~KEY_SHOWFPS; + HideText(); + DestroyPic(); + } + else + { + ulKeybits|=KEY_SHOWFPS; + szDispBuf[0]=0; + BuildDispMenu(0); + + } + break; + + case VK_PRIOR: BuildDispMenu(-1); break; + case VK_NEXT: BuildDispMenu( 1); break; + case VK_END: SwitchDispMenu( 1); break; + case VK_HOME: SwitchDispMenu(-1); break; +#if defined (_MACGL) + default: { void HandleKey(int keycode); HandleKey(keycode); }; +#endif + } + +} + +void InitKeyHandler(void) +{ +} + +void ExitKeyHandler(void) +{ +} + +//////////////////////////////////////////////////////////////////////// +// reset stuff on special keyboard commands +//////////////////////////////////////////////////////////////////////// + +void ResetStuff(void) +{ + ResetTextureArea(TRUE); + ulKeybits&=~KEY_RESETTEXSTORE; + + if(ulKeybits&KEY_BLACKWHITE) + { + if(bUseFixes) {bUseFixes=FALSE;dwActFixes=0;} + else {bUseFixes=TRUE; dwActFixes=dwCfgFixes;} + SetExtGLFuncs(); + if(iFrameLimit==2) SetAutoFrameCap(); + ulKeybits&=~KEY_BLACKWHITE; + } + + if(ulKeybits&KEY_RESETFILTER) + { + if(ulKeybits&KEY_STEPDOWN) + iFilterType--; + else iFilterType++; + if(iFilterType>6) iFilterType=0; + if(iFilterType<0) iFilterType=6; + SetExtGLFuncs(); + ulKeybits&=~(KEY_RESETFILTER|KEY_STEPDOWN); + BuildDispMenu(0); + } + + if(ulKeybits&KEY_RESETOPAQUE) + { + bOpaquePass=!bOpaquePass; + SetExtGLFuncs(); + ulKeybits&=~KEY_RESETOPAQUE; + BuildDispMenu(0); + } + + if(ulKeybits&KEY_RESETADVBLEND) + { + bAdvancedBlend=!bAdvancedBlend; + SetExtGLFuncs(); + ulKeybits&=~KEY_RESETADVBLEND; + BuildDispMenu(0); + } + + if(ulKeybits&KEY_RESETDITHER) + { + bDrawDither=!bDrawDither; + if(bDrawDither) glEnable(GL_DITHER); + else glDisable(GL_DITHER); + ulKeybits&=~KEY_RESETDITHER; + BuildDispMenu(0); + } + + if(ulKeybits & KEY_TOGGLEFBTEXTURE) + { + if(ulKeybits&KEY_STEPDOWN) + iFrameTexType--; + else iFrameTexType++; + if(iFrameTexType>3) iFrameTexType=0; + if(iFrameTexType<0) iFrameTexType=3; + if(gTexFrameName!=0) + glDeleteTextures(1, &gTexFrameName); + gTexFrameName=0; + ulKeybits&=~(KEY_TOGGLEFBTEXTURE|KEY_STEPDOWN); + } + + if(ulKeybits & KEY_TOGGLEFBREAD) + { + if(ulKeybits&KEY_STEPDOWN) + iFrameReadType--; + else iFrameReadType++; + if(iFrameReadType>4) iFrameReadType=0; + if(iFrameReadType<0) iFrameReadType=4; + if(iFrameReadType==4) bFullVRam=TRUE; + else bFullVRam=FALSE; + iRenderFVR=0; + ulKeybits&=~(KEY_TOGGLEFBREAD|KEY_STEPDOWN); + } +} diff --git a/plugins/peopsxgl/prim.c b/plugins/peopsxgl/prim.c index 3ee37c27..2209a1ad 100644 --- a/plugins/peopsxgl/prim.c +++ b/plugins/peopsxgl/prim.c @@ -1,4662 +1,4661 @@ -/*************************************************************************** - prim.c - description - ------------------- - begin : Sun Mar 08 2009 - copyright : (C) 1999-2009 by Pete Bernert - web : www.pbernert.com - ***************************************************************************/ - -/*************************************************************************** - * * - * 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 "stdafx.h" - -#define _IN_PRIMDRAW - -#include "externals.h" -#include "gpu.h" -#include "draw.h" -#include "soft.h" -#include "texture.h" -#include "prim.h" - -//////////////////////////////////////////////////////////////////////// -// defines -//////////////////////////////////////////////////////////////////////// - -#define DEFOPAQUEON glAlphaFunc(GL_EQUAL,0.0f);bBlendEnable=FALSE;glDisable(GL_BLEND); -#define DEFOPAQUEOFF glAlphaFunc(GL_GREATER,0.49f); - -//////////////////////////////////////////////////////////////////////// -// globals -//////////////////////////////////////////////////////////////////////// - -BOOL bDrawTextured; // current active drawing states -BOOL bDrawSmoothShaded; -BOOL bOldSmoothShaded; -BOOL bDrawNonShaded; -BOOL bDrawMultiPass; -int iOffscreenDrawing; -int iDrawnSomething=0; - -BOOL bRenderFrontBuffer=FALSE; // flag for front buffer rendering - -GLubyte ubGloAlpha; // texture alpha -GLubyte ubGloColAlpha; // color alpha -int iFilterType; // type of filter -BOOL bFullVRam=FALSE; // sign for tex win -BOOL bDrawDither; // sign for dither -BOOL bUseMultiPass; // sign for multi pass -GLuint gTexName; // binded texture -BOOL bTexEnabled; // texture enable flag -BOOL bBlendEnable; // blend enable flag -PSXRect_t xrUploadArea; // rect to upload -PSXRect_t xrUploadAreaIL; // rect to upload -PSXRect_t xrUploadAreaRGB24; // rect to upload rgb24 -int iSpriteTex=0; // flag for "hey, it's a sprite" -unsigned short usMirror; // mirror, mirror on the wall - -BOOL bNeedUploadAfter=FALSE; // sign for uploading in next frame -BOOL bNeedUploadTest=FALSE; // sign for upload test -BOOL bUsingTWin=FALSE; // tex win active flag -BOOL bUsingMovie=FALSE; // movie active flag -PSXRect_t xrMovieArea; // rect for movie upload -short sSprite_ux2; // needed for sprire adjust -short sSprite_vy2; // -uint32_t ulOLDCOL=0; // active color -uint32_t ulClutID; // clut - -uint32_t dwCfgFixes; // game fixes -uint32_t dwActFixes=0; -uint32_t dwEmuFixes=0; -BOOL bUseFixes; - -int drawX,drawY,drawW,drawH; // offscreen drawing checkers -short sxmin,sxmax,symin,symax; - -//////////////////////////////////////////////////////////////////////// -// Update global TP infos -//////////////////////////////////////////////////////////////////////// - -static void UpdateGlobalTP(unsigned short gdata) -{ - GlobalTextAddrX = (gdata << 6) & 0x3c0; - - if(iGPUHeight==1024) // ZN mode - { - if(dwGPUVersion==2) // very special zn gpu - { - GlobalTextAddrY =((gdata & 0x60 ) << 3); - GlobalTextIL =(gdata & 0x2000) >> 13; - GlobalTextABR = (unsigned short)((gdata >> 7) & 0x3); - GlobalTextTP = (gdata >> 9) & 0x3; - if(GlobalTextTP==3) GlobalTextTP=2; - GlobalTexturePage = (GlobalTextAddrX>>6)+(GlobalTextAddrY>>4); - usMirror =0; - STATUSREG = (STATUSREG & 0xffffe000 ) | (gdata & 0x1fff ); - return; - } - else // "enhanced" psx gpu - { - GlobalTextAddrY = (unsigned short)(((gdata << 4) & 0x100) | ((gdata >> 2) & 0x200)); - } - } - else GlobalTextAddrY = (gdata << 4) & 0x100; // "normal" psx gpu - - usMirror=gdata&0x3000; - - GlobalTextTP = (gdata >> 7) & 0x3; // tex mode (4,8,15) - if(GlobalTextTP==3) GlobalTextTP=2; // seen in Wild9 :( - GlobalTextABR = (gdata >> 5) & 0x3; // blend mode - - GlobalTexturePage = (GlobalTextAddrX>>6)+(GlobalTextAddrY>>4); - - STATUSREG&=~0x07ff; // Clear the necessary bits - STATUSREG|=(gdata & 0x07ff); // set the necessary bits -} - -static unsigned int DoubleBGR2RGB (unsigned int BGR) -{ - unsigned int ebx,eax,edx; - - ebx=(BGR&0x000000ff)<<1; - if(ebx&0x00000100) ebx=0x000000ff; - - eax=(BGR&0x0000ff00)<<1; - if(eax&0x00010000) eax=0x0000ff00; - - edx=(BGR&0x00ff0000)<<1; - if(edx&0x01000000) edx=0x00ff0000; - - return (ebx|eax|edx); -} - -static unsigned short BGR24to16 (uint32_t BGR) -{ - return ((BGR>>3)&0x1f)|((BGR&0xf80000)>>9)|((BGR&0xf800)>>6); -} - -//////////////////////////////////////////////////////////////////////// -// OpenGL primitive drawing commands -//////////////////////////////////////////////////////////////////////// - -static __inline void PRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2, - OGLVertex* vertex3, OGLVertex* vertex4) -{ - glBegin(GL_TRIANGLE_STRIP); - glTexCoord2fv(&vertex1->sow); - glVertex3fv(&vertex1->x); - - glTexCoord2fv(&vertex2->sow); - glVertex3fv(&vertex2->x); - - glTexCoord2fv(&vertex4->sow); - glVertex3fv(&vertex4->x); - - glTexCoord2fv(&vertex3->sow); - glVertex3fv(&vertex3->x); - glEnd(); -} - -///////////////////////////////////////////////////////// - -static __inline void PRIMdrawTexturedTri(OGLVertex* vertex1, OGLVertex* vertex2, - OGLVertex* vertex3) -{ - glBegin(GL_TRIANGLES); - glTexCoord2fv(&vertex1->sow); - glVertex3fv(&vertex1->x); - - glTexCoord2fv(&vertex2->sow); - glVertex3fv(&vertex2->x); - - glTexCoord2fv(&vertex3->sow); - glVertex3fv(&vertex3->x); - glEnd(); -} - -///////////////////////////////////////////////////////// - -static __inline void PRIMdrawTexGouraudTriColor(OGLVertex* vertex1, OGLVertex* vertex2, - OGLVertex* vertex3) -{ - glBegin(GL_TRIANGLES); - - SETPCOL(vertex1); - glTexCoord2fv(&vertex1->sow); - glVertex3fv(&vertex1->x); - - SETPCOL(vertex2); - glTexCoord2fv(&vertex2->sow); - glVertex3fv(&vertex2->x); - - SETPCOL(vertex3); - glTexCoord2fv(&vertex3->sow); - glVertex3fv(&vertex3->x); - glEnd(); -} - -///////////////////////////////////////////////////////// - -static __inline void PRIMdrawTexGouraudTriColorQuad(OGLVertex* vertex1, OGLVertex* vertex2, - OGLVertex* vertex3, OGLVertex* vertex4) -{ - glBegin(GL_TRIANGLE_STRIP); - SETPCOL(vertex1); - glTexCoord2fv(&vertex1->sow); - glVertex3fv(&vertex1->x); - - SETPCOL(vertex2); - glTexCoord2fv(&vertex2->sow); - glVertex3fv(&vertex2->x); - - SETPCOL(vertex4); - glTexCoord2fv(&vertex4->sow); - glVertex3fv(&vertex4->x); - - SETPCOL(vertex3); - glTexCoord2fv(&vertex3->sow); - glVertex3fv(&vertex3->x); - glEnd(); -} - -///////////////////////////////////////////////////////// - -static __inline void PRIMdrawTri(OGLVertex* vertex1, OGLVertex* vertex2, OGLVertex* vertex3) -{ - glBegin(GL_TRIANGLES); - glVertex3fv(&vertex1->x); - glVertex3fv(&vertex2->x); - glVertex3fv(&vertex3->x); - glEnd(); -} - -///////////////////////////////////////////////////////// - -static __inline void PRIMdrawTri2(OGLVertex* vertex1, OGLVertex* vertex2, - OGLVertex* vertex3, OGLVertex* vertex4) -{ - glBegin(GL_TRIANGLE_STRIP); - glVertex3fv(&vertex1->x); - glVertex3fv(&vertex3->x); - glVertex3fv(&vertex2->x); - glVertex3fv(&vertex4->x); - glEnd(); -} - -///////////////////////////////////////////////////////// - -static __inline void PRIMdrawGouraudTriColor(OGLVertex* vertex1, OGLVertex* vertex2, - OGLVertex* vertex3) -{ - glBegin(GL_TRIANGLES); - SETPCOL(vertex1); - glVertex3fv(&vertex1->x); - - SETPCOL(vertex2); - glVertex3fv(&vertex2->x); - - SETPCOL(vertex3); - glVertex3fv(&vertex3->x); - glEnd(); -} - -///////////////////////////////////////////////////////// - -static __inline void PRIMdrawGouraudTri2Color(OGLVertex* vertex1, OGLVertex* vertex2, - OGLVertex* vertex3, OGLVertex* vertex4) -{ - glBegin(GL_TRIANGLE_STRIP); - SETPCOL(vertex1); - glVertex3fv(&vertex1->x); - - SETPCOL(vertex3); - glVertex3fv(&vertex3->x); - - SETPCOL(vertex2); - glVertex3fv(&vertex2->x); - - SETPCOL(vertex4); - glVertex3fv(&vertex4->x); - glEnd(); -} - -///////////////////////////////////////////////////////// - -static __inline void PRIMdrawFlatLine(OGLVertex* vertex1, OGLVertex* vertex2,OGLVertex* vertex3, OGLVertex* vertex4) -{ - glBegin(GL_QUADS); - - SETPCOL(vertex1); - - glVertex3fv(&vertex1->x); - glVertex3fv(&vertex2->x); - glVertex3fv(&vertex3->x); - glVertex3fv(&vertex4->x); - glEnd(); -} - -///////////////////////////////////////////////////////// - -static __inline void PRIMdrawGouraudLine(OGLVertex* vertex1, OGLVertex* vertex2,OGLVertex* vertex3, OGLVertex* vertex4) -{ - glBegin(GL_QUADS); - - SETPCOL(vertex1); - glVertex3fv(&vertex1->x); - - SETPCOL(vertex2); - glVertex3fv(&vertex2->x); - - SETPCOL(vertex3); - glVertex3fv(&vertex3->x); - - SETPCOL(vertex4); - glVertex3fv(&vertex4->x); - glEnd(); -} - -///////////////////////////////////////////////////////// - -static __inline void PRIMdrawQuad(OGLVertex* vertex1, OGLVertex* vertex2, - OGLVertex* vertex3, OGLVertex* vertex4) -{ - glBegin(GL_QUADS); - glVertex3fv(&vertex1->x); - glVertex3fv(&vertex2->x); - glVertex3fv(&vertex3->x); - glVertex3fv(&vertex4->x); - glEnd(); -} - -//////////////////////////////////////////////////////////////////////// -// Transparent blending settings -//////////////////////////////////////////////////////////////////////// - -static GLenum obm1=GL_ZERO; -static GLenum obm2=GL_ZERO; - -typedef struct SEMITRANSTAG -{ - GLenum srcFac; - GLenum dstFac; - GLubyte alpha; -} SemiTransParams; - -SemiTransParams TransSets[4]= -{ - {GL_SRC_ALPHA,GL_SRC_ALPHA, 127}, - {GL_ONE, GL_ONE, 255}, - {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255}, - {GL_ONE_MINUS_SRC_ALPHA,GL_ONE, 192} -}; - -//////////////////////////////////////////////////////////////////////// - -static void SetSemiTrans(void) -{ -/* -* 0.5 x B + 0.5 x F -* 1.0 x B + 1.0 x F -* 1.0 x B - 1.0 x F -* 1.0 x B +0.25 x F -*/ - - if(!DrawSemiTrans) // no semi trans at all? - { - if(bBlendEnable) - {glDisable(GL_BLEND);bBlendEnable=FALSE;} // -> don't wanna blend - ubGloAlpha=ubGloColAlpha=255; // -> full alpha - return; // -> and bye - } - - ubGloAlpha=ubGloColAlpha=TransSets[GlobalTextABR].alpha; - - if(!bBlendEnable) - {glEnable(GL_BLEND);bBlendEnable=TRUE;} // wanna blend - - if(TransSets[GlobalTextABR].srcFac!=obm1 || - TransSets[GlobalTextABR].dstFac!=obm2) - { - if(glBlendEquationEXTEx==NULL) - { - obm1=TransSets[GlobalTextABR].srcFac; - obm2=TransSets[GlobalTextABR].dstFac; - glBlendFunc(obm1,obm2); // set blend func - } - else - if(TransSets[GlobalTextABR].dstFac !=GL_ONE_MINUS_SRC_COLOR) - { - if(obm2==GL_ONE_MINUS_SRC_COLOR) - glBlendEquationEXTEx(FUNC_ADD_EXT); - obm1=TransSets[GlobalTextABR].srcFac; - obm2=TransSets[GlobalTextABR].dstFac; - glBlendFunc(obm1,obm2); // set blend func - } - else - { - glBlendEquationEXTEx(FUNC_REVERSESUBTRACT_EXT); - obm1=TransSets[GlobalTextABR].srcFac; - obm2=TransSets[GlobalTextABR].dstFac; - glBlendFunc(GL_ONE,GL_ONE); // set blend func - } - } -} - -void SetScanTrans(void) // blending for scan lines -{ - if(glBlendEquationEXTEx!=NULL) - { - if(obm2==GL_ONE_MINUS_SRC_COLOR) - glBlendEquationEXTEx(FUNC_ADD_EXT); - } - - obm1=TransSets[0].srcFac; - obm2=TransSets[0].dstFac; - glBlendFunc(obm1,obm2); // set blend func -} - -void SetScanTexTrans(void) // blending for scan mask texture -{ - if(glBlendEquationEXTEx!=NULL) - { - if(obm2==GL_ONE_MINUS_SRC_COLOR) - glBlendEquationEXTEx(FUNC_ADD_EXT); - } - - obm1=TransSets[2].srcFac; - obm2=TransSets[2].dstFac; - glBlendFunc(obm1,obm2); // set blend func -} - -//////////////////////////////////////////////////////////////////////// -// multi pass in old 'Advanced blending' mode... got it from Lewpy :) -//////////////////////////////////////////////////////////////////////// - -SemiTransParams MultiTexTransSets[4][2]= -{ - { - {GL_ONE ,GL_SRC_ALPHA, 127}, - {GL_SRC_ALPHA,GL_ONE, 127} - }, - { - {GL_ONE, GL_SRC_ALPHA, 255}, - {GL_SRC_ALPHA,GL_ONE, 255} - }, - { - {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255}, - {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255} - }, - { - {GL_SRC_ALPHA,GL_ONE, 127}, - {GL_ONE_MINUS_SRC_ALPHA,GL_ONE, 255} - } -}; - -//////////////////////////////////////////////////////////////////////// - -SemiTransParams MultiColTransSets[4]= -{ - {GL_ONE_MINUS_SRC_ALPHA,GL_SRC_ALPHA,127}, - {GL_ONE, GL_ONE, 255}, - {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255}, - {GL_SRC_ALPHA,GL_ONE, 127} -}; - -//////////////////////////////////////////////////////////////////////// - -static void SetSemiTransMulti(int Pass) -{ - static GLenum bm1=GL_ZERO; - static GLenum bm2=GL_ONE; - - ubGloAlpha=255; - ubGloColAlpha=255; - - // are we enabling SemiTransparent mode? - if(DrawSemiTrans) - { - if(bDrawTextured) - { - bm1=MultiTexTransSets[GlobalTextABR][Pass].srcFac; - bm2=MultiTexTransSets[GlobalTextABR][Pass].dstFac; - ubGloAlpha=MultiTexTransSets[GlobalTextABR][Pass].alpha; - } - // no texture - else - { - bm1=MultiColTransSets[GlobalTextABR].srcFac; - bm2=MultiColTransSets[GlobalTextABR].dstFac; - ubGloColAlpha=MultiColTransSets[GlobalTextABR].alpha; - } - } - // no shading - else - { - if(Pass==0) - { - // disable blending - bm1=GL_ONE;bm2=GL_ZERO; - } - else - { - // disable blending, but add src col a second time - bm1=GL_ONE;bm2=GL_ONE; - } - } - - if(!bBlendEnable) - {glEnable(GL_BLEND);bBlendEnable=TRUE;} // wanna blend - - if(bm1!=obm1 || bm2!=obm2) - { - glBlendFunc(bm1,bm2); // set blend func - obm1=bm1;obm2=bm2; - } -} - -//////////////////////////////////////////////////////////////////////// -// Set several rendering stuff including blending -//////////////////////////////////////////////////////////////////////// - -static __inline void SetZMask3O(void) -{ - if(iUseMask && DrawSemiTrans && !iSetMask) - { - vertex[0].z=vertex[1].z=vertex[2].z=gl_z; - gl_z+=0.00004f; - } -} - -static __inline void SetZMask3(void) -{ - if(iUseMask) - { - if(iSetMask || DrawSemiTrans) - {vertex[0].z=vertex[1].z=vertex[2].z=0.95f;} - else - { - vertex[0].z=vertex[1].z=vertex[2].z=gl_z; - gl_z+=0.00004f; - } - } -} - -static __inline void SetZMask3NT(void) -{ - if(iUseMask) - { - if(iSetMask) - {vertex[0].z=vertex[1].z=vertex[2].z=0.95f;} - else - { - vertex[0].z=vertex[1].z=vertex[2].z=gl_z; - gl_z+=0.00004f; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void SetZMask4O(void) -{ - if(iUseMask && DrawSemiTrans && !iSetMask) - { - vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; - gl_z+=0.00004f; - } -} - -static __inline void SetZMask4(void) -{ - if(iUseMask) - { - if(iSetMask || DrawSemiTrans) - {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} - else - { - vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; - gl_z+=0.00004f; - } - } -} - -static __inline void SetZMask4NT(void) -{ - if(iUseMask) - { - if(iSetMask==1) - {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} - else - { - vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; - gl_z+=0.00004f; - } - } -} - -static __inline void SetZMask4SP(void) -{ - if(iUseMask) - { - if(iSetMask==1) - {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} - else - { - if(bCheckMask) - { - vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; - gl_z+=0.00004f; - } - else - {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void SetRenderState(uint32_t DrawAttributes) -{ - bDrawNonShaded = (SHADETEXBIT(DrawAttributes)) ? TRUE : FALSE; - DrawSemiTrans = (SEMITRANSBIT(DrawAttributes)) ? TRUE : FALSE; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void SetRenderColor(uint32_t DrawAttributes) -{ - if(bDrawNonShaded) {g_m1=g_m2=g_m3=128;} - else - { - g_m1=DrawAttributes&0xff; - g_m2=(DrawAttributes>>8)&0xff; - g_m3=(DrawAttributes>>16)&0xff; - } -} - -//////////////////////////////////////////////////////////////////////// - -static void SetRenderMode(uint32_t DrawAttributes, BOOL bSCol) -{ - if((bUseMultiPass) && (bDrawTextured) && !(bDrawNonShaded)) - {bDrawMultiPass = TRUE; SetSemiTransMulti(0);} - else {bDrawMultiPass = FALSE;SetSemiTrans();} - - if(bDrawTextured) // texture ? build it/get it from cache - { - GLuint currTex; - if(bUsingTWin) currTex=LoadTextureWnd(GlobalTexturePage,GlobalTextTP, ulClutID); - else if(bUsingMovie) currTex=LoadTextureMovie(); - else currTex=SelectSubTextureS(GlobalTextTP,ulClutID); - - if(gTexName!=currTex) - {gTexName=currTex;glBindTexture(GL_TEXTURE_2D,currTex);} - - if(!bTexEnabled) // -> turn texturing on - {bTexEnabled=TRUE;glEnable(GL_TEXTURE_2D);} - } - else // no texture ? - if(bTexEnabled) - {bTexEnabled=FALSE;glDisable(GL_TEXTURE_2D);} // -> turn texturing off - - if(bSCol) // also set color ? - { - if((dwActFixes&4) && ((DrawAttributes&0x00ffffff)==0)) - DrawAttributes|=0x007f7f7f; - - if(bDrawNonShaded) // -> non shaded? - { - if(bGLBlend) vertex[0].c.lcol=0x7f7f7f; // --> solid color... - else vertex[0].c.lcol=0xffffff; - } - else // -> shaded? - { - if(!bUseMultiPass && !bGLBlend) // --> given color... - vertex[0].c.lcol=DoubleBGR2RGB(DrawAttributes); - else vertex[0].c.lcol=DrawAttributes; - } - vertex[0].c.col[3]=ubGloAlpha; // -> set color with - SETCOL(vertex[0]); // texture alpha - } - - if(bDrawSmoothShaded!=bOldSmoothShaded) // shading changed? - { - if(bDrawSmoothShaded) glShadeModel(GL_SMOOTH); // -> set actual shading - else glShadeModel(GL_FLAT); - bOldSmoothShaded=bDrawSmoothShaded; - } -} - -//////////////////////////////////////////////////////////////////////// -// Set Opaque multipass color -//////////////////////////////////////////////////////////////////////// - -static void SetOpaqueColor(uint32_t DrawAttributes) -{ - if(bDrawNonShaded) return; // no shading? bye - - DrawAttributes=DoubleBGR2RGB(DrawAttributes); // multipass is just half color, so double it on opaque pass - vertex[0].c.lcol=DrawAttributes|0xff000000; - SETCOL(vertex[0]); // set color -} - -//////////////////////////////////////////////////////////////////////// -// Fucking stupid screen coord checking -//////////////////////////////////////////////////////////////////////// - -static BOOL ClipVertexListScreen(void) -{ - if (lx0 >= PSXDisplay.DisplayEnd.x) goto NEXTSCRTEST; - if (ly0 >= PSXDisplay.DisplayEnd.y) goto NEXTSCRTEST; - if (lx2 < PSXDisplay.DisplayPosition.x) goto NEXTSCRTEST; - if (ly2 < PSXDisplay.DisplayPosition.y) goto NEXTSCRTEST; - - return TRUE; - -NEXTSCRTEST: - if(PSXDisplay.InterlacedTest) return FALSE; - - if (lx0 >= PreviousPSXDisplay.DisplayEnd.x) return FALSE; - if (ly0 >= PreviousPSXDisplay.DisplayEnd.y) return FALSE; - if (lx2 < PreviousPSXDisplay.DisplayPosition.x) return FALSE; - if (ly2 < PreviousPSXDisplay.DisplayPosition.y) return FALSE; - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////// - -static BOOL bDrawOffscreenFront(void) -{ - if(sxmin < PSXDisplay.DisplayPosition.x) return FALSE; // must be complete in front - if(symin < PSXDisplay.DisplayPosition.y) return FALSE; - if(sxmax > PSXDisplay.DisplayEnd.x) return FALSE; - if(symax > PSXDisplay.DisplayEnd.y) return FALSE; - return TRUE; -} - -static BOOL bOnePointInFront(void) -{ - if(sxmax< PSXDisplay.DisplayPosition.x) - return FALSE; - - if(symax< PSXDisplay.DisplayPosition.y) - return FALSE; - - if(sxmin>=PSXDisplay.DisplayEnd.x) - return FALSE; - - if(symin>=PSXDisplay.DisplayEnd.y) - return FALSE; - - return TRUE; -} - - -static BOOL bOnePointInBack(void) -{ - if(sxmax< PreviousPSXDisplay.DisplayPosition.x) - return FALSE; - - if(symax< PreviousPSXDisplay.DisplayPosition.y) - return FALSE; - - if(sxmin>=PreviousPSXDisplay.DisplayEnd.x) - return FALSE; - - if(symin>=PreviousPSXDisplay.DisplayEnd.y) - return FALSE; - - return TRUE; -} - -static BOOL bDrawOffscreen4(void) -{ - BOOL bFront;short sW,sH; - - sxmax=max(lx0,max(lx1,max(lx2,lx3))); - if(sxmaxdrawW) return FALSE; - symax=max(ly0,max(ly1,max(ly2,ly3))); - if(symaxdrawH) return FALSE; - - if(PSXDisplay.Disabled) return TRUE; // disabled? ever - - if(iOffscreenDrawing==1) return bFullVRam; - - if(dwActFixes&1 && iOffscreenDrawing==4) - { - if(PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x && - PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y && - PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x && - PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y) - { - bRenderFrontBuffer=TRUE; - return FALSE; - } - } - - sW=drawW-1;sH=drawH-1; - - sxmin=min(sW,max(sxmin,drawX)); - sxmax=max(drawX,min(sxmax,sW)); - symin=min(sH,max(symin,drawY)); - symax=max(drawY,min(symax,sH)); - - if(bOnePointInBack()) return bFullVRam; - - if(iOffscreenDrawing==2) - bFront=bDrawOffscreenFront(); - else bFront=bOnePointInFront(); - - if(bFront) - { - if(PSXDisplay.InterlacedTest) return bFullVRam; // -> ok, no need for adjust - - vertex[0].x=lx0 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; - vertex[1].x=lx1 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; - vertex[2].x=lx2 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; - vertex[3].x=lx3 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; - vertex[0].y=ly0 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; - vertex[1].y=ly1 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; - vertex[2].y=ly2 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; - vertex[3].y=ly3 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; - - if(iOffscreenDrawing==4 && !(dwActFixes&1)) // -> frontbuffer wanted - { - bRenderFrontBuffer=TRUE; - //return TRUE; - } - return bFullVRam; // -> but no od - } - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////// - -static BOOL bDrawOffscreen3(void) -{ - BOOL bFront;short sW,sH; - - sxmax=max(lx0,max(lx1,lx2)); - if(sxmaxdrawW) return FALSE; - symax=max(ly0,max(ly1,ly2)); - if(symaxdrawH) return FALSE; - - if(PSXDisplay.Disabled) return TRUE; // disabled? ever - - if(iOffscreenDrawing==1) return bFullVRam; - - sW=drawW-1;sH=drawH-1; - sxmin=min(sW,max(sxmin,drawX)); - sxmax=max(drawX,min(sxmax,sW)); - symin=min(sH,max(symin,drawY)); - symax=max(drawY,min(symax,sH)); - - if(bOnePointInBack()) return bFullVRam; - - if(iOffscreenDrawing==2) - bFront=bDrawOffscreenFront(); - else bFront=bOnePointInFront(); - - if(bFront) - { - if(PSXDisplay.InterlacedTest) return bFullVRam; // -> ok, no need for adjust - - vertex[0].x=lx0 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; - vertex[1].x=lx1 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; - vertex[2].x=lx2 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; - vertex[0].y=ly0 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; - vertex[1].y=ly1 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; - vertex[2].y=ly2 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; - - if(iOffscreenDrawing==4) // -> frontbuffer wanted - { - bRenderFrontBuffer=TRUE; - // return TRUE; - } - - return bFullVRam; // -> but no od - } - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////// - -BOOL FastCheckAgainstScreen(short imageX0,short imageY0,short imageX1,short imageY1) -{ - PSXRect_t xUploadArea; - - imageX1 += imageX0; - imageY1 += imageY0; - - if (imageX0 < PreviousPSXDisplay.DisplayPosition.x) - xUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; - else - if (imageX0 > PreviousPSXDisplay.DisplayEnd.x) - xUploadArea.x0 = PreviousPSXDisplay.DisplayEnd.x; - else - xUploadArea.x0 = imageX0; - - if(imageX1 < PreviousPSXDisplay.DisplayPosition.x) - xUploadArea.x1 = PreviousPSXDisplay.DisplayPosition.x; - else - if (imageX1 > PreviousPSXDisplay.DisplayEnd.x) - xUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; - else - xUploadArea.x1 = imageX1; - - if (imageY0 < PreviousPSXDisplay.DisplayPosition.y) - xUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; - else - if (imageY0 > PreviousPSXDisplay.DisplayEnd.y) - xUploadArea.y0 = PreviousPSXDisplay.DisplayEnd.y; - else - xUploadArea.y0 = imageY0; - - if (imageY1 < PreviousPSXDisplay.DisplayPosition.y) - xUploadArea.y1 = PreviousPSXDisplay.DisplayPosition.y; - else - if (imageY1 > PreviousPSXDisplay.DisplayEnd.y) - xUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; - else - xUploadArea.y1 = imageY1; - - if ((xUploadArea.x0 != xUploadArea.x1) && (xUploadArea.y0 != xUploadArea.y1)) - return TRUE; - else return FALSE; -} - -BOOL CheckAgainstScreen(short imageX0,short imageY0,short imageX1,short imageY1) -{ - imageX1 += imageX0; - imageY1 += imageY0; - - if (imageX0 < PreviousPSXDisplay.DisplayPosition.x) - xrUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; - else - if (imageX0 > PreviousPSXDisplay.DisplayEnd.x) - xrUploadArea.x0 = PreviousPSXDisplay.DisplayEnd.x; - else - xrUploadArea.x0 = imageX0; - - if(imageX1 < PreviousPSXDisplay.DisplayPosition.x) - xrUploadArea.x1 = PreviousPSXDisplay.DisplayPosition.x; - else - if (imageX1 > PreviousPSXDisplay.DisplayEnd.x) - xrUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; - else - xrUploadArea.x1 = imageX1; - - if (imageY0 < PreviousPSXDisplay.DisplayPosition.y) - xrUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; - else - if (imageY0 > PreviousPSXDisplay.DisplayEnd.y) - xrUploadArea.y0 = PreviousPSXDisplay.DisplayEnd.y; - else - xrUploadArea.y0 = imageY0; - - if (imageY1 < PreviousPSXDisplay.DisplayPosition.y) - xrUploadArea.y1 = PreviousPSXDisplay.DisplayPosition.y; - else - if (imageY1 > PreviousPSXDisplay.DisplayEnd.y) - xrUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; - else - xrUploadArea.y1 = imageY1; - - if ((xrUploadArea.x0 != xrUploadArea.x1) && (xrUploadArea.y0 != xrUploadArea.y1)) - return TRUE; - else return FALSE; -} - -BOOL FastCheckAgainstFrontScreen(short imageX0,short imageY0,short imageX1,short imageY1) -{ - PSXRect_t xUploadArea; - - imageX1 += imageX0; - imageY1 += imageY0; - - if (imageX0 < PSXDisplay.DisplayPosition.x) - xUploadArea.x0 = PSXDisplay.DisplayPosition.x; - else - if (imageX0 > PSXDisplay.DisplayEnd.x) - xUploadArea.x0 = PSXDisplay.DisplayEnd.x; - else - xUploadArea.x0 = imageX0; - - if(imageX1 < PSXDisplay.DisplayPosition.x) - xUploadArea.x1 = PSXDisplay.DisplayPosition.x; - else - if (imageX1 > PSXDisplay.DisplayEnd.x) - xUploadArea.x1 = PSXDisplay.DisplayEnd.x; - else - xUploadArea.x1 = imageX1; - - if (imageY0 < PSXDisplay.DisplayPosition.y) - xUploadArea.y0 = PSXDisplay.DisplayPosition.y; - else - if (imageY0 > PSXDisplay.DisplayEnd.y) - xUploadArea.y0 = PSXDisplay.DisplayEnd.y; - else - xUploadArea.y0 = imageY0; - - if (imageY1 < PSXDisplay.DisplayPosition.y) - xUploadArea.y1 = PSXDisplay.DisplayPosition.y; - else - if (imageY1 > PSXDisplay.DisplayEnd.y) - xUploadArea.y1 = PSXDisplay.DisplayEnd.y; - else - xUploadArea.y1 = imageY1; - - if ((xUploadArea.x0 != xUploadArea.x1) && (xUploadArea.y0 != xUploadArea.y1)) - return TRUE; - else return FALSE; -} - -BOOL CheckAgainstFrontScreen(short imageX0,short imageY0,short imageX1,short imageY1) -{ - imageX1 += imageX0; - imageY1 += imageY0; - - if (imageX0 < PSXDisplay.DisplayPosition.x) - xrUploadArea.x0 = PSXDisplay.DisplayPosition.x; - else - if (imageX0 > PSXDisplay.DisplayEnd.x) - xrUploadArea.x0 = PSXDisplay.DisplayEnd.x; - else - xrUploadArea.x0 = imageX0; - - if(imageX1 < PSXDisplay.DisplayPosition.x) - xrUploadArea.x1 = PSXDisplay.DisplayPosition.x; - else - if (imageX1 > PSXDisplay.DisplayEnd.x) - xrUploadArea.x1 = PSXDisplay.DisplayEnd.x; - else - xrUploadArea.x1 = imageX1; - - if (imageY0 < PSXDisplay.DisplayPosition.y) - xrUploadArea.y0 = PSXDisplay.DisplayPosition.y; - else - if (imageY0 > PSXDisplay.DisplayEnd.y) - xrUploadArea.y0 = PSXDisplay.DisplayEnd.y; - else - xrUploadArea.y0 = imageY0; - - if (imageY1 < PSXDisplay.DisplayPosition.y) - xrUploadArea.y1 = PSXDisplay.DisplayPosition.y; - else - if (imageY1 > PSXDisplay.DisplayEnd.y) - xrUploadArea.y1 = PSXDisplay.DisplayEnd.y; - else - xrUploadArea.y1 = imageY1; - - if ((xrUploadArea.x0 != xrUploadArea.x1) && (xrUploadArea.y0 != xrUploadArea.y1)) - return TRUE; - else return FALSE; -} - -//////////////////////////////////////////////////////////////////////// - -void PrepareFullScreenUpload (int Position) -{ - if (Position==-1) // rgb24 - { - if(PSXDisplay.Interlaced) - { - xrUploadArea.x0 = PSXDisplay.DisplayPosition.x; - xrUploadArea.x1 = PSXDisplay.DisplayEnd.x; - xrUploadArea.y0 = PSXDisplay.DisplayPosition.y; - xrUploadArea.y1 = PSXDisplay.DisplayEnd.y; - } - else - { - xrUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; - xrUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; - xrUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; - xrUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; - } - - if(bNeedRGB24Update) - { - if(lClearOnSwap) - { -// lClearOnSwap=0; - } - else - if(PSXDisplay.Interlaced && PreviousPSXDisplay.RGB24<2) // in interlaced mode we upload at least two full frames (GT1 menu) - { - PreviousPSXDisplay.RGB24++; - } - else - { - xrUploadArea.y1 = min(xrUploadArea.y0+xrUploadAreaRGB24.y1,xrUploadArea.y1); - xrUploadArea.y0+=xrUploadAreaRGB24.y0; - } - } - } - else - if (Position) - { - xrUploadArea.x0 = PSXDisplay.DisplayPosition.x; - xrUploadArea.x1 = PSXDisplay.DisplayEnd.x; - xrUploadArea.y0 = PSXDisplay.DisplayPosition.y; - xrUploadArea.y1 = PSXDisplay.DisplayEnd.y; - } - else - { - xrUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; - xrUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; - xrUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; - xrUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; - } - - if (xrUploadArea.x0 < 0) xrUploadArea.x0 = 0; - else - if (xrUploadArea.x0 > 1023) xrUploadArea.x0 = 1023; - - if (xrUploadArea.x1 < 0) xrUploadArea.x1 = 0; - else - if (xrUploadArea.x1 > 1024) xrUploadArea.x1 = 1024; - - if (xrUploadArea.y0 < 0) xrUploadArea.y0 = 0; - else - if (xrUploadArea.y0 > iGPUHeightMask) xrUploadArea.y0 = iGPUHeightMask; - - if (xrUploadArea.y1 < 0) xrUploadArea.y1 = 0; - else - if (xrUploadArea.y1 > iGPUHeight) xrUploadArea.y1 = iGPUHeight; - - if (PSXDisplay.RGB24) - { - InvalidateTextureArea(xrUploadArea.x0,xrUploadArea.y0,xrUploadArea.x1-xrUploadArea.x0,xrUploadArea.y1-xrUploadArea.y0); - } -} - -//////////////////////////////////////////////////////////////////////// -// Upload screen (MDEC and such) -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -static void UploadScreenEx(int Position) -{ - short ya,yb,xa,xb,x, y, YStep, XStep, U, UStep,ux[4],vy[4]; - - if(!PSXDisplay.DisplayMode.x) return; - if(!PSXDisplay.DisplayMode.y) return; - - glDisable(GL_SCISSOR_TEST); - glShadeModel(GL_FLAT); - bOldSmoothShaded=FALSE; - glDisable(GL_BLEND); - bBlendEnable=FALSE; - glDisable(GL_TEXTURE_2D); - bTexEnabled=FALSE; - glDisable(GL_ALPHA_TEST); - - glPixelZoom(((float)rRatioRect.right)/((float)PSXDisplay.DisplayMode.x), - -1.0f*(((float)rRatioRect.bottom)/((float)PSXDisplay.DisplayMode.y))); - - //----------------------------------------------------// - - YStep = 256; // max texture size - XStep = 256; - UStep = (PSXDisplay.RGB24 ? 128 : 0); - ya = xrUploadArea.y0; - yb = xrUploadArea.y1; - xa = xrUploadArea.x0; - xb = xrUploadArea.x1; - - for(y=ya;y<=yb;y+=YStep) // loop y - { - U = 0; - for(x=xa;x<=xb;x+=XStep) // loop x - { - ly0 = ly1 = y; // -> get y coords - ly2 = y + YStep; - if (ly2 > yb) ly2 = yb; - ly3 = ly2; - - lx0 = lx3 = x; // -> get x coords - lx1 = x + XStep; - if (lx1 > xb) lx1 = xb; - - lx2 = lx1; - - ux[0]=ux[3]=(xa - x); // -> set tex x coords - if (ux[0] < 0) ux[0]=ux[3]=0; - ux[2]=ux[1]=(xb - x); - if (ux[2] > 256) ux[2]=ux[1]=256; - - vy[0]=vy[1]=(ya - y); // -> set tex y coords - if (vy[0] < 0) vy[0]=vy[1]=0; - vy[2]=vy[3]=(yb - y); - if (vy[2] > 256) vy[2]=vy[3]=256; - - if ((ux[0] >= ux[2]) || // -> cheaters never win... - (vy[0] >= vy[2])) continue; // (but winners always cheat...) - - xrMovieArea.x0=lx0+U; xrMovieArea.y0=ly0; - xrMovieArea.x1=lx2+U; xrMovieArea.y1=ly2; - - offsetScreenUpload(Position); - - glRasterPos2f(vertex[0].x,vertex[0].y); - - glDrawPixels(xrMovieArea.x1-xrMovieArea.x0, - xrMovieArea.y1-xrMovieArea.y0, - GL_RGBA,GL_UNSIGNED_BYTE, - LoadDirectMovieFast()); - - U+=UStep; - } - } - - //----------------------------------------------------// - - glPixelZoom(1.0F,1.0F); - - glEnable(GL_ALPHA_TEST); - glEnable(GL_SCISSOR_TEST); -} - -//////////////////////////////////////////////////////////////////////// - -void UploadScreen(int Position) -{ - short x, y, YStep, XStep, U, s, UStep,ux[4],vy[4]; - short xa,xb,ya,yb; - - if(xrUploadArea.x0>1023) xrUploadArea.x0=1023; - if(xrUploadArea.x1>1024) xrUploadArea.x1=1024; - if(xrUploadArea.y0>iGPUHeightMask) xrUploadArea.y0=iGPUHeightMask; - if(xrUploadArea.y1>iGPUHeight) xrUploadArea.y1=iGPUHeight; - - if(xrUploadArea.x0==xrUploadArea.x1) return; - if(xrUploadArea.y0==xrUploadArea.y1) return; - - if(PSXDisplay.Disabled && iOffscreenDrawing<4) return; - - iDrawnSomething = 2; - iLastRGB24=PSXDisplay.RGB24+1; - - if(bSkipNextFrame) return; - - if(dwActFixes & 2) {UploadScreenEx(Position);return;} - - bUsingMovie = TRUE; - bDrawTextured = TRUE; // just doing textures - bDrawSmoothShaded = FALSE; - - if(bGLBlend) vertex[0].c.lcol=0xff7f7f7f; // set solid col - else vertex[0].c.lcol=0xffffffff; - SETCOL(vertex[0]); - - SetOGLDisplaySettings(0); - - YStep = 256; // max texture size - XStep = 256; - - UStep = (PSXDisplay.RGB24 ? 128 : 0); - - ya=xrUploadArea.y0; - yb=xrUploadArea.y1; - xa=xrUploadArea.x0; - xb=xrUploadArea.x1; - - for(y=ya;y<=yb;y+=YStep) // loop y - { - U = 0; - for(x=xa;x<=xb;x+=XStep) // loop x - { - ly0 = ly1 = y; // -> get y coords - ly2 = y + YStep; - if (ly2 > yb) ly2 = yb; - ly3 = ly2; - - lx0 = lx3 = x; // -> get x coords - lx1 = x + XStep; - if (lx1 > xb) lx1 = xb; - - lx2 = lx1; - - ux[0]=ux[3]=(xa - x); // -> set tex x coords - if (ux[0] < 0) ux[0]=ux[3]=0; - ux[2]=ux[1]=(xb - x); - if (ux[2] > 256) ux[2]=ux[1]=256; - - vy[0]=vy[1]=(ya - y); // -> set tex y coords - if (vy[0] < 0) vy[0]=vy[1]=0; - vy[2]=vy[3]=(yb - y); - if (vy[2] > 256) vy[2]=vy[3]=256; - - if ((ux[0] >= ux[2]) || // -> cheaters never win... - (vy[0] >= vy[2])) continue; // (but winners always cheat...) - - xrMovieArea.x0=lx0+U; xrMovieArea.y0=ly0; - xrMovieArea.x1=lx2+U; xrMovieArea.y1=ly2; - - s=ux[2] - ux[0]; if(s>255) s=255; - - gl_ux[2] = gl_ux[1] = s; - s=vy[2] - vy[0]; if(s>255) s=255; - gl_vy[2] = gl_vy[3] = s; - gl_ux[0] = gl_ux[3] = gl_vy[0] = gl_vy[1] = 0; - - SetRenderState((uint32_t)0x01000000); - SetRenderMode((uint32_t)0x01000000, FALSE); // upload texture data - offsetScreenUpload(Position); - assignTextureVRAMWrite(); - - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - - U+=UStep; - } - } - - bUsingMovie=FALSE; // done... - bDisplayNotSet = TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// Detect next screen -//////////////////////////////////////////////////////////////////////// - -static BOOL IsCompleteInsideNextScreen(short x, short y, short xoff, short yoff) -{ - if (x > PSXDisplay.DisplayPosition.x+1) return FALSE; - if ((x + xoff) < PSXDisplay.DisplayEnd.x-1) return FALSE; - yoff+=y; - if (y >= PSXDisplay.DisplayPosition.y && - y <= PSXDisplay.DisplayEnd.y ) - { - if ((yoff) >= PSXDisplay.DisplayPosition.y && - (yoff) <= PSXDisplay.DisplayEnd.y ) return TRUE; - } - if (y > PSXDisplay.DisplayPosition.y+1) return FALSE; - if (yoff < PSXDisplay.DisplayEnd.y-1) return FALSE; - return TRUE; -} - -static BOOL IsPrimCompleteInsideNextScreen(short x, short y, short xoff, short yoff) -{ - x+=PSXDisplay.DrawOffset.x; - if (x > PSXDisplay.DisplayPosition.x+1) return FALSE; - y+=PSXDisplay.DrawOffset.y; - if (y > PSXDisplay.DisplayPosition.y+1) return FALSE; - xoff+=PSXDisplay.DrawOffset.x; - if (xoff < PSXDisplay.DisplayEnd.x-1) return FALSE; - yoff+=PSXDisplay.DrawOffset.y; - if (yoff < PSXDisplay.DisplayEnd.y-1) return FALSE; - return TRUE; -} - -#if 0 -static BOOL IsInsideNextScreen(short x, short y, short xoff, short yoff) -{ - if (x > PSXDisplay.DisplayEnd.x) return FALSE; - if (y > PSXDisplay.DisplayEnd.y) return FALSE; - if ((x + xoff) < PSXDisplay.DisplayPosition.x) return FALSE; - if ((y + yoff) < PSXDisplay.DisplayPosition.y) return FALSE; - return TRUE; -} -#endif - -//////////////////////////////////////////////////////////////////////// -// mask stuff... -//////////////////////////////////////////////////////////////////////// - -//Mask1 Set mask bit while drawing. 1 = on -//Mask2 Do not draw to mask areas. 1= on - -static void cmdSTP(unsigned char * baseAddr) -{ - uint32_t gdata = ((uint32_t*)baseAddr)[0]; - - STATUSREG&=~0x1800; // clear the necessary bits - STATUSREG|=((gdata & 0x03) << 11); // set the current bits - - if(!iUseMask) return; - - if(gdata&1) {sSetMask=0x8000;lSetMask=0x80008000;iSetMask=1;} - else {sSetMask=0; lSetMask=0; iSetMask=0;} - - if(gdata&2) - { - if(!(gdata&1)) iSetMask=2; - bCheckMask=TRUE; - if(iDepthFunc==0) return; - iDepthFunc=0; - glDepthFunc(GL_LESS); - } - else - { - bCheckMask=FALSE; - if(iDepthFunc==1) return; - glDepthFunc(GL_ALWAYS); - iDepthFunc=1; - } -} - -//////////////////////////////////////////////////////////////////////// -// cmd: Set texture page infos -//////////////////////////////////////////////////////////////////////// - -static void cmdTexturePage(unsigned char * baseAddr) -{ - uint32_t gdata = ((uint32_t *)baseAddr)[0]; - UpdateGlobalTP((unsigned short)gdata); - GlobalTextREST = (gdata&0x00ffffff)>>9; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: turn on/off texture window -//////////////////////////////////////////////////////////////////////// - -static void cmdTextureWindow(unsigned char *baseAddr) -{ - uint32_t gdata = ((uint32_t *)baseAddr)[0]; - uint32_t YAlign,XAlign; - - ulGPUInfoVals[INFO_TW]=gdata&0xFFFFF; - - if(gdata & 0x020) - TWin.Position.y1 = 8; // xxxx1 - else if (gdata & 0x040) - TWin.Position.y1 = 16; // xxx10 - else if (gdata & 0x080) - TWin.Position.y1 = 32; // xx100 - else if (gdata & 0x100) - TWin.Position.y1 = 64; // x1000 - else if (gdata & 0x200) - TWin.Position.y1 = 128; // 10000 - else - TWin.Position.y1 = 256; // 00000 - - // Texture window size is determined by the least bit set of the relevant 5 bits - - if (gdata & 0x001) - TWin.Position.x1 = 8; // xxxx1 - else if (gdata & 0x002) - TWin.Position.x1 = 16; // xxx10 - else if (gdata & 0x004) - TWin.Position.x1 = 32; // xx100 - else if (gdata & 0x008) - TWin.Position.x1 = 64; // x1000 - else if (gdata & 0x010) - TWin.Position.x1 = 128; // 10000 - else - 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 - (TWin.Position.y1 >> 3)); - XAlign = (uint32_t)(32 - (TWin.Position.x1 >> 3)); - - // Absolute position of the start of the texture window - - TWin.Position.y0 = (short)(((gdata >> 15) & YAlign) << 3); - TWin.Position.x0 = (short)(((gdata >> 10) & XAlign) << 3); - - if((TWin.Position.x0 == 0 && // tw turned off - TWin.Position.y0 == 0 && - TWin.Position.x1 == 0 && - TWin.Position.y1 == 0) || - (TWin.Position.x1 == 256 && - TWin.Position.y1 == 256)) - { - bUsingTWin = FALSE; // -> just do it - -#ifdef OWNSCALE - TWin.UScaleFactor = 1.0f; - TWin.VScaleFactor = 1.0f; -#else - TWin.UScaleFactor = - TWin.VScaleFactor = 1.0f/256.0f; -#endif - } - else // tw turned on - { - bUsingTWin = TRUE; - - TWin.OPosition.y1 = TWin.Position.y1; // -> get psx sizes - TWin.OPosition.x1 = TWin.Position.x1; - - if(TWin.Position.x1<=2) TWin.Position.x1=2; // -> set OGL sizes - else - if(TWin.Position.x1<=4) TWin.Position.x1=4; - else - if(TWin.Position.x1<=8) TWin.Position.x1=8; - else - if(TWin.Position.x1<=16) TWin.Position.x1=16; - else - if(TWin.Position.x1<=32) TWin.Position.x1=32; - else - if(TWin.Position.x1<=64) TWin.Position.x1=64; - else - if(TWin.Position.x1<=128) TWin.Position.x1=128; - else - if(TWin.Position.x1<=256) TWin.Position.x1=256; - - if(TWin.Position.y1<=2) TWin.Position.y1=2; - else - if(TWin.Position.y1<=4) TWin.Position.y1=4; - else - if(TWin.Position.y1<=8) TWin.Position.y1=8; - else - if(TWin.Position.y1<=16) TWin.Position.y1=16; - else - if(TWin.Position.y1<=32) TWin.Position.y1=32; - else - if(TWin.Position.y1<=64) TWin.Position.y1=64; - else - if(TWin.Position.y1<=128) TWin.Position.y1=128; - else - if(TWin.Position.y1<=256) TWin.Position.y1=256; - -#ifdef OWNSCALE - TWin.UScaleFactor = (float)TWin.Position.x1; - TWin.VScaleFactor = (float)TWin.Position.y1; -#else - TWin.UScaleFactor = ((float)TWin.Position.x1)/256.0f; // -> set scale factor - TWin.VScaleFactor = ((float)TWin.Position.y1)/256.0f; -#endif - } -} - -//////////////////////////////////////////////////////////////////////// -// mmm, Lewpy uses that in TileS ... I don't ;) -//////////////////////////////////////////////////////////////////////// - -/* -void ClampToPSXDrawAreaOffset(short *x0, short *y0, short *x1, short *y1) -{ - if (*x0 < PSXDisplay.DrawArea.x0) - { - *x1 -= (PSXDisplay.DrawArea.x0 - *x0); - *x0 = PSXDisplay.DrawArea.x0; - } - else - if (*x0 > PSXDisplay.DrawArea.x1) - { - *x0 = PSXDisplay.DrawArea.x1; - *x1 = 0; - } - - if (*y0 < PSXDisplay.DrawArea.y0) - { - *y1 -= (PSXDisplay.DrawArea.y0 - *y0); - *y0 = PSXDisplay.DrawArea.y0; - } - else - if (*y0 > PSXDisplay.DrawArea.y1) - { - *y0 = PSXDisplay.DrawArea.y1; - *y1 = 0; - } - - if (*x1 < 0) *x1 = 0; - - if ((*x1 + *x0) > PSXDisplay.DrawArea.x1) - *x1 = (PSXDisplay.DrawArea.x1 - *x0 + 1); - - if (*y1 < 0) *y1 = 0; - - if ((*y1 + *y0) > PSXDisplay.DrawArea.y1) - *y1 = (PSXDisplay.DrawArea.y1 - *y0 + 1); -} -*/ - -//////////////////////////////////////////////////////////////////////// -// Check draw area dimensions -//////////////////////////////////////////////////////////////////////// - -static void ClampToPSXScreen(short *x0, short *y0, short *x1, short *y1) -{ - if (*x0 < 0) *x0 = 0; - else - if (*x0 > 1023) *x0 = 1023; - - if (*x1 < 0) *x1 = 0; - else - if (*x1 > 1023) *x1 = 1023; - - if (*y0 < 0) *y0 = 0; - else - if (*y0 > iGPUHeightMask) *y0 = iGPUHeightMask; - - if (*y1 < 0) *y1 = 0; - else - if (*y1 > iGPUHeightMask) *y1 = iGPUHeightMask; -} - -//////////////////////////////////////////////////////////////////////// -// Used in Load Image and Blk Fill -//////////////////////////////////////////////////////////////////////// - -static void ClampToPSXScreenOffset(short *x0, short *y0, short *x1, short *y1) -{ - if (*x0 < 0) - { *x1 += *x0; *x0 = 0; } - else - if (*x0 > 1023) - { *x0 = 1023; *x1 = 0; } - - if (*y0 < 0) - { *y1 += *y0; *y0 = 0; } - else - if (*y0 > iGPUHeightMask) - { *y0 = iGPUHeightMask; *y1 = 0; } - - if (*x1 < 0) *x1 = 0; - - if ((*x1 + *x0) > 1024) *x1 = (1024 - *x0); - - if (*y1 < 0) *y1 = 0; - - if ((*y1 + *y0) > iGPUHeight) *y1 = (iGPUHeight - *y0); -} - -//////////////////////////////////////////////////////////////////////// -// cmd: start of drawing area... primitives will be clipped inside -//////////////////////////////////////////////////////////////////////// - -static void cmdDrawAreaStart(unsigned char * baseAddr) -{ - uint32_t gdata = ((uint32_t *)baseAddr)[0]; - - drawX = gdata & 0x3ff; // for soft drawing - if(drawX>=1024) drawX=1023; - - if(dwGPUVersion==2) - { - ulGPUInfoVals[INFO_DRAWSTART]=gdata&0x3FFFFF; - drawY = (gdata>>12)&0x3ff; - } - else - { - ulGPUInfoVals[INFO_DRAWSTART]=gdata&0xFFFFF; - drawY = (gdata>>10)&0x3ff; - } - - if(drawY>=iGPUHeight) drawY=iGPUHeightMask; - - PreviousPSXDisplay.DrawArea.y0=PSXDisplay.DrawArea.y0; - PreviousPSXDisplay.DrawArea.x0=PSXDisplay.DrawArea.x0; - - PSXDisplay.DrawArea.y0 = (short)drawY; // for OGL drawing - PSXDisplay.DrawArea.x0 = (short)drawX; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: end of drawing area... primitives will be clipped inside -//////////////////////////////////////////////////////////////////////// - -static void cmdDrawAreaEnd(unsigned char * baseAddr) -{ - uint32_t gdata = ((uint32_t *)baseAddr)[0]; - - drawW = gdata & 0x3ff; // for soft drawing - if(drawW>=1024) drawW=1023; - - if(dwGPUVersion==2) - { - ulGPUInfoVals[INFO_DRAWEND]=gdata&0x3FFFFF; - drawH = (gdata>>12)&0x3ff; - } - else - { - ulGPUInfoVals[INFO_DRAWEND]=gdata&0xFFFFF; - drawH = (gdata>>10)&0x3ff; - } - - if(drawH>=iGPUHeight) drawH=iGPUHeightMask; - - PSXDisplay.DrawArea.y1 = (short)drawH; // for OGL drawing - PSXDisplay.DrawArea.x1 = (short)drawW; - - ClampToPSXScreen(&PSXDisplay.DrawArea.x0, // clamp - &PSXDisplay.DrawArea.y0, - &PSXDisplay.DrawArea.x1, - &PSXDisplay.DrawArea.y1); - - bDisplayNotSet = TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: draw offset... will be added to prim coords -//////////////////////////////////////////////////////////////////////// - -static void cmdDrawOffset(unsigned char * baseAddr) -{ - uint32_t gdata = ((uint32_t *)baseAddr)[0]; - - PreviousPSXDisplay.DrawOffset.x = - PSXDisplay.DrawOffset.x = (short)(gdata & 0x7ff); - - if (dwGPUVersion == 2) - { - ulGPUInfoVals[INFO_DRAWOFF] = gdata&0x7FFFFF; - PSXDisplay.DrawOffset.y = (short)((gdata>>12) & 0x7ff); - } - else - { - ulGPUInfoVals[INFO_DRAWOFF]=gdata&0x3FFFFF; - PSXDisplay.DrawOffset.y = (short)((gdata>>11) & 0x7ff); - } - - PSXDisplay.DrawOffset.x=(short)(((int)PSXDisplay.DrawOffset.x<<21)>>21); - PSXDisplay.DrawOffset.y=(short)(((int)PSXDisplay.DrawOffset.y<<21)>>21); - - PSXDisplay.CumulOffset.x = // new OGL prim offsets - PSXDisplay.DrawOffset.x - PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; - PSXDisplay.CumulOffset.y = - PSXDisplay.DrawOffset.y - PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: load image to vram -//////////////////////////////////////////////////////////////////////// - -static void primLoadImage(unsigned char * baseAddr) -{ - unsigned short *sgpuData = ((unsigned short *) baseAddr); - - VRAMWrite.x = sgpuData[2]&0x03ff; - VRAMWrite.y = sgpuData[3]&iGPUHeightMask; - VRAMWrite.Width = sgpuData[4]; - VRAMWrite.Height = sgpuData[5]; - - iDataWriteMode = DR_VRAMTRANSFER; - VRAMWrite.ImagePtr = psxVuw + (VRAMWrite.y<<10) + VRAMWrite.x; - VRAMWrite.RowsRemaining = VRAMWrite.Width; - VRAMWrite.ColsRemaining = VRAMWrite.Height; - - bNeedWriteUpload=TRUE; -} - -//////////////////////////////////////////////////////////////////////// - -static void PrepareRGB24Upload(void) -{ - VRAMWrite.x=(VRAMWrite.x*2)/3; - VRAMWrite.Width=(VRAMWrite.Width*2)/3; - - if(!PSXDisplay.InterlacedTest && // NEW - CheckAgainstScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) - { - xrUploadArea.x0-=PreviousPSXDisplay.DisplayPosition.x; - xrUploadArea.x1-=PreviousPSXDisplay.DisplayPosition.x; - xrUploadArea.y0-=PreviousPSXDisplay.DisplayPosition.y; - xrUploadArea.y1-=PreviousPSXDisplay.DisplayPosition.y; - } - else - if(CheckAgainstFrontScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) - { - xrUploadArea.x0-=PSXDisplay.DisplayPosition.x; - xrUploadArea.x1-=PSXDisplay.DisplayPosition.x; - xrUploadArea.y0-=PSXDisplay.DisplayPosition.y; - xrUploadArea.y1-=PSXDisplay.DisplayPosition.y; - } - else return; - - if(bRenderFrontBuffer) - { - updateFrontDisplay(); - } - - if(bNeedRGB24Update==FALSE) - { - xrUploadAreaRGB24=xrUploadArea; - bNeedRGB24Update=TRUE; - } - else - { - xrUploadAreaRGB24.x0=min(xrUploadAreaRGB24.x0,xrUploadArea.x0); - xrUploadAreaRGB24.x1=max(xrUploadAreaRGB24.x1,xrUploadArea.x1); - xrUploadAreaRGB24.y0=min(xrUploadAreaRGB24.y0,xrUploadArea.y0); - xrUploadAreaRGB24.y1=max(xrUploadAreaRGB24.y1,xrUploadArea.y1); - } -} - -//////////////////////////////////////////////////////////////////////// - -void CheckWriteUpdate() -{ - int iX=0,iY=0; - - if(VRAMWrite.Width) iX=1; - if(VRAMWrite.Height) iY=1; - - InvalidateTextureArea(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width-iX, VRAMWrite.Height-iY); - - if(PSXDisplay.Interlaced && !iOffscreenDrawing) return; - - if(PSXDisplay.RGB24) {PrepareRGB24Upload();return;} - - if(!PSXDisplay.InterlacedTest && - CheckAgainstScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) - { - if(dwActFixes&0x800) return; - - if(bRenderFrontBuffer) - { - updateFrontDisplay(); - } - - UploadScreen(FALSE); - - bNeedUploadTest=TRUE; - } - else - if(iOffscreenDrawing) - { - if (CheckAgainstFrontScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) - { - if(PSXDisplay.InterlacedTest) - { - if(PreviousPSXDisplay.InterlacedNew) - { - PreviousPSXDisplay.InterlacedNew=FALSE; - bNeedInterlaceUpdate=TRUE; - xrUploadAreaIL.x0=PSXDisplay.DisplayPosition.x; - xrUploadAreaIL.y0=PSXDisplay.DisplayPosition.y; - xrUploadAreaIL.x1=PSXDisplay.DisplayPosition.x+PSXDisplay.DisplayModeNew.x; - xrUploadAreaIL.y1=PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayModeNew.y; - if(xrUploadAreaIL.x1>1023) xrUploadAreaIL.x1=1023; - if(xrUploadAreaIL.y1>511) xrUploadAreaIL.y1=511; - } - - if(bNeedInterlaceUpdate==FALSE) - { - xrUploadAreaIL=xrUploadArea; - bNeedInterlaceUpdate=TRUE; - } - else - { - xrUploadAreaIL.x0=min(xrUploadAreaIL.x0,xrUploadArea.x0); - xrUploadAreaIL.x1=max(xrUploadAreaIL.x1,xrUploadArea.x1); - xrUploadAreaIL.y0=min(xrUploadAreaIL.y0,xrUploadArea.y0); - xrUploadAreaIL.y1=max(xrUploadAreaIL.y1,xrUploadArea.y1); - } - return; - } - - if(!bNeedUploadAfter) - { - bNeedUploadAfter = TRUE; - xrUploadArea.x0=VRAMWrite.x; - xrUploadArea.x1=VRAMWrite.x+VRAMWrite.Width; - xrUploadArea.y0=VRAMWrite.y; - xrUploadArea.y1=VRAMWrite.y+VRAMWrite.Height; - } - else - { - xrUploadArea.x0=min(xrUploadArea.x0,VRAMWrite.x); - xrUploadArea.x1=max(xrUploadArea.x1,VRAMWrite.x+VRAMWrite.Width); - xrUploadArea.y0=min(xrUploadArea.y0,VRAMWrite.y); - xrUploadArea.y1=max(xrUploadArea.y1,VRAMWrite.y+VRAMWrite.Height); - } - - if(dwActFixes&0x8000) - { - if((xrUploadArea.x1-xrUploadArea.x0)>=(PSXDisplay.DisplayMode.x-32) && - (xrUploadArea.y1-xrUploadArea.y0)>=(PSXDisplay.DisplayMode.y-32)) - { - UploadScreen(-1); - updateFrontDisplay(); - } - } - } - } -} - -//////////////////////////////////////////////////////////////////////// -// cmd: vram -> psx mem -//////////////////////////////////////////////////////////////////////// - -static void primStoreImage(unsigned char * baseAddr) -{ - unsigned short *sgpuData = ((unsigned short *) baseAddr); - - VRAMRead.x = sgpuData[2]&0x03ff; - VRAMRead.y = sgpuData[3]&iGPUHeightMask; - VRAMRead.Width = sgpuData[4]; - VRAMRead.Height = sgpuData[5]; - - VRAMRead.ImagePtr = psxVuw + (VRAMRead.y<<10) + VRAMRead.x; - VRAMRead.RowsRemaining = VRAMRead.Width; - VRAMRead.ColsRemaining = VRAMRead.Height; - - iDataReadMode = DR_VRAMTRANSFER; - - STATUSREG |= GPUSTATUS_READYFORVRAM; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: blkfill - NO primitive! Doesn't care about draw areas... -//////////////////////////////////////////////////////////////////////// - -static void primBlkFill(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - iDrawnSomething = 1; - - sprtX = sgpuData[2]; - sprtY = sgpuData[3]; - sprtW = sgpuData[4] & 0x3ff; - sprtH = sgpuData[5] & iGPUHeightMask; - - sprtW = (sprtW + 15) & ~15; - - // Increase H & W if they are one short of full values, because they never can be full values - if (sprtH == iGPUHeightMask) sprtH=iGPUHeight; - if (sprtW == 1023) sprtW=1024; - - // x and y of start - ly0 = ly1 = sprtY; - ly2 = ly3 = (sprtY+sprtH); - lx0 = lx3 = sprtX; - lx1 = lx2 = (sprtX+sprtW); - - offsetBlk(); - - if(ClipVertexListScreen()) - { - PSXDisplay_t * pd; - if(PSXDisplay.InterlacedTest) pd=&PSXDisplay; - else pd=&PreviousPSXDisplay; - - if ((lx0 <= pd->DisplayPosition.x+16) && - (ly0 <= pd->DisplayPosition.y+16) && - (lx2 >= pd->DisplayEnd.x-16) && - (ly2 >= pd->DisplayEnd.y-16)) - { - GLclampf g,b,r; - g=((GLclampf)GREEN(gpuData[0]))/255.0f; - b=((GLclampf)BLUE(gpuData[0]))/255.0f; - r=((GLclampf)RED(gpuData[0]))/255.0f; - - glDisable(GL_SCISSOR_TEST); - glClearColor(r,g,b,1.0f); - glClear(uiBufferBits); - gl_z=0.0f; - - if(gpuData[0]!=0x02000000 && - (ly0>pd->DisplayPosition.y || - ly2DisplayEnd.y)) - { - bDrawTextured = FALSE; - bDrawSmoothShaded = FALSE; - SetRenderState((uint32_t)0x01000000); - SetRenderMode((uint32_t)0x01000000, FALSE); - vertex[0].c.lcol=0xff000000; - SETCOL(vertex[0]); - if(ly0>pd->DisplayPosition.y) - { - vertex[0].x=0;vertex[0].y=0; - vertex[1].x=pd->DisplayEnd.x-pd->DisplayPosition.x;vertex[1].y=0; - vertex[2].x=vertex[1].x;vertex[2].y=ly0-pd->DisplayPosition.y; - vertex[3].x=0;vertex[3].y=vertex[2].y; - PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - } - if(ly2DisplayEnd.y) - { - vertex[0].x=0;vertex[0].y=(pd->DisplayEnd.y-pd->DisplayPosition.y)-(pd->DisplayEnd.y-ly2); - vertex[1].x=pd->DisplayEnd.x-pd->DisplayPosition.x;vertex[1].y=vertex[0].y; - vertex[2].x=vertex[1].x;vertex[2].y=pd->DisplayEnd.y; - vertex[3].x=0;vertex[3].y=vertex[2].y; - PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - } - } - - glEnable(GL_SCISSOR_TEST); - } - else - { - bDrawTextured = FALSE; - bDrawSmoothShaded = FALSE; - SetRenderState((uint32_t)0x01000000); - SetRenderMode((uint32_t)0x01000000, FALSE); - vertex[0].c.lcol=gpuData[0]|0xff000000; - SETCOL(vertex[0]); - glDisable(GL_SCISSOR_TEST); - PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - glEnable(GL_SCISSOR_TEST); - } - } - - //mmm... will clean all stuff, also if not all _should_ be cleaned... - //if (IsInsideNextScreen(sprtX, sprtY, sprtW, sprtH)) - // try this: - if (IsCompleteInsideNextScreen(sprtX, sprtY, sprtW, sprtH)) - { - lClearOnSwapColor = COLOR(gpuData[0]); - lClearOnSwap = 1; - } - - if(iOffscreenDrawing) - { - ClampToPSXScreenOffset( &sprtX, &sprtY, &sprtW, &sprtH); - if ((sprtW == 0) || (sprtH == 0)) return; - InvalidateTextureArea(sprtX, sprtY, sprtW-1, sprtH-1); - - sprtW+=sprtX; - sprtH+=sprtY; - - FillSoftwareArea(sprtX, sprtY, sprtW, sprtH, BGR24to16(gpuData[0])); - } -} - -//////////////////////////////////////////////////////////////////////// -// cmd: move image vram -> vram -//////////////////////////////////////////////////////////////////////// - -static void MoveImageWrapped(short imageX0,short imageY0, - short imageX1,short imageY1, - short imageSX,short imageSY) -{ - int i,j,imageXE,imageYE; - - if(iFrameReadType&2) - { - imageXE=imageX0+imageSX; - imageYE=imageY0+imageSY; - - if(imageYE>iGPUHeight && imageXE>1024) - { - CheckVRamRead(0,0, - (imageXE&0x3ff), - (imageY0&iGPUHeightMask), - FALSE); - } - - if(imageXE>1024) - { - CheckVRamRead(0,imageY0, - (imageXE&0x3ff), - (imageYE>iGPUHeight)?iGPUHeight:imageYE, - FALSE); - } - - if(imageYE>iGPUHeight) - { - CheckVRamRead(imageX0,0, - (imageXE>1024)?1024:imageXE, - imageYE&iGPUHeightMask, - FALSE); - } - - CheckVRamRead(imageX0,imageY0, - (imageXE>1024)?1024:imageXE, - (imageYE>iGPUHeight)?iGPUHeight:imageYE, - FALSE); - } - - for(j=0;jiGPUHeight && imageXE>1024) - { - InvalidateTextureArea(0,0, - (imageXE&0x3ff)-1, - (imageYE&iGPUHeightMask)-1); - } - - if(imageXE>1024) - { - InvalidateTextureArea(0,imageY1, - (imageXE&0x3ff)-1, - ((imageYE>iGPUHeight)?iGPUHeight:imageYE)-imageY1-1); - } - - if(imageYE>iGPUHeight) - { - InvalidateTextureArea(imageX1,0, - ((imageXE>1024)?1024:imageXE)-imageX1-1, - (imageYE&iGPUHeightMask)-1); - } - - InvalidateTextureArea(imageX1,imageY1, - ((imageXE>1024)?1024:imageXE)-imageX1-1, - ((imageYE>iGPUHeight)?iGPUHeight:imageYE)-imageY1-1); - } -} - -//////////////////////////////////////////////////////////////////////// - -static void primMoveImage(unsigned char * baseAddr) -{ - short *sgpuData = ((short *) baseAddr); - short imageY0,imageX0,imageY1,imageX1,imageSX,imageSY,i,j; - - imageX0 = sgpuData[2]&0x03ff; - imageY0 = sgpuData[3]&iGPUHeightMask; - imageX1 = sgpuData[4]&0x03ff; - imageY1 = sgpuData[5]&iGPUHeightMask; - imageSX = sgpuData[6]; - imageSY = sgpuData[7]; - - if((imageX0 == imageX1) && (imageY0 == imageY1)) return; - if(imageSX<=0) return; - if(imageSY<=0) return; - - if(iGPUHeight==1024 && sgpuData[7]>1024) return; - - if((imageY0+imageSY)>iGPUHeight || - (imageX0+imageSX)>1024 || - (imageY1+imageSY)>iGPUHeight || - (imageX1+imageSX)>1024) - { - MoveImageWrapped(imageX0,imageY0,imageX1,imageY1,imageSX,imageSY); - if((imageY0+imageSY)>iGPUHeight) imageSY=iGPUHeight-imageY0; - if((imageX0+imageSX)>1024) imageSX=1024-imageX0; - if((imageY1+imageSY)>iGPUHeight) imageSY=iGPUHeight-imageY1; - if((imageX1+imageSX)>1024) imageSX=1024-imageX1; - } - - if(iFrameReadType&2) - CheckVRamRead(imageX0,imageY0, - imageX0+imageSX, - imageY0+imageSY, - FALSE); - - if(imageSX&1) - { - unsigned short *SRCPtr, *DSTPtr; - unsigned short LineOffset; - - SRCPtr = psxVuw + (1024*imageY0) + imageX0; - DSTPtr = psxVuw + (1024*imageY1) + imageX1; - - LineOffset = 1024 - imageSX; - - for(j=0;j>1; - - SRCPtr = (uint32_t *)(psxVuw + (1024*imageY0) + imageX0); - DSTPtr = (uint32_t *)(psxVuw + (1024*imageY1) + imageX1); - - LineOffset = 512 - dx; - - for(j=0;j=PreviousPSXDisplay.DisplayPosition.x && - imageX1=PreviousPSXDisplay.DisplayPosition.y && - imageY1=PreviousPSXDisplay.DisplayPosition.x && - imageX1<=PreviousPSXDisplay.DisplayEnd.x && - imageY1>=PreviousPSXDisplay.DisplayPosition.y && - imageY1<=PreviousPSXDisplay.DisplayEnd.y) - { - if(!( - imageX0>=PSXDisplay.DisplayPosition.x && - imageX0=PSXDisplay.DisplayPosition.y && - imageY0=PreviousPSXDisplay.DisplayPosition.x && - imageX0=PreviousPSXDisplay.DisplayPosition.y && - imageY0=PSXDisplay.DisplayPosition.x && - imageX0=PSXDisplay.DisplayPosition.y && - imageY0 set color with - SETCOL(vertex[0]); // texture alpha - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - vertex[0].x+=POFF;vertex[1].x+=POFF; - vertex[2].x+=POFF;vertex[3].x+=POFF; - vertex[0].y+=POFF;vertex[1].y+=POFF; - vertex[2].y+=POFF;vertex[3].y+=POFF; - GlobalTextABR=0; - DrawSemiTrans=1; - SetSemiTrans(); - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - GlobalTextABR=lABR; - DrawSemiTrans=lDST; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: small sprite (textured rect) -//////////////////////////////////////////////////////////////////////// - -static void primSprt8(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - short s; - - iSpriteTex=1; - - sprtX = sgpuData[2]; - sprtY = sgpuData[3]; - sprtW = 8; - sprtH = 8; - - lx0 = sprtX; - ly0 = sprtY; - - offsetST(); - - // do texture stuff - gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; - - if(usMirror & 0x1000) - { - s=gl_ux[0]; - s-=sprtW-1; - if(s<0) {s=0;} - gl_ux[0]=gl_ux[3]=s; - } - - sSprite_ux2=s=gl_ux[0]+sprtW; - if(s) s--; - if(s>255) s=255; - gl_ux[1]=gl_ux[2]=s; - // Y coords - gl_vy[0]=gl_vy[1]=baseAddr[9];//(gpuData[2]>>8)&0xff; - - if(usMirror & 0x2000) - { - s=gl_vy[0]; - s-=sprtH-1; - if(s<0) {s=0;} - gl_vy[0]=gl_vy[1]=s; - } - - sSprite_vy2=s=gl_vy[0]+sprtH; - if(s) s--; - if(s>255) s=255; - gl_vy[2]=gl_vy[3]=s; - - ulClutID=(gpuData[2]>>16); - - bDrawTextured = TRUE; - bDrawSmoothShaded = FALSE; - SetRenderState(gpuData[0]); - - if(iOffscreenDrawing) - { - offsetPSX4(); - - if(bDrawOffscreen4()) - { - InvalidateTextureAreaEx(); - SetRenderColor(gpuData[0]); - lx0-=PSXDisplay.DrawOffset.x; - ly0-=PSXDisplay.DrawOffset.y; - - if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,8,8); - else - if(usMirror) DrawSoftwareSpriteMirror(baseAddr,8,8); - else - DrawSoftwareSprite(baseAddr,8,8,baseAddr[8],baseAddr[9]); - } - } - - SetRenderMode(gpuData[0], TRUE); - SetZMask4SP(); - - sSprite_ux2=gl_ux[0]+sprtW; - sSprite_vy2=gl_vy[0]+sprtH; - - assignTextureSprite(); - - if(iFilterType>4) - DrawMultiFilterSprite(); - else - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - - if(bDrawMultiPass) - { - SetSemiTransMulti(1); - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - } - - if(ubOpaqueDraw) - { - SetZMask4O(); - if(bUseMultiPass) SetOpaqueColor(gpuData[0]); - DEFOPAQUEON - - if(bSmallAlpha && iFilterType<=2) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - SetZMask4O(); - } - - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - DEFOPAQUEOFF - } - - iSpriteTex=0; - iDrawnSomething=1; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: medium sprite (textured rect) -//////////////////////////////////////////////////////////////////////// - -static void primSprt16(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - short s; - - iSpriteTex=1; - - sprtX = sgpuData[2]; - sprtY = sgpuData[3]; - sprtW = 16; - sprtH = 16; - - lx0 = sprtX; - ly0 = sprtY; - - offsetST(); - - // do texture stuff - gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; - - if(usMirror & 0x1000) - { - s=gl_ux[0]; - s-=sprtW-1; - if(s<0) {s=0;} - gl_ux[0]=gl_ux[3]=s; - } - - sSprite_ux2=s=gl_ux[0]+sprtW; - if(s) s--; - if(s>255) s=255; - gl_ux[1]=gl_ux[2]=s; - // Y coords - gl_vy[0]=gl_vy[1]=baseAddr[9];//(gpuData[2]>>8)&0xff; - - if(usMirror & 0x2000) - { - s=gl_vy[0]; - s-=sprtH-1; - if(s<0) {s=0;} - gl_vy[0]=gl_vy[1]=s; - } - - sSprite_vy2=s=gl_vy[0]+sprtH; - if(s) s--; - if(s>255) s=255; - gl_vy[2]=gl_vy[3]=s; - - ulClutID=(gpuData[2]>>16); - - bDrawTextured = TRUE; - bDrawSmoothShaded = FALSE; - SetRenderState(gpuData[0]); - - if(iOffscreenDrawing) - { - offsetPSX4(); - - if(bDrawOffscreen4()) - { - InvalidateTextureAreaEx(); - SetRenderColor(gpuData[0]); - lx0-=PSXDisplay.DrawOffset.x; - ly0-=PSXDisplay.DrawOffset.y; - if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,16,16); - else - if(usMirror) DrawSoftwareSpriteMirror(baseAddr,16,16); - else - DrawSoftwareSprite(baseAddr,16,16,baseAddr[8],baseAddr[9]); - } - } - - SetRenderMode(gpuData[0], TRUE); - SetZMask4SP(); - - sSprite_ux2=gl_ux[0]+sprtW; - sSprite_vy2=gl_vy[0]+sprtH; - - assignTextureSprite(); - - if(iFilterType>4) - DrawMultiFilterSprite(); - else - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - - if(bDrawMultiPass) - { - SetSemiTransMulti(1); - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - } - - if(ubOpaqueDraw) - { - SetZMask4O(); - if(bUseMultiPass) SetOpaqueColor(gpuData[0]); - DEFOPAQUEON - - if(bSmallAlpha && iFilterType<=2) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - SetZMask4O(); - } - - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - DEFOPAQUEOFF - } - - iSpriteTex=0; - iDrawnSomething=1; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: free-size sprite (textured rect) -//////////////////////////////////////////////////////////////////////// - -static void primSprtSRest(unsigned char * baseAddr,unsigned short type) -{ - uint32_t *gpuData = ((uint32_t *)baseAddr); - short *sgpuData = ((short *) baseAddr); - short s; - unsigned short sTypeRest=0; - - sprtX = sgpuData[2]; - sprtY = sgpuData[3]; - sprtW = sgpuData[6] & 0x3ff; - sprtH = sgpuData[7] & 0x1ff; - - // do texture stuff - switch(type) - { - case 1: - gl_vy[0]=gl_vy[1]=baseAddr[9]; - s=256-baseAddr[8]; - sprtW-=s; - sprtX+=s; - gl_ux[0]=gl_ux[3]=0; - break; - case 2: - gl_ux[0]=gl_ux[3]=baseAddr[8]; - s=256-baseAddr[9]; - sprtH-=s; - sprtY+=s; - gl_vy[0]=gl_vy[1]=0; - break; - case 3: - s=256-baseAddr[8]; - sprtW-=s; - sprtX+=s; - gl_ux[0]=gl_ux[3]=0; - s=256-baseAddr[9]; - sprtH-=s; - sprtY+=s; - gl_vy[0]=gl_vy[1]=0; - break; - - case 4: - gl_vy[0]=gl_vy[1]=baseAddr[9]; - s=512-baseAddr[8]; - sprtW-=s; - sprtX+=s; - gl_ux[0]=gl_ux[3]=0; - break; - case 5: - gl_ux[0]=gl_ux[3]=baseAddr[8]; - s=512-baseAddr[9]; - sprtH-=s; - sprtY+=s; - gl_vy[0]=gl_vy[1]=0; - break; - case 6: - s=512-baseAddr[8]; - sprtW-=s; - sprtX+=s; - gl_ux[0]=gl_ux[3]=0; - s=512-baseAddr[9]; - sprtH-=s; - sprtY+=s; - gl_vy[0]=gl_vy[1]=0; - break; - - } - - if(usMirror & 0x1000) - { - s=gl_ux[0]; - s-=sprtW-1;if(s<0) s=0; - gl_ux[0]=gl_ux[3]=s; - } - if(usMirror & 0x2000) - { - s=gl_vy[0]; - s-=sprtH-1;if(s<0) {s=0;} - gl_vy[0]=gl_vy[1]=s; - } - - sSprite_ux2=s=gl_ux[0]+sprtW; - if(s>255) s=255; - gl_ux[1]=gl_ux[2]=s; - sSprite_vy2=s=gl_vy[0]+sprtH; - if(s>255) s=255; - gl_vy[2]=gl_vy[3]=s; - - if(!bUsingTWin) - { - if(sSprite_ux2>256) - {sprtW=256-gl_ux[0];sSprite_ux2=256;sTypeRest+=1;} - if(sSprite_vy2>256) - {sprtH=256-gl_vy[0];sSprite_vy2=256;sTypeRest+=2;} - } - - lx0 = sprtX; - ly0 = sprtY; - - offsetST(); - - ulClutID=(gpuData[2]>>16); - - bDrawTextured = TRUE; - bDrawSmoothShaded = FALSE; - SetRenderState(gpuData[0]); - - if(iOffscreenDrawing) - { - offsetPSX4(); - - if(bDrawOffscreen4()) - { - InvalidateTextureAreaEx(); - SetRenderColor(gpuData[0]); - lx0-=PSXDisplay.DrawOffset.x; - ly0-=PSXDisplay.DrawOffset.y; - if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,sprtW,sprtH); - else - if(usMirror) DrawSoftwareSpriteMirror(baseAddr,sprtW,sprtH); - else - DrawSoftwareSprite(baseAddr,sprtW,sprtH,baseAddr[8],baseAddr[9]); - } - } - - SetRenderMode(gpuData[0], TRUE); - SetZMask4SP(); - - sSprite_ux2=gl_ux[0]+sprtW; - sSprite_vy2=gl_vy[0]+sprtH; - - assignTextureSprite(); - - if(iFilterType>4) - DrawMultiFilterSprite(); - else - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - - if(bDrawMultiPass) - { - SetSemiTransMulti(1); - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - } - - if(ubOpaqueDraw) - { - SetZMask4O(); - if(bUseMultiPass) SetOpaqueColor(gpuData[0]); - DEFOPAQUEON - - if(bSmallAlpha && iFilterType<=2) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - SetZMask4O(); - } - - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - DEFOPAQUEOFF - } - - 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); - } -} - -static void primSprtS(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - short s; - unsigned short sTypeRest=0; - - sprtX = sgpuData[2]; - sprtY = sgpuData[3]; - sprtW = sgpuData[6] & 0x3ff; - sprtH = sgpuData[7] & 0x1ff; - - if(!sprtH) return; - if(!sprtW) return; - - iSpriteTex=1; - - // do texture stuff - gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; - gl_vy[0]=gl_vy[1]=baseAddr[9];//(gpuData[2]>>8)&0xff; - - if(usMirror & 0x1000) - { - s=gl_ux[0]; - s-=sprtW-1; - if(s<0) {s=0;} - gl_ux[0]=gl_ux[3]=s; - } - if(usMirror & 0x2000) - { - s=gl_vy[0]; - s-=sprtH-1; - if(s<0) {s=0;} - gl_vy[0]=gl_vy[1]=s; - } - - sSprite_ux2=s=gl_ux[0]+sprtW; - if(s) s--; - if(s>255) s=255; - gl_ux[1]=gl_ux[2]=s; - sSprite_vy2=s=gl_vy[0]+sprtH; - if(s) s--; - if(s>255) s=255; - gl_vy[2]=gl_vy[3]=s; - - if(!bUsingTWin) - { - if(sSprite_ux2>256) - {sprtW=256-gl_ux[0];sSprite_ux2=256;sTypeRest+=1;} - if(sSprite_vy2>256) - {sprtH=256-gl_vy[0];sSprite_vy2=256;sTypeRest+=2;} - } - - lx0 = sprtX; - ly0 = sprtY; - - offsetST(); - - ulClutID=(gpuData[2]>>16); - - bDrawTextured = TRUE; - bDrawSmoothShaded = FALSE; - SetRenderState(gpuData[0]); - - if(iOffscreenDrawing) - { - offsetPSX4(); - - if(bDrawOffscreen4()) - { - InvalidateTextureAreaEx(); - SetRenderColor(gpuData[0]); - lx0-=PSXDisplay.DrawOffset.x; - ly0-=PSXDisplay.DrawOffset.y; - if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,sprtW,sprtH); - else - if(usMirror) DrawSoftwareSpriteMirror(baseAddr,sprtW,sprtH); - else - DrawSoftwareSprite(baseAddr,sprtW,sprtH,baseAddr[8],baseAddr[9]); - } - } - - SetRenderMode(gpuData[0], TRUE); - SetZMask4SP(); - - if((dwActFixes&1) && gTexFrameName && gTexName==gTexFrameName) - {iSpriteTex=0;return;} - - sSprite_ux2=gl_ux[0]+sprtW; - sSprite_vy2=gl_vy[0]+sprtH; - - assignTextureSprite(); - - if(iFilterType>4) - DrawMultiFilterSprite(); - else - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - - if(bDrawMultiPass) - { - SetSemiTransMulti(1); - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - } - - if(ubOpaqueDraw) - { - SetZMask4O(); - if(bUseMultiPass) SetOpaqueColor(gpuData[0]); - DEFOPAQUEON - - if(bSmallAlpha && iFilterType<=2) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - SetZMask4O(); - } - - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - DEFOPAQUEOFF - } - - if(sTypeRest) - { - if(sTypeRest&1) primSprtSRest(baseAddr,1); - if(sTypeRest&2) primSprtSRest(baseAddr,2); - if(sTypeRest==3) primSprtSRest(baseAddr,3); - } - - iSpriteTex=0; - iDrawnSomething=1; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: flat shaded Poly4 -//////////////////////////////////////////////////////////////////////// - -static void primPolyF4(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = sgpuData[2]; - ly0 = sgpuData[3]; - lx1 = sgpuData[4]; - ly1 = sgpuData[5]; - lx2 = sgpuData[6]; - ly2 = sgpuData[7]; - lx3 = sgpuData[8]; - ly3 = sgpuData[9]; - - if(offset4()) return; - - bDrawTextured = FALSE; - bDrawSmoothShaded = FALSE; - SetRenderState(gpuData[0]); - - if(iOffscreenDrawing) - { - offsetPSX4(); - if(bDrawOffscreen4()) - { - InvalidateTextureAreaEx(); - drawPoly4F(gpuData[0]); - } - } - - SetRenderMode(gpuData[0], FALSE); - SetZMask4NT(); - - vertex[0].c.lcol=gpuData[0];vertex[0].c.col[3]=ubGloColAlpha; - SETCOL(vertex[0]); - - PRIMdrawTri2(&vertex[0], &vertex[1], &vertex[2],&vertex[3]); - - iDrawnSomething=1; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: smooth shaded Poly4 -//////////////////////////////////////////////////////////////////////// - -void primPolyG4(unsigned char * baseAddr); - -static BOOL bDrawOffscreenFrontFF9G4(void) -{ - if(lx0< PSXDisplay.DisplayPosition.x) return FALSE; // must be complete in front - if(lx0> PSXDisplay.DisplayEnd.x) return FALSE; - if(ly0< PSXDisplay.DisplayPosition.y) return FALSE; - if(ly0> PSXDisplay.DisplayEnd.y) return FALSE; - if(lx1< PSXDisplay.DisplayPosition.x) return FALSE; - if(lx1> PSXDisplay.DisplayEnd.x) return FALSE; - if(ly1< PSXDisplay.DisplayPosition.y) return FALSE; - if(ly1> PSXDisplay.DisplayEnd.y) return FALSE; - if(lx2< PSXDisplay.DisplayPosition.x) return FALSE; - if(lx2> PSXDisplay.DisplayEnd.x) return FALSE; - if(ly2< PSXDisplay.DisplayPosition.y) return FALSE; - if(ly2> PSXDisplay.DisplayEnd.y) return FALSE; - if(lx3< PSXDisplay.DisplayPosition.x) return FALSE; - if(lx3> PSXDisplay.DisplayEnd.x) return FALSE; - if(ly3< PSXDisplay.DisplayPosition.y) return FALSE; - if(ly3> PSXDisplay.DisplayEnd.y) return FALSE; - return TRUE; -} - -BOOL bCheckFF9G4(unsigned char * baseAddr) -{ - static unsigned char pFF9G4Cache[32]; - static int iFF9Fix=0; - - if(baseAddr) - { - if(iFF9Fix==0) - { - if(bDrawOffscreenFrontFF9G4()) - { - short *sgpuData = ((short *) pFF9G4Cache); - iFF9Fix=2; - memcpy(pFF9G4Cache,baseAddr,32); - - if(sgpuData[2]==142) - { - sgpuData[2] +=65; - sgpuData[10]+=65; - } - return TRUE; - } - else iFF9Fix=1; - } - return FALSE; - } - - if(iFF9Fix==2) - { - int labr=GlobalTextABR; - GlobalTextABR = 1; - primPolyG4(pFF9G4Cache); - GlobalTextABR = labr; - } - iFF9Fix = 0; - - return FALSE; -} - -//////////////////////////////////////////////////////////////////////// - -void primPolyG4(unsigned char * baseAddr) -{ - uint32_t *gpuData = (uint32_t *)baseAddr; - short *sgpuData = ((short *)baseAddr); - - lx0 = sgpuData[2]; - ly0 = sgpuData[3]; - lx1 = sgpuData[6]; - ly1 = sgpuData[7]; - lx2 = sgpuData[10]; - ly2 = sgpuData[11]; - lx3 = sgpuData[14]; - ly3 = sgpuData[15]; - - if(offset4()) return; - - bDrawTextured = FALSE; - bDrawSmoothShaded = TRUE; - SetRenderState(gpuData[0]); - - if(iOffscreenDrawing) - { - offsetPSX4(); - - if((dwActFixes&512) && bCheckFF9G4(baseAddr)) return; - - if(bDrawOffscreen4()) - { - InvalidateTextureAreaEx(); - drawPoly4G(gpuData[0], gpuData[2], gpuData[4], gpuData[6]); - } - } - - SetRenderMode(gpuData[0], FALSE); - SetZMask4NT(); - - vertex[0].c.lcol=gpuData[0]; - vertex[1].c.lcol=gpuData[2]; - vertex[2].c.lcol=gpuData[4]; - vertex[3].c.lcol=gpuData[6]; - - vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloAlpha; - - - PRIMdrawGouraudTri2Color(&vertex[0],&vertex[1], &vertex[2], &vertex[3]); - - iDrawnSomething=1; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: flat shaded Texture3 -//////////////////////////////////////////////////////////////////////// - -static BOOL DoLineCheck(uint32_t *gpuData) -{ - BOOL bQuad=FALSE;short dx,dy; - - if(lx0==lx1) - { - dx=lx0-lx2;if(dx<0) dx=-dx; - - if(ly1==ly2) - { - dy=ly1-ly0;if(dy<0) dy=-dy; - if(dx<=1) - { - vertex[3]=vertex[2]; - vertex[2]=vertex[0]; - vertex[2].x=vertex[3].x; - } - else - if(dy<=1) - { - vertex[3]=vertex[2]; - vertex[2].y=vertex[0].y; - } - else return FALSE; - - bQuad=TRUE; - } - else - if(ly0==ly2) - { - dy=ly0-ly1;if(dy<0) dy=-dy; - if(dx<=1) - { - vertex[3]=vertex[1]; - vertex[3].x=vertex[2].x; - } - else - if(dy<=1) - { - vertex[3]=vertex[2]; - vertex[3].y=vertex[1].y; - } - else return FALSE; - - bQuad=TRUE; - } - } - - if(lx0==lx2) - { - dx=lx0-lx1;if(dx<0) dx=-dx; - - if(ly2==ly1) - { - dy=ly2-ly0;if(dy<0) dy=-dy; - if(dx<=1) - { - vertex[3]=vertex[1]; - vertex[1]=vertex[0]; - vertex[1].x=vertex[3].x; - } - else - if(dy<=1) - { - vertex[3]=vertex[1]; - vertex[1].y=vertex[0].y; - } - else return FALSE; - - bQuad=TRUE; - } - else - if(ly0==ly1) - { - dy=ly2-ly0;if(dy<0) dy=-dy; - if(dx<=1) - { - vertex[3]=vertex[2]; - vertex[3].x=vertex[1].x; - } - else - if(dy<=1) - { - vertex[3]=vertex[1]; - vertex[3].y=vertex[2].y; - } - else return FALSE; - - bQuad=TRUE; - } - } - - if(lx1==lx2) - { - dx=lx1-lx0;if(dx<0) dx=-dx; - - if(ly1==ly0) - { - dy=ly1-ly2;if(dy<0) dy=-dy; - - if(dx<=1) - { - vertex[3]=vertex[2]; - vertex[2].x=vertex[0].x; - } - else - if(dy<=1) - { - vertex[3]=vertex[2]; - vertex[2]=vertex[0]; - vertex[2].y=vertex[3].y; - } - else return FALSE; - - bQuad=TRUE; - } - else - if(ly2==ly0) - { - dy=ly2-ly1;if(dy<0) dy=-dy; - - if(dx<=1) - { - vertex[3]=vertex[1]; - vertex[1].x=vertex[0].x; - } - else - if(dy<=1) - { - vertex[3]=vertex[1]; - vertex[1]=vertex[0]; - vertex[1].y=vertex[3].y; - } - else return FALSE; - - bQuad=TRUE; - } - } - - if(!bQuad) return FALSE; - - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); - - if(bDrawMultiPass) - { - SetSemiTransMulti(1); - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); - } - - if(ubOpaqueDraw) - { - SetZMask4O(); - if(bUseMultiPass) SetOpaqueColor(gpuData[0]); - DEFOPAQUEON - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); - DEFOPAQUEOFF - } - - iDrawnSomething=1; - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////// - -static void primPolyFT3(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = sgpuData[2]; - ly0 = sgpuData[3]; - lx1 = sgpuData[6]; - ly1 = sgpuData[7]; - lx2 = sgpuData[10]; - ly2 = sgpuData[11]; - - if(offset3()) return; - - // do texture UV coordinates stuff - gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; - gl_vy[0]=gl_vy[3]=baseAddr[9];//(gpuData[2]>>8)&0xff; - gl_ux[1]=baseAddr[16];//gpuData[4]&0xff; - gl_vy[1]=baseAddr[17];//(gpuData[4]>>8)&0xff; - gl_ux[2]=baseAddr[24];//gpuData[6]&0xff; - gl_vy[2]=baseAddr[25];//(gpuData[6]>>8)&0xff; - - UpdateGlobalTP((unsigned short)(gpuData[4]>>16)); - ulClutID=gpuData[2]>>16; - - bDrawTextured = TRUE; - bDrawSmoothShaded = FALSE; - SetRenderState(gpuData[0]); - - if(iOffscreenDrawing) - { - offsetPSX3(); - if(bDrawOffscreen3()) - { - InvalidateTextureAreaEx(); - SetRenderColor(gpuData[0]); - drawPoly3FT(baseAddr); - } - } - - SetRenderMode(gpuData[0], TRUE); - SetZMask3(); - - assignTexture3(); - - if(!(dwActFixes&0x10)) - { - if(DoLineCheck(gpuData)) return; - } - - PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); - - if(bDrawMultiPass) - { - SetSemiTransMulti(1); - PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); - } - - if(ubOpaqueDraw) - { - SetZMask3O(); - if(bUseMultiPass) SetOpaqueColor(gpuData[0]); - DEFOPAQUEON - PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); - DEFOPAQUEOFF - } - - iDrawnSomething=1; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: flat shaded Texture4 -//////////////////////////////////////////////////////////////////////// - -#define ST_FAC 255.99f - -static void RectTexAlign(void) -{ - int UFlipped = FALSE; - int VFlipped = FALSE; - - if(gTexName==gTexFrameName) return; - - if(ly0==ly1) - { - if(!((lx1==lx3 && ly3==ly2 && lx2==lx0) || - (lx1==lx2 && ly2==ly3 && lx3==lx0))) - return; - - if(ly0 vertex[2].tow) - VFlipped = 1; - } - else - { - if (vertex[0].tow < vertex[2].tow) - VFlipped = 2; - } - } - else - if(ly0==ly2) - { - if(!((lx2==lx3 && ly3==ly1 && lx1==lx0) || - (lx2==lx1 && ly1==ly3 && lx3==lx0))) - return; - - if(ly0 vertex[1].tow) - VFlipped = 3; - } - else - { - if (vertex[0].tow < vertex[1].tow) - VFlipped = 4; - } - } - else - if(ly0==ly3) - { - if(!((lx3==lx2 && ly2==ly1 && lx1==lx0) || - (lx3==lx1 && ly1==ly2 && lx2==lx0))) - return; - - if(ly0 vertex[1].tow) - VFlipped = 5; - } - else - { - if (vertex[0].tow < vertex[1].tow) - VFlipped = 6; - } - } - else return; - - if(lx0==lx1) - { - if(lx0 vertex[2].sow) - UFlipped = 1; - } - else - { - if (vertex[0].sow < vertex[2].sow) - UFlipped = 2; - } - } - else - if(lx0==lx2) - { - if(lx0 vertex[1].sow) - UFlipped = 3; - } - else - { - if (vertex[0].sow < vertex[1].sow) - UFlipped = 4; - } - } - else - if(lx0==lx3) - { - if(lx0 vertex[1].sow) - UFlipped = 5; - } - else - { - if (vertex[0].sow < vertex[1].sow) - UFlipped = 6; - } - } - - if (UFlipped) - { -#ifdef OWNSCALE - if(bUsingTWin) - { - switch(UFlipped) - { - case 1: - vertex[2].sow+=0.95f/TWin.UScaleFactor; - vertex[3].sow+=0.95f/TWin.UScaleFactor; - break; - case 2: - vertex[0].sow+=0.95f/TWin.UScaleFactor; - vertex[1].sow+=0.95f/TWin.UScaleFactor; - break; - case 3: - vertex[1].sow+=0.95f/TWin.UScaleFactor; - vertex[3].sow+=0.95f/TWin.UScaleFactor; - break; - case 4: - vertex[0].sow+=0.95f/TWin.UScaleFactor; - vertex[2].sow+=0.95f/TWin.UScaleFactor; - break; - case 5: - vertex[1].sow+=0.95f/TWin.UScaleFactor; - vertex[2].sow+=0.95f/TWin.UScaleFactor; - break; - case 6: - vertex[0].sow+=0.95f/TWin.UScaleFactor; - vertex[3].sow+=0.95f/TWin.UScaleFactor; - break; - } - } - else - { - switch(UFlipped) - { - case 1: - vertex[2].sow+=1.0f/ST_FAC; - vertex[3].sow+=1.0f/ST_FAC; - break; - case 2: - vertex[0].sow+=1.0f/ST_FAC; - vertex[1].sow+=1.0f/ST_FAC; - break; - case 3: - vertex[1].sow+=1.0f/ST_FAC; - vertex[3].sow+=1.0f/ST_FAC; - break; - case 4: - vertex[0].sow+=1.0f/ST_FAC; - vertex[2].sow+=1.0f/ST_FAC; - break; - case 5: - vertex[1].sow+=1.0f/ST_FAC; - vertex[2].sow+=1.0f/ST_FAC; - break; - case 6: - vertex[0].sow+=1.0f/ST_FAC; - vertex[3].sow+=1.0f/ST_FAC; - break; - } - } -#else - if(bUsingTWin) - { - switch(UFlipped) - { - case 1: - vertex[2].sow+=1.0f/TWin.UScaleFactor; - vertex[3].sow+=1.0f/TWin.UScaleFactor; - break; - case 2: - vertex[0].sow+=1.0f/TWin.UScaleFactor; - vertex[1].sow+=1.0f/TWin.UScaleFactor; - break; - case 3: - vertex[1].sow+=1.0f/TWin.UScaleFactor; - vertex[3].sow+=1.0f/TWin.UScaleFactor; - break; - case 4: - vertex[0].sow+=1.0f/TWin.UScaleFactor; - vertex[2].sow+=1.0f/TWin.UScaleFactor; - break; - case 5: - vertex[1].sow+=1.0f/TWin.UScaleFactor; - vertex[2].sow+=1.0f/TWin.UScaleFactor; - break; - case 6: - vertex[0].sow+=1.0f/TWin.UScaleFactor; - vertex[3].sow+=1.0f/TWin.UScaleFactor; - break; - } - } - else - { - switch(UFlipped) - { - case 1: - vertex[2].sow+=1.0f; - vertex[3].sow+=1.0f; - break; - case 2: - vertex[0].sow+=1.0f; - vertex[1].sow+=1.0f; - break; - case 3: - vertex[1].sow+=1.0f; - vertex[3].sow+=1.0f; - break; - case 4: - vertex[0].sow+=1.0f; - vertex[2].sow+=1.0f; - break; - case 5: - vertex[1].sow+=1.0f; - vertex[2].sow+=1.0f; - break; - case 6: - vertex[0].sow+=1.0f; - vertex[3].sow+=1.0f; - break; - } - } -#endif - } - - if (VFlipped) - { -#ifdef OWNSCALE - if(bUsingTWin) - { - switch(VFlipped) - { - case 1: - vertex[2].tow+=0.95f/TWin.VScaleFactor; - vertex[3].tow+=0.95f/TWin.VScaleFactor; - break; - case 2: - vertex[0].tow+=0.95f/TWin.VScaleFactor; - vertex[1].tow+=0.95f/TWin.VScaleFactor; - break; - case 3: - vertex[1].tow+=0.95f/TWin.VScaleFactor; - vertex[3].tow+=0.95f/TWin.VScaleFactor; - break; - case 4: - vertex[0].tow+=0.95f/TWin.VScaleFactor; - vertex[2].tow+=0.95f/TWin.VScaleFactor; - break; - case 5: - vertex[1].tow+=0.95f/TWin.VScaleFactor; - vertex[2].tow+=0.95f/TWin.VScaleFactor; - break; - case 6: - vertex[0].tow+=0.95f/TWin.VScaleFactor; - vertex[3].tow+=0.95f/TWin.VScaleFactor; - break; - } - } - else - { - switch(VFlipped) - { - case 1: - vertex[2].tow+=1.0f/ST_FAC; - vertex[3].tow+=1.0f/ST_FAC; - break; - case 2: - vertex[0].tow+=1.0f/ST_FAC; - vertex[1].tow+=1.0f/ST_FAC; - break; - case 3: - vertex[1].tow+=1.0f/ST_FAC; - vertex[3].tow+=1.0f/ST_FAC; - break; - case 4: - vertex[0].tow+=1.0f/ST_FAC; - vertex[2].tow+=1.0f/ST_FAC; - break; - case 5: - vertex[1].tow+=1.0f/ST_FAC; - vertex[2].tow+=1.0f/ST_FAC; - break; - case 6: - vertex[0].tow+=1.0f/ST_FAC; - vertex[3].tow+=1.0f/ST_FAC; - break; - } - } -#else - if(bUsingTWin) - { - switch(VFlipped) - { - case 1: - vertex[2].tow+=1.0f/TWin.VScaleFactor; - vertex[3].tow+=1.0f/TWin.VScaleFactor; - break; - case 2: - vertex[0].tow+=1.0f/TWin.VScaleFactor; - vertex[1].tow+=1.0f/TWin.VScaleFactor; - break; - case 3: - vertex[1].tow+=1.0f/TWin.VScaleFactor; - vertex[3].tow+=1.0f/TWin.VScaleFactor; - break; - case 4: - vertex[0].tow+=1.0f/TWin.VScaleFactor; - vertex[2].tow+=1.0f/TWin.VScaleFactor; - break; - case 5: - vertex[1].tow+=1.0f/TWin.VScaleFactor; - vertex[2].tow+=1.0f/TWin.VScaleFactor; - break; - case 6: - vertex[0].tow+=1.0f/TWin.VScaleFactor; - vertex[3].tow+=1.0f/TWin.VScaleFactor; - break; - } - } - else - { - switch(VFlipped) - { - case 1: - vertex[2].tow+=1.0f; - vertex[3].tow+=1.0f; - break; - case 2: - vertex[0].tow+=1.0f; - vertex[1].tow+=1.0f; - break; - case 3: - vertex[1].tow+=1.0f; - vertex[3].tow+=1.0f; - break; - case 4: - vertex[0].tow+=1.0f; - vertex[2].tow+=1.0f; - break; - case 5: - vertex[1].tow+=1.0f; - vertex[2].tow+=1.0f; - break; - case 6: - vertex[0].tow+=1.0f; - vertex[3].tow+=1.0f; - break; - } - } -#endif - } - -} - -static void primPolyFT4(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t *)baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = sgpuData[2]; - ly0 = sgpuData[3]; - lx1 = sgpuData[6]; - ly1 = sgpuData[7]; - lx2 = sgpuData[10]; - ly2 = sgpuData[11]; - lx3 = sgpuData[14]; - ly3 = sgpuData[15]; - - if(offset4()) return; - - gl_vy[0]=baseAddr[9];//((gpuData[2]>>8)&0xff); - gl_vy[1]=baseAddr[17];//((gpuData[4]>>8)&0xff); - gl_vy[2]=baseAddr[25];//((gpuData[6]>>8)&0xff); - gl_vy[3]=baseAddr[33];//((gpuData[8]>>8)&0xff); - - gl_ux[0]=baseAddr[8];//(gpuData[2]&0xff); - gl_ux[1]=baseAddr[16];//(gpuData[4]&0xff); - gl_ux[2]=baseAddr[24];//(gpuData[6]&0xff); - gl_ux[3]=baseAddr[32];//(gpuData[8]&0xff); - - UpdateGlobalTP((unsigned short)(gpuData[4]>>16)); - ulClutID=(gpuData[2]>>16); - - bDrawTextured = TRUE; - bDrawSmoothShaded = FALSE; - SetRenderState(gpuData[0]); - - if(iOffscreenDrawing) - { - offsetPSX4(); - if(bDrawOffscreen4()) - { - InvalidateTextureAreaEx(); - SetRenderColor(gpuData[0]); - drawPoly4FT(baseAddr); - } - } - - SetRenderMode(gpuData[0], TRUE); - - SetZMask4(); - - assignTexture4(); - - RectTexAlign(); - - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); - - if(bDrawMultiPass) - { - SetSemiTransMulti(1); - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); - } - - if(ubOpaqueDraw) - { - SetZMask4O(); - if(bUseMultiPass) SetOpaqueColor(gpuData[0]); - DEFOPAQUEON - - if(bSmallAlpha && iFilterType<=2) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - SetZMask4O(); - } - - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); - DEFOPAQUEOFF - } - - iDrawnSomething=1; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: smooth shaded Texture3 -//////////////////////////////////////////////////////////////////////// - -static void primPolyGT3(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = sgpuData[2]; - ly0 = sgpuData[3]; - lx1 = sgpuData[8]; - ly1 = sgpuData[9]; - lx2 = sgpuData[14]; - ly2 = sgpuData[15]; - - if(offset3()) return; - - // do texture stuff - gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; - gl_vy[0]=gl_vy[3]=baseAddr[9];//(gpuData[2]>>8)&0xff; - gl_ux[1]=baseAddr[20];//gpuData[5]&0xff; - gl_vy[1]=baseAddr[21];//(gpuData[5]>>8)&0xff; - gl_ux[2]=baseAddr[32];//gpuData[8]&0xff; - gl_vy[2]=baseAddr[33];//(gpuData[8]>>8)&0xff; - - UpdateGlobalTP((unsigned short)(gpuData[5]>>16)); - ulClutID=(gpuData[2]>>16); - - bDrawTextured = TRUE; - bDrawSmoothShaded = TRUE; - SetRenderState(gpuData[0]); - - if(iOffscreenDrawing) - { - offsetPSX3(); - if(bDrawOffscreen3()) - { - InvalidateTextureAreaEx(); - drawPoly3GT(baseAddr); - } - } - - SetRenderMode(gpuData[0], FALSE); - SetZMask3(); - - assignTexture3(); - - if(bDrawNonShaded) - { - //if(!bUseMultiPass) vertex[0].lcol=DoubleBGR2RGB(gpuData[0]); else vertex[0].lcol=gpuData[0]; - // eat this... - if(bGLBlend) vertex[0].c.lcol=0x7f7f7f; - else vertex[0].c.lcol=0xffffff; - vertex[0].c.col[3]=ubGloAlpha; - SETCOL(vertex[0]); - - PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); - - if(ubOpaqueDraw) - { - SetZMask3O(); - DEFOPAQUEON - PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); - DEFOPAQUEOFF - } - return; - } - - if(!bUseMultiPass && !bGLBlend) - { - vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); - vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); - vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); - } - else - { - vertex[0].c.lcol=gpuData[0]; - vertex[1].c.lcol=gpuData[3]; - vertex[2].c.lcol=gpuData[6]; - } - vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=ubGloAlpha; - - PRIMdrawTexGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); - - if(bDrawMultiPass) - { - SetSemiTransMulti(1); - PRIMdrawTexGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); - } - - if(ubOpaqueDraw) - { - SetZMask3O(); - if(bUseMultiPass) - { - vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); - vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); - vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); - vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=ubGloAlpha; - } - DEFOPAQUEON - PRIMdrawTexGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); - DEFOPAQUEOFF - } - - iDrawnSomething=1; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: smooth shaded Poly3 -//////////////////////////////////////////////////////////////////////// - -static void primPolyG3(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *)baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = sgpuData[2]; - ly0 = sgpuData[3]; - lx1 = sgpuData[6]; - ly1 = sgpuData[7]; - lx2 = sgpuData[10]; - ly2 = sgpuData[11]; - - if(offset3()) return; - - bDrawTextured = FALSE; - bDrawSmoothShaded = TRUE; - SetRenderState(gpuData[0]); - - if(iOffscreenDrawing) - { - offsetPSX3(); - if(bDrawOffscreen3()) - { - InvalidateTextureAreaEx(); - drawPoly3G(gpuData[0], gpuData[2], gpuData[4]); - } - } - - SetRenderMode(gpuData[0], FALSE); - SetZMask3NT(); - - vertex[0].c.lcol=gpuData[0]; - vertex[1].c.lcol=gpuData[2]; - vertex[2].c.lcol=gpuData[4]; - vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=ubGloColAlpha; - - PRIMdrawGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); - - iDrawnSomething=1; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: smooth shaded Texture4 -//////////////////////////////////////////////////////////////////////// - -static void primPolyGT4(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *)baseAddr); - short *sgpuData = ((short *)baseAddr); - - lx0 = sgpuData[2]; - ly0 = sgpuData[3]; - lx1 = sgpuData[8]; - ly1 = sgpuData[9]; - lx2 = sgpuData[14]; - ly2 = sgpuData[15]; - lx3 = sgpuData[20]; - ly3 = sgpuData[21]; - - if(offset4()) return; - - // do texture stuff - gl_ux[0]=baseAddr[8];//gpuData[2]&0xff; - gl_vy[0]=baseAddr[9];//(gpuData[2]>>8)&0xff; - gl_ux[1]=baseAddr[20];//gpuData[5]&0xff; - gl_vy[1]=baseAddr[21];//(gpuData[5]>>8)&0xff; - gl_ux[2]=baseAddr[32];//gpuData[8]&0xff; - gl_vy[2]=baseAddr[33];//(gpuData[8]>>8)&0xff; - gl_ux[3]=baseAddr[44];//gpuData[11]&0xff; - gl_vy[3]=baseAddr[45];//(gpuData[11]>>8)&0xff; - - UpdateGlobalTP((unsigned short)(gpuData[5]>>16)); - ulClutID=(gpuData[2]>>16); - - bDrawTextured = TRUE; - bDrawSmoothShaded = TRUE; - SetRenderState(gpuData[0]); - - if(iOffscreenDrawing) - { - offsetPSX4(); - if(bDrawOffscreen4()) - { - InvalidateTextureAreaEx(); - drawPoly4GT(baseAddr); - } - } - - SetRenderMode(gpuData[0], FALSE); - SetZMask4(); - - assignTexture4(); - - RectTexAlign(); - - if(bDrawNonShaded) - { - //if(!bUseMultiPass) vertex[0].lcol=DoubleBGR2RGB(gpuData[0]); else vertex[0].lcol=gpuData[0]; - if(bGLBlend) vertex[0].c.lcol=0x7f7f7f; - else vertex[0].c.lcol=0xffffff; - vertex[0].c.col[3]=ubGloAlpha; - SETCOL(vertex[0]); - - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); - - if(ubOpaqueDraw) - { - SetZMask4O(); - ubGloAlpha=ubGloColAlpha=0xff; - DEFOPAQUEON - PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); - DEFOPAQUEOFF - } - return; - } - - if(!bUseMultiPass && !bGLBlend) - { - vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); - vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); - vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); - vertex[3].c.lcol=DoubleBGR2RGB(gpuData[9]); - } - else - { - vertex[0].c.lcol=gpuData[0]; - vertex[1].c.lcol=gpuData[3]; - vertex[2].c.lcol=gpuData[6]; - vertex[3].c.lcol=gpuData[9]; - } - - vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloAlpha; - - PRIMdrawTexGouraudTriColorQuad(&vertex[0], &vertex[1], &vertex[3],&vertex[2]); - - if(bDrawMultiPass) - { - SetSemiTransMulti(1); - PRIMdrawTexGouraudTriColorQuad(&vertex[0], &vertex[1], &vertex[3],&vertex[2]); - } - - if(ubOpaqueDraw) - { - SetZMask4O(); - if(bUseMultiPass) - { - vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); - vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); - vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); - vertex[3].c.lcol=DoubleBGR2RGB(gpuData[9]); - vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloAlpha; - } - ubGloAlpha=ubGloColAlpha=0xff; - DEFOPAQUEON - PRIMdrawTexGouraudTriColorQuad(&vertex[0], &vertex[1], &vertex[3],&vertex[2]); - DEFOPAQUEOFF - } - - iDrawnSomething=1; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: smooth shaded Poly3 -//////////////////////////////////////////////////////////////////////// - -static void primPolyF3(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = sgpuData[2]; - ly0 = sgpuData[3]; - lx1 = sgpuData[4]; - ly1 = sgpuData[5]; - lx2 = sgpuData[6]; - ly2 = sgpuData[7]; - - if(offset3()) return; - - bDrawTextured = FALSE; - bDrawSmoothShaded = FALSE; - SetRenderState(gpuData[0]); - - if(iOffscreenDrawing) - { - offsetPSX3(); - if(bDrawOffscreen3()) - { - InvalidateTextureAreaEx(); - drawPoly3F(gpuData[0]); - } - } - - SetRenderMode(gpuData[0], FALSE); - SetZMask3NT(); - - vertex[0].c.lcol=gpuData[0]; - vertex[0].c.col[3]=ubGloColAlpha; - SETCOL(vertex[0]); - - PRIMdrawTri(&vertex[0], &vertex[1], &vertex[2]); - - iDrawnSomething=1; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: skipping shaded polylines -//////////////////////////////////////////////////////////////////////// - -static void primLineGSkip(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - int iMax=255; - int i=2; - - lx1 = sgpuData[2]; - ly1 = sgpuData[3]; - - while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=4)) - { - i++; - - ly1 = (short)((gpuData[i]>>16) & 0xffff); - lx1 = (short)(gpuData[i] & 0xffff); - - i++;if(i>iMax) break; - } -} - -//////////////////////////////////////////////////////////////////////// -// cmd: shaded polylines -//////////////////////////////////////////////////////////////////////// - -static void primLineGEx(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - int iMax=255; - short cx0,cx1,cy0,cy1;int i;BOOL bDraw=TRUE; - - bDrawTextured = FALSE; - bDrawSmoothShaded = TRUE; - SetRenderState(gpuData[0]); - SetRenderMode(gpuData[0], FALSE); - SetZMask4NT(); - - vertex[0].c.lcol=vertex[3].c.lcol=gpuData[0]; - vertex[0].c.col[3]=vertex[3].c.col[3]=ubGloColAlpha; - ly1 = (short)((gpuData[1]>>16) & 0xffff); - lx1 = (short)(gpuData[1] & 0xffff); - - i=2; - - //while((gpuData[i]>>24)!=0x55) - //while((gpuData[i]&0x50000000)!=0x50000000) - // currently best way to check for poly line end: - while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=4)) - { - ly0 = ly1;lx0=lx1; - vertex[1].c.lcol=vertex[2].c.lcol=vertex[0].c.lcol; - vertex[0].c.lcol=vertex[3].c.lcol=gpuData[i]; - vertex[0].c.col[3]=vertex[3].c.col[3]=ubGloColAlpha; - - i++; - - ly1 = (short)((gpuData[i]>>16) & 0xffff); - lx1 = (short)(gpuData[i] & 0xffff); - - if(offsetline()) bDraw=FALSE; else bDraw=TRUE; - - if (bDraw && ((lx0 != lx1) || (ly0 != ly1))) - { - if(iOffscreenDrawing) - { - cx0=lx0;cx1=lx1;cy0=ly0;cy1=ly1; - offsetPSXLine(); - if(bDrawOffscreen4()) - { - InvalidateTextureAreaEx(); - drawPoly4G(gpuData[i-3],gpuData[i-1],gpuData[i-3],gpuData[i-1]); - } - lx0=cx0;lx1=cx1;ly0=cy0;ly1=cy1; - } - - PRIMdrawGouraudLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - } - i++; - - if(i>iMax) break; - } - - iDrawnSomething=1; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: shaded polyline2 -//////////////////////////////////////////////////////////////////////// - -static void primLineG2(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = sgpuData[2]; - ly0 = sgpuData[3]; - lx1 = sgpuData[6]; - ly1 = sgpuData[7]; - - vertex[0].c.lcol=vertex[3].c.lcol=gpuData[0]; - vertex[1].c.lcol=vertex[2].c.lcol=gpuData[2]; - vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloColAlpha; - - bDrawTextured = FALSE; - bDrawSmoothShaded = TRUE; - - if((lx0 == lx1) && (ly0 == ly1)) return; - - if(offsetline()) return; - - SetRenderState(gpuData[0]); - SetRenderMode(gpuData[0], FALSE); - SetZMask4NT(); - - if(iOffscreenDrawing) - { - offsetPSXLine(); - if(bDrawOffscreen4()) - { - InvalidateTextureAreaEx(); - drawPoly4G(gpuData[0],gpuData[2],gpuData[0],gpuData[2]); - } - } - - //if(ClipVertexList4()) - PRIMdrawGouraudLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - - iDrawnSomething=1; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: skipping flat polylines -//////////////////////////////////////////////////////////////////////// - -static void primLineFSkip(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - int i=2,iMax=255; - - ly1 = (short)((gpuData[1]>>16) & 0xffff); - lx1 = (short)(gpuData[1] & 0xffff); - - while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=3)) - { - ly1 = (short)((gpuData[i]>>16) & 0xffff); - lx1 = (short)(gpuData[i] & 0xffff); - i++;if(i>iMax) break; - } -} - -//////////////////////////////////////////////////////////////////////// -// cmd: drawing flat polylines -//////////////////////////////////////////////////////////////////////// - -static void primLineFEx(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - int iMax; - short cx0,cx1,cy0,cy1;int i; - - iMax=255; - - bDrawTextured = FALSE; - bDrawSmoothShaded = FALSE; - SetRenderState(gpuData[0]); - SetRenderMode(gpuData[0], FALSE); - SetZMask4NT(); - - vertex[0].c.lcol=gpuData[0]; - vertex[0].c.col[3]=ubGloColAlpha; - - ly1 = (short)((gpuData[1]>>16) & 0xffff); - lx1 = (short)(gpuData[1] & 0xffff); - - i=2; - -// while(!(gpuData[i]&0x40000000)) -// while((gpuData[i]>>24)!=0x55) -// while((gpuData[i]&0x50000000)!=0x50000000) -// currently best way to check for poly line end: - while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=3)) - { - ly0 = ly1;lx0=lx1; - ly1 = (short)((gpuData[i]>>16) & 0xffff); - lx1 = (short)(gpuData[i] & 0xffff); - - if(!offsetline()) - { - if(iOffscreenDrawing) - { - cx0=lx0;cx1=lx1;cy0=ly0;cy1=ly1; - offsetPSXLine(); - if(bDrawOffscreen4()) - { - InvalidateTextureAreaEx(); - drawPoly4F(gpuData[0]); - } - lx0=cx0;lx1=cx1;ly0=cy0;ly1=cy1; - } - PRIMdrawFlatLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - } - - i++;if(i>iMax) break; - } - - iDrawnSomething=1; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: drawing flat polyline2 -//////////////////////////////////////////////////////////////////////// - -static void primLineF2(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - short *sgpuData = ((short *) baseAddr); - - lx0 = sgpuData[2]; - ly0 = sgpuData[3]; - lx1 = sgpuData[4]; - ly1 = sgpuData[5]; - - if(offsetline()) return; - - bDrawTextured = FALSE; - bDrawSmoothShaded = FALSE; - SetRenderState(gpuData[0]); - SetRenderMode(gpuData[0], FALSE); - SetZMask4NT(); - - vertex[0].c.lcol=gpuData[0]; - vertex[0].c.col[3]=ubGloColAlpha; - - if(iOffscreenDrawing) - { - offsetPSXLine(); - if(bDrawOffscreen4()) - { - InvalidateTextureAreaEx(); - drawPoly4F(gpuData[0]); - } - } - - //if(ClipVertexList4()) - PRIMdrawFlatLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - - iDrawnSomething=1; -} - -//////////////////////////////////////////////////////////////////////// -// cmd: well, easiest command... not implemented -//////////////////////////////////////////////////////////////////////// - -static void primNI(unsigned char *bA) -{ -} - -//////////////////////////////////////////////////////////////////////// -// cmd func ptr table -//////////////////////////////////////////////////////////////////////// - -void (*primTableJ[256])(unsigned char *) = -{ - // 00 - primNI,primNI,primBlkFill,primNI,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 -}; - -//////////////////////////////////////////////////////////////////////// -// cmd func ptr table for skipping -//////////////////////////////////////////////////////////////////////// - -void (*primTableSkip[256])(unsigned char *) = -{ - // 00 - primNI,primNI,primBlkFill,primNI,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 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 28 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 30 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 38 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 40 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 48 - primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip, - // 50 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 58 - primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip, - // 60 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 68 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 70 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 78 - primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, - // 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 -}; +/*************************************************************************** + prim.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "stdafx.h" + +#define _IN_PRIMDRAW + +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "soft.h" +#include "texture.h" + +//////////////////////////////////////////////////////////////////////// +// defines +//////////////////////////////////////////////////////////////////////// + +#define DEFOPAQUEON glAlphaFunc(GL_EQUAL,0.0f);bBlendEnable=FALSE;glDisable(GL_BLEND); +#define DEFOPAQUEOFF glAlphaFunc(GL_GREATER,0.49f); + +//////////////////////////////////////////////////////////////////////// +// globals +//////////////////////////////////////////////////////////////////////// + +BOOL bDrawTextured; // current active drawing states +BOOL bDrawSmoothShaded; +BOOL bOldSmoothShaded; +BOOL bDrawNonShaded; +BOOL bDrawMultiPass; +int iOffscreenDrawing; +int iDrawnSomething=0; + +BOOL bRenderFrontBuffer=FALSE; // flag for front buffer rendering + +GLubyte ubGloAlpha; // texture alpha +GLubyte ubGloColAlpha; // color alpha +int iFilterType; // type of filter +BOOL bFullVRam=FALSE; // sign for tex win +BOOL bDrawDither; // sign for dither +BOOL bUseMultiPass; // sign for multi pass +GLuint gTexName; // binded texture +BOOL bTexEnabled; // texture enable flag +BOOL bBlendEnable; // blend enable flag +PSXRect_t xrUploadArea; // rect to upload +PSXRect_t xrUploadAreaIL; // rect to upload +PSXRect_t xrUploadAreaRGB24; // rect to upload rgb24 +int iSpriteTex=0; // flag for "hey, it's a sprite" +unsigned short usMirror; // mirror, mirror on the wall + +BOOL bNeedUploadAfter=FALSE; // sign for uploading in next frame +BOOL bNeedUploadTest=FALSE; // sign for upload test +BOOL bUsingTWin=FALSE; // tex win active flag +BOOL bUsingMovie=FALSE; // movie active flag +PSXRect_t xrMovieArea; // rect for movie upload +short sSprite_ux2; // needed for sprire adjust +short sSprite_vy2; // +uint32_t ulOLDCOL=0; // active color +uint32_t ulClutID; // clut + +uint32_t dwCfgFixes; // game fixes +uint32_t dwActFixes=0; +uint32_t dwEmuFixes=0; +BOOL bUseFixes; + +int drawX,drawY,drawW,drawH; // offscreen drawing checkers +short sxmin,sxmax,symin,symax; + +//////////////////////////////////////////////////////////////////////// +// Update global TP infos +//////////////////////////////////////////////////////////////////////// + +void UpdateGlobalTP(unsigned short gdata) +{ + GlobalTextAddrX = (gdata << 6) & 0x3c0; + + if(iGPUHeight==1024) // ZN mode + { + if(dwGPUVersion==2) // very special zn gpu + { + GlobalTextAddrY =((gdata & 0x60 ) << 3); + GlobalTextIL =(gdata & 0x2000) >> 13; + GlobalTextABR = (unsigned short)((gdata >> 7) & 0x3); + GlobalTextTP = (gdata >> 9) & 0x3; + if(GlobalTextTP==3) GlobalTextTP=2; + GlobalTexturePage = (GlobalTextAddrX>>6)+(GlobalTextAddrY>>4); + usMirror =0; + STATUSREG = (STATUSREG & 0xffffe000 ) | (gdata & 0x1fff ); + return; + } + else // "enhanced" psx gpu + { + GlobalTextAddrY = (unsigned short)(((gdata << 4) & 0x100) | ((gdata >> 2) & 0x200)); + } + } + else GlobalTextAddrY = (gdata << 4) & 0x100; // "normal" psx gpu + + usMirror=gdata&0x3000; + + GlobalTextTP = (gdata >> 7) & 0x3; // tex mode (4,8,15) + if(GlobalTextTP==3) GlobalTextTP=2; // seen in Wild9 :( + GlobalTextABR = (gdata >> 5) & 0x3; // blend mode + + GlobalTexturePage = (GlobalTextAddrX>>6)+(GlobalTextAddrY>>4); + + STATUSREG&=~0x07ff; // Clear the necessary bits + STATUSREG|=(gdata & 0x07ff); // set the necessary bits +} + +unsigned int DoubleBGR2RGB (unsigned int BGR) +{ + unsigned int ebx,eax,edx; + + ebx=(BGR&0x000000ff)<<1; + if(ebx&0x00000100) ebx=0x000000ff; + + eax=(BGR&0x0000ff00)<<1; + if(eax&0x00010000) eax=0x0000ff00; + + edx=(BGR&0x00ff0000)<<1; + if(edx&0x01000000) edx=0x00ff0000; + + return (ebx|eax|edx); +} + +unsigned short BGR24to16 (uint32_t BGR) +{ + return ((BGR>>3)&0x1f)|((BGR&0xf80000)>>9)|((BGR&0xf800)>>6); +} + +//////////////////////////////////////////////////////////////////////// +// OpenGL primitive drawing commands +//////////////////////////////////////////////////////////////////////// + +__inline void PRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2fv(&vertex1->sow); + glVertex3fv(&vertex1->x); + + glTexCoord2fv(&vertex2->sow); + glVertex3fv(&vertex2->x); + + glTexCoord2fv(&vertex4->sow); + glVertex3fv(&vertex4->x); + + glTexCoord2fv(&vertex3->sow); + glVertex3fv(&vertex3->x); + glEnd(); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawTexturedTri(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3) +{ + glBegin(GL_TRIANGLES); + glTexCoord2fv(&vertex1->sow); + glVertex3fv(&vertex1->x); + + glTexCoord2fv(&vertex2->sow); + glVertex3fv(&vertex2->x); + + glTexCoord2fv(&vertex3->sow); + glVertex3fv(&vertex3->x); + glEnd(); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawTexGouraudTriColor(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3) +{ + glBegin(GL_TRIANGLES); + + SETPCOL(vertex1); + glTexCoord2fv(&vertex1->sow); + glVertex3fv(&vertex1->x); + + SETPCOL(vertex2); + glTexCoord2fv(&vertex2->sow); + glVertex3fv(&vertex2->x); + + SETPCOL(vertex3); + glTexCoord2fv(&vertex3->sow); + glVertex3fv(&vertex3->x); + glEnd(); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawTexGouraudTriColorQuad(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ + glBegin(GL_TRIANGLE_STRIP); + SETPCOL(vertex1); + glTexCoord2fv(&vertex1->sow); + glVertex3fv(&vertex1->x); + + SETPCOL(vertex2); + glTexCoord2fv(&vertex2->sow); + glVertex3fv(&vertex2->x); + + SETPCOL(vertex4); + glTexCoord2fv(&vertex4->sow); + glVertex3fv(&vertex4->x); + + SETPCOL(vertex3); + glTexCoord2fv(&vertex3->sow); + glVertex3fv(&vertex3->x); + glEnd(); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawTri(OGLVertex* vertex1, OGLVertex* vertex2, OGLVertex* vertex3) +{ + glBegin(GL_TRIANGLES); + glVertex3fv(&vertex1->x); + glVertex3fv(&vertex2->x); + glVertex3fv(&vertex3->x); + glEnd(); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawTri2(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ + glBegin(GL_TRIANGLE_STRIP); + glVertex3fv(&vertex1->x); + glVertex3fv(&vertex3->x); + glVertex3fv(&vertex2->x); + glVertex3fv(&vertex4->x); + glEnd(); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawGouraudTriColor(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3) +{ + glBegin(GL_TRIANGLES); + SETPCOL(vertex1); + glVertex3fv(&vertex1->x); + + SETPCOL(vertex2); + glVertex3fv(&vertex2->x); + + SETPCOL(vertex3); + glVertex3fv(&vertex3->x); + glEnd(); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawGouraudTri2Color(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ + glBegin(GL_TRIANGLE_STRIP); + SETPCOL(vertex1); + glVertex3fv(&vertex1->x); + + SETPCOL(vertex3); + glVertex3fv(&vertex3->x); + + SETPCOL(vertex2); + glVertex3fv(&vertex2->x); + + SETPCOL(vertex4); + glVertex3fv(&vertex4->x); + glEnd(); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawFlatLine(OGLVertex* vertex1, OGLVertex* vertex2,OGLVertex* vertex3, OGLVertex* vertex4) +{ + glBegin(GL_QUADS); + + SETPCOL(vertex1); + + glVertex3fv(&vertex1->x); + glVertex3fv(&vertex2->x); + glVertex3fv(&vertex3->x); + glVertex3fv(&vertex4->x); + glEnd(); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawGouraudLine(OGLVertex* vertex1, OGLVertex* vertex2,OGLVertex* vertex3, OGLVertex* vertex4) +{ + glBegin(GL_QUADS); + + SETPCOL(vertex1); + glVertex3fv(&vertex1->x); + + SETPCOL(vertex2); + glVertex3fv(&vertex2->x); + + SETPCOL(vertex3); + glVertex3fv(&vertex3->x); + + SETPCOL(vertex4); + glVertex3fv(&vertex4->x); + glEnd(); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawQuad(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ + glBegin(GL_QUADS); + glVertex3fv(&vertex1->x); + glVertex3fv(&vertex2->x); + glVertex3fv(&vertex3->x); + glVertex3fv(&vertex4->x); + glEnd(); +} + +//////////////////////////////////////////////////////////////////////// +// Transparent blending settings +//////////////////////////////////////////////////////////////////////// + +static GLenum obm1=GL_ZERO; +static GLenum obm2=GL_ZERO; + +typedef struct SEMITRANSTAG +{ + GLenum srcFac; + GLenum dstFac; + GLubyte alpha; +} SemiTransParams; + +SemiTransParams TransSets[4]= +{ + {GL_SRC_ALPHA,GL_SRC_ALPHA, 127}, + {GL_ONE, GL_ONE, 255}, + {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255}, + {GL_ONE_MINUS_SRC_ALPHA,GL_ONE, 192} +}; + +//////////////////////////////////////////////////////////////////////// + +void SetSemiTrans(void) +{ +/* +* 0.5 x B + 0.5 x F +* 1.0 x B + 1.0 x F +* 1.0 x B - 1.0 x F +* 1.0 x B +0.25 x F +*/ + + if(!DrawSemiTrans) // no semi trans at all? + { + if(bBlendEnable) + {glDisable(GL_BLEND);bBlendEnable=FALSE;} // -> don't wanna blend + ubGloAlpha=ubGloColAlpha=255; // -> full alpha + return; // -> and bye + } + + ubGloAlpha=ubGloColAlpha=TransSets[GlobalTextABR].alpha; + + if(!bBlendEnable) + {glEnable(GL_BLEND);bBlendEnable=TRUE;} // wanna blend + + if(TransSets[GlobalTextABR].srcFac!=obm1 || + TransSets[GlobalTextABR].dstFac!=obm2) + { + if(glBlendEquationEXTEx==NULL) + { + obm1=TransSets[GlobalTextABR].srcFac; + obm2=TransSets[GlobalTextABR].dstFac; + glBlendFunc(obm1,obm2); // set blend func + } + else + if(TransSets[GlobalTextABR].dstFac !=GL_ONE_MINUS_SRC_COLOR) + { + if(obm2==GL_ONE_MINUS_SRC_COLOR) + glBlendEquationEXTEx(FUNC_ADD_EXT); + obm1=TransSets[GlobalTextABR].srcFac; + obm2=TransSets[GlobalTextABR].dstFac; + glBlendFunc(obm1,obm2); // set blend func + } + else + { + glBlendEquationEXTEx(FUNC_REVERSESUBTRACT_EXT); + obm1=TransSets[GlobalTextABR].srcFac; + obm2=TransSets[GlobalTextABR].dstFac; + glBlendFunc(GL_ONE,GL_ONE); // set blend func + } + } +} + +void SetScanTrans(void) // blending for scan lines +{ + if(glBlendEquationEXTEx!=NULL) + { + if(obm2==GL_ONE_MINUS_SRC_COLOR) + glBlendEquationEXTEx(FUNC_ADD_EXT); + } + + obm1=TransSets[0].srcFac; + obm2=TransSets[0].dstFac; + glBlendFunc(obm1,obm2); // set blend func +} + +void SetScanTexTrans(void) // blending for scan mask texture +{ + if(glBlendEquationEXTEx!=NULL) + { + if(obm2==GL_ONE_MINUS_SRC_COLOR) + glBlendEquationEXTEx(FUNC_ADD_EXT); + } + + obm1=TransSets[2].srcFac; + obm2=TransSets[2].dstFac; + glBlendFunc(obm1,obm2); // set blend func +} + +//////////////////////////////////////////////////////////////////////// +// multi pass in old 'Advanced blending' mode... got it from Lewpy :) +//////////////////////////////////////////////////////////////////////// + +SemiTransParams MultiTexTransSets[4][2]= +{ + { + {GL_ONE ,GL_SRC_ALPHA, 127}, + {GL_SRC_ALPHA,GL_ONE, 127} + }, + { + {GL_ONE, GL_SRC_ALPHA, 255}, + {GL_SRC_ALPHA,GL_ONE, 255} + }, + { + {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255}, + {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255} + }, + { + {GL_SRC_ALPHA,GL_ONE, 127}, + {GL_ONE_MINUS_SRC_ALPHA,GL_ONE, 255} + } +}; + +//////////////////////////////////////////////////////////////////////// + +SemiTransParams MultiColTransSets[4]= +{ + {GL_ONE_MINUS_SRC_ALPHA,GL_SRC_ALPHA,127}, + {GL_ONE, GL_ONE, 255}, + {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255}, + {GL_SRC_ALPHA,GL_ONE, 127} +}; + +//////////////////////////////////////////////////////////////////////// + +void SetSemiTransMulti(int Pass) +{ + static GLenum bm1=GL_ZERO; + static GLenum bm2=GL_ONE; + + ubGloAlpha=255; + ubGloColAlpha=255; + + // are we enabling SemiTransparent mode? + if(DrawSemiTrans) + { + if(bDrawTextured) + { + bm1=MultiTexTransSets[GlobalTextABR][Pass].srcFac; + bm2=MultiTexTransSets[GlobalTextABR][Pass].dstFac; + ubGloAlpha=MultiTexTransSets[GlobalTextABR][Pass].alpha; + } + // no texture + else + { + bm1=MultiColTransSets[GlobalTextABR].srcFac; + bm2=MultiColTransSets[GlobalTextABR].dstFac; + ubGloColAlpha=MultiColTransSets[GlobalTextABR].alpha; + } + } + // no shading + else + { + if(Pass==0) + { + // disable blending + bm1=GL_ONE;bm2=GL_ZERO; + } + else + { + // disable blending, but add src col a second time + bm1=GL_ONE;bm2=GL_ONE; + } + } + + if(!bBlendEnable) + {glEnable(GL_BLEND);bBlendEnable=TRUE;} // wanna blend + + if(bm1!=obm1 || bm2!=obm2) + { + glBlendFunc(bm1,bm2); // set blend func + obm1=bm1;obm2=bm2; + } +} + +//////////////////////////////////////////////////////////////////////// +// Set several rendering stuff including blending +//////////////////////////////////////////////////////////////////////// + +__inline void SetZMask3O(void) +{ + if(iUseMask && DrawSemiTrans && !iSetMask) + { + vertex[0].z=vertex[1].z=vertex[2].z=gl_z; + gl_z+=0.00004f; + } +} + +__inline void SetZMask3(void) +{ + if(iUseMask) + { + if(iSetMask || DrawSemiTrans) + {vertex[0].z=vertex[1].z=vertex[2].z=0.95f;} + else + { + vertex[0].z=vertex[1].z=vertex[2].z=gl_z; + gl_z+=0.00004f; + } + } +} + +__inline void SetZMask3NT(void) +{ + if(iUseMask) + { + if(iSetMask) + {vertex[0].z=vertex[1].z=vertex[2].z=0.95f;} + else + { + vertex[0].z=vertex[1].z=vertex[2].z=gl_z; + gl_z+=0.00004f; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +__inline void SetZMask4O(void) +{ + if(iUseMask && DrawSemiTrans && !iSetMask) + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } +} + +__inline void SetZMask4(void) +{ + if(iUseMask) + { + if(iSetMask || DrawSemiTrans) + {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} + else + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } + } +} + +__inline void SetZMask4NT(void) +{ + if(iUseMask) + { + if(iSetMask==1) + {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} + else + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } + } +} + +__inline void SetZMask4SP(void) +{ + if(iUseMask) + { + if(iSetMask==1) + {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} + else + { + if(bCheckMask) + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } + else + {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} + } + } +} + +//////////////////////////////////////////////////////////////////////// + +__inline void SetRenderState(uint32_t DrawAttributes) +{ + bDrawNonShaded = (SHADETEXBIT(DrawAttributes)) ? TRUE : FALSE; + DrawSemiTrans = (SEMITRANSBIT(DrawAttributes)) ? TRUE : FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline void SetRenderColor(uint32_t DrawAttributes) +{ + if(bDrawNonShaded) {g_m1=g_m2=g_m3=128;} + else + { + g_m1=DrawAttributes&0xff; + g_m2=(DrawAttributes>>8)&0xff; + g_m3=(DrawAttributes>>16)&0xff; + } +} + +//////////////////////////////////////////////////////////////////////// + +void SetRenderMode(uint32_t DrawAttributes, BOOL bSCol) +{ + if((bUseMultiPass) && (bDrawTextured) && !(bDrawNonShaded)) + {bDrawMultiPass = TRUE; SetSemiTransMulti(0);} + else {bDrawMultiPass = FALSE;SetSemiTrans();} + + if(bDrawTextured) // texture ? build it/get it from cache + { + GLuint currTex; + if(bUsingTWin) currTex=LoadTextureWnd(GlobalTexturePage,GlobalTextTP, ulClutID); + else if(bUsingMovie) currTex=LoadTextureMovie(); + else currTex=SelectSubTextureS(GlobalTextTP,ulClutID); + + if(gTexName!=currTex) + {gTexName=currTex;glBindTexture(GL_TEXTURE_2D,currTex);} + + if(!bTexEnabled) // -> turn texturing on + {bTexEnabled=TRUE;glEnable(GL_TEXTURE_2D);} + } + else // no texture ? + if(bTexEnabled) + {bTexEnabled=FALSE;glDisable(GL_TEXTURE_2D);} // -> turn texturing off + + if(bSCol) // also set color ? + { + if((dwActFixes&4) && ((DrawAttributes&0x00ffffff)==0)) + DrawAttributes|=0x007f7f7f; + + if(bDrawNonShaded) // -> non shaded? + { + if(bGLBlend) vertex[0].c.lcol=0x7f7f7f; // --> solid color... + else vertex[0].c.lcol=0xffffff; + } + else // -> shaded? + { + if(!bUseMultiPass && !bGLBlend) // --> given color... + vertex[0].c.lcol=DoubleBGR2RGB(DrawAttributes); + else vertex[0].c.lcol=DrawAttributes; + } + vertex[0].c.col[3]=ubGloAlpha; // -> set color with + SETCOL(vertex[0]); // texture alpha + } + + if(bDrawSmoothShaded!=bOldSmoothShaded) // shading changed? + { + if(bDrawSmoothShaded) glShadeModel(GL_SMOOTH); // -> set actual shading + else glShadeModel(GL_FLAT); + bOldSmoothShaded=bDrawSmoothShaded; + } +} + +//////////////////////////////////////////////////////////////////////// +// Set Opaque multipass color +//////////////////////////////////////////////////////////////////////// + +void SetOpaqueColor(uint32_t DrawAttributes) +{ + if(bDrawNonShaded) return; // no shading? bye + + DrawAttributes=DoubleBGR2RGB(DrawAttributes); // multipass is just half color, so double it on opaque pass + vertex[0].c.lcol=DrawAttributes|0xff000000; + SETCOL(vertex[0]); // set color +} + +//////////////////////////////////////////////////////////////////////// +// Fucking stupid screen coord checking +//////////////////////////////////////////////////////////////////////// + +BOOL ClipVertexListScreen(void) +{ + if (lx0 >= PSXDisplay.DisplayEnd.x) goto NEXTSCRTEST; + if (ly0 >= PSXDisplay.DisplayEnd.y) goto NEXTSCRTEST; + if (lx2 < PSXDisplay.DisplayPosition.x) goto NEXTSCRTEST; + if (ly2 < PSXDisplay.DisplayPosition.y) goto NEXTSCRTEST; + + return TRUE; + +NEXTSCRTEST: + if(PSXDisplay.InterlacedTest) return FALSE; + + if (lx0 >= PreviousPSXDisplay.DisplayEnd.x) return FALSE; + if (ly0 >= PreviousPSXDisplay.DisplayEnd.y) return FALSE; + if (lx2 < PreviousPSXDisplay.DisplayPosition.x) return FALSE; + if (ly2 < PreviousPSXDisplay.DisplayPosition.y) return FALSE; + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +BOOL bDrawOffscreenFront(void) +{ + if(sxmin < PSXDisplay.DisplayPosition.x) return FALSE; // must be complete in front + if(symin < PSXDisplay.DisplayPosition.y) return FALSE; + if(sxmax > PSXDisplay.DisplayEnd.x) return FALSE; + if(symax > PSXDisplay.DisplayEnd.y) return FALSE; + return TRUE; +} + +BOOL bOnePointInFront(void) +{ + if(sxmax< PSXDisplay.DisplayPosition.x) + return FALSE; + + if(symax< PSXDisplay.DisplayPosition.y) + return FALSE; + + if(sxmin>=PSXDisplay.DisplayEnd.x) + return FALSE; + + if(symin>=PSXDisplay.DisplayEnd.y) + return FALSE; + + return TRUE; +} + + +BOOL bOnePointInBack(void) +{ + if(sxmax< PreviousPSXDisplay.DisplayPosition.x) + return FALSE; + + if(symax< PreviousPSXDisplay.DisplayPosition.y) + return FALSE; + + if(sxmin>=PreviousPSXDisplay.DisplayEnd.x) + return FALSE; + + if(symin>=PreviousPSXDisplay.DisplayEnd.y) + return FALSE; + + return TRUE; +} + +BOOL bDrawOffscreen4(void) +{ + BOOL bFront;short sW,sH; + + sxmax=max(lx0,max(lx1,max(lx2,lx3))); + if(sxmaxdrawW) return FALSE; + symax=max(ly0,max(ly1,max(ly2,ly3))); + if(symaxdrawH) return FALSE; + + if(PSXDisplay.Disabled) return TRUE; // disabled? ever + + if(iOffscreenDrawing==1) return bFullVRam; + + if(dwActFixes&1 && iOffscreenDrawing==4) + { + if(PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x && + PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y && + PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x && + PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y) + { + bRenderFrontBuffer=TRUE; + return FALSE; + } + } + + sW=drawW-1;sH=drawH-1; + + sxmin=min(sW,max(sxmin,drawX)); + sxmax=max(drawX,min(sxmax,sW)); + symin=min(sH,max(symin,drawY)); + symax=max(drawY,min(symax,sH)); + + if(bOnePointInBack()) return bFullVRam; + + if(iOffscreenDrawing==2) + bFront=bDrawOffscreenFront(); + else bFront=bOnePointInFront(); + + if(bFront) + { + if(PSXDisplay.InterlacedTest) return bFullVRam; // -> ok, no need for adjust + + vertex[0].x=lx0 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[1].x=lx1 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[2].x=lx2 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[3].x=lx3 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[0].y=ly0 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + vertex[1].y=ly1 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + vertex[2].y=ly2 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + vertex[3].y=ly3 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + + if(iOffscreenDrawing==4 && !(dwActFixes&1)) // -> frontbuffer wanted + { + bRenderFrontBuffer=TRUE; + //return TRUE; + } + return bFullVRam; // -> but no od + } + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +BOOL bDrawOffscreen3(void) +{ + BOOL bFront;short sW,sH; + + sxmax=max(lx0,max(lx1,lx2)); + if(sxmaxdrawW) return FALSE; + symax=max(ly0,max(ly1,ly2)); + if(symaxdrawH) return FALSE; + + if(PSXDisplay.Disabled) return TRUE; // disabled? ever + + if(iOffscreenDrawing==1) return bFullVRam; + + sW=drawW-1;sH=drawH-1; + sxmin=min(sW,max(sxmin,drawX)); + sxmax=max(drawX,min(sxmax,sW)); + symin=min(sH,max(symin,drawY)); + symax=max(drawY,min(symax,sH)); + + if(bOnePointInBack()) return bFullVRam; + + if(iOffscreenDrawing==2) + bFront=bDrawOffscreenFront(); + else bFront=bOnePointInFront(); + + if(bFront) + { + if(PSXDisplay.InterlacedTest) return bFullVRam; // -> ok, no need for adjust + + vertex[0].x=lx0 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[1].x=lx1 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[2].x=lx2 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[0].y=ly0 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + vertex[1].y=ly1 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + vertex[2].y=ly2 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + + if(iOffscreenDrawing==4) // -> frontbuffer wanted + { + bRenderFrontBuffer=TRUE; + // return TRUE; + } + + return bFullVRam; // -> but no od + } + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +BOOL FastCheckAgainstScreen(short imageX0,short imageY0,short imageX1,short imageY1) +{ + PSXRect_t xUploadArea; + + imageX1 += imageX0; + imageY1 += imageY0; + + if (imageX0 < PreviousPSXDisplay.DisplayPosition.x) + xUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; + else + if (imageX0 > PreviousPSXDisplay.DisplayEnd.x) + xUploadArea.x0 = PreviousPSXDisplay.DisplayEnd.x; + else + xUploadArea.x0 = imageX0; + + if(imageX1 < PreviousPSXDisplay.DisplayPosition.x) + xUploadArea.x1 = PreviousPSXDisplay.DisplayPosition.x; + else + if (imageX1 > PreviousPSXDisplay.DisplayEnd.x) + xUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; + else + xUploadArea.x1 = imageX1; + + if (imageY0 < PreviousPSXDisplay.DisplayPosition.y) + xUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; + else + if (imageY0 > PreviousPSXDisplay.DisplayEnd.y) + xUploadArea.y0 = PreviousPSXDisplay.DisplayEnd.y; + else + xUploadArea.y0 = imageY0; + + if (imageY1 < PreviousPSXDisplay.DisplayPosition.y) + xUploadArea.y1 = PreviousPSXDisplay.DisplayPosition.y; + else + if (imageY1 > PreviousPSXDisplay.DisplayEnd.y) + xUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; + else + xUploadArea.y1 = imageY1; + + if ((xUploadArea.x0 != xUploadArea.x1) && (xUploadArea.y0 != xUploadArea.y1)) + return TRUE; + else return FALSE; +} + +BOOL CheckAgainstScreen(short imageX0,short imageY0,short imageX1,short imageY1) +{ + imageX1 += imageX0; + imageY1 += imageY0; + + if (imageX0 < PreviousPSXDisplay.DisplayPosition.x) + xrUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; + else + if (imageX0 > PreviousPSXDisplay.DisplayEnd.x) + xrUploadArea.x0 = PreviousPSXDisplay.DisplayEnd.x; + else + xrUploadArea.x0 = imageX0; + + if(imageX1 < PreviousPSXDisplay.DisplayPosition.x) + xrUploadArea.x1 = PreviousPSXDisplay.DisplayPosition.x; + else + if (imageX1 > PreviousPSXDisplay.DisplayEnd.x) + xrUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; + else + xrUploadArea.x1 = imageX1; + + if (imageY0 < PreviousPSXDisplay.DisplayPosition.y) + xrUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; + else + if (imageY0 > PreviousPSXDisplay.DisplayEnd.y) + xrUploadArea.y0 = PreviousPSXDisplay.DisplayEnd.y; + else + xrUploadArea.y0 = imageY0; + + if (imageY1 < PreviousPSXDisplay.DisplayPosition.y) + xrUploadArea.y1 = PreviousPSXDisplay.DisplayPosition.y; + else + if (imageY1 > PreviousPSXDisplay.DisplayEnd.y) + xrUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; + else + xrUploadArea.y1 = imageY1; + + if ((xrUploadArea.x0 != xrUploadArea.x1) && (xrUploadArea.y0 != xrUploadArea.y1)) + return TRUE; + else return FALSE; +} + +BOOL FastCheckAgainstFrontScreen(short imageX0,short imageY0,short imageX1,short imageY1) +{ + PSXRect_t xUploadArea; + + imageX1 += imageX0; + imageY1 += imageY0; + + if (imageX0 < PSXDisplay.DisplayPosition.x) + xUploadArea.x0 = PSXDisplay.DisplayPosition.x; + else + if (imageX0 > PSXDisplay.DisplayEnd.x) + xUploadArea.x0 = PSXDisplay.DisplayEnd.x; + else + xUploadArea.x0 = imageX0; + + if(imageX1 < PSXDisplay.DisplayPosition.x) + xUploadArea.x1 = PSXDisplay.DisplayPosition.x; + else + if (imageX1 > PSXDisplay.DisplayEnd.x) + xUploadArea.x1 = PSXDisplay.DisplayEnd.x; + else + xUploadArea.x1 = imageX1; + + if (imageY0 < PSXDisplay.DisplayPosition.y) + xUploadArea.y0 = PSXDisplay.DisplayPosition.y; + else + if (imageY0 > PSXDisplay.DisplayEnd.y) + xUploadArea.y0 = PSXDisplay.DisplayEnd.y; + else + xUploadArea.y0 = imageY0; + + if (imageY1 < PSXDisplay.DisplayPosition.y) + xUploadArea.y1 = PSXDisplay.DisplayPosition.y; + else + if (imageY1 > PSXDisplay.DisplayEnd.y) + xUploadArea.y1 = PSXDisplay.DisplayEnd.y; + else + xUploadArea.y1 = imageY1; + + if ((xUploadArea.x0 != xUploadArea.x1) && (xUploadArea.y0 != xUploadArea.y1)) + return TRUE; + else return FALSE; +} + +BOOL CheckAgainstFrontScreen(short imageX0,short imageY0,short imageX1,short imageY1) +{ + imageX1 += imageX0; + imageY1 += imageY0; + + if (imageX0 < PSXDisplay.DisplayPosition.x) + xrUploadArea.x0 = PSXDisplay.DisplayPosition.x; + else + if (imageX0 > PSXDisplay.DisplayEnd.x) + xrUploadArea.x0 = PSXDisplay.DisplayEnd.x; + else + xrUploadArea.x0 = imageX0; + + if(imageX1 < PSXDisplay.DisplayPosition.x) + xrUploadArea.x1 = PSXDisplay.DisplayPosition.x; + else + if (imageX1 > PSXDisplay.DisplayEnd.x) + xrUploadArea.x1 = PSXDisplay.DisplayEnd.x; + else + xrUploadArea.x1 = imageX1; + + if (imageY0 < PSXDisplay.DisplayPosition.y) + xrUploadArea.y0 = PSXDisplay.DisplayPosition.y; + else + if (imageY0 > PSXDisplay.DisplayEnd.y) + xrUploadArea.y0 = PSXDisplay.DisplayEnd.y; + else + xrUploadArea.y0 = imageY0; + + if (imageY1 < PSXDisplay.DisplayPosition.y) + xrUploadArea.y1 = PSXDisplay.DisplayPosition.y; + else + if (imageY1 > PSXDisplay.DisplayEnd.y) + xrUploadArea.y1 = PSXDisplay.DisplayEnd.y; + else + xrUploadArea.y1 = imageY1; + + if ((xrUploadArea.x0 != xrUploadArea.x1) && (xrUploadArea.y0 != xrUploadArea.y1)) + return TRUE; + else return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +void PrepareFullScreenUpload (int Position) +{ + if (Position==-1) // rgb24 + { + if(PSXDisplay.Interlaced) + { + xrUploadArea.x0 = PSXDisplay.DisplayPosition.x; + xrUploadArea.x1 = PSXDisplay.DisplayEnd.x; + xrUploadArea.y0 = PSXDisplay.DisplayPosition.y; + xrUploadArea.y1 = PSXDisplay.DisplayEnd.y; + } + else + { + xrUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; + xrUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; + xrUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; + xrUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; + } + + if(bNeedRGB24Update) + { + if(lClearOnSwap) + { +// lClearOnSwap=0; + } + else + if(PSXDisplay.Interlaced && PreviousPSXDisplay.RGB24<2) // in interlaced mode we upload at least two full frames (GT1 menu) + { + PreviousPSXDisplay.RGB24++; + } + else + { + xrUploadArea.y1 = min(xrUploadArea.y0+xrUploadAreaRGB24.y1,xrUploadArea.y1); + xrUploadArea.y0+=xrUploadAreaRGB24.y0; + } + } + } + else + if (Position) + { + xrUploadArea.x0 = PSXDisplay.DisplayPosition.x; + xrUploadArea.x1 = PSXDisplay.DisplayEnd.x; + xrUploadArea.y0 = PSXDisplay.DisplayPosition.y; + xrUploadArea.y1 = PSXDisplay.DisplayEnd.y; + } + else + { + xrUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; + xrUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; + xrUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; + xrUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; + } + + if (xrUploadArea.x0 < 0) xrUploadArea.x0 = 0; + else + if (xrUploadArea.x0 > 1023) xrUploadArea.x0 = 1023; + + if (xrUploadArea.x1 < 0) xrUploadArea.x1 = 0; + else + if (xrUploadArea.x1 > 1024) xrUploadArea.x1 = 1024; + + if (xrUploadArea.y0 < 0) xrUploadArea.y0 = 0; + else + if (xrUploadArea.y0 > iGPUHeightMask) xrUploadArea.y0 = iGPUHeightMask; + + if (xrUploadArea.y1 < 0) xrUploadArea.y1 = 0; + else + if (xrUploadArea.y1 > iGPUHeight) xrUploadArea.y1 = iGPUHeight; + + if (PSXDisplay.RGB24) + { + InvalidateTextureArea(xrUploadArea.x0,xrUploadArea.y0,xrUploadArea.x1-xrUploadArea.x0,xrUploadArea.y1-xrUploadArea.y0); + } +} + +//////////////////////////////////////////////////////////////////////// +// Upload screen (MDEC and such) +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +unsigned char * LoadDirectMovieFast(void); + +void UploadScreenEx(int Position) +{ + short ya,yb,xa,xb,x, y, YStep, XStep, U, UStep,ux[4],vy[4]; + + if(!PSXDisplay.DisplayMode.x) return; + if(!PSXDisplay.DisplayMode.y) return; + + glDisable(GL_SCISSOR_TEST); + glShadeModel(GL_FLAT); + bOldSmoothShaded=FALSE; + glDisable(GL_BLEND); + bBlendEnable=FALSE; + glDisable(GL_TEXTURE_2D); + bTexEnabled=FALSE; + glDisable(GL_ALPHA_TEST); + + glPixelZoom(((float)rRatioRect.right)/((float)PSXDisplay.DisplayMode.x), + -1.0f*(((float)rRatioRect.bottom)/((float)PSXDisplay.DisplayMode.y))); + + //----------------------------------------------------// + + YStep = 256; // max texture size + XStep = 256; + UStep = (PSXDisplay.RGB24 ? 128 : 0); + ya = xrUploadArea.y0; + yb = xrUploadArea.y1; + xa = xrUploadArea.x0; + xb = xrUploadArea.x1; + + for(y=ya;y<=yb;y+=YStep) // loop y + { + U = 0; + for(x=xa;x<=xb;x+=XStep) // loop x + { + ly0 = ly1 = y; // -> get y coords + ly2 = y + YStep; + if (ly2 > yb) ly2 = yb; + ly3 = ly2; + + lx0 = lx3 = x; // -> get x coords + lx1 = x + XStep; + if (lx1 > xb) lx1 = xb; + + lx2 = lx1; + + ux[0]=ux[3]=(xa - x); // -> set tex x coords + if (ux[0] < 0) ux[0]=ux[3]=0; + ux[2]=ux[1]=(xb - x); + if (ux[2] > 256) ux[2]=ux[1]=256; + + vy[0]=vy[1]=(ya - y); // -> set tex y coords + if (vy[0] < 0) vy[0]=vy[1]=0; + vy[2]=vy[3]=(yb - y); + if (vy[2] > 256) vy[2]=vy[3]=256; + + if ((ux[0] >= ux[2]) || // -> cheaters never win... + (vy[0] >= vy[2])) continue; // (but winners always cheat...) + + xrMovieArea.x0=lx0+U; xrMovieArea.y0=ly0; + xrMovieArea.x1=lx2+U; xrMovieArea.y1=ly2; + + offsetScreenUpload(Position); + + glRasterPos2f(vertex[0].x,vertex[0].y); + + glDrawPixels(xrMovieArea.x1-xrMovieArea.x0, + xrMovieArea.y1-xrMovieArea.y0, + GL_RGBA,GL_UNSIGNED_BYTE, + LoadDirectMovieFast()); + + U+=UStep; + } + } + + //----------------------------------------------------// + + glPixelZoom(1.0F,1.0F); + + glEnable(GL_ALPHA_TEST); + glEnable(GL_SCISSOR_TEST); +} + +//////////////////////////////////////////////////////////////////////// + +void UploadScreen(int Position) +{ + short x, y, YStep, XStep, U, s, UStep,ux[4],vy[4]; + short xa,xb,ya,yb; + + if(xrUploadArea.x0>1023) xrUploadArea.x0=1023; + if(xrUploadArea.x1>1024) xrUploadArea.x1=1024; + if(xrUploadArea.y0>iGPUHeightMask) xrUploadArea.y0=iGPUHeightMask; + if(xrUploadArea.y1>iGPUHeight) xrUploadArea.y1=iGPUHeight; + + if(xrUploadArea.x0==xrUploadArea.x1) return; + if(xrUploadArea.y0==xrUploadArea.y1) return; + + if(PSXDisplay.Disabled && iOffscreenDrawing<4) return; + + iDrawnSomething = 2; + iLastRGB24=PSXDisplay.RGB24+1; + + if(bSkipNextFrame) return; + + if(dwActFixes & 2) {UploadScreenEx(Position);return;} + + bUsingMovie = TRUE; + bDrawTextured = TRUE; // just doing textures + bDrawSmoothShaded = FALSE; + + if(bGLBlend) vertex[0].c.lcol=0xff7f7f7f; // set solid col + else vertex[0].c.lcol=0xffffffff; + SETCOL(vertex[0]); + + SetOGLDisplaySettings(0); + + YStep = 256; // max texture size + XStep = 256; + + UStep = (PSXDisplay.RGB24 ? 128 : 0); + + ya=xrUploadArea.y0; + yb=xrUploadArea.y1; + xa=xrUploadArea.x0; + xb=xrUploadArea.x1; + + for(y=ya;y<=yb;y+=YStep) // loop y + { + U = 0; + for(x=xa;x<=xb;x+=XStep) // loop x + { + ly0 = ly1 = y; // -> get y coords + ly2 = y + YStep; + if (ly2 > yb) ly2 = yb; + ly3 = ly2; + + lx0 = lx3 = x; // -> get x coords + lx1 = x + XStep; + if (lx1 > xb) lx1 = xb; + + lx2 = lx1; + + ux[0]=ux[3]=(xa - x); // -> set tex x coords + if (ux[0] < 0) ux[0]=ux[3]=0; + ux[2]=ux[1]=(xb - x); + if (ux[2] > 256) ux[2]=ux[1]=256; + + vy[0]=vy[1]=(ya - y); // -> set tex y coords + if (vy[0] < 0) vy[0]=vy[1]=0; + vy[2]=vy[3]=(yb - y); + if (vy[2] > 256) vy[2]=vy[3]=256; + + if ((ux[0] >= ux[2]) || // -> cheaters never win... + (vy[0] >= vy[2])) continue; // (but winners always cheat...) + + xrMovieArea.x0=lx0+U; xrMovieArea.y0=ly0; + xrMovieArea.x1=lx2+U; xrMovieArea.y1=ly2; + + s=ux[2] - ux[0]; if(s>255) s=255; + + gl_ux[2] = gl_ux[1] = s; + s=vy[2] - vy[0]; if(s>255) s=255; + gl_vy[2] = gl_vy[3] = s; + gl_ux[0] = gl_ux[3] = gl_vy[0] = gl_vy[1] = 0; + + SetRenderState((uint32_t)0x01000000); + SetRenderMode((uint32_t)0x01000000, FALSE); // upload texture data + offsetScreenUpload(Position); + assignTextureVRAMWrite(); + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + U+=UStep; + } + } + + bUsingMovie=FALSE; // done... + bDisplayNotSet = TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// Detect next screen +//////////////////////////////////////////////////////////////////////// + +BOOL IsCompleteInsideNextScreen(short x, short y, short xoff, short yoff) +{ + if (x > PSXDisplay.DisplayPosition.x+1) return FALSE; + if ((x + xoff) < PSXDisplay.DisplayEnd.x-1) return FALSE; + yoff+=y; + if (y >= PSXDisplay.DisplayPosition.y && + y <= PSXDisplay.DisplayEnd.y ) + { + if ((yoff) >= PSXDisplay.DisplayPosition.y && + (yoff) <= PSXDisplay.DisplayEnd.y ) return TRUE; + } + if (y > PSXDisplay.DisplayPosition.y+1) return FALSE; + if (yoff < PSXDisplay.DisplayEnd.y-1) return FALSE; + return TRUE; +} + +BOOL IsPrimCompleteInsideNextScreen(short x, short y, short xoff, short yoff) +{ + x+=PSXDisplay.DrawOffset.x; + if (x > PSXDisplay.DisplayPosition.x+1) return FALSE; + y+=PSXDisplay.DrawOffset.y; + if (y > PSXDisplay.DisplayPosition.y+1) return FALSE; + xoff+=PSXDisplay.DrawOffset.x; + if (xoff < PSXDisplay.DisplayEnd.x-1) return FALSE; + yoff+=PSXDisplay.DrawOffset.y; + if (yoff < PSXDisplay.DisplayEnd.y-1) return FALSE; + return TRUE; +} + +BOOL IsInsideNextScreen(short x, short y, short xoff, short yoff) +{ + if (x > PSXDisplay.DisplayEnd.x) return FALSE; + if (y > PSXDisplay.DisplayEnd.y) return FALSE; + if ((x + xoff) < PSXDisplay.DisplayPosition.x) return FALSE; + if ((y + yoff) < PSXDisplay.DisplayPosition.y) return FALSE; + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// mask stuff... +//////////////////////////////////////////////////////////////////////// + +//Mask1 Set mask bit while drawing. 1 = on +//Mask2 Do not draw to mask areas. 1= on + +void cmdSTP(unsigned char * baseAddr) +{ + uint32_t gdata = ((uint32_t*)baseAddr)[0]; + + STATUSREG&=~0x1800; // clear the necessary bits + STATUSREG|=((gdata & 0x03) << 11); // set the current bits + + if(!iUseMask) return; + + if(gdata&1) {sSetMask=0x8000;lSetMask=0x80008000;iSetMask=1;} + else {sSetMask=0; lSetMask=0; iSetMask=0;} + + if(gdata&2) + { + if(!(gdata&1)) iSetMask=2; + bCheckMask=TRUE; + if(iDepthFunc==0) return; + iDepthFunc=0; + glDepthFunc(GL_LESS); + } + else + { + bCheckMask=FALSE; + if(iDepthFunc==1) return; + glDepthFunc(GL_ALWAYS); + iDepthFunc=1; + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: Set texture page infos +//////////////////////////////////////////////////////////////////////// + +void cmdTexturePage(unsigned char * baseAddr) +{ + uint32_t gdata = ((uint32_t *)baseAddr)[0]; + UpdateGlobalTP((unsigned short)gdata); + GlobalTextREST = (gdata&0x00ffffff)>>9; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: turn on/off texture window +//////////////////////////////////////////////////////////////////////// + +void cmdTextureWindow(unsigned char *baseAddr) +{ + uint32_t gdata = ((uint32_t *)baseAddr)[0]; + uint32_t YAlign,XAlign; + + ulGPUInfoVals[INFO_TW]=gdata&0xFFFFF; + + if(gdata & 0x020) + TWin.Position.y1 = 8; // xxxx1 + else if (gdata & 0x040) + TWin.Position.y1 = 16; // xxx10 + else if (gdata & 0x080) + TWin.Position.y1 = 32; // xx100 + else if (gdata & 0x100) + TWin.Position.y1 = 64; // x1000 + else if (gdata & 0x200) + TWin.Position.y1 = 128; // 10000 + else + TWin.Position.y1 = 256; // 00000 + + // Texture window size is determined by the least bit set of the relevant 5 bits + + if (gdata & 0x001) + TWin.Position.x1 = 8; // xxxx1 + else if (gdata & 0x002) + TWin.Position.x1 = 16; // xxx10 + else if (gdata & 0x004) + TWin.Position.x1 = 32; // xx100 + else if (gdata & 0x008) + TWin.Position.x1 = 64; // x1000 + else if (gdata & 0x010) + TWin.Position.x1 = 128; // 10000 + else + 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 - (TWin.Position.y1 >> 3)); + XAlign = (uint32_t)(32 - (TWin.Position.x1 >> 3)); + + // Absolute position of the start of the texture window + + TWin.Position.y0 = (short)(((gdata >> 15) & YAlign) << 3); + TWin.Position.x0 = (short)(((gdata >> 10) & XAlign) << 3); + + if((TWin.Position.x0 == 0 && // tw turned off + TWin.Position.y0 == 0 && + TWin.Position.x1 == 0 && + TWin.Position.y1 == 0) || + (TWin.Position.x1 == 256 && + TWin.Position.y1 == 256)) + { + bUsingTWin = FALSE; // -> just do it + +#ifdef OWNSCALE + TWin.UScaleFactor = 1.0f; + TWin.VScaleFactor = 1.0f; +#else + TWin.UScaleFactor = + TWin.VScaleFactor = 1.0f/256.0f; +#endif + } + else // tw turned on + { + bUsingTWin = TRUE; + + TWin.OPosition.y1 = TWin.Position.y1; // -> get psx sizes + TWin.OPosition.x1 = TWin.Position.x1; + + if(TWin.Position.x1<=2) TWin.Position.x1=2; // -> set OGL sizes + else + if(TWin.Position.x1<=4) TWin.Position.x1=4; + else + if(TWin.Position.x1<=8) TWin.Position.x1=8; + else + if(TWin.Position.x1<=16) TWin.Position.x1=16; + else + if(TWin.Position.x1<=32) TWin.Position.x1=32; + else + if(TWin.Position.x1<=64) TWin.Position.x1=64; + else + if(TWin.Position.x1<=128) TWin.Position.x1=128; + else + if(TWin.Position.x1<=256) TWin.Position.x1=256; + + if(TWin.Position.y1<=2) TWin.Position.y1=2; + else + if(TWin.Position.y1<=4) TWin.Position.y1=4; + else + if(TWin.Position.y1<=8) TWin.Position.y1=8; + else + if(TWin.Position.y1<=16) TWin.Position.y1=16; + else + if(TWin.Position.y1<=32) TWin.Position.y1=32; + else + if(TWin.Position.y1<=64) TWin.Position.y1=64; + else + if(TWin.Position.y1<=128) TWin.Position.y1=128; + else + if(TWin.Position.y1<=256) TWin.Position.y1=256; + +#ifdef OWNSCALE + TWin.UScaleFactor = (float)TWin.Position.x1; + TWin.VScaleFactor = (float)TWin.Position.y1; +#else + TWin.UScaleFactor = ((float)TWin.Position.x1)/256.0f; // -> set scale factor + TWin.VScaleFactor = ((float)TWin.Position.y1)/256.0f; +#endif + } +} + +//////////////////////////////////////////////////////////////////////// +// mmm, Lewpy uses that in TileS ... I don't ;) +//////////////////////////////////////////////////////////////////////// + +/* +void ClampToPSXDrawAreaOffset(short *x0, short *y0, short *x1, short *y1) +{ + if (*x0 < PSXDisplay.DrawArea.x0) + { + *x1 -= (PSXDisplay.DrawArea.x0 - *x0); + *x0 = PSXDisplay.DrawArea.x0; + } + else + if (*x0 > PSXDisplay.DrawArea.x1) + { + *x0 = PSXDisplay.DrawArea.x1; + *x1 = 0; + } + + if (*y0 < PSXDisplay.DrawArea.y0) + { + *y1 -= (PSXDisplay.DrawArea.y0 - *y0); + *y0 = PSXDisplay.DrawArea.y0; + } + else + if (*y0 > PSXDisplay.DrawArea.y1) + { + *y0 = PSXDisplay.DrawArea.y1; + *y1 = 0; + } + + if (*x1 < 0) *x1 = 0; + + if ((*x1 + *x0) > PSXDisplay.DrawArea.x1) + *x1 = (PSXDisplay.DrawArea.x1 - *x0 + 1); + + if (*y1 < 0) *y1 = 0; + + if ((*y1 + *y0) > PSXDisplay.DrawArea.y1) + *y1 = (PSXDisplay.DrawArea.y1 - *y0 + 1); +} +*/ + +//////////////////////////////////////////////////////////////////////// +// Check draw area dimensions +//////////////////////////////////////////////////////////////////////// + +void ClampToPSXScreen(short *x0, short *y0, short *x1, short *y1) +{ + if (*x0 < 0) *x0 = 0; + else + if (*x0 > 1023) *x0 = 1023; + + if (*x1 < 0) *x1 = 0; + else + if (*x1 > 1023) *x1 = 1023; + + if (*y0 < 0) *y0 = 0; + else + if (*y0 > iGPUHeightMask) *y0 = iGPUHeightMask; + + if (*y1 < 0) *y1 = 0; + else + if (*y1 > iGPUHeightMask) *y1 = iGPUHeightMask; +} + +//////////////////////////////////////////////////////////////////////// +// Used in Load Image and Blk Fill +//////////////////////////////////////////////////////////////////////// + +void ClampToPSXScreenOffset(short *x0, short *y0, short *x1, short *y1) +{ + if (*x0 < 0) + { *x1 += *x0; *x0 = 0; } + else + if (*x0 > 1023) + { *x0 = 1023; *x1 = 0; } + + if (*y0 < 0) + { *y1 += *y0; *y0 = 0; } + else + if (*y0 > iGPUHeightMask) + { *y0 = iGPUHeightMask; *y1 = 0; } + + if (*x1 < 0) *x1 = 0; + + if ((*x1 + *x0) > 1024) *x1 = (1024 - *x0); + + if (*y1 < 0) *y1 = 0; + + if ((*y1 + *y0) > iGPUHeight) *y1 = (iGPUHeight - *y0); +} + +//////////////////////////////////////////////////////////////////////// +// cmd: start of drawing area... primitives will be clipped inside +//////////////////////////////////////////////////////////////////////// + +void cmdDrawAreaStart(unsigned char * baseAddr) +{ + uint32_t gdata = ((uint32_t *)baseAddr)[0]; + + drawX = gdata & 0x3ff; // for soft drawing + if(drawX>=1024) drawX=1023; + + if(dwGPUVersion==2) + { + ulGPUInfoVals[INFO_DRAWSTART]=gdata&0x3FFFFF; + drawY = (gdata>>12)&0x3ff; + } + else + { + ulGPUInfoVals[INFO_DRAWSTART]=gdata&0xFFFFF; + drawY = (gdata>>10)&0x3ff; + } + + if(drawY>=iGPUHeight) drawY=iGPUHeightMask; + + PreviousPSXDisplay.DrawArea.y0=PSXDisplay.DrawArea.y0; + PreviousPSXDisplay.DrawArea.x0=PSXDisplay.DrawArea.x0; + + PSXDisplay.DrawArea.y0 = (short)drawY; // for OGL drawing + PSXDisplay.DrawArea.x0 = (short)drawX; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: end of drawing area... primitives will be clipped inside +//////////////////////////////////////////////////////////////////////// + +void cmdDrawAreaEnd(unsigned char * baseAddr) +{ + uint32_t gdata = ((uint32_t *)baseAddr)[0]; + + drawW = gdata & 0x3ff; // for soft drawing + if(drawW>=1024) drawW=1023; + + if(dwGPUVersion==2) + { + ulGPUInfoVals[INFO_DRAWEND]=gdata&0x3FFFFF; + drawH = (gdata>>12)&0x3ff; + } + else + { + ulGPUInfoVals[INFO_DRAWEND]=gdata&0xFFFFF; + drawH = (gdata>>10)&0x3ff; + } + + if(drawH>=iGPUHeight) drawH=iGPUHeightMask; + + PSXDisplay.DrawArea.y1 = (short)drawH; // for OGL drawing + PSXDisplay.DrawArea.x1 = (short)drawW; + + ClampToPSXScreen(&PSXDisplay.DrawArea.x0, // clamp + &PSXDisplay.DrawArea.y0, + &PSXDisplay.DrawArea.x1, + &PSXDisplay.DrawArea.y1); + + bDisplayNotSet = TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: draw offset... will be added to prim coords +//////////////////////////////////////////////////////////////////////// + +void cmdDrawOffset(unsigned char * baseAddr) +{ + uint32_t gdata = ((uint32_t *)baseAddr)[0]; + + PreviousPSXDisplay.DrawOffset.x = + PSXDisplay.DrawOffset.x = (short)(gdata & 0x7ff); + + if (dwGPUVersion == 2) + { + ulGPUInfoVals[INFO_DRAWOFF] = gdata&0x7FFFFF; + PSXDisplay.DrawOffset.y = (short)((gdata>>12) & 0x7ff); + } + else + { + ulGPUInfoVals[INFO_DRAWOFF]=gdata&0x3FFFFF; + PSXDisplay.DrawOffset.y = (short)((gdata>>11) & 0x7ff); + } + + PSXDisplay.DrawOffset.x=(short)(((int)PSXDisplay.DrawOffset.x<<21)>>21); + PSXDisplay.DrawOffset.y=(short)(((int)PSXDisplay.DrawOffset.y<<21)>>21); + + PSXDisplay.CumulOffset.x = // new OGL prim offsets + PSXDisplay.DrawOffset.x - PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; + PSXDisplay.CumulOffset.y = + PSXDisplay.DrawOffset.y - PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: load image to vram +//////////////////////////////////////////////////////////////////////// + +void primLoadImage(unsigned char * baseAddr) +{ + unsigned short *sgpuData = ((unsigned short *) baseAddr); + + VRAMWrite.x = sgpuData[2]&0x03ff; + VRAMWrite.y = sgpuData[3]&iGPUHeightMask; + VRAMWrite.Width = sgpuData[4]; + VRAMWrite.Height = sgpuData[5]; + + iDataWriteMode = DR_VRAMTRANSFER; + VRAMWrite.ImagePtr = psxVuw + (VRAMWrite.y<<10) + VRAMWrite.x; + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ColsRemaining = VRAMWrite.Height; + + bNeedWriteUpload=TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +void PrepareRGB24Upload(void) +{ + VRAMWrite.x=(VRAMWrite.x*2)/3; + VRAMWrite.Width=(VRAMWrite.Width*2)/3; + + if(!PSXDisplay.InterlacedTest && // NEW + CheckAgainstScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) + { + xrUploadArea.x0-=PreviousPSXDisplay.DisplayPosition.x; + xrUploadArea.x1-=PreviousPSXDisplay.DisplayPosition.x; + xrUploadArea.y0-=PreviousPSXDisplay.DisplayPosition.y; + xrUploadArea.y1-=PreviousPSXDisplay.DisplayPosition.y; + } + else + if(CheckAgainstFrontScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) + { + xrUploadArea.x0-=PSXDisplay.DisplayPosition.x; + xrUploadArea.x1-=PSXDisplay.DisplayPosition.x; + xrUploadArea.y0-=PSXDisplay.DisplayPosition.y; + xrUploadArea.y1-=PSXDisplay.DisplayPosition.y; + } + else return; + + if(bRenderFrontBuffer) + { + updateFrontDisplay(); + } + + if(bNeedRGB24Update==FALSE) + { + xrUploadAreaRGB24=xrUploadArea; + bNeedRGB24Update=TRUE; + } + else + { + xrUploadAreaRGB24.x0=min(xrUploadAreaRGB24.x0,xrUploadArea.x0); + xrUploadAreaRGB24.x1=max(xrUploadAreaRGB24.x1,xrUploadArea.x1); + xrUploadAreaRGB24.y0=min(xrUploadAreaRGB24.y0,xrUploadArea.y0); + xrUploadAreaRGB24.y1=max(xrUploadAreaRGB24.y1,xrUploadArea.y1); + } +} + +//////////////////////////////////////////////////////////////////////// + +void CheckWriteUpdate() +{ + int iX=0,iY=0; + + if(VRAMWrite.Width) iX=1; + if(VRAMWrite.Height) iY=1; + + InvalidateTextureArea(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width-iX, VRAMWrite.Height-iY); + + if(PSXDisplay.Interlaced && !iOffscreenDrawing) return; + + if(PSXDisplay.RGB24) {PrepareRGB24Upload();return;} + + if(!PSXDisplay.InterlacedTest && + CheckAgainstScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) + { + if(dwActFixes&0x800) return; + + if(bRenderFrontBuffer) + { + updateFrontDisplay(); + } + + UploadScreen(FALSE); + + bNeedUploadTest=TRUE; + } + else + if(iOffscreenDrawing) + { + if (CheckAgainstFrontScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) + { + if(PSXDisplay.InterlacedTest) + { + if(PreviousPSXDisplay.InterlacedNew) + { + PreviousPSXDisplay.InterlacedNew=FALSE; + bNeedInterlaceUpdate=TRUE; + xrUploadAreaIL.x0=PSXDisplay.DisplayPosition.x; + xrUploadAreaIL.y0=PSXDisplay.DisplayPosition.y; + xrUploadAreaIL.x1=PSXDisplay.DisplayPosition.x+PSXDisplay.DisplayModeNew.x; + xrUploadAreaIL.y1=PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayModeNew.y; + if(xrUploadAreaIL.x1>1023) xrUploadAreaIL.x1=1023; + if(xrUploadAreaIL.y1>511) xrUploadAreaIL.y1=511; + } + + if(bNeedInterlaceUpdate==FALSE) + { + xrUploadAreaIL=xrUploadArea; + bNeedInterlaceUpdate=TRUE; + } + else + { + xrUploadAreaIL.x0=min(xrUploadAreaIL.x0,xrUploadArea.x0); + xrUploadAreaIL.x1=max(xrUploadAreaIL.x1,xrUploadArea.x1); + xrUploadAreaIL.y0=min(xrUploadAreaIL.y0,xrUploadArea.y0); + xrUploadAreaIL.y1=max(xrUploadAreaIL.y1,xrUploadArea.y1); + } + return; + } + + if(!bNeedUploadAfter) + { + bNeedUploadAfter = TRUE; + xrUploadArea.x0=VRAMWrite.x; + xrUploadArea.x1=VRAMWrite.x+VRAMWrite.Width; + xrUploadArea.y0=VRAMWrite.y; + xrUploadArea.y1=VRAMWrite.y+VRAMWrite.Height; + } + else + { + xrUploadArea.x0=min(xrUploadArea.x0,VRAMWrite.x); + xrUploadArea.x1=max(xrUploadArea.x1,VRAMWrite.x+VRAMWrite.Width); + xrUploadArea.y0=min(xrUploadArea.y0,VRAMWrite.y); + xrUploadArea.y1=max(xrUploadArea.y1,VRAMWrite.y+VRAMWrite.Height); + } + + if(dwActFixes&0x8000) + { + if((xrUploadArea.x1-xrUploadArea.x0)>=(PSXDisplay.DisplayMode.x-32) && + (xrUploadArea.y1-xrUploadArea.y0)>=(PSXDisplay.DisplayMode.y-32)) + { + UploadScreen(-1); + updateFrontDisplay(); + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: vram -> psx mem +//////////////////////////////////////////////////////////////////////// + +void primStoreImage(unsigned char * baseAddr) +{ + unsigned short *sgpuData = ((unsigned short *) baseAddr); + + VRAMRead.x = sgpuData[2]&0x03ff; + VRAMRead.y = sgpuData[3]&iGPUHeightMask; + VRAMRead.Width = sgpuData[4]; + VRAMRead.Height = sgpuData[5]; + + VRAMRead.ImagePtr = psxVuw + (VRAMRead.y<<10) + VRAMRead.x; + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining = VRAMRead.Height; + + iDataReadMode = DR_VRAMTRANSFER; + + STATUSREG |= GPUSTATUS_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); + + iDrawnSomething = 1; + + sprtX = sgpuData[2]; + sprtY = sgpuData[3]; + sprtW = sgpuData[4] & 0x3ff; + sprtH = sgpuData[5] & iGPUHeightMask; + + sprtW = (sprtW + 15) & ~15; + + // Increase H & W if they are one short of full values, because they never can be full values + if (sprtH == iGPUHeightMask) sprtH=iGPUHeight; + if (sprtW == 1023) sprtW=1024; + + // x and y of start + ly0 = ly1 = sprtY; + ly2 = ly3 = (sprtY+sprtH); + lx0 = lx3 = sprtX; + lx1 = lx2 = (sprtX+sprtW); + + offsetBlk(); + + if(ClipVertexListScreen()) + { + PSXDisplay_t * pd; + if(PSXDisplay.InterlacedTest) pd=&PSXDisplay; + else pd=&PreviousPSXDisplay; + + if ((lx0 <= pd->DisplayPosition.x+16) && + (ly0 <= pd->DisplayPosition.y+16) && + (lx2 >= pd->DisplayEnd.x-16) && + (ly2 >= pd->DisplayEnd.y-16)) + { + GLclampf g,b,r; + g=((GLclampf)GREEN(gpuData[0]))/255.0f; + b=((GLclampf)BLUE(gpuData[0]))/255.0f; + r=((GLclampf)RED(gpuData[0]))/255.0f; + + glDisable(GL_SCISSOR_TEST); + glClearColor(r,g,b,1.0f); + glClear(uiBufferBits); + gl_z=0.0f; + + if(gpuData[0]!=0x02000000 && + (ly0>pd->DisplayPosition.y || + ly2DisplayEnd.y)) + { + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState((uint32_t)0x01000000); + SetRenderMode((uint32_t)0x01000000, FALSE); + vertex[0].c.lcol=0xff000000; + SETCOL(vertex[0]); + if(ly0>pd->DisplayPosition.y) + { + vertex[0].x=0;vertex[0].y=0; + vertex[1].x=pd->DisplayEnd.x-pd->DisplayPosition.x;vertex[1].y=0; + vertex[2].x=vertex[1].x;vertex[2].y=ly0-pd->DisplayPosition.y; + vertex[3].x=0;vertex[3].y=vertex[2].y; + PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + if(ly2DisplayEnd.y) + { + vertex[0].x=0;vertex[0].y=(pd->DisplayEnd.y-pd->DisplayPosition.y)-(pd->DisplayEnd.y-ly2); + vertex[1].x=pd->DisplayEnd.x-pd->DisplayPosition.x;vertex[1].y=vertex[0].y; + vertex[2].x=vertex[1].x;vertex[2].y=pd->DisplayEnd.y; + vertex[3].x=0;vertex[3].y=vertex[2].y; + PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + } + + glEnable(GL_SCISSOR_TEST); + } + else + { + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState((uint32_t)0x01000000); + SetRenderMode((uint32_t)0x01000000, FALSE); + vertex[0].c.lcol=gpuData[0]|0xff000000; + SETCOL(vertex[0]); + glDisable(GL_SCISSOR_TEST); + PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + glEnable(GL_SCISSOR_TEST); + } + } + + //mmm... will clean all stuff, also if not all _should_ be cleaned... + //if (IsInsideNextScreen(sprtX, sprtY, sprtW, sprtH)) + // try this: + if (IsCompleteInsideNextScreen(sprtX, sprtY, sprtW, sprtH)) + { + lClearOnSwapColor = COLOR(gpuData[0]); + lClearOnSwap = 1; + } + + if(iOffscreenDrawing) + { + ClampToPSXScreenOffset( &sprtX, &sprtY, &sprtW, &sprtH); + if ((sprtW == 0) || (sprtH == 0)) return; + InvalidateTextureArea(sprtX, sprtY, sprtW-1, sprtH-1); + + sprtW+=sprtX; + sprtH+=sprtY; + + FillSoftwareArea(sprtX, sprtY, sprtW, sprtH, BGR24to16(gpuData[0])); + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: move image vram -> vram +//////////////////////////////////////////////////////////////////////// + +void MoveImageWrapped(short imageX0,short imageY0, + short imageX1,short imageY1, + short imageSX,short imageSY) +{ + int i,j,imageXE,imageYE; + + if(iFrameReadType&2) + { + imageXE=imageX0+imageSX; + imageYE=imageY0+imageSY; + + if(imageYE>iGPUHeight && imageXE>1024) + { + CheckVRamRead(0,0, + (imageXE&0x3ff), + (imageY0&iGPUHeightMask), + FALSE); + } + + if(imageXE>1024) + { + CheckVRamRead(0,imageY0, + (imageXE&0x3ff), + (imageYE>iGPUHeight)?iGPUHeight:imageYE, + FALSE); + } + + if(imageYE>iGPUHeight) + { + CheckVRamRead(imageX0,0, + (imageXE>1024)?1024:imageXE, + imageYE&iGPUHeightMask, + FALSE); + } + + CheckVRamRead(imageX0,imageY0, + (imageXE>1024)?1024:imageXE, + (imageYE>iGPUHeight)?iGPUHeight:imageYE, + FALSE); + } + + for(j=0;jiGPUHeight && imageXE>1024) + { + InvalidateTextureArea(0,0, + (imageXE&0x3ff)-1, + (imageYE&iGPUHeightMask)-1); + } + + if(imageXE>1024) + { + InvalidateTextureArea(0,imageY1, + (imageXE&0x3ff)-1, + ((imageYE>iGPUHeight)?iGPUHeight:imageYE)-imageY1-1); + } + + if(imageYE>iGPUHeight) + { + InvalidateTextureArea(imageX1,0, + ((imageXE>1024)?1024:imageXE)-imageX1-1, + (imageYE&iGPUHeightMask)-1); + } + + InvalidateTextureArea(imageX1,imageY1, + ((imageXE>1024)?1024:imageXE)-imageX1-1, + ((imageYE>iGPUHeight)?iGPUHeight:imageYE)-imageY1-1); + } +} + +//////////////////////////////////////////////////////////////////////// + +void primMoveImage(unsigned char * baseAddr) +{ + short *sgpuData = ((short *) baseAddr); + short imageY0,imageX0,imageY1,imageX1,imageSX,imageSY,i,j; + + imageX0 = sgpuData[2]&0x03ff; + imageY0 = sgpuData[3]&iGPUHeightMask; + imageX1 = sgpuData[4]&0x03ff; + imageY1 = sgpuData[5]&iGPUHeightMask; + imageSX = sgpuData[6]; + imageSY = sgpuData[7]; + + if((imageX0 == imageX1) && (imageY0 == imageY1)) return; + if(imageSX<=0) return; + if(imageSY<=0) return; + + if(iGPUHeight==1024 && sgpuData[7]>1024) return; + + if((imageY0+imageSY)>iGPUHeight || + (imageX0+imageSX)>1024 || + (imageY1+imageSY)>iGPUHeight || + (imageX1+imageSX)>1024) + { + MoveImageWrapped(imageX0,imageY0,imageX1,imageY1,imageSX,imageSY); + if((imageY0+imageSY)>iGPUHeight) imageSY=iGPUHeight-imageY0; + if((imageX0+imageSX)>1024) imageSX=1024-imageX0; + if((imageY1+imageSY)>iGPUHeight) imageSY=iGPUHeight-imageY1; + if((imageX1+imageSX)>1024) imageSX=1024-imageX1; + } + + if(iFrameReadType&2) + CheckVRamRead(imageX0,imageY0, + imageX0+imageSX, + imageY0+imageSY, + FALSE); + + if(imageSX&1) + { + unsigned short *SRCPtr, *DSTPtr; + unsigned short LineOffset; + + SRCPtr = psxVuw + (1024*imageY0) + imageX0; + DSTPtr = psxVuw + (1024*imageY1) + imageX1; + + LineOffset = 1024 - imageSX; + + for(j=0;j>1; + + SRCPtr = (uint32_t *)(psxVuw + (1024*imageY0) + imageX0); + DSTPtr = (uint32_t *)(psxVuw + (1024*imageY1) + imageX1); + + LineOffset = 512 - dx; + + for(j=0;j=PreviousPSXDisplay.DisplayPosition.x && + imageX1=PreviousPSXDisplay.DisplayPosition.y && + imageY1=PreviousPSXDisplay.DisplayPosition.x && + imageX1<=PreviousPSXDisplay.DisplayEnd.x && + imageY1>=PreviousPSXDisplay.DisplayPosition.y && + imageY1<=PreviousPSXDisplay.DisplayEnd.y) + { + if(!( + imageX0>=PSXDisplay.DisplayPosition.x && + imageX0=PSXDisplay.DisplayPosition.y && + imageY0=PreviousPSXDisplay.DisplayPosition.x && + imageX0=PreviousPSXDisplay.DisplayPosition.y && + imageY0=PSXDisplay.DisplayPosition.x && + imageX0=PSXDisplay.DisplayPosition.y && + imageY0 set color with + SETCOL(vertex[0]); // texture alpha + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + vertex[0].x+=POFF;vertex[1].x+=POFF; + vertex[2].x+=POFF;vertex[3].x+=POFF; + vertex[0].y+=POFF;vertex[1].y+=POFF; + vertex[2].y+=POFF;vertex[3].y+=POFF; + GlobalTextABR=0; + DrawSemiTrans=1; + SetSemiTrans(); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + GlobalTextABR=lABR; + DrawSemiTrans=lDST; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: small sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +void primSprt8(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + short s; + + iSpriteTex=1; + + sprtX = sgpuData[2]; + sprtY = sgpuData[3]; + sprtW = 8; + sprtH = 8; + + lx0 = sprtX; + ly0 = sprtY; + + offsetST(); + + // do texture stuff + gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; + + if(usMirror & 0x1000) + { + s=gl_ux[0]; + s-=sprtW-1; + if(s<0) {s=0;} + gl_ux[0]=gl_ux[3]=s; + } + + sSprite_ux2=s=gl_ux[0]+sprtW; + if(s) s--; + if(s>255) s=255; + gl_ux[1]=gl_ux[2]=s; + // Y coords + gl_vy[0]=gl_vy[1]=baseAddr[9];//(gpuData[2]>>8)&0xff; + + if(usMirror & 0x2000) + { + s=gl_vy[0]; + s-=sprtH-1; + if(s<0) {s=0;} + gl_vy[0]=gl_vy[1]=s; + } + + sSprite_vy2=s=gl_vy[0]+sprtH; + if(s) s--; + if(s>255) s=255; + gl_vy[2]=gl_vy[3]=s; + + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + + if(iOffscreenDrawing) + { + offsetPSX4(); + + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + lx0-=PSXDisplay.DrawOffset.x; + ly0-=PSXDisplay.DrawOffset.y; + + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,8,8); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,8,8); + else + DrawSoftwareSprite(baseAddr,8,8,baseAddr[8],baseAddr[9]); + } + } + + SetRenderMode(gpuData[0], TRUE); + SetZMask4SP(); + + sSprite_ux2=gl_ux[0]+sprtW; + sSprite_vy2=gl_vy[0]+sprtH; + + assignTextureSprite(); + + if(iFilterType>4) + DrawMultiFilterSprite(); + else + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + + if(bSmallAlpha && iFilterType<=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SetZMask4O(); + } + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + DEFOPAQUEOFF + } + + iSpriteTex=0; + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: medium sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +void primSprt16(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + short s; + + iSpriteTex=1; + + sprtX = sgpuData[2]; + sprtY = sgpuData[3]; + sprtW = 16; + sprtH = 16; + + lx0 = sprtX; + ly0 = sprtY; + + offsetST(); + + // do texture stuff + gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; + + if(usMirror & 0x1000) + { + s=gl_ux[0]; + s-=sprtW-1; + if(s<0) {s=0;} + gl_ux[0]=gl_ux[3]=s; + } + + sSprite_ux2=s=gl_ux[0]+sprtW; + if(s) s--; + if(s>255) s=255; + gl_ux[1]=gl_ux[2]=s; + // Y coords + gl_vy[0]=gl_vy[1]=baseAddr[9];//(gpuData[2]>>8)&0xff; + + if(usMirror & 0x2000) + { + s=gl_vy[0]; + s-=sprtH-1; + if(s<0) {s=0;} + gl_vy[0]=gl_vy[1]=s; + } + + sSprite_vy2=s=gl_vy[0]+sprtH; + if(s) s--; + if(s>255) s=255; + gl_vy[2]=gl_vy[3]=s; + + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + + if(iOffscreenDrawing) + { + offsetPSX4(); + + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + lx0-=PSXDisplay.DrawOffset.x; + ly0-=PSXDisplay.DrawOffset.y; + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,16,16); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,16,16); + else + DrawSoftwareSprite(baseAddr,16,16,baseAddr[8],baseAddr[9]); + } + } + + SetRenderMode(gpuData[0], TRUE); + SetZMask4SP(); + + sSprite_ux2=gl_ux[0]+sprtW; + sSprite_vy2=gl_vy[0]+sprtH; + + assignTextureSprite(); + + if(iFilterType>4) + DrawMultiFilterSprite(); + else + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + + if(bSmallAlpha && iFilterType<=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SetZMask4O(); + } + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + DEFOPAQUEOFF + } + + iSpriteTex=0; + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: free-size sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +void primSprtSRest(unsigned char * baseAddr,unsigned short type) +{ + uint32_t *gpuData = ((uint32_t *)baseAddr); + short *sgpuData = ((short *) baseAddr); + short s; + unsigned short sTypeRest=0; + + sprtX = sgpuData[2]; + sprtY = sgpuData[3]; + sprtW = sgpuData[6] & 0x3ff; + sprtH = sgpuData[7] & 0x1ff; + + // do texture stuff + switch(type) + { + case 1: + gl_vy[0]=gl_vy[1]=baseAddr[9]; + s=256-baseAddr[8]; + sprtW-=s; + sprtX+=s; + gl_ux[0]=gl_ux[3]=0; + break; + case 2: + gl_ux[0]=gl_ux[3]=baseAddr[8]; + s=256-baseAddr[9]; + sprtH-=s; + sprtY+=s; + gl_vy[0]=gl_vy[1]=0; + break; + case 3: + s=256-baseAddr[8]; + sprtW-=s; + sprtX+=s; + gl_ux[0]=gl_ux[3]=0; + s=256-baseAddr[9]; + sprtH-=s; + sprtY+=s; + gl_vy[0]=gl_vy[1]=0; + break; + + case 4: + gl_vy[0]=gl_vy[1]=baseAddr[9]; + s=512-baseAddr[8]; + sprtW-=s; + sprtX+=s; + gl_ux[0]=gl_ux[3]=0; + break; + case 5: + gl_ux[0]=gl_ux[3]=baseAddr[8]; + s=512-baseAddr[9]; + sprtH-=s; + sprtY+=s; + gl_vy[0]=gl_vy[1]=0; + break; + case 6: + s=512-baseAddr[8]; + sprtW-=s; + sprtX+=s; + gl_ux[0]=gl_ux[3]=0; + s=512-baseAddr[9]; + sprtH-=s; + sprtY+=s; + gl_vy[0]=gl_vy[1]=0; + break; + + } + + if(usMirror & 0x1000) + { + s=gl_ux[0]; + s-=sprtW-1;if(s<0) s=0; + gl_ux[0]=gl_ux[3]=s; + } + if(usMirror & 0x2000) + { + s=gl_vy[0]; + s-=sprtH-1;if(s<0) {s=0;} + gl_vy[0]=gl_vy[1]=s; + } + + sSprite_ux2=s=gl_ux[0]+sprtW; + if(s>255) s=255; + gl_ux[1]=gl_ux[2]=s; + sSprite_vy2=s=gl_vy[0]+sprtH; + if(s>255) s=255; + gl_vy[2]=gl_vy[3]=s; + + if(!bUsingTWin) + { + if(sSprite_ux2>256) + {sprtW=256-gl_ux[0];sSprite_ux2=256;sTypeRest+=1;} + if(sSprite_vy2>256) + {sprtH=256-gl_vy[0];sSprite_vy2=256;sTypeRest+=2;} + } + + lx0 = sprtX; + ly0 = sprtY; + + offsetST(); + + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + + if(iOffscreenDrawing) + { + offsetPSX4(); + + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + lx0-=PSXDisplay.DrawOffset.x; + ly0-=PSXDisplay.DrawOffset.y; + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,sprtW,sprtH); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,sprtW,sprtH); + else + DrawSoftwareSprite(baseAddr,sprtW,sprtH,baseAddr[8],baseAddr[9]); + } + } + + SetRenderMode(gpuData[0], TRUE); + SetZMask4SP(); + + sSprite_ux2=gl_ux[0]+sprtW; + sSprite_vy2=gl_vy[0]+sprtH; + + assignTextureSprite(); + + if(iFilterType>4) + DrawMultiFilterSprite(); + else + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + + if(bSmallAlpha && iFilterType<=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SetZMask4O(); + } + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + DEFOPAQUEOFF + } + + 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 s; + unsigned short sTypeRest=0; + + sprtX = sgpuData[2]; + sprtY = sgpuData[3]; + sprtW = sgpuData[6] & 0x3ff; + sprtH = sgpuData[7] & 0x1ff; + + if(!sprtH) return; + if(!sprtW) return; + + iSpriteTex=1; + + // do texture stuff + gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; + gl_vy[0]=gl_vy[1]=baseAddr[9];//(gpuData[2]>>8)&0xff; + + if(usMirror & 0x1000) + { + s=gl_ux[0]; + s-=sprtW-1; + if(s<0) {s=0;} + gl_ux[0]=gl_ux[3]=s; + } + if(usMirror & 0x2000) + { + s=gl_vy[0]; + s-=sprtH-1; + if(s<0) {s=0;} + gl_vy[0]=gl_vy[1]=s; + } + + sSprite_ux2=s=gl_ux[0]+sprtW; + if(s) s--; + if(s>255) s=255; + gl_ux[1]=gl_ux[2]=s; + sSprite_vy2=s=gl_vy[0]+sprtH; + if(s) s--; + if(s>255) s=255; + gl_vy[2]=gl_vy[3]=s; + + if(!bUsingTWin) + { + if(sSprite_ux2>256) + {sprtW=256-gl_ux[0];sSprite_ux2=256;sTypeRest+=1;} + if(sSprite_vy2>256) + {sprtH=256-gl_vy[0];sSprite_vy2=256;sTypeRest+=2;} + } + + lx0 = sprtX; + ly0 = sprtY; + + offsetST(); + + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + + if(iOffscreenDrawing) + { + offsetPSX4(); + + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + lx0-=PSXDisplay.DrawOffset.x; + ly0-=PSXDisplay.DrawOffset.y; + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,sprtW,sprtH); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,sprtW,sprtH); + else + DrawSoftwareSprite(baseAddr,sprtW,sprtH,baseAddr[8],baseAddr[9]); + } + } + + SetRenderMode(gpuData[0], TRUE); + SetZMask4SP(); + + if((dwActFixes&1) && gTexFrameName && gTexName==gTexFrameName) + {iSpriteTex=0;return;} + + sSprite_ux2=gl_ux[0]+sprtW; + sSprite_vy2=gl_vy[0]+sprtH; + + assignTextureSprite(); + + if(iFilterType>4) + DrawMultiFilterSprite(); + else + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + + if(bSmallAlpha && iFilterType<=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SetZMask4O(); + } + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + DEFOPAQUEOFF + } + + if(sTypeRest) + { + if(sTypeRest&1) primSprtSRest(baseAddr,1); + if(sTypeRest&2) primSprtSRest(baseAddr,2); + if(sTypeRest==3) primSprtSRest(baseAddr,3); + } + + iSpriteTex=0; + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Poly4 +//////////////////////////////////////////////////////////////////////// + +void primPolyF4(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[4]; + ly1 = sgpuData[5]; + lx2 = sgpuData[6]; + ly2 = sgpuData[7]; + lx3 = sgpuData[8]; + ly3 = sgpuData[9]; + + if(offset4()) return; + + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + + if(iOffscreenDrawing) + { + offsetPSX4(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4F(gpuData[0]); + } + } + + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + vertex[0].c.lcol=gpuData[0];vertex[0].c.col[3]=ubGloColAlpha; + SETCOL(vertex[0]); + + PRIMdrawTri2(&vertex[0], &vertex[1], &vertex[2],&vertex[3]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly4 +//////////////////////////////////////////////////////////////////////// + +void primPolyG4(unsigned char * baseAddr); + +BOOL bDrawOffscreenFrontFF9G4(void) +{ + if(lx0< PSXDisplay.DisplayPosition.x) return FALSE; // must be complete in front + if(lx0> PSXDisplay.DisplayEnd.x) return FALSE; + if(ly0< PSXDisplay.DisplayPosition.y) return FALSE; + if(ly0> PSXDisplay.DisplayEnd.y) return FALSE; + if(lx1< PSXDisplay.DisplayPosition.x) return FALSE; + if(lx1> PSXDisplay.DisplayEnd.x) return FALSE; + if(ly1< PSXDisplay.DisplayPosition.y) return FALSE; + if(ly1> PSXDisplay.DisplayEnd.y) return FALSE; + if(lx2< PSXDisplay.DisplayPosition.x) return FALSE; + if(lx2> PSXDisplay.DisplayEnd.x) return FALSE; + if(ly2< PSXDisplay.DisplayPosition.y) return FALSE; + if(ly2> PSXDisplay.DisplayEnd.y) return FALSE; + if(lx3< PSXDisplay.DisplayPosition.x) return FALSE; + if(lx3> PSXDisplay.DisplayEnd.x) return FALSE; + if(ly3< PSXDisplay.DisplayPosition.y) return FALSE; + if(ly3> PSXDisplay.DisplayEnd.y) return FALSE; + return TRUE; +} + +BOOL bCheckFF9G4(unsigned char * baseAddr) +{ + static unsigned char pFF9G4Cache[32]; + static int iFF9Fix=0; + + if(baseAddr) + { + if(iFF9Fix==0) + { + if(bDrawOffscreenFrontFF9G4()) + { + short *sgpuData = ((short *) pFF9G4Cache); + iFF9Fix=2; + memcpy(pFF9G4Cache,baseAddr,32); + + if(sgpuData[2]==142) + { + sgpuData[2] +=65; + sgpuData[10]+=65; + } + return TRUE; + } + else iFF9Fix=1; + } + return FALSE; + } + + if(iFF9Fix==2) + { + int labr=GlobalTextABR; + GlobalTextABR = 1; + primPolyG4(pFF9G4Cache); + GlobalTextABR = labr; + } + iFF9Fix = 0; + + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +void primPolyG4(unsigned char * baseAddr) +{ + uint32_t *gpuData = (uint32_t *)baseAddr; + short *sgpuData = ((short *)baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[6]; + ly1 = sgpuData[7]; + lx2 = sgpuData[10]; + ly2 = sgpuData[11]; + lx3 = sgpuData[14]; + ly3 = sgpuData[15]; + + if(offset4()) return; + + bDrawTextured = FALSE; + bDrawSmoothShaded = TRUE; + SetRenderState(gpuData[0]); + + if(iOffscreenDrawing) + { + offsetPSX4(); + + if((dwActFixes&512) && bCheckFF9G4(baseAddr)) return; + + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4G(gpuData[0], gpuData[2], gpuData[4], gpuData[6]); + } + } + + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + vertex[0].c.lcol=gpuData[0]; + vertex[1].c.lcol=gpuData[2]; + vertex[2].c.lcol=gpuData[4]; + vertex[3].c.lcol=gpuData[6]; + + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloAlpha; + + + PRIMdrawGouraudTri2Color(&vertex[0],&vertex[1], &vertex[2], &vertex[3]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Texture3 +//////////////////////////////////////////////////////////////////////// + +BOOL DoLineCheck(uint32_t *gpuData) +{ + BOOL bQuad=FALSE;short dx,dy; + + if(lx0==lx1) + { + dx=lx0-lx2;if(dx<0) dx=-dx; + + if(ly1==ly2) + { + dy=ly1-ly0;if(dy<0) dy=-dy; + if(dx<=1) + { + vertex[3]=vertex[2]; + vertex[2]=vertex[0]; + vertex[2].x=vertex[3].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[2]; + vertex[2].y=vertex[0].y; + } + else return FALSE; + + bQuad=TRUE; + } + else + if(ly0==ly2) + { + dy=ly0-ly1;if(dy<0) dy=-dy; + if(dx<=1) + { + vertex[3]=vertex[1]; + vertex[3].x=vertex[2].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[2]; + vertex[3].y=vertex[1].y; + } + else return FALSE; + + bQuad=TRUE; + } + } + + if(lx0==lx2) + { + dx=lx0-lx1;if(dx<0) dx=-dx; + + if(ly2==ly1) + { + dy=ly2-ly0;if(dy<0) dy=-dy; + if(dx<=1) + { + vertex[3]=vertex[1]; + vertex[1]=vertex[0]; + vertex[1].x=vertex[3].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[1]; + vertex[1].y=vertex[0].y; + } + else return FALSE; + + bQuad=TRUE; + } + else + if(ly0==ly1) + { + dy=ly2-ly0;if(dy<0) dy=-dy; + if(dx<=1) + { + vertex[3]=vertex[2]; + vertex[3].x=vertex[1].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[1]; + vertex[3].y=vertex[2].y; + } + else return FALSE; + + bQuad=TRUE; + } + } + + if(lx1==lx2) + { + dx=lx1-lx0;if(dx<0) dx=-dx; + + if(ly1==ly0) + { + dy=ly1-ly2;if(dy<0) dy=-dy; + + if(dx<=1) + { + vertex[3]=vertex[2]; + vertex[2].x=vertex[0].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[2]; + vertex[2]=vertex[0]; + vertex[2].y=vertex[3].y; + } + else return FALSE; + + bQuad=TRUE; + } + else + if(ly2==ly0) + { + dy=ly2-ly1;if(dy<0) dy=-dy; + + if(dx<=1) + { + vertex[3]=vertex[1]; + vertex[1].x=vertex[0].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[1]; + vertex[1]=vertex[0]; + vertex[1].y=vertex[3].y; + } + else return FALSE; + + bQuad=TRUE; + } + } + + if(!bQuad) return FALSE; + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + DEFOPAQUEOFF + } + + iDrawnSomething=1; + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +void primPolyFT3(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[6]; + ly1 = sgpuData[7]; + lx2 = sgpuData[10]; + ly2 = sgpuData[11]; + + if(offset3()) return; + + // do texture UV coordinates stuff + gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; + gl_vy[0]=gl_vy[3]=baseAddr[9];//(gpuData[2]>>8)&0xff; + gl_ux[1]=baseAddr[16];//gpuData[4]&0xff; + gl_vy[1]=baseAddr[17];//(gpuData[4]>>8)&0xff; + gl_ux[2]=baseAddr[24];//gpuData[6]&0xff; + gl_vy[2]=baseAddr[25];//(gpuData[6]>>8)&0xff; + + UpdateGlobalTP((unsigned short)(gpuData[4]>>16)); + ulClutID=gpuData[2]>>16; + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + + if(iOffscreenDrawing) + { + offsetPSX3(); + if(bDrawOffscreen3()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + drawPoly3FT(baseAddr); + } + } + + SetRenderMode(gpuData[0], TRUE); + SetZMask3(); + + assignTexture3(); + + if(!(dwActFixes&0x10)) + { + if(DoLineCheck(gpuData)) return; + } + + PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); + } + + if(ubOpaqueDraw) + { + SetZMask3O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); + DEFOPAQUEOFF + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Texture4 +//////////////////////////////////////////////////////////////////////// + +#define ST_FAC 255.99f + +void RectTexAlign(void) +{ + int UFlipped = FALSE; + int VFlipped = FALSE; + + if(gTexName==gTexFrameName) return; + + if(ly0==ly1) + { + if(!((lx1==lx3 && ly3==ly2 && lx2==lx0) || + (lx1==lx2 && ly2==ly3 && lx3==lx0))) + return; + + if(ly0 vertex[2].tow) + VFlipped = 1; + } + else + { + if (vertex[0].tow < vertex[2].tow) + VFlipped = 2; + } + } + else + if(ly0==ly2) + { + if(!((lx2==lx3 && ly3==ly1 && lx1==lx0) || + (lx2==lx1 && ly1==ly3 && lx3==lx0))) + return; + + if(ly0 vertex[1].tow) + VFlipped = 3; + } + else + { + if (vertex[0].tow < vertex[1].tow) + VFlipped = 4; + } + } + else + if(ly0==ly3) + { + if(!((lx3==lx2 && ly2==ly1 && lx1==lx0) || + (lx3==lx1 && ly1==ly2 && lx2==lx0))) + return; + + if(ly0 vertex[1].tow) + VFlipped = 5; + } + else + { + if (vertex[0].tow < vertex[1].tow) + VFlipped = 6; + } + } + else return; + + if(lx0==lx1) + { + if(lx0 vertex[2].sow) + UFlipped = 1; + } + else + { + if (vertex[0].sow < vertex[2].sow) + UFlipped = 2; + } + } + else + if(lx0==lx2) + { + if(lx0 vertex[1].sow) + UFlipped = 3; + } + else + { + if (vertex[0].sow < vertex[1].sow) + UFlipped = 4; + } + } + else + if(lx0==lx3) + { + if(lx0 vertex[1].sow) + UFlipped = 5; + } + else + { + if (vertex[0].sow < vertex[1].sow) + UFlipped = 6; + } + } + + if (UFlipped) + { +#ifdef OWNSCALE + if(bUsingTWin) + { + switch(UFlipped) + { + case 1: + vertex[2].sow+=0.95f/TWin.UScaleFactor; + vertex[3].sow+=0.95f/TWin.UScaleFactor; + break; + case 2: + vertex[0].sow+=0.95f/TWin.UScaleFactor; + vertex[1].sow+=0.95f/TWin.UScaleFactor; + break; + case 3: + vertex[1].sow+=0.95f/TWin.UScaleFactor; + vertex[3].sow+=0.95f/TWin.UScaleFactor; + break; + case 4: + vertex[0].sow+=0.95f/TWin.UScaleFactor; + vertex[2].sow+=0.95f/TWin.UScaleFactor; + break; + case 5: + vertex[1].sow+=0.95f/TWin.UScaleFactor; + vertex[2].sow+=0.95f/TWin.UScaleFactor; + break; + case 6: + vertex[0].sow+=0.95f/TWin.UScaleFactor; + vertex[3].sow+=0.95f/TWin.UScaleFactor; + break; + } + } + else + { + switch(UFlipped) + { + case 1: + vertex[2].sow+=1.0f/ST_FAC; + vertex[3].sow+=1.0f/ST_FAC; + break; + case 2: + vertex[0].sow+=1.0f/ST_FAC; + vertex[1].sow+=1.0f/ST_FAC; + break; + case 3: + vertex[1].sow+=1.0f/ST_FAC; + vertex[3].sow+=1.0f/ST_FAC; + break; + case 4: + vertex[0].sow+=1.0f/ST_FAC; + vertex[2].sow+=1.0f/ST_FAC; + break; + case 5: + vertex[1].sow+=1.0f/ST_FAC; + vertex[2].sow+=1.0f/ST_FAC; + break; + case 6: + vertex[0].sow+=1.0f/ST_FAC; + vertex[3].sow+=1.0f/ST_FAC; + break; + } + } +#else + if(bUsingTWin) + { + switch(UFlipped) + { + case 1: + vertex[2].sow+=1.0f/TWin.UScaleFactor; + vertex[3].sow+=1.0f/TWin.UScaleFactor; + break; + case 2: + vertex[0].sow+=1.0f/TWin.UScaleFactor; + vertex[1].sow+=1.0f/TWin.UScaleFactor; + break; + case 3: + vertex[1].sow+=1.0f/TWin.UScaleFactor; + vertex[3].sow+=1.0f/TWin.UScaleFactor; + break; + case 4: + vertex[0].sow+=1.0f/TWin.UScaleFactor; + vertex[2].sow+=1.0f/TWin.UScaleFactor; + break; + case 5: + vertex[1].sow+=1.0f/TWin.UScaleFactor; + vertex[2].sow+=1.0f/TWin.UScaleFactor; + break; + case 6: + vertex[0].sow+=1.0f/TWin.UScaleFactor; + vertex[3].sow+=1.0f/TWin.UScaleFactor; + break; + } + } + else + { + switch(UFlipped) + { + case 1: + vertex[2].sow+=1.0f; + vertex[3].sow+=1.0f; + break; + case 2: + vertex[0].sow+=1.0f; + vertex[1].sow+=1.0f; + break; + case 3: + vertex[1].sow+=1.0f; + vertex[3].sow+=1.0f; + break; + case 4: + vertex[0].sow+=1.0f; + vertex[2].sow+=1.0f; + break; + case 5: + vertex[1].sow+=1.0f; + vertex[2].sow+=1.0f; + break; + case 6: + vertex[0].sow+=1.0f; + vertex[3].sow+=1.0f; + break; + } + } +#endif + } + + if (VFlipped) + { +#ifdef OWNSCALE + if(bUsingTWin) + { + switch(VFlipped) + { + case 1: + vertex[2].tow+=0.95f/TWin.VScaleFactor; + vertex[3].tow+=0.95f/TWin.VScaleFactor; + break; + case 2: + vertex[0].tow+=0.95f/TWin.VScaleFactor; + vertex[1].tow+=0.95f/TWin.VScaleFactor; + break; + case 3: + vertex[1].tow+=0.95f/TWin.VScaleFactor; + vertex[3].tow+=0.95f/TWin.VScaleFactor; + break; + case 4: + vertex[0].tow+=0.95f/TWin.VScaleFactor; + vertex[2].tow+=0.95f/TWin.VScaleFactor; + break; + case 5: + vertex[1].tow+=0.95f/TWin.VScaleFactor; + vertex[2].tow+=0.95f/TWin.VScaleFactor; + break; + case 6: + vertex[0].tow+=0.95f/TWin.VScaleFactor; + vertex[3].tow+=0.95f/TWin.VScaleFactor; + break; + } + } + else + { + switch(VFlipped) + { + case 1: + vertex[2].tow+=1.0f/ST_FAC; + vertex[3].tow+=1.0f/ST_FAC; + break; + case 2: + vertex[0].tow+=1.0f/ST_FAC; + vertex[1].tow+=1.0f/ST_FAC; + break; + case 3: + vertex[1].tow+=1.0f/ST_FAC; + vertex[3].tow+=1.0f/ST_FAC; + break; + case 4: + vertex[0].tow+=1.0f/ST_FAC; + vertex[2].tow+=1.0f/ST_FAC; + break; + case 5: + vertex[1].tow+=1.0f/ST_FAC; + vertex[2].tow+=1.0f/ST_FAC; + break; + case 6: + vertex[0].tow+=1.0f/ST_FAC; + vertex[3].tow+=1.0f/ST_FAC; + break; + } + } +#else + if(bUsingTWin) + { + switch(VFlipped) + { + case 1: + vertex[2].tow+=1.0f/TWin.VScaleFactor; + vertex[3].tow+=1.0f/TWin.VScaleFactor; + break; + case 2: + vertex[0].tow+=1.0f/TWin.VScaleFactor; + vertex[1].tow+=1.0f/TWin.VScaleFactor; + break; + case 3: + vertex[1].tow+=1.0f/TWin.VScaleFactor; + vertex[3].tow+=1.0f/TWin.VScaleFactor; + break; + case 4: + vertex[0].tow+=1.0f/TWin.VScaleFactor; + vertex[2].tow+=1.0f/TWin.VScaleFactor; + break; + case 5: + vertex[1].tow+=1.0f/TWin.VScaleFactor; + vertex[2].tow+=1.0f/TWin.VScaleFactor; + break; + case 6: + vertex[0].tow+=1.0f/TWin.VScaleFactor; + vertex[3].tow+=1.0f/TWin.VScaleFactor; + break; + } + } + else + { + switch(VFlipped) + { + case 1: + vertex[2].tow+=1.0f; + vertex[3].tow+=1.0f; + break; + case 2: + vertex[0].tow+=1.0f; + vertex[1].tow+=1.0f; + break; + case 3: + vertex[1].tow+=1.0f; + vertex[3].tow+=1.0f; + break; + case 4: + vertex[0].tow+=1.0f; + vertex[2].tow+=1.0f; + break; + case 5: + vertex[1].tow+=1.0f; + vertex[2].tow+=1.0f; + break; + case 6: + vertex[0].tow+=1.0f; + vertex[3].tow+=1.0f; + break; + } + } +#endif + } + +} + +void primPolyFT4(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *)baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[6]; + ly1 = sgpuData[7]; + lx2 = sgpuData[10]; + ly2 = sgpuData[11]; + lx3 = sgpuData[14]; + ly3 = sgpuData[15]; + + if(offset4()) return; + + gl_vy[0]=baseAddr[9];//((gpuData[2]>>8)&0xff); + gl_vy[1]=baseAddr[17];//((gpuData[4]>>8)&0xff); + gl_vy[2]=baseAddr[25];//((gpuData[6]>>8)&0xff); + gl_vy[3]=baseAddr[33];//((gpuData[8]>>8)&0xff); + + gl_ux[0]=baseAddr[8];//(gpuData[2]&0xff); + gl_ux[1]=baseAddr[16];//(gpuData[4]&0xff); + gl_ux[2]=baseAddr[24];//(gpuData[6]&0xff); + gl_ux[3]=baseAddr[32];//(gpuData[8]&0xff); + + UpdateGlobalTP((unsigned short)(gpuData[4]>>16)); + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + + if(iOffscreenDrawing) + { + offsetPSX4(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + drawPoly4FT(baseAddr); + } + } + + SetRenderMode(gpuData[0], TRUE); + + SetZMask4(); + + assignTexture4(); + + RectTexAlign(); + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + + if(bSmallAlpha && iFilterType<=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SetZMask4O(); + } + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + DEFOPAQUEOFF + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Texture3 +//////////////////////////////////////////////////////////////////////// + +void primPolyGT3(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[8]; + ly1 = sgpuData[9]; + lx2 = sgpuData[14]; + ly2 = sgpuData[15]; + + if(offset3()) return; + + // do texture stuff + gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; + gl_vy[0]=gl_vy[3]=baseAddr[9];//(gpuData[2]>>8)&0xff; + gl_ux[1]=baseAddr[20];//gpuData[5]&0xff; + gl_vy[1]=baseAddr[21];//(gpuData[5]>>8)&0xff; + gl_ux[2]=baseAddr[32];//gpuData[8]&0xff; + gl_vy[2]=baseAddr[33];//(gpuData[8]>>8)&0xff; + + UpdateGlobalTP((unsigned short)(gpuData[5]>>16)); + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = TRUE; + SetRenderState(gpuData[0]); + + if(iOffscreenDrawing) + { + offsetPSX3(); + if(bDrawOffscreen3()) + { + InvalidateTextureAreaEx(); + drawPoly3GT(baseAddr); + } + } + + SetRenderMode(gpuData[0], FALSE); + SetZMask3(); + + assignTexture3(); + + if(bDrawNonShaded) + { + //if(!bUseMultiPass) vertex[0].lcol=DoubleBGR2RGB(gpuData[0]); else vertex[0].lcol=gpuData[0]; + // eat this... + if(bGLBlend) vertex[0].c.lcol=0x7f7f7f; + else vertex[0].c.lcol=0xffffff; + vertex[0].c.col[3]=ubGloAlpha; + SETCOL(vertex[0]); + + PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); + + if(ubOpaqueDraw) + { + SetZMask3O(); + DEFOPAQUEON + PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); + DEFOPAQUEOFF + } + return; + } + + if(!bUseMultiPass && !bGLBlend) + { + vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); + vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); + vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); + } + else + { + vertex[0].c.lcol=gpuData[0]; + vertex[1].c.lcol=gpuData[3]; + vertex[2].c.lcol=gpuData[6]; + } + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=ubGloAlpha; + + PRIMdrawTexGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); + } + + if(ubOpaqueDraw) + { + SetZMask3O(); + if(bUseMultiPass) + { + vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); + vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); + vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=ubGloAlpha; + } + DEFOPAQUEON + PRIMdrawTexGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); + DEFOPAQUEOFF + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly3 +//////////////////////////////////////////////////////////////////////// + +void primPolyG3(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *)baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[6]; + ly1 = sgpuData[7]; + lx2 = sgpuData[10]; + ly2 = sgpuData[11]; + + if(offset3()) return; + + bDrawTextured = FALSE; + bDrawSmoothShaded = TRUE; + SetRenderState(gpuData[0]); + + if(iOffscreenDrawing) + { + offsetPSX3(); + if(bDrawOffscreen3()) + { + InvalidateTextureAreaEx(); + drawPoly3G(gpuData[0], gpuData[2], gpuData[4]); + } + } + + SetRenderMode(gpuData[0], FALSE); + SetZMask3NT(); + + vertex[0].c.lcol=gpuData[0]; + vertex[1].c.lcol=gpuData[2]; + vertex[2].c.lcol=gpuData[4]; + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=ubGloColAlpha; + + PRIMdrawGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Texture4 +//////////////////////////////////////////////////////////////////////// + +void primPolyGT4(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *)baseAddr); + short *sgpuData = ((short *)baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[8]; + ly1 = sgpuData[9]; + lx2 = sgpuData[14]; + ly2 = sgpuData[15]; + lx3 = sgpuData[20]; + ly3 = sgpuData[21]; + + if(offset4()) return; + + // do texture stuff + gl_ux[0]=baseAddr[8];//gpuData[2]&0xff; + gl_vy[0]=baseAddr[9];//(gpuData[2]>>8)&0xff; + gl_ux[1]=baseAddr[20];//gpuData[5]&0xff; + gl_vy[1]=baseAddr[21];//(gpuData[5]>>8)&0xff; + gl_ux[2]=baseAddr[32];//gpuData[8]&0xff; + gl_vy[2]=baseAddr[33];//(gpuData[8]>>8)&0xff; + gl_ux[3]=baseAddr[44];//gpuData[11]&0xff; + gl_vy[3]=baseAddr[45];//(gpuData[11]>>8)&0xff; + + UpdateGlobalTP((unsigned short)(gpuData[5]>>16)); + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = TRUE; + SetRenderState(gpuData[0]); + + if(iOffscreenDrawing) + { + offsetPSX4(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4GT(baseAddr); + } + } + + SetRenderMode(gpuData[0], FALSE); + SetZMask4(); + + assignTexture4(); + + RectTexAlign(); + + if(bDrawNonShaded) + { + //if(!bUseMultiPass) vertex[0].lcol=DoubleBGR2RGB(gpuData[0]); else vertex[0].lcol=gpuData[0]; + if(bGLBlend) vertex[0].c.lcol=0x7f7f7f; + else vertex[0].c.lcol=0xffffff; + vertex[0].c.col[3]=ubGloAlpha; + SETCOL(vertex[0]); + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + + if(ubOpaqueDraw) + { + SetZMask4O(); + ubGloAlpha=ubGloColAlpha=0xff; + DEFOPAQUEON + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + DEFOPAQUEOFF + } + return; + } + + if(!bUseMultiPass && !bGLBlend) + { + vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); + vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); + vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); + vertex[3].c.lcol=DoubleBGR2RGB(gpuData[9]); + } + else + { + vertex[0].c.lcol=gpuData[0]; + vertex[1].c.lcol=gpuData[3]; + vertex[2].c.lcol=gpuData[6]; + vertex[3].c.lcol=gpuData[9]; + } + + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloAlpha; + + PRIMdrawTexGouraudTriColorQuad(&vertex[0], &vertex[1], &vertex[3],&vertex[2]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexGouraudTriColorQuad(&vertex[0], &vertex[1], &vertex[3],&vertex[2]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) + { + vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); + vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); + vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); + vertex[3].c.lcol=DoubleBGR2RGB(gpuData[9]); + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloAlpha; + } + ubGloAlpha=ubGloColAlpha=0xff; + DEFOPAQUEON + PRIMdrawTexGouraudTriColorQuad(&vertex[0], &vertex[1], &vertex[3],&vertex[2]); + DEFOPAQUEOFF + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly3 +//////////////////////////////////////////////////////////////////////// + +void primPolyF3(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[4]; + ly1 = sgpuData[5]; + lx2 = sgpuData[6]; + ly2 = sgpuData[7]; + + if(offset3()) return; + + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + + if(iOffscreenDrawing) + { + offsetPSX3(); + if(bDrawOffscreen3()) + { + InvalidateTextureAreaEx(); + drawPoly3F(gpuData[0]); + } + } + + SetRenderMode(gpuData[0], FALSE); + SetZMask3NT(); + + vertex[0].c.lcol=gpuData[0]; + vertex[0].c.col[3]=ubGloColAlpha; + SETCOL(vertex[0]); + + PRIMdrawTri(&vertex[0], &vertex[1], &vertex[2]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: skipping shaded polylines +//////////////////////////////////////////////////////////////////////// + +void primLineGSkip(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + int iMax=255; + int i=2; + + lx1 = sgpuData[2]; + ly1 = sgpuData[3]; + + while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=4)) + { + i++; + + ly1 = (short)((gpuData[i]>>16) & 0xffff); + lx1 = (short)(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; + short cx0,cx1,cy0,cy1;int i;BOOL bDraw=TRUE; + + bDrawTextured = FALSE; + bDrawSmoothShaded = TRUE; + SetRenderState(gpuData[0]); + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + vertex[0].c.lcol=vertex[3].c.lcol=gpuData[0]; + vertex[0].c.col[3]=vertex[3].c.col[3]=ubGloColAlpha; + ly1 = (short)((gpuData[1]>>16) & 0xffff); + lx1 = (short)(gpuData[1] & 0xffff); + + i=2; + + //while((gpuData[i]>>24)!=0x55) + //while((gpuData[i]&0x50000000)!=0x50000000) + // currently best way to check for poly line end: + while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=4)) + { + ly0 = ly1;lx0=lx1; + vertex[1].c.lcol=vertex[2].c.lcol=vertex[0].c.lcol; + vertex[0].c.lcol=vertex[3].c.lcol=gpuData[i]; + vertex[0].c.col[3]=vertex[3].c.col[3]=ubGloColAlpha; + + i++; + + ly1 = (short)((gpuData[i]>>16) & 0xffff); + lx1 = (short)(gpuData[i] & 0xffff); + + if(offsetline()) bDraw=FALSE; else bDraw=TRUE; + + if (bDraw && ((lx0 != lx1) || (ly0 != ly1))) + { + if(iOffscreenDrawing) + { + cx0=lx0;cx1=lx1;cy0=ly0;cy1=ly1; + offsetPSXLine(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4G(gpuData[i-3],gpuData[i-1],gpuData[i-3],gpuData[i-1]); + } + lx0=cx0;lx1=cx1;ly0=cy0;ly1=cy1; + } + + PRIMdrawGouraudLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + i++; + + if(i>iMax) break; + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: shaded polyline2 +//////////////////////////////////////////////////////////////////////// + +void primLineG2(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[6]; + ly1 = sgpuData[7]; + + vertex[0].c.lcol=vertex[3].c.lcol=gpuData[0]; + vertex[1].c.lcol=vertex[2].c.lcol=gpuData[2]; + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloColAlpha; + + bDrawTextured = FALSE; + bDrawSmoothShaded = TRUE; + + if((lx0 == lx1) && (ly0 == ly1)) return; + + if(offsetline()) return; + + SetRenderState(gpuData[0]); + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + if(iOffscreenDrawing) + { + offsetPSXLine(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4G(gpuData[0],gpuData[2],gpuData[0],gpuData[2]); + } + } + + //if(ClipVertexList4()) + PRIMdrawGouraudLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: skipping flat polylines +//////////////////////////////////////////////////////////////////////// + +void primLineFSkip(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + int i=2,iMax=255; + + ly1 = (short)((gpuData[1]>>16) & 0xffff); + lx1 = (short)(gpuData[1] & 0xffff); + + while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=3)) + { + ly1 = (short)((gpuData[i]>>16) & 0xffff); + lx1 = (short)(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 cx0,cx1,cy0,cy1;int i; + + iMax=255; + + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + vertex[0].c.lcol=gpuData[0]; + vertex[0].c.col[3]=ubGloColAlpha; + + ly1 = (short)((gpuData[1]>>16) & 0xffff); + lx1 = (short)(gpuData[1] & 0xffff); + + i=2; + +// while(!(gpuData[i]&0x40000000)) +// while((gpuData[i]>>24)!=0x55) +// while((gpuData[i]&0x50000000)!=0x50000000) +// currently best way to check for poly line end: + while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=3)) + { + ly0 = ly1;lx0=lx1; + ly1 = (short)((gpuData[i]>>16) & 0xffff); + lx1 = (short)(gpuData[i] & 0xffff); + + if(!offsetline()) + { + if(iOffscreenDrawing) + { + cx0=lx0;cx1=lx1;cy0=ly0;cy1=ly1; + offsetPSXLine(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4F(gpuData[0]); + } + lx0=cx0;lx1=cx1;ly0=cy0;ly1=cy1; + } + PRIMdrawFlatLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + + i++;if(i>iMax) break; + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: drawing flat polyline2 +//////////////////////////////////////////////////////////////////////// + +void primLineF2(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[4]; + ly1 = sgpuData[5]; + + if(offsetline()) return; + + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + vertex[0].c.lcol=gpuData[0]; + vertex[0].c.col[3]=ubGloColAlpha; + + if(iOffscreenDrawing) + { + offsetPSXLine(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4F(gpuData[0]); + } + } + + //if(ClipVertexList4()) + PRIMdrawFlatLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: well, easiest command... not implemented +//////////////////////////////////////////////////////////////////////// + +void primNI(unsigned char *bA) +{ +} + +//////////////////////////////////////////////////////////////////////// +// cmd func ptr table +//////////////////////////////////////////////////////////////////////// + +void (*primTableJ[256])(unsigned char *) = +{ + // 00 + primNI,primNI,primBlkFill,primNI,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 +}; + +//////////////////////////////////////////////////////////////////////// +// cmd func ptr table for skipping +//////////////////////////////////////////////////////////////////////// + +void (*primTableSkip[256])(unsigned char *) = +{ + // 00 + primNI,primNI,primBlkFill,primNI,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 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 28 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 30 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 38 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 40 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 48 + primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip, + // 50 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 58 + primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip, + // 60 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 68 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 70 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 78 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 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/peopsxgl/soft.c b/plugins/peopsxgl/soft.c index 1ab93f07..9f10a2a0 100644 --- a/plugins/peopsxgl/soft.c +++ b/plugins/peopsxgl/soft.c @@ -1,8409 +1,8407 @@ -/*************************************************************************** - soft.c - description - ------------------- - begin : Sun Oct 28 2001 - copyright : (C) 2001 by Pete Bernert - web : www.pbernert.com - ***************************************************************************/ - -/*************************************************************************** - * * - * 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 "stdafx.h" - -#define _IN_SOFT - -#include "externals.h" -#include "soft.h" - -int iDither = 0; - -//////////////////////////////////////////////////////////////////////////////////// -// "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 -//////////////////////////////////////////////////////////////////////////////////// - -short g_m1 = 255, g_m2 = 255, g_m3 = 255; -short DrawSemiTrans = FALSE; -short Ymin; -short Ymax; - -short ly0, lx0, ly1, lx1, ly2, lx2, ly3, lx3; // global psx vertex coords -int GlobalTextAddrX, GlobalTextAddrY, GlobalTextTP; -int GlobalTextREST, GlobalTextABR, GlobalTextPAGE; - -//////////////////////////////////////////////////////////////////////// -// POLYGON OFFSET FUNCS -//////////////////////////////////////////////////////////////////////// - -void offsetPSXLine(void) -{ - short x0,x1,y0,y1,dx,dy;float px,py; - - x0 = lx0+1+PSXDisplay.DrawOffset.x; - x1 = lx1+1+PSXDisplay.DrawOffset.x; - y0 = ly0+1+PSXDisplay.DrawOffset.y; - y1 = ly1+1+PSXDisplay.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(dxdy) px= 0.5f; - else if(dx=0) - { - py=0.5f; - dx=-dx; - if(dx>dy) px=-0.5f; - else if(dxdy) py=-0.5f; - else if(dx> 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++; - - *pdest=((unsigned short)b<<10) | - ((unsigned short)g<<5) | - (unsigned short)r | sM; -} - -///////////////////////////////////////////////////////////////// - -static __inline void GetShadeTransCol_Dither(unsigned short *pdest, int m1, int m2, int m3) -{ - int r,g,b; - - if (bCheckMask && *pdest & 0x8000) return; - - if (DrawSemiTrans) - { - r=((XCOL1D(*pdest))<<3); - b=((XCOL2D(*pdest))<<3); - g=((XCOL3D(*pdest))<<3); - - if(GlobalTextABR==0) - { - r=(r>>1)+(m1>>1); - b=(b>>1)+(m2>>1); - g=(g>>1)+(m3>>1); - } - else - if(GlobalTextABR==1) - { - r+=m1; - b+=m2; - g+=m3; - } - else - if(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,sSetMask); -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetShadeTransCol(unsigned short * pdest,unsigned short color) -{ - if(bCheckMask && *pdest&0x8000) return; - - if(DrawSemiTrans) - { - int r,g,b; - - if(GlobalTextABR==0) - { - *pdest=((((*pdest)&0x7bde)>>1)+(((color)&0x7bde)>>1))|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(GlobalTextABR==1) - { - r=(XCOL1(*pdest))+((XCOL1(color))); - b=(XCOL2(*pdest))+((XCOL2(color))); - g=(XCOL3(*pdest))+((XCOL3(color))); - } - else - if(GlobalTextABR==2) - { - r=(XCOL1(*pdest))-((XCOL1(color))); - b=(XCOL2(*pdest))-((XCOL2(color))); - g=(XCOL3(*pdest))-((XCOL3(color))); - if(r&0x80000000) r=0; - if(b&0x80000000) b=0; - if(g&0x80000000) g=0; - } - else - { -#ifdef HALFBRIGHTMODE3 - r=(XCOL1(*pdest))+((XCOL1(color))>>2); - b=(XCOL2(*pdest))+((XCOL2(color))>>2); - g=(XCOL3(*pdest))+((XCOL3(color))>>2); -#else - r=(XCOL1(*pdest))+((XCOL1(color))>>1); - b=(XCOL2(*pdest))+((XCOL2(color))>>1); - g=(XCOL3(*pdest))+((XCOL3(color))>>1); -#endif - } - - if(r&0x7FFFFFE0) r=0x1f; - if(b&0x7FFFFC00) b=0x3e0; - if(g&0x7FFF8000) g=0x7c00; - - *pdest=(XPSXCOL(r,g,b))|sSetMask;//0x8000; - } - else *pdest=color|sSetMask; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetShadeTransCol32(uint32_t *pdest, uint32_t color) -{ - if (DrawSemiTrans) - { - int r,g,b; - - if(GlobalTextABR==0) - { - if(!bCheckMask) - { - *pdest=((((*pdest)&0x7bde7bde)>>1)+(((color)&0x7bde7bde)>>1))|lSetMask;//0x80008000; - return; - } - r=(X32ACOL1(*pdest)>>1)+((X32ACOL1(color))>>1); - b=(X32ACOL2(*pdest)>>1)+((X32ACOL2(color))>>1); - g=(X32ACOL3(*pdest)>>1)+((X32ACOL3(color))>>1); - } - else - if(GlobalTextABR==1) - { - r=(X32COL1(*pdest))+((X32COL1(color))); - b=(X32COL2(*pdest))+((X32COL2(color))); - g=(X32COL3(*pdest))+((X32COL3(color))); - } - else - if(GlobalTextABR==2) - { - int sr,sb,sg,src,sbc,sgc,c; - src=XCOL1(color);sbc=XCOL2(color);sgc=XCOL3(color); - c=(*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=((int)sr)<<16;b=((int)sb)<<11;g=((int)sg)<<6; - c=LOWORD(*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(*pdest))+((X32BCOL1(color))>>2); - b=(X32COL2(*pdest))+((X32BCOL2(color))>>2); - g=(X32COL3(*pdest))+((X32BCOL3(color))>>2); -#else - r=(X32COL1(*pdest))+((X32ACOL1(color))>>1); - b=(X32COL2(*pdest))+((X32ACOL2(color))>>1); - g=(X32COL3(*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(bCheckMask) - { - uint32_t ma=*pdest; - *pdest=(X32PSXCOL(r,g,b))|lSetMask;//0x80008000; - if(ma&0x80000000) *pdest=(ma&0xFFFF0000)|(*pdest&0xFFFF); - if(ma&0x00008000) *pdest=(ma&0xFFFF) |(*pdest&0xFFFF0000); - return; - } - *pdest=(X32PSXCOL(r,g,b))|lSetMask;//0x80008000; - } - else - { - if(bCheckMask) - { - uint32_t ma=*pdest; - *pdest=color|lSetMask;//0x80008000; - if(ma&0x80000000) *pdest=(ma&0xFFFF0000)|(*pdest&0xFFFF); - if(ma&0x00008000) *pdest=(ma&0xFFFF) |(*pdest&0xFFFF0000); - return; - } - - *pdest=color|lSetMask;//0x80008000; - } -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColG(unsigned short * pdest,unsigned short color) -{ - int r,g,b;unsigned short l; - - if(color==0) return; - - if(bCheckMask && *pdest&0x8000) return; - - l=sSetMask|(color&0x8000); - - if(DrawSemiTrans && (color&0x8000)) - { - if(GlobalTextABR==0) - { - unsigned short d; - d =((*pdest)&0x7bde)>>1; - color =((color) &0x7bde)>>1; - r=(XCOL1(d))+((((XCOL1(color)))* g_m1)>>7); - b=(XCOL2(d))+((((XCOL2(color)))* g_m2)>>7); - g=(XCOL3(d))+((((XCOL3(color)))* g_m3)>>7); - -/* - r=(XCOL1(*pdest)>>1)+((((XCOL1(color))>>1)* g_m1)>>7); - b=(XCOL2(*pdest)>>1)+((((XCOL2(color))>>1)* g_m2)>>7); - g=(XCOL3(*pdest)>>1)+((((XCOL3(color))>>1)* g_m3)>>7); -*/ - } - else - if(GlobalTextABR==1) - { - r=(XCOL1(*pdest))+((((XCOL1(color)))* g_m1)>>7); - b=(XCOL2(*pdest))+((((XCOL2(color)))* g_m2)>>7); - g=(XCOL3(*pdest))+((((XCOL3(color)))* g_m3)>>7); - } - else - if(GlobalTextABR==2) - { - r=(XCOL1(*pdest))-((((XCOL1(color)))* g_m1)>>7); - b=(XCOL2(*pdest))-((((XCOL2(color)))* g_m2)>>7); - g=(XCOL3(*pdest))-((((XCOL3(color)))* g_m3)>>7); - if(r&0x80000000) r=0; - if(b&0x80000000) b=0; - if(g&0x80000000) g=0; - } - else - { -#ifdef HALFBRIGHTMODE3 - r=(XCOL1(*pdest))+((((XCOL1(color))>>2)* g_m1)>>7); - b=(XCOL2(*pdest))+((((XCOL2(color))>>2)* g_m2)>>7); - g=(XCOL3(*pdest))+((((XCOL3(color))>>2)* g_m3)>>7); -#else - r=(XCOL1(*pdest))+((((XCOL1(color))>>1)* g_m1)>>7); - b=(XCOL2(*pdest))+((((XCOL2(color))>>1)* g_m2)>>7); - g=(XCOL3(*pdest))+((((XCOL3(color))>>1)* g_m3)>>7); -#endif - } - } - else - { - r=((XCOL1(color))* g_m1)>>7; - b=((XCOL2(color))* g_m2)>>7; - g=((XCOL3(color))* g_m3)>>7; - } - - if(r&0x7FFFFFE0) r=0x1f; - if(b&0x7FFFFC00) b=0x3e0; - if(g&0x7FFF8000) g=0x7c00; - - *pdest=(XPSXCOL(r,g,b))|l; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColG_S(unsigned short * pdest,unsigned short color) -{ - int r,g,b;unsigned short l; - - if(color==0) return; - - l=sSetMask|(color&0x8000); - - r=((XCOL1(color))* g_m1)>>7; - b=((XCOL2(color))* g_m2)>>7; - g=((XCOL3(color))* g_m3)>>7; - - if(r&0x7FFFFFE0) r=0x1f; - if(b&0x7FFFFC00) b=0x3e0; - if(g&0x7FFF8000) g=0x7c00; - - *pdest=(XPSXCOL(r,g,b))|l; -} - - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColG_SPR(unsigned short * pdest,unsigned short color) -{ - int r,g,b;unsigned short l; - - if(color==0) return; - - if(bCheckMask && *pdest&0x8000) return; - - l=sSetMask|(color&0x8000); - - if(DrawSemiTrans && (color&0x8000)) - { - if(GlobalTextABR==0) - { - unsigned short d; - d =((*pdest)&0x7bde)>>1; - color =((color) &0x7bde)>>1; - r=(XCOL1(d))+((((XCOL1(color)))* g_m1)>>7); - b=(XCOL2(d))+((((XCOL2(color)))* g_m2)>>7); - g=(XCOL3(d))+((((XCOL3(color)))* g_m3)>>7); - -/* - r=(XCOL1(*pdest)>>1)+((((XCOL1(color))>>1)* g_m1)>>7); - b=(XCOL2(*pdest)>>1)+((((XCOL2(color))>>1)* g_m2)>>7); - g=(XCOL3(*pdest)>>1)+((((XCOL3(color))>>1)* g_m3)>>7); -*/ - } - else - if(GlobalTextABR==1) - { - r=(XCOL1(*pdest))+((((XCOL1(color)))* g_m1)>>7); - b=(XCOL2(*pdest))+((((XCOL2(color)))* g_m2)>>7); - g=(XCOL3(*pdest))+((((XCOL3(color)))* g_m3)>>7); - } - else - if(GlobalTextABR==2) - { - r=(XCOL1(*pdest))-((((XCOL1(color)))* g_m1)>>7); - b=(XCOL2(*pdest))-((((XCOL2(color)))* g_m2)>>7); - g=(XCOL3(*pdest))-((((XCOL3(color)))* g_m3)>>7); - if(r&0x80000000) r=0; - if(b&0x80000000) b=0; - if(g&0x80000000) g=0; - } - else - { -#ifdef HALFBRIGHTMODE3 - r=(XCOL1(*pdest))+((((XCOL1(color))>>2)* g_m1)>>7); - b=(XCOL2(*pdest))+((((XCOL2(color))>>2)* g_m2)>>7); - g=(XCOL3(*pdest))+((((XCOL3(color))>>2)* g_m3)>>7); -#else - r=(XCOL1(*pdest))+((((XCOL1(color))>>1)* g_m1)>>7); - b=(XCOL2(*pdest))+((((XCOL2(color))>>1)* g_m2)>>7); - g=(XCOL3(*pdest))+((((XCOL3(color))>>1)* g_m3)>>7); -#endif - } - } - else - { - r=((XCOL1(color))* g_m1)>>7; - b=((XCOL2(color))* g_m2)>>7; - g=((XCOL3(color))* g_m3)>>7; - } - - if(r&0x7FFFFFE0) r=0x1f; - if(b&0x7FFFFC00) b=0x3e0; - if(g&0x7FFF8000) g=0x7c00; - - *pdest=(XPSXCOL(r,g,b))|l; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColG32(uint32_t *pdest, uint32_t color) -{ - int r,g,b,l; - - if(color==0) return; - - l=lSetMask|(color&0x80008000); - - if(DrawSemiTrans && (color&0x80008000)) - { - if(GlobalTextABR==0) - { - r=((((X32TCOL1(*pdest))+((X32COL1(color)) * g_m1))&0xFF00FF00)>>8); - b=((((X32TCOL2(*pdest))+((X32COL2(color)) * g_m2))&0xFF00FF00)>>8); - g=((((X32TCOL3(*pdest))+((X32COL3(color)) * g_m3))&0xFF00FF00)>>8); - } - else - if(GlobalTextABR==1) - { - r=(X32COL1(*pdest))+(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); - b=(X32COL2(*pdest))+(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); - g=(X32COL3(*pdest))+(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); - } - else - if(GlobalTextABR==2) - { - int t; - r=(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); - t=(*pdest&0x001f0000)-(r&0x003f0000); if(t&0x80000000) t=0; - r=(*pdest&0x0000001f)-(r&0x0000003f); if(r&0x80000000) r=0; - r|=t; - - b=(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); - t=((*pdest>>5)&0x001f0000)-(b&0x003f0000); if(t&0x80000000) t=0; - b=((*pdest>>5)&0x0000001f)-(b&0x0000003f); if(b&0x80000000) b=0; - b|=t; - - g=(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); - t=((*pdest>>10)&0x001f0000)-(g&0x003f0000); if(t&0x80000000) t=0; - g=((*pdest>>10)&0x0000001f)-(g&0x0000003f); if(g&0x80000000) g=0; - g|=t; - } - else - { -#ifdef HALFBRIGHTMODE3 - r=(X32COL1(*pdest))+(((((X32BCOL1(color))>>2)* g_m1)&0xFF80FF80)>>7); - b=(X32COL2(*pdest))+(((((X32BCOL2(color))>>2)* g_m2)&0xFF80FF80)>>7); - g=(X32COL3(*pdest))+(((((X32BCOL3(color))>>2)* g_m3)&0xFF80FF80)>>7); -#else - r=(X32COL1(*pdest))+(((((X32ACOL1(color))>>1)* g_m1)&0xFF80FF80)>>7); - b=(X32COL2(*pdest))+(((((X32ACOL2(color))>>1)* g_m2)&0xFF80FF80)>>7); - g=(X32COL3(*pdest))+(((((X32ACOL3(color))>>1)* g_m3)&0xFF80FF80)>>7); -#endif - } - - if(!(color&0x8000)) - { - r=(r&0xffff0000)|((((X32COL1(color))* g_m1)&0x0000FF80)>>7); - b=(b&0xffff0000)|((((X32COL2(color))* g_m2)&0x0000FF80)>>7); - g=(g&0xffff0000)|((((X32COL3(color))* g_m3)&0x0000FF80)>>7); - } - if(!(color&0x80000000)) - { - r=(r&0xffff)|((((X32COL1(color))* g_m1)&0xFF800000)>>7); - b=(b&0xffff)|((((X32COL2(color))* g_m2)&0xFF800000)>>7); - g=(g&0xffff)|((((X32COL3(color))* g_m3)&0xFF800000)>>7); - } - - } - else - { - r=(((X32COL1(color))* g_m1)&0xFF80FF80)>>7; - b=(((X32COL2(color))* g_m2)&0xFF80FF80)>>7; - g=(((X32COL3(color))* 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(bCheckMask) - { - uint32_t ma=*pdest; - - *pdest=(X32PSXCOL(r,g,b))|l; - - if((color&0xffff)==0 ) *pdest=(ma&0xffff)|(*pdest&0xffff0000); - if((color&0xffff0000)==0) *pdest=(ma&0xffff0000)|(*pdest&0xffff); - if(ma&0x80000000) *pdest=(ma&0xFFFF0000)|(*pdest&0xFFFF); - if(ma&0x00008000) *pdest=(ma&0xFFFF) |(*pdest&0xFFFF0000); - - return; - } - if((color&0xffff)==0 ) {*pdest=(*pdest&0xffff)|(((X32PSXCOL(r,g,b))|l)&0xffff0000);return;} - if((color&0xffff0000)==0) {*pdest=(*pdest&0xffff0000)|(((X32PSXCOL(r,g,b))|l)&0xffff);return;} - - *pdest=(X32PSXCOL(r,g,b))|l; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColG32_S(uint32_t *pdest, uint32_t color) -{ - int r,g,b; - - if(color==0) return; - - r=(((X32COL1(color))* g_m1)&0xFF80FF80)>>7; - b=(((X32COL2(color))* g_m2)&0xFF80FF80)>>7; - g=(((X32COL3(color))* 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) {*pdest=(*pdest&0xffff)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff0000);return;} - if((color&0xffff0000)==0) {*pdest=(*pdest&0xffff0000)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff);return;} - - *pdest=(X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000); -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColG32_SPR(uint32_t *pdest, uint32_t color) -{ - int r,g,b; - - if(color==0) return; - - if(DrawSemiTrans && (color&0x80008000)) - { - if(GlobalTextABR==0) - { - r=((((X32TCOL1(*pdest))+((X32COL1(color)) * g_m1))&0xFF00FF00)>>8); - b=((((X32TCOL2(*pdest))+((X32COL2(color)) * g_m2))&0xFF00FF00)>>8); - g=((((X32TCOL3(*pdest))+((X32COL3(color)) * g_m3))&0xFF00FF00)>>8); - } - else - if(GlobalTextABR==1) - { - r=(X32COL1(*pdest))+(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); - b=(X32COL2(*pdest))+(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); - g=(X32COL3(*pdest))+(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); - } - else - if(GlobalTextABR==2) - { - int t; - r=(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); - t=(*pdest&0x001f0000)-(r&0x003f0000); if(t&0x80000000) t=0; - r=(*pdest&0x0000001f)-(r&0x0000003f); if(r&0x80000000) r=0; - r|=t; - - b=(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); - t=((*pdest>>5)&0x001f0000)-(b&0x003f0000); if(t&0x80000000) t=0; - b=((*pdest>>5)&0x0000001f)-(b&0x0000003f); if(b&0x80000000) b=0; - b|=t; - - g=(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); - t=((*pdest>>10)&0x001f0000)-(g&0x003f0000); if(t&0x80000000) t=0; - g=((*pdest>>10)&0x0000001f)-(g&0x0000003f); if(g&0x80000000) g=0; - g|=t; - } - else - { -#ifdef HALFBRIGHTMODE3 - r=(X32COL1(*pdest))+(((((X32BCOL1(color))>>2)* g_m1)&0xFF80FF80)>>7); - b=(X32COL2(*pdest))+(((((X32BCOL2(color))>>2)* g_m2)&0xFF80FF80)>>7); - g=(X32COL3(*pdest))+(((((X32BCOL3(color))>>2)* g_m3)&0xFF80FF80)>>7); -#else - r=(X32COL1(*pdest))+(((((X32ACOL1(color))>>1)* g_m1)&0xFF80FF80)>>7); - b=(X32COL2(*pdest))+(((((X32ACOL2(color))>>1)* g_m2)&0xFF80FF80)>>7); - g=(X32COL3(*pdest))+(((((X32ACOL3(color))>>1)* g_m3)&0xFF80FF80)>>7); -#endif - } - - if(!(color&0x8000)) - { - r=(r&0xffff0000)|((((X32COL1(color))* g_m1)&0x0000FF80)>>7); - b=(b&0xffff0000)|((((X32COL2(color))* g_m2)&0x0000FF80)>>7); - g=(g&0xffff0000)|((((X32COL3(color))* g_m3)&0x0000FF80)>>7); - } - if(!(color&0x80000000)) - { - r=(r&0xffff)|((((X32COL1(color))* g_m1)&0xFF800000)>>7); - b=(b&0xffff)|((((X32COL2(color))* g_m2)&0xFF800000)>>7); - g=(g&0xffff)|((((X32COL3(color))* g_m3)&0xFF800000)>>7); - } - - } - else - { - r=(((X32COL1(color))* g_m1)&0xFF80FF80)>>7; - b=(((X32COL2(color))* g_m2)&0xFF80FF80)>>7; - g=(((X32COL3(color))* 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(bCheckMask) - { - uint32_t ma=*pdest; - - *pdest=(X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000); - - if((color&0xffff)==0 ) *pdest=(ma&0xffff)|(*pdest&0xffff0000); - if((color&0xffff0000)==0) *pdest=(ma&0xffff0000)|(*pdest&0xffff); - if(ma&0x80000000) *pdest=(ma&0xFFFF0000)|(*pdest&0xFFFF); - if(ma&0x00008000) *pdest=(ma&0xFFFF) |(*pdest&0xFFFF0000); - - return; - } - if((color&0xffff)==0 ) {*pdest=(*pdest&0xffff)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff0000);return;} - if((color&0xffff0000)==0) {*pdest=(*pdest&0xffff0000)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff);return;} - - *pdest=(X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000); -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColGX_Dither(unsigned short * pdest, unsigned short color, int m1, int m2, int m3) -{ - int r,g,b; - - if(color==0) return; - - if(bCheckMask && *pdest&0x8000) return; - - m1=(((XCOL1D(color)))*m1)>>4; - m2=(((XCOL2D(color)))*m2)>>4; - m3=(((XCOL3D(color)))*m3)>>4; - - if(DrawSemiTrans && (color&0x8000)) - { - r=((XCOL1D(*pdest))<<3); - b=((XCOL2D(*pdest))<<3); - g=((XCOL3D(*pdest))<<3); - - if(GlobalTextABR==0) - { - r=(r>>1)+(m1>>1); - b=(b>>1)+(m2>>1); - g=(g>>1)+(m3>>1); - } - else - if(GlobalTextABR==1) - { - r+=m1; - b+=m2; - g+=m3; - } - else - if(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,sSetMask|(color&0x8000)); - -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColGX(unsigned short * pdest,unsigned short color,short m1,short m2,short m3) -{ - int r,g,b;unsigned short l; - - if(color==0) return; - - if(bCheckMask && *pdest&0x8000) return; - - l=sSetMask|(color&0x8000); - - if(DrawSemiTrans && (color&0x8000)) - { - if(GlobalTextABR==0) - { - unsigned short d; - d =((*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(GlobalTextABR==1) - { - r=(XCOL1(*pdest))+((((XCOL1(color)))* m1)>>7); - b=(XCOL2(*pdest))+((((XCOL2(color)))* m2)>>7); - g=(XCOL3(*pdest))+((((XCOL3(color)))* m3)>>7); - } - else - if(GlobalTextABR==2) - { - r=(XCOL1(*pdest))-((((XCOL1(color)))* m1)>>7); - b=(XCOL2(*pdest))-((((XCOL2(color)))* m2)>>7); - g=(XCOL3(*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(*pdest))+((((XCOL1(color))>>2)* m1)>>7); - b=(XCOL2(*pdest))+((((XCOL2(color))>>2)* m2)>>7); - g=(XCOL3(*pdest))+((((XCOL3(color))>>2)* m3)>>7); -#else - r=(XCOL1(*pdest))+((((XCOL1(color))>>1)* m1)>>7); - b=(XCOL2(*pdest))+((((XCOL2(color))>>1)* m2)>>7); - g=(XCOL3(*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; - - *pdest=(XPSXCOL(r,g,b))|l; -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColGX_S(unsigned short * pdest,unsigned short color,short m1,short m2,short m3) -{ - int 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; - - *pdest=(XPSXCOL(r,g,b))|sSetMask|(color&0x8000); -} - -//////////////////////////////////////////////////////////////////////// - -static __inline void GetTextureTransColGX32_S(uint32_t *pdest, uint32_t color, short m1, short m2, short m3) -{ - int 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) {*pdest=(*pdest&0xffff)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff0000);return;} - if((color&0xffff0000)==0) {*pdest=(*pdest&0xffff0000)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff);return;} - - *pdest=(X32PSXCOL(r,g,b))|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(x1drawW) return; - if(y0>drawH) return; - - x1=min(x1,drawW+1); - y1=min(y1,drawH+1); - x0=max(x0,drawX); - y0=max(y0,drawY); - - if(y0>=iGPUHeight) return; - if(x0>1023) return; - - if(y1>iGPUHeight) y1=iGPUHeight; - 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 = psxVuw + (1024*y0) + x0; - LineOffset = 1024 - dx; - for(i=0;i>=1; - DSTPtr = (uint32_t *)(psxVuw + (1024*y0) + x0); - LineOffset = 512 - dx; - - if(!bCheckMask && !DrawSemiTrans) - { - for(i=0;iy1) return; - if(x0>x1) return; - - if(y0>=iGPUHeight) return; - if(x0>1023) return; - - if(y1>iGPUHeight) y1=iGPUHeight; - if(x1>1024) x1=1024; - - dx=x1-x0;dy=y1-y0; - if(dx&1) - { - unsigned short *DSTPtr; - unsigned short LineOffset; - - DSTPtr = psxVuw + (1024*y0) + x0; - LineOffset = 1024 - dx; - - for(i=0;i>=1; - DSTPtr = (uint32_t *)(psxVuw + (1024*y0) + x0); - LineOffset = 512 - dx; - - for(i=0;iy - 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; -} - -static __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; -} - -static __inline BOOL NextRow_F(void) -{ - if(--left_section_height<=0) - { - if(--left_section <= 0) {return TRUE;} - if(LeftSection_F() <= 0) {return TRUE;} - } - else - { - left_x += delta_left_x; - } - - if(--right_section_height<=0) - { - if(--right_section<=0) {return TRUE;} - if(RightSection_F() <=0) {return TRUE;} - } - else - { - right_x += delta_right_x; - } - return FALSE; -} - -static __inline BOOL 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 FALSE;} - longest = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x)>>16) + (v1->x - v2->x); - if(longest == 0) {return FALSE;} - - 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 FALSE; - if(RightSection_F() <= 0) - { - right_section--; - if(RightSection_F() <= 0) return FALSE; - } - } - 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 FALSE; - if(LeftSection_F() <= 0) - { - left_section--; - if(LeftSection_F() <= 0) return FALSE; - } - } - - Ymin=v1->y; - Ymax=min(v3->y-1,drawH); - - return TRUE; -} - -static __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; -} - -static __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; -} - -static __inline BOOL NextRow_G(void) -{ - if(--left_section_height<=0) - { - if(--left_section <= 0) {return TRUE;} - if(LeftSection_G() <= 0) {return TRUE;} - } - 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 TRUE;} - if(RightSection_G() <=0) {return TRUE;} - } - else - { - right_x += delta_right_x; - } - return FALSE; -} - -static __inline BOOL SetupSections_G(short x1,short y1,short x2,short y2,short x3,short y3, int rgb1, int rgb2, int 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 FALSE;} - temp=(((v2->y - v1->y) << 16) / height); - longest = temp * ((v3->x - v1->x)>>16) + (v1->x - v2->x); - if(longest == 0) {return FALSE;} - - 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 FALSE; - if(RightSection_G() <= 0) - { - right_section--; - if(RightSection_G() <= 0) return FALSE; - } - 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 FALSE; - if(LeftSection_G() <= 0) - { - left_section--; - if(LeftSection_G() <= 0) return FALSE; - } - if(longest < 0x1000) longest = 0x1000; - } - - Ymin=v1->y; - Ymax=min(v3->y-1,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 TRUE; -} - -static __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; -} - -static __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; -} - -static __inline BOOL NextRow_FT(void) -{ - if(--left_section_height<=0) - { - if(--left_section <= 0) {return TRUE;} - if(LeftSection_FT() <= 0) {return TRUE;} - } - 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 TRUE;} - if(RightSection_FT() <=0) {return TRUE;} - } - else - { - right_x += delta_right_x; - } - return FALSE; -} - -static __inline BOOL 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 FALSE;} - - temp=(((v2->y - v1->y) << 16) / height); - longest = temp * ((v3->x - v1->x)>>16) + (v1->x - v2->x); - - if(longest == 0) {return FALSE;} - - 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 FALSE; - if(RightSection_FT() <= 0) - { - right_section--; - if(RightSection_FT() <= 0) return FALSE; - } - 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 FALSE; - if(LeftSection_FT() <= 0) - { - left_section--; - if(LeftSection_FT() <= 0) return FALSE; - } - if(longest < 0x1000) longest = 0x1000; - } - - Ymin=v1->y; - Ymax=min(v3->y-1,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 TRUE; -} - -static __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; -} - -static __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; -} - -static __inline BOOL NextRow_GT(void) -{ - if(--left_section_height<=0) - { - if(--left_section <= 0) {return TRUE;} - if(LeftSection_GT() <= 0) {return TRUE;} - } - 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 TRUE;} - if(RightSection_GT() <=0) {return TRUE;} - } - else - { - right_x += delta_right_x; - } - return FALSE; -} - -static __inline BOOL 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, int rgb1, int rgb2, int 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 FALSE;} - - temp=(((v2->y - v1->y) << 16) / height); - longest = temp * ((v3->x - v1->x)>>16) + (v1->x - v2->x); - - if(longest == 0) {return FALSE;} - - 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 FALSE; - if(RightSection_GT() <= 0) - { - right_section--; - if(RightSection_GT() <= 0) return FALSE; - } - - 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 FALSE; - if(LeftSection_GT() <= 0) - { - left_section--; - if(LeftSection_GT() <= 0) return FALSE; - } - if(longest < 0x1000) longest = 0x1000; - } - - Ymin=v1->y; - Ymax=min(v3->y-1,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 TRUE; -} - -static __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; -} - -static __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; -} - -static __inline BOOL 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 FALSE; -} - -static __inline BOOL 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; - } - - Ymin=v1->y; - Ymax=min(v4->y-1,drawH); - - return TRUE; -} - -static __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; -} - -static __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; -} - -static __inline BOOL 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 FALSE; -} - -static __inline BOOL 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; - } - - Ymin=v1->y; - Ymax=min(v4->y-1,drawH); - - return TRUE; -} - -static __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; -} - -static __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; -} - -static __inline BOOL 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 FALSE; -} - -static __inline BOOL 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, int rgb1, int rgb2, int rgb3, int 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; - } - - Ymin=v1->y; - Ymax=min(v4->y-1,drawH); - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////// -// POLY FUNCS -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -// POLY 3/4 FLAT SHADED -//////////////////////////////////////////////////////////////////////// - -static __inline void drawPoly3Fi(short x1, short y1, short x2, short y2, short x3, short y3, int rgb) -{ - int i,j,xmin,xmax,ymin,ymax; - unsigned short color; - uint32_t lcolor; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_F(x1,y1,x2,y2,x3,y3)) return; - - ymax=Ymax; - - color = ((rgb & 0x00f80000)>>9) | ((rgb & 0x0000f800)>>6) | ((rgb & 0x000000f8)>>3); - lcolor=lSetMask|(((uint32_t)(color))<<16)|color; - - for(ymin=Ymin;ymin> 16; if(drawX>xmin) xmin=drawX; - xmax=(right_x >> 16)-1; if(drawW> 16; if(drawX>xmin) xmin=drawX; - xmax=(right_x >> 16)-1; if(drawWdrawW && lx1>drawW && lx2>drawW && lx3>drawW) return; - if(ly0>drawH && ly1>drawH && ly2>drawH && ly3>drawH) return; - if(lx0=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_F4(lx0,ly0,lx1,ly1,lx2,ly2,lx3,ly3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin>9) | ((rgb & 0x0000f800)>>6) | ((rgb & 0x000000f8)>>3); - lcolor= lSetMask|(((uint32_t)(color))<<16)|color; - -#ifdef FASTSOLID - - if(!bCheckMask && !DrawSemiTrans) - { - color |=sSetMask; - for (i=ymin;i<=ymax;i++) - { - xmin=left_x >> 16; if(drawX>xmin) xmin=drawX; - xmax=(right_x >> 16)-1; if(drawW> 16; if(drawX > xmin) xmin = drawX; - xmax = (right_x >> 16) - 1; if(drawW < xmax) xmax = drawW; - - for(j = xmin; j < xmax; j += 2) - { - GetShadeTransCol32((uint32_t *)&psxVuw[(i<<10) + j],lcolor); - } - if(j == xmax) GetShadeTransCol(&psxVuw[(i<<10) + j],color); - - if(NextRow_F4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// -// POLY 3/4 F-SHADED TEX PAL 4 -//////////////////////////////////////////////////////////////////////// - -static 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; - int difX, difY,difX2, difY2; - int posX,posY,YAdjust,XAdjust; - int clutP; - short tC1,tC2; - - if (x1 > drawW && x2 > drawW && x3 > drawW) return; - if (y1 > drawH && y2 > drawH && y3 > drawH) return; - if (x1 < drawX && x2 < drawX && x3 < drawX) return; - if (y1 < drawY && y2 < drawY && y3 < drawY) return; - if (drawY >= drawH) return; - if (drawX >= drawW) return; - - if (!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax = Ymax; - - for (ymin = Ymin; ymin < drawY; ymin++) - if (NextRow_FT()) return; - - clutP = (clY << 10) + clX; - - YAdjust = ((GlobalTextAddrY) << 11) + (GlobalTextAddrX << 1); - - difX = delta_right_u; difX2 = difX << 1; - difY = delta_right_v; difY2 = difY << 1; - -#ifdef FASTSOLID - - if(!bCheckMask && !DrawSemiTrans) - { - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16); - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16); - tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16); - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT()) - { - return; - } - } - return; - } - -#endif - - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16); - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16); - tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16); - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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; - int difX, difY,difX2, difY2; - int posX,posY,YAdjust,XAdjust; - int clutP; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16); - - TXV=posY>>16; - n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); - - tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT()) - { - return; - } - } - return; - } - -#endif - - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16); - - TXV=posY>>16; - n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); - - tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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; - int difX, difY,difX2, difY2; - int posX,posY,YAdjust,XAdjust; - int clutP; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin>1); - - difX=delta_right_u;difX2=difX<<1; - difY=delta_right_v;difY2=difY<<1; - -#ifdef FASTSOLID - - if(!bCheckMask && !DrawSemiTrans) - { - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16);//-1; //!!!!!!!!!!!!!!!! - if(xmax>xmin) xmax--; - - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16)%TWin.Position.x1; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i << 10) + j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT()) - { - return; - } - } - return; - } - -#endif - - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16)%TWin.Position.x1; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -#ifdef POLYQUAD3 - -static 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: - -static 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) -{ - int num; - int i,j,xmin,xmax,ymin,ymax; - int difX, difY, difX2, difY2; - int posX,posY,YAdjust,clutP,XAdjust; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16); - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16); - tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16); - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>16); - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16); - tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16); - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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) -{ - int num; - int i,j,xmin,xmax,ymin,ymax,n_xi,n_yi,TXV; - int difX, difY, difX2, difY2; - int posX,posY,YAdjust,clutP,XAdjust; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16); - - TXV=posY>>16; - n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); - - tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>16); - - TXV=posY>>16; - n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); - - tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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) -{ - int num; - int i,j,xmin,xmax,ymin,ymax; - int difX, difY, difX2, difY2; - int posX,posY,YAdjust,clutP,XAdjust; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin>1); - -#ifdef FASTSOLID - - if(!bCheckMask && !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>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16)%TWin.Position.x1; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16)%TWin.Position.x1; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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) -{ - int num; - int i,j,xmin,xmax,ymin,ymax; - int difX, difY, difX2, difY2; - int posX,posY,YAdjust,clutP,XAdjust; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin>1); - -#ifdef FASTSOLID - - if(!bCheckMask && !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>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16)%TWin.Position.x1; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16)%TWin.Position.x1; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColG32_SPR((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - XAdjust=(posX>>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColG_SPR(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT4()) return; - } -} -//////////////////////////////////////////////////////////////////////// -// POLY 3 F-SHADED TEX PAL 8 -//////////////////////////////////////////////////////////////////////// - -static 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; - int difX, difY,difX2, difY2; - int posX,posY,YAdjust,clutP; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; - tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ - ((posX+difX)>>16)]; - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX+=difX2; - posY+=difY2; - } - - if(j==xmax) - { - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT()) - { - return; - } - } - return; - } - -#endif - - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; - tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ - ((posX+difX)>>16)]; - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX+=difX2; - posY+=difY2; - } - - if(j==xmax) - { - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; - GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - - } - if(NextRow_FT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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; - int difX, difY,difX2, difY2; - int posX,posY,YAdjust,clutP; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16; - TXV=posY>>16; - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT()) - { - return; - } - } - return; - } - -#endif - - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16; - TXV=posY>>16; - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - - } - if(NextRow_FT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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; - int difX, difY,difX2, difY2; - int posX,posY,YAdjust,clutP; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16);//-1; //!!!!!!!!!!!!!!!! - if(xmax>xmin) xmax--; - - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX+=difX2; - posY+=difY2; - } - - if(j==xmax) - { - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT()) - { - return; - } - } - return; - } - -#endif - - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX+=difX2; - posY+=difY2; - } - - if(j==xmax) - { - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - - } - if(NextRow_FT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -#ifdef POLYQUAD3 - -static 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: - -static 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) -{ - int num; - int i,j,xmin,xmax,ymin,ymax; - int difX, difY, difX2, difY2; - int posX,posY,YAdjust,clutP; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; - tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ - ((posX+difX)>>16)]; - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; - tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ - ((posX+difX)>>16)]; - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; - GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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) -{ - int num; - int i,j,xmin,xmax,ymin,ymax,n_xi,n_yi,TXV,TXU; - int difX, difY, difX2, difY2; - int posX,posY,YAdjust,clutP; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16; - TXV=posY>>16; - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>16; - TXV=posY>>16; - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; - GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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) -{ - int num; - int i, j, xmin, xmax, ymin, ymax; - int difX, difY, difX2, difY2; - int posX, posY, YAdjust, clutP; - short tC1, tC2; - - if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX += difX2; - posY += difY2; - } - if(j==xmax) - { - tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; - GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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) -{ - int num; - int i,j,xmin,xmax,ymin,ymax; - int difX, difY, difX2, difY2; - int posX,posY,YAdjust,clutP; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; - GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; - GetTextureTransColG32_SPR((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[clutP+tC2])<<16); - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - { - tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - GetTextureTransColG_SPR(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); - } - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// -// POLY 3 F-SHADED TEX 15 BIT -//////////////////////////////////////////////////////////////////////// - -static 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; - int difX, difY,difX2, difY2; - int posX,posY; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX])<<16)| - psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX]); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG_S(&psxVuw[(i<<10)+j], - psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]); - } - if(NextRow_FT()) - { - return; - } - } - return; - } - -#endif - - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX])<<16)| - psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX]); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG(&psxVuw[(i<<10)+j], - psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]); - } - if(NextRow_FT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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; - int difX, difY,difX2, difY2; - int posX,posY; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])<<16)| - psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG_S(&psxVuw[(i<<10)+j], - psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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(drawW=xmin) - { - posX=left_u; - posY=left_v; - - if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])<<16)| - psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG(&psxVuw[(i<<10)+j], - psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]); - } - if(NextRow_FT()) - { - return; - } - } -} - - -//////////////////////////////////////////////////////////////////////// - -#ifdef POLYQUAD3 - -static 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: - -static 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) -{ - int num; - int i,j,xmin,xmax,ymin,ymax; - int difX, difY, difX2, difY2; - int posX,posY; - - if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX])<<16)| - psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX]); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG_S(&psxVuw[(i<<10)+j], - psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX])<<16)| - psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX]); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG(&psxVuw[(i<<10)+j], - psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]); - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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) -{ - int num; - int i,j,xmin,xmax,ymin,ymax; - int difX, difY, difX2, difY2; - int posX,posY; - - if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])<<16)| - psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY)<<10)+TWin.Position.y0+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG_S(&psxVuw[(i<<10)+j], - psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])<<16)| - psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG(&psxVuw[(i<<10)+j], - psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]); - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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) -{ - int num; - int i,j,xmin,xmax,ymin,ymax; - int difX, difY, difX2, difY2; - int posX, posY; - - if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])<<16)| - psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY)<<10)+TWin.Position.y0+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG_S(&psxVuw[(i<<10)+j], - psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])<<16)| - psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]); - - posX+=difX2; - posY+=difY2; - } - if(j==xmax) - GetTextureTransColG_SPR(&psxVuw[(i<<10)+j], - psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]); - } - if(NextRow_FT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// -// POLY 3/4 G-SHADED -//////////////////////////////////////////////////////////////////////// - -static __inline void drawPoly3Gi(short x1,short y1,short x2,short y2,short x3,short y3, int rgb1, int rgb2, int rgb3) -{ - int i,j,xmin,xmax,ymin,ymax; - int cR1,cG1,cB1; - int difR,difB,difG,difR2,difB2,difG2; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_G(x1,y1,x2,y2,x3,y3,rgb1,rgb2,rgb3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1;if(drawW=xmin) - { - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>3)&0x001f0000)| - (((cR1) >> 9)&0x7c00)|(((cG1) >> 14)&0x03e0)|(((cB1) >> 19)&0x001f))|lSetMask; - - cR1+=difR2; - cG1+=difG2; - cB1+=difB2; - } - if(j==xmax) - psxVuw[(i<<10)+j]=(((cR1 >> 9)&0x7c00)|((cG1 >> 14)&0x03e0)|((cB1 >> 19)&0x001f))|sSetMask; - } - if(NextRow_G()) return; - } - return; - } - -#endif - - if(iDither==2) - for (i=ymin;i<=ymax;i++) - { - xmin=(left_x >> 16); - xmax=(right_x >> 16)-1;if(drawW=xmin) - { - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>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(drawW=xmin) - { - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin> 9)&0x7c00)|((cG1 >> 14)&0x03e0)|((cB1 >> 19)&0x001f)); - - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_G()) return; - } - -} - -//////////////////////////////////////////////////////////////////////// - -void drawPoly3G(int rgb1, int rgb2, int rgb3) -{ - drawPoly3Gi(lx0,ly0,lx1,ly1,lx2,ly2,rgb1,rgb2,rgb3); -} - -// draw two g-shaded tris for right psx shading emulation - -void drawPoly4G(int rgb1, int rgb2, int rgb3, int rgb4) -{ - drawPoly3Gi(lx1,ly1,lx3,ly3,lx2,ly2, - rgb2,rgb4,rgb3); - drawPoly3Gi(lx0,ly0,lx1,ly1,lx2,ly2, - rgb1,rgb2,rgb3); -} - -//////////////////////////////////////////////////////////////////////// -// POLY 3/4 G-SHADED TEX PAL4 -//////////////////////////////////////////////////////////////////////// - -static 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,int col1, int col2, int col3) -{ - int i,j,xmin,xmax,ymin,ymax; - int cR1,cG1,cB1; - int difR,difB,difG,difR2,difB2,difG2; - int difX, difY,difX2, difY2; - int posX,posY,YAdjust,clutP,XAdjust; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=((right_x) >> 16)-1; //!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16); - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16); - tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - psxVuw[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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16); - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1], - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1], - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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,int col1, int col2, int col3) -{ - int i,j,xmin,xmax,ymin,ymax,n_xi,n_yi,TXV; - int cR1,cG1,cB1; - int difR,difB,difG,difR2,difB2,difG2; - int difX, difY,difX2, difY2; - int posX,posY,YAdjust,clutP,XAdjust; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=((right_x) >> 16)-1; //!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16); - - TXV=posY>>16; - n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); - - tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - psxVuw[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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16); - - TXV=posY>>16; - n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); - - tC1= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; - - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1], - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1], - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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, int col1, int col2, int col3) -{ - int i, j, xmin, xmax, ymin, ymax; - int cR1, cG1, cB1; - int difR, difB, difG, difR2, difB2, difG2; - int difX, difY,difX2, difY2; - int posX, posY, YAdjust, clutP, XAdjust; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin>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(!bCheckMask && !DrawSemiTrans && !iDither) - { - for (i=ymin;i<=ymax;i++) - { - xmin=((left_x) >> 16); - xmax=((right_x) >> 16)-1; //!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16)%TWin.Position.x1; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - psxVuw[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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)%TWin.Position.x1; - tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1], - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - psxVuw[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... - -static 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, - int col1, int col2, int col3, int 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 - -static 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, - int col1, int col2, int col3, int 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 - -//////////////////////////////////////////////////////////////////////// - -static 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, - int col1, int col2, int col4, int col3) -{ - int num; - int i,j,xmin,xmax,ymin,ymax; - int cR1,cG1,cB1; - int difR,difB,difG,difR2,difB2,difG2; - int difX, difY, difX2, difY2; - int posX,posY,YAdjust,clutP,XAdjust; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=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=Ymax; - - for(ymin=Ymin;ymin> 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>16); - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - XAdjust=((posX+difX)>>16); - tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC2=(tC2>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - psxVuw[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>16); - tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+ - (XAdjust>>1)]; - tC1=(tC1>>((XAdjust&1)<<2))&0xf; - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1], - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1], - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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, - int col1, int col2, int col3, int 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 -//////////////////////////////////////////////////////////////////////// - -static 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, int col1, int col2, int col3) -{ - int i,j,xmin,xmax,ymin,ymax; - int cR1,cG1,cB1; - int difR,difB,difG,difR2,difB2,difG2; - int difX, difY,difX2, difY2; - int posX,posY,YAdjust,clutP; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; // !!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>5)&(int)0xFFFFF800)+YAdjust+((posX>>16))]; - tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ - (((posX+difX)>>16))]; - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+((posX>>16))]; - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - psxVuw[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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>5)&(int)0xFFFFF800)+YAdjust+((posX>>16))]; - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1], - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1], - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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, int col1, int col2, int col3) -{ - int i,j,xmin,xmax,ymin,ymax,n_xi,n_yi,TXV,TXU; - int cR1,cG1,cB1; - int difR,difB,difG,difR2,difB2,difG2; - int difX, difY,difX2, difY2; - int posX,posY,YAdjust,clutP; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; // !!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16; - TXV=posY>>16; - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; - - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - psxVuw[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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16; - TXV=posY>>16; - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - tC1= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; - - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1], - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1], - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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, int col1, int col2, int col3) -{ - int i,j,xmin,xmax,ymin,ymax; - int cR1,cG1,cB1; - int difR,difB,difG,difR2,difB2,difG2; - int difX, difY,difX2, difY2; - int posX,posY,YAdjust,clutP; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; // !!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ - YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; - - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - psxVuw[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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)%TWin.Position.y1)<<11)+ - YAdjust+((posX>>16)%TWin.Position.x1)]; - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1], - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - psxVuw[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 - -static 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, - int col1, int col2, int col3, int 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 - -static 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, - int col1, int col2, int col3, int 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 - -static 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, - int col1, int col2, int col4, int col3) -{ - int num; - int i,j,xmin,xmax,ymin,ymax; - int cR1,cG1,cB1; - int difR,difB,difG,difR2,difB2,difG2; - int difX, difY, difX2, difY2; - int posX,posY,YAdjust,clutP; - short tC1,tC2; - - if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=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=Ymax; - - for(ymin=Ymin;ymin> 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>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; - tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ - ((posX+difX)>>16)]; - - GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1]| - ((int)psxVuw[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 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; - GetTextureTransColGX_S(&psxVuw[(i<<10)+j], - psxVuw[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>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; - if(iDither) - GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1], - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - psxVuw[clutP+tC1], - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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, - int col1, int col2, int col3, int 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 -//////////////////////////////////////////////////////////////////////// - -static 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, int col1, int col2, int col3) -{ - int i,j,xmin,xmax,ymin,ymax; - int cR1,cG1,cB1; - int difR,difB,difG,difR2,difB2,difG2; - int difX, difY,difX2, difY2; - int posX,posY; - - if(x1>drawW && x2>drawW && x3>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH) return; - if(x1=drawH) return; - if(drawX>=drawW) return; - - if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax=Ymax; - - for(ymin=Ymin;ymin> 16); - xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX])<<16)| - psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+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(&psxVuw[(i<<10)+j], - psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX], - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX], - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT()) - { - return; - } - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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, int col1, int col2, int col3) -{ - int i,j,xmin,xmax,ymin,ymax; - int cR1,cG1,cB1; - int difR,difB,difG,difR2,difB2,difG2; - int difX, difY,difX2, difY2; - int posX,posY; - - if (x1>drawW && x2>drawW && x3>drawW) return; - if (y1>drawH && y2>drawH && y3>drawH) return; - if (x1= drawH) return; - if (drawX >= drawW) return; - - if (!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; - - ymax = Ymax; - - for(ymin = Ymin; ymin < 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 (!bCheckMask && !DrawSemiTrans && !iDither) - { - for (i = ymin; i <= ymax; i++) - { - xmin = (left_x >> 16); - xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!!!!!! - if(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])<<16)| - psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - (((posX)>>16)%TWin.Position.x1)+GlobalTextAddrX+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(&psxVuw[(i<<10)+j], - psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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(drawW=xmin) - { - posX=left_u; - posY=left_v; - cR1=left_R; - cG1=left_G; - cB1=left_B; - - if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0], - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ - ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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 - -static 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, int col1, int col2, int col3, int 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 - -static 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, int col1, int col2, int col4, int col3) -{ - int num; - int i,j,xmin,xmax,ymin,ymax; - int cR1,cG1,cB1; - int difR,difB,difG,difR2,difB2,difG2; - int difX, difY, difX2, difY2; - int posX,posY; - - if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; - if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; - if(x1=drawH) return; - if(drawX>=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 = Ymax; - - for (ymin = Ymin; ymin < drawY; ymin++) - if (NextRow_GT4()) return; - -#ifdef FASTSOLID - - if(!bCheckMask && !DrawSemiTrans && !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>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX])<<16)| - psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+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(&psxVuw[(i<<10)+j], - psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX], - (cB1>>16),(cG1>>16),(cR1>>16)); - else - GetTextureTransColGX(&psxVuw[(i<<10)+j], - psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX], - (cB1>>16),(cG1>>16),(cR1>>16)); - posX+=difX; - posY+=difY; - cR1+=difR; - cG1+=difG; - cB1+=difB; - } - } - if(NextRow_GT4()) return; - } -} - -//////////////////////////////////////////////////////////////////////// - -static 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, int col1, int col2, int col3, int 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 BOOL IsNoRect(void) -{ - if(lx0==lx1 && lx2==lx3) return FALSE; - if(lx0==lx2 && lx1==lx3) return FALSE; - if(lx0==lx3 && lx1==lx2) return FALSE; - return TRUE; -} -*/ - -// real rect test -static __inline BOOL IsNoRect(void) -{ - //if(!(dwActFixes&0x200)) return FALSE; - - if(ly0==ly1) - { - if(lx1==lx3 && ly3==ly2 && lx2==lx0) return FALSE; - if(lx1==lx2 && ly2==ly3 && lx3==lx0) return FALSE; - return TRUE; - } - - if(ly0==ly2) - { - if(lx2==lx3 && ly3==ly1 && lx1==lx0) return FALSE; - if(lx2==lx1 && ly1==ly3 && lx3==lx0) return FALSE; - return TRUE; - } - - if(ly0==ly3) - { - if(lx3==lx2 && ly2==ly1 && lx1==lx0) return FALSE; - if(lx3==lx1 && ly1==ly2 && lx2==lx0) return FALSE; - return TRUE; - } - return TRUE; -} - -//////////////////////////////////////////////////////////////////////// - -void drawPoly3FT(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - - if(GlobalTextIL && GlobalTextTP<2) - { - if(GlobalTextTP==0) - drawPoly3TEx4_IL(lx0,ly0,lx1,ly1,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - else - drawPoly3TEx8_IL(lx0,ly0,lx1,ly1,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - return; - } - - if(!bUsingTWin)// && !(dwActFixes&0x100)) - { - switch(GlobalTextTP) // depending on texture mode - { - case 0: - drawPoly3TEx4(lx0,ly0,lx1,ly1,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - return; - case 1: - drawPoly3TEx8(lx0,ly0,lx1,ly1,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - return; - case 2: - drawPoly3TD(lx0,ly0,lx1,ly1,lx2,ly2,(gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff)); - return; - } - return; - } - - switch(GlobalTextTP) // depending on texture mode - { - case 0: - drawPoly3TEx4_TW(lx0,ly0,lx1,ly1,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - return; - case 1: - drawPoly3TEx8_TW(lx0,ly0,lx1,ly1,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - return; - case 2: - drawPoly3TD_TW(lx0,ly0,lx1,ly1,lx2,ly2,(gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff)); - return; - } -} - -//////////////////////////////////////////////////////////////////////// - -void drawPoly4FT(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - - if(GlobalTextIL && GlobalTextTP<2) - { - if(GlobalTextTP==0) - drawPoly4TEx4_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - else - drawPoly4TEx8_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - return; - } - - if(!bUsingTWin) - { -#ifdef POLYQUAD3GT - if(IsNoRect()) - { - switch (GlobalTextTP) - { - case 0: - drawPoly4TEx4_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - return; - case 1: - drawPoly4TEx8_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - return; - case 2: - drawPoly4TD_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff)); - return; - } - return; - } -#endif - - switch (GlobalTextTP) - { - case 0: // grandia investigations needed - drawPoly4TEx4(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - return; - case 1: - drawPoly4TEx8(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - return; - case 2: - drawPoly4TD(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff)); - return; - } - return; - } - - switch (GlobalTextTP) - { - case 0: - drawPoly4TEx4_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - return; - case 1: - drawPoly4TEx8_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - return; - case 2: - drawPoly4TD_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff)); - return; - } -} - -//////////////////////////////////////////////////////////////////////// - -void drawPoly3GT(unsigned char * baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - - if(GlobalTextIL && GlobalTextTP<2) - { - if(GlobalTextTP==0) - drawPoly3TGEx4_IL(lx0,ly0,lx1,ly1,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask), - gpuData[0],gpuData[3],gpuData[6]); - else - drawPoly3TGEx8_IL(lx0,ly0,lx1,ly1,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask), - gpuData[0],gpuData[3],gpuData[6]); - return; - } - - if(!bUsingTWin) - { - switch (GlobalTextTP) - { - case 0: - drawPoly3TGEx4(lx0,ly0,lx1,ly1,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask), - gpuData[0],gpuData[3],gpuData[6]); - return; - case 1: - drawPoly3TGEx8(lx0,ly0,lx1,ly1,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask), - gpuData[0],gpuData[3],gpuData[6]); - return; - case 2: - drawPoly3TGD(lx0,ly0,lx1,ly1,lx2,ly2,(gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),gpuData[0],gpuData[3],gpuData[6]); - return; - } - return; - } - - switch(GlobalTextTP) - { - case 0: - drawPoly3TGEx4_TW(lx0,ly0,lx1,ly1,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask), - gpuData[0],gpuData[3],gpuData[6]); - return; - case 1: - drawPoly3TGEx8_TW(lx0,ly0,lx1,ly1,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask), - gpuData[0],gpuData[3],gpuData[6]); - return; - case 2: - drawPoly3TGD_TW(lx0,ly0,lx1,ly1,lx2,ly2,(gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),gpuData[0],gpuData[3],gpuData[6]); - return; - } -} - -//////////////////////////////////////////////////////////////////////// - -void drawPoly4GT(unsigned char *baseAddr) -{ - uint32_t *gpuData = ((uint32_t *) baseAddr); - - if(GlobalTextIL && GlobalTextTP<2) - { - if(GlobalTextTP==0) - drawPoly4TGEx4_TRI_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), - gpuData[0],gpuData[3],gpuData[6],gpuData[9]); - else - drawPoly4TGEx8_TRI_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), - gpuData[0],gpuData[3],gpuData[6],gpuData[9]); - return; - } - - if(!bUsingTWin) - { -#ifdef POLYQUAD3GT - if(IsNoRect()) - { - switch (GlobalTextTP) - { - case 0: - drawPoly4TGEx4_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), - gpuData[0],gpuData[3],gpuData[6],gpuData[9]); - - return; - case 1: - drawPoly4TGEx8_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), - gpuData[0],gpuData[3],gpuData[6],gpuData[9]); - return; - case 2: - drawPoly4TGD_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(gpuData[2] & 0x000000ff),((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),gpuData[0],gpuData[3],gpuData[6],gpuData[9]); - return; - } - return; - } -#endif - - switch (GlobalTextTP) - { - case 0: - drawPoly4TGEx4(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), - gpuData[0],gpuData[3],gpuData[6],gpuData[9]); - - return; - case 1: - drawPoly4TGEx8(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), - gpuData[0],gpuData[3],gpuData[6],gpuData[9]); - return; - case 2: - drawPoly4TGD(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(gpuData[2] & 0x000000ff),((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),gpuData[0],gpuData[3],gpuData[6],gpuData[9]); - return; - } - return; - } - - switch (GlobalTextTP) - { - case 0: - drawPoly4TGEx4_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), - gpuData[0],gpuData[3],gpuData[6],gpuData[9]); - return; - case 1: - drawPoly4TGEx8_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, - (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), - ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), - gpuData[0],gpuData[3],gpuData[6],gpuData[9]); - return; - case 2: - drawPoly4TGD_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(gpuData[2] & 0x000000ff),((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),gpuData[0],gpuData[3],gpuData[6],gpuData[9]); - return; - } -} - -//////////////////////////////////////////////////////////////////////// -// SPRITE FUNCS -//////////////////////////////////////////////////////////////////////// - -void DrawSoftwareSpriteTWin(unsigned char * baseAddr, int w, int 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=lx0; - sy0=ly0; - - sx0=sx3=sx0+PSXDisplay.DrawOffset.x; - sx1=sx2=sx0+w; - sy0=sy1=sy0+PSXDisplay.DrawOffset.y; - sy2=sy3=sy0+h; - - tx0=tx3=gpuData[2]&0xff; - tx1=tx2=tx0+w; - ty0=ty1=(gpuData[2]>>8)&0xff; - ty2=ty3=ty0+h; - - switch (GlobalTextTP) - { - case 0: - drawPoly4TEx4_TW_S(sx0,sy0,sx1,sy1,sx2,sy2,sx3,sy3, - tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3, - ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - return; - case 1: - drawPoly4TEx8_TW_S(sx0,sy0,sx1,sy1,sx2,sy2,sx3,sy3, - tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3, - ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); - 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, int w, int h) -{ - int sprtY,sprtX,sprtW,sprtH,lXDir,lYDir; - int clutY0,clutX0,clutP,textX0,textY0,sprtYa,sprCY,sprCX,sprA; - short tC; - uint32_t *gpuData = (uint32_t *)baseAddr; - sprtY = ly0; - sprtX = lx0; - sprtH = h; - sprtW = w; - clutY0 = (gpuData[2]>>22) & iGPUHeightMask; - clutX0 = (gpuData[2]>>12) & 0x3f0; - clutP = (clutY0<<11) + (clutX0<<1); - textY0 = ((gpuData[2]>>8) & 0x000000ff) + GlobalTextAddrY; - textX0 = (gpuData[2] & 0x000000ff); - - sprtX+=PSXDisplay.DrawOffset.x; - sprtY+=PSXDisplay.DrawOffset.y; - -// while (sprtX>1023) sprtX-=1024; -// while (sprtY>MAXYLINESMIN1) sprtY-=MAXYLINES; - - if(sprtX>drawW) - { -// if((sprtX+sprtW)>1023) sprtX-=1024; -// else return; - return; - } - - if(sprtY>drawH) - { -// if ((sprtY+sprtH)>MAXYLINESMIN1) sprtY-=MAXYLINES; -// else return; - return; - } - - if(sprtYdrawH) sprtH=drawH-sprtY+1; - if((sprtX+sprtW)>drawW) sprtW=drawW-sprtX+1; - - if(usMirror&0x1000) lXDir=-1; else lXDir=1; - if(usMirror&0x2000) lYDir=-1; else lYDir=1; - - switch (GlobalTextTP) - { - case 0: // texture is 4-bit - - sprtW=sprtW/2; - textX0=(GlobalTextAddrX<<1)+(textX0>>1); - sprtYa=(sprtY<<10); - clutP=(clutY0<<10)+clutX0; - for (sprCY=0;sprCY>4)&0xf)]); - GetTextureTransColG_SPR(&psxVuw[sprA+1],psxVuw[clutP+(tC&0xf)]); - } - return; - - case 1: - - clutP>>=1; - for(sprCY=0;sprCYdrawW) return; - if(sprtY>drawH) return; - - tdx=tx+sprtW; - tdy=ty+sprtH; - - sprtW+=sprtX; - sprtH+=sprtY; - - // Pete is too lazy to make a faster version ;) - - if(GlobalTextTP==0) - drawPoly4TEx4_IL(sprtX,sprtY,sprtX,sprtH,sprtW,sprtH,sprtW,sprtY, - tx,ty, tx,tdy, tdx,tdy, tdx,ty, - (gpuData[2]>>12) & 0x3f0, ((gpuData[2]>>22) & iGPUHeightMask)); - - - else - drawPoly4TEx8_IL(sprtX,sprtY,sprtX,sprtH,sprtW,sprtH,sprtW,sprtY, - tx,ty, tx,tdy, tdx,tdy, tdx,ty, - (gpuData[2]>>12) & 0x3f0, ((gpuData[2]>>22) & iGPUHeightMask)); -} - -//////////////////////////////////////////////////////////////////////// - -void DrawSoftwareSprite(unsigned char *baseAddr, short w, short h, int tx, int ty) -{ - int sprtY, sprtX, sprtW, sprtH; - int clutY0, clutX0, clutP, textX0, textY0, sprtYa, sprCY, sprCX, sprA; - short tC, tC2; - uint32_t *gpuData = (uint32_t *)baseAddr; - unsigned char *pV; - BOOL bWT,bWS; - - if(GlobalTextIL && GlobalTextTP<2) - {DrawSoftwareSprite_IL(baseAddr,w,h,tx,ty);return;} - - sprtY = ly0; - sprtX = lx0; - sprtH = h; - sprtW = w; - clutY0 = (gpuData[2]>>22) & iGPUHeightMask; - clutX0 = (gpuData[2]>>12) & 0x3f0; - - clutP = (clutY0<<11) + (clutX0<<1); - - textY0 =ty+ GlobalTextAddrY; - textX0 =tx; - - sprtX+=PSXDisplay.DrawOffset.x; - sprtY+=PSXDisplay.DrawOffset.y; - - //while (sprtX>1023) sprtX-=1024; - //while (sprtY>MAXYLINESMIN1) sprtY-=MAXYLINES; - - if(sprtX>drawW) - { -// if((sprtX+sprtW)>1023) sprtX-=1024; -// else return; - return; - } - - if(sprtY>drawH) - { -// if ((sprtY+sprtH)>MAXYLINESMIN1) sprtY-=MAXYLINES; -// else return; - return; - } - - if(sprtYdrawH) sprtH=drawH-sprtY+1; - if((sprtX+sprtW)>drawW) sprtW=drawW-sprtX+1; - - - bWT=FALSE; - bWS=FALSE; - - switch (GlobalTextTP) - { - case 0: - - if(textX0&1) {bWS=TRUE;sprtW--;} - if(sprtW&1) bWT=TRUE; - - sprtW=sprtW>>1; - textX0=(GlobalTextAddrX<<1)+(textX0>>1)+(textY0<<11); - sprtYa=(sprtY<<10)+sprtX; - clutP=(clutY0<<10)+clutX0; - -#ifdef FASTSOLID - - if(!bCheckMask && !DrawSemiTrans) - { - for (sprCY=0;sprCY>4)&0xf)]); - } - - for (sprCX=0;sprCX>4)&0xf)])<<16)| - psxVuw[clutP+(tC&0x0f)]); - } - - if(bWT) - { - tC=*pV; - GetTextureTransColG_S(&psxVuw[sprA],psxVuw[clutP+(tC&0x0f)]); - } - } - return; - } - -#endif - - for (sprCY=0;sprCY>4)&0xf)]); - } - - for (sprCX=0;sprCX>4)&0xf)])<<16)| - psxVuw[clutP+(tC&0x0f)]); - } - - if(bWT) - { - tC=*pV; - GetTextureTransColG_SPR(&psxVuw[sprA],psxVuw[clutP+(tC&0x0f)]); - } - } - return; - - case 1: - clutP>>=1;sprtW--; - textX0+=(GlobalTextAddrX<<1) + (textY0<<11); - -#ifdef FASTSOLID - - if(!bCheckMask && !DrawSemiTrans) - { - for(sprCY=0;sprCY 0) - { - dr = ((int)r1 - (int)r0) / dx; - dg = ((int)g1 - (int)g0) / dx; - db = ((int)b1 - (int)b0) / dx; - } - else - { - dr = ((int)r1 - (int)r0); - dg = ((int)g1 - (int)g0); - db = ((int)b1 - (int)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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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; - int 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 = ((int)r1 - (int)r0) / dy; - dg = ((int)g1 - (int)g0) / dy; - db = ((int)b1 - (int)b0) / dy; - } - else - { - dr = ((int)r1 - (int)r0); - dg = ((int)g1 - (int)g0); - db = ((int)b1 - (int)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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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; - int 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 = ((uint32_t)r1 - (uint32_t)r0) / dy; - dg = ((uint32_t)g1 - (uint32_t)g0) / dy; - db = ((uint32_t)b1 - (uint32_t)b0) / dy; - } - else - { - dr = ((uint32_t)r1 - (uint32_t)r0); - dg = ((uint32_t)g1 - (uint32_t)g0); - db = ((uint32_t)b1 - (uint32_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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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; - int 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 = ((int)r1 - (int)r0) / dx; - dg = ((int)g1 - (int)g0) / dx; - db = ((int)b1 - (int)b0) / dx; - } - else - { - dr = ((int)r1 - (int)r0); - dg = ((int)g1 - (int)g0); - db = ((int)b1 - (int)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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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; - int 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 = ((int)r1 - (int)r0) / dy; - dg = ((int)g1 - (int)g0) / dy; - db = ((int)b1 - (int)b0) / dy; - } - else - { - dr = ((int)r1 - (int)r0); - dg = ((int)g1 - (int)g0); - db = ((int)b1 - (int)b0); - } - - if (y0 < drawY) - { - r0+=dr*(drawY - y0); - g0+=dg*(drawY - y0); - b0+=db*(drawY - y0); - y0 = drawY; - } - - if (y1 > drawH) - y1 = drawH; - - for (y = y0; y <= y1; y++) - { - GetShadeTransCol(&psxVuw[(y<<10)+x],(unsigned short)(((r0 >> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); - r0+=dr; - g0+=dg; - b0+=db; - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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; - int 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 = ((int)r1 - (int)r0) / dx; - dg = ((int)g1 - (int)g0) / dx; - db = ((int)b1 - (int)b0) / dx; - } - else - { - dr = ((int)r1 - (int)r0); - dg = ((int)g1 - (int)g0); - db = ((int)b1 - (int)b0); - } - - if (x0 < drawX) - { - r0+=dr*(drawX - x0); - g0+=dg*(drawX - x0); - b0+=db*(drawX - x0); - x0 = drawX; - } - - if (x1 > drawW) - x1 = drawW; - - for (x = x0; x <= x1; x++) - { - GetShadeTransCol(&psxVuw[(y<<10)+x],(unsigned short)(((r0 >> 9)&0x7c00)|((g0 >> 14)&0x03e0)|((b0 >> 19)&0x001f))); - r0+=dr; - g0+=dg; - b0+=db; - } -} - -/////////////////////////////////////////////////////////////////////// - -static 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>=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y y1) - { - if (d <= 0) - { - d = d + incrN; /* Choose N */ - y--; - } - else - { - d = d + incrNE; /* Choose NE */ - x++; - y--; - } - if ((x>=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y drawH) - y1 = drawH; - - for (y = y0; y <= y1; y++) - GetShadeTransCol(&psxVuw[(y<<10)+x], colour); -} - -/////////////////////////////////////////////////////////////////////// - -static void HorzLineFlat(int y, int x0, int x1, unsigned short colour) -{ - int x; - - if (x0 < drawX) - x0 = drawX; - - if (x1 > drawW) - x1 = drawW; - - for (x = x0; x <= x1; x++) - GetShadeTransCol(&psxVuw[(y<<10)+x], colour); -} - -/////////////////////////////////////////////////////////////////////// - -/* Bresenham Line drawing function */ -static void DrawSoftwareLineShade(int rgb0, int rgb1) -{ - short x0, y0, x1, y1, xt, yt; - int rgbt; - double m, dy, dx; - - if(lx0>drawW && lx1>drawW) return; - if(ly0>drawH && ly1>drawH) return; - if(lx0=drawH) return; - if(drawX>=drawW) return; - - x0 = lx0; - y0 = ly0; - x1 = lx1; - y1 = 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); - } -} - -/////////////////////////////////////////////////////////////////////// - -static void DrawSoftwareLineFlat(int rgb) -{ - short x0, y0, x1, y1, xt, yt; - double m, dy, dx; - unsigned short colour = 0; - - if(lx0>drawW && lx1>drawW) return; - if(ly0>drawH && ly1>drawH) return; - if(lx0=drawH) return; - if(drawX>=drawW) return; - - colour = ((rgb & 0x00f80000)>>9) | ((rgb & 0x0000f800)>>6) | ((rgb & 0x000000f8)>>3); - - x0 = lx0; - y0 = ly0; - x1 = lx1; - y1 = 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); - } -} -#endif - -/////////////////////////////////////////////////////////////////////// +/*************************************************************************** + soft.c - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "stdafx.h" + +#define _IN_SOFT + +#include "externals.h" +#include "soft.h" + +int iDither = 0; + +//////////////////////////////////////////////////////////////////////////////////// +// "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 +//////////////////////////////////////////////////////////////////////////////////// + +short g_m1 = 255, g_m2 = 255, g_m3 = 255; +short DrawSemiTrans = FALSE; +short Ymin; +short Ymax; + +short ly0, lx0, ly1, lx1, ly2, lx2, ly3, lx3; // global psx vertex coords +int GlobalTextAddrX, GlobalTextAddrY, GlobalTextTP; +int GlobalTextREST, GlobalTextABR, GlobalTextPAGE; + +//////////////////////////////////////////////////////////////////////// +// POLYGON OFFSET FUNCS +//////////////////////////////////////////////////////////////////////// + +void offsetPSXLine(void) +{ + short x0,x1,y0,y1,dx,dy;float px,py; + + x0 = lx0+1+PSXDisplay.DrawOffset.x; + x1 = lx1+1+PSXDisplay.DrawOffset.x; + y0 = ly0+1+PSXDisplay.DrawOffset.y; + y1 = ly1+1+PSXDisplay.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(dxdy) px= 0.5f; + else if(dx=0) + { + py=0.5f; + dx=-dx; + if(dx>dy) px=-0.5f; + else if(dxdy) py=-0.5f; + else if(dx> 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++; + + *pdest=((unsigned short)b<<10) | + ((unsigned short)g<<5) | + (unsigned short)r | sM; +} + +///////////////////////////////////////////////////////////////// + +__inline void GetShadeTransCol_Dither(unsigned short *pdest, int m1, int m2, int m3) +{ + int r,g,b; + + if (bCheckMask && *pdest & 0x8000) return; + + if (DrawSemiTrans) + { + r=((XCOL1D(*pdest))<<3); + b=((XCOL2D(*pdest))<<3); + g=((XCOL3D(*pdest))<<3); + + if(GlobalTextABR==0) + { + r=(r>>1)+(m1>>1); + b=(b>>1)+(m2>>1); + g=(g>>1)+(m3>>1); + } + else + if(GlobalTextABR==1) + { + r+=m1; + b+=m2; + g+=m3; + } + else + if(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,sSetMask); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetShadeTransCol(unsigned short * pdest,unsigned short color) +{ + if(bCheckMask && *pdest&0x8000) return; + + if(DrawSemiTrans) + { + int r,g,b; + + if(GlobalTextABR==0) + { + *pdest=((((*pdest)&0x7bde)>>1)+(((color)&0x7bde)>>1))|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(GlobalTextABR==1) + { + r=(XCOL1(*pdest))+((XCOL1(color))); + b=(XCOL2(*pdest))+((XCOL2(color))); + g=(XCOL3(*pdest))+((XCOL3(color))); + } + else + if(GlobalTextABR==2) + { + r=(XCOL1(*pdest))-((XCOL1(color))); + b=(XCOL2(*pdest))-((XCOL2(color))); + g=(XCOL3(*pdest))-((XCOL3(color))); + if(r&0x80000000) r=0; + if(b&0x80000000) b=0; + if(g&0x80000000) g=0; + } + else + { +#ifdef HALFBRIGHTMODE3 + r=(XCOL1(*pdest))+((XCOL1(color))>>2); + b=(XCOL2(*pdest))+((XCOL2(color))>>2); + g=(XCOL3(*pdest))+((XCOL3(color))>>2); +#else + r=(XCOL1(*pdest))+((XCOL1(color))>>1); + b=(XCOL2(*pdest))+((XCOL2(color))>>1); + g=(XCOL3(*pdest))+((XCOL3(color))>>1); +#endif + } + + if(r&0x7FFFFFE0) r=0x1f; + if(b&0x7FFFFC00) b=0x3e0; + if(g&0x7FFF8000) g=0x7c00; + + *pdest=(XPSXCOL(r,g,b))|sSetMask;//0x8000; + } + else *pdest=color|sSetMask; +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetShadeTransCol32(uint32_t *pdest, uint32_t color) +{ + if (DrawSemiTrans) + { + int r,g,b; + + if(GlobalTextABR==0) + { + if(!bCheckMask) + { + *pdest=((((*pdest)&0x7bde7bde)>>1)+(((color)&0x7bde7bde)>>1))|lSetMask;//0x80008000; + return; + } + r=(X32ACOL1(*pdest)>>1)+((X32ACOL1(color))>>1); + b=(X32ACOL2(*pdest)>>1)+((X32ACOL2(color))>>1); + g=(X32ACOL3(*pdest)>>1)+((X32ACOL3(color))>>1); + } + else + if(GlobalTextABR==1) + { + r=(X32COL1(*pdest))+((X32COL1(color))); + b=(X32COL2(*pdest))+((X32COL2(color))); + g=(X32COL3(*pdest))+((X32COL3(color))); + } + else + if(GlobalTextABR==2) + { + int sr,sb,sg,src,sbc,sgc,c; + src=XCOL1(color);sbc=XCOL2(color);sgc=XCOL3(color); + c=(*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=((int)sr)<<16;b=((int)sb)<<11;g=((int)sg)<<6; + c=LOWORD(*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(*pdest))+((X32BCOL1(color))>>2); + b=(X32COL2(*pdest))+((X32BCOL2(color))>>2); + g=(X32COL3(*pdest))+((X32BCOL3(color))>>2); +#else + r=(X32COL1(*pdest))+((X32ACOL1(color))>>1); + b=(X32COL2(*pdest))+((X32ACOL2(color))>>1); + g=(X32COL3(*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(bCheckMask) + { + uint32_t ma=*pdest; + *pdest=(X32PSXCOL(r,g,b))|lSetMask;//0x80008000; + if(ma&0x80000000) *pdest=(ma&0xFFFF0000)|(*pdest&0xFFFF); + if(ma&0x00008000) *pdest=(ma&0xFFFF) |(*pdest&0xFFFF0000); + return; + } + *pdest=(X32PSXCOL(r,g,b))|lSetMask;//0x80008000; + } + else + { + if(bCheckMask) + { + uint32_t ma=*pdest; + *pdest=color|lSetMask;//0x80008000; + if(ma&0x80000000) *pdest=(ma&0xFFFF0000)|(*pdest&0xFFFF); + if(ma&0x00008000) *pdest=(ma&0xFFFF) |(*pdest&0xFFFF0000); + return; + } + + *pdest=color|lSetMask;//0x80008000; + } +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColG(unsigned short * pdest,unsigned short color) +{ + int r,g,b;unsigned short l; + + if(color==0) return; + + if(bCheckMask && *pdest&0x8000) return; + + l=sSetMask|(color&0x8000); + + if(DrawSemiTrans && (color&0x8000)) + { + if(GlobalTextABR==0) + { + unsigned short d; + d =((*pdest)&0x7bde)>>1; + color =((color) &0x7bde)>>1; + r=(XCOL1(d))+((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(d))+((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(d))+((((XCOL3(color)))* g_m3)>>7); + +/* + r=(XCOL1(*pdest)>>1)+((((XCOL1(color))>>1)* g_m1)>>7); + b=(XCOL2(*pdest)>>1)+((((XCOL2(color))>>1)* g_m2)>>7); + g=(XCOL3(*pdest)>>1)+((((XCOL3(color))>>1)* g_m3)>>7); +*/ + } + else + if(GlobalTextABR==1) + { + r=(XCOL1(*pdest))+((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(*pdest))+((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(*pdest))+((((XCOL3(color)))* g_m3)>>7); + } + else + if(GlobalTextABR==2) + { + r=(XCOL1(*pdest))-((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(*pdest))-((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(*pdest))-((((XCOL3(color)))* g_m3)>>7); + if(r&0x80000000) r=0; + if(b&0x80000000) b=0; + if(g&0x80000000) g=0; + } + else + { +#ifdef HALFBRIGHTMODE3 + r=(XCOL1(*pdest))+((((XCOL1(color))>>2)* g_m1)>>7); + b=(XCOL2(*pdest))+((((XCOL2(color))>>2)* g_m2)>>7); + g=(XCOL3(*pdest))+((((XCOL3(color))>>2)* g_m3)>>7); +#else + r=(XCOL1(*pdest))+((((XCOL1(color))>>1)* g_m1)>>7); + b=(XCOL2(*pdest))+((((XCOL2(color))>>1)* g_m2)>>7); + g=(XCOL3(*pdest))+((((XCOL3(color))>>1)* g_m3)>>7); +#endif + } + } + else + { + r=((XCOL1(color))* g_m1)>>7; + b=((XCOL2(color))* g_m2)>>7; + g=((XCOL3(color))* g_m3)>>7; + } + + if(r&0x7FFFFFE0) r=0x1f; + if(b&0x7FFFFC00) b=0x3e0; + if(g&0x7FFF8000) g=0x7c00; + + *pdest=(XPSXCOL(r,g,b))|l; +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColG_S(unsigned short * pdest,unsigned short color) +{ + int r,g,b;unsigned short l; + + if(color==0) return; + + l=sSetMask|(color&0x8000); + + r=((XCOL1(color))* g_m1)>>7; + b=((XCOL2(color))* g_m2)>>7; + g=((XCOL3(color))* g_m3)>>7; + + if(r&0x7FFFFFE0) r=0x1f; + if(b&0x7FFFFC00) b=0x3e0; + if(g&0x7FFF8000) g=0x7c00; + + *pdest=(XPSXCOL(r,g,b))|l; +} + + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColG_SPR(unsigned short * pdest,unsigned short color) +{ + int r,g,b;unsigned short l; + + if(color==0) return; + + if(bCheckMask && *pdest&0x8000) return; + + l=sSetMask|(color&0x8000); + + if(DrawSemiTrans && (color&0x8000)) + { + if(GlobalTextABR==0) + { + unsigned short d; + d =((*pdest)&0x7bde)>>1; + color =((color) &0x7bde)>>1; + r=(XCOL1(d))+((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(d))+((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(d))+((((XCOL3(color)))* g_m3)>>7); + +/* + r=(XCOL1(*pdest)>>1)+((((XCOL1(color))>>1)* g_m1)>>7); + b=(XCOL2(*pdest)>>1)+((((XCOL2(color))>>1)* g_m2)>>7); + g=(XCOL3(*pdest)>>1)+((((XCOL3(color))>>1)* g_m3)>>7); +*/ + } + else + if(GlobalTextABR==1) + { + r=(XCOL1(*pdest))+((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(*pdest))+((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(*pdest))+((((XCOL3(color)))* g_m3)>>7); + } + else + if(GlobalTextABR==2) + { + r=(XCOL1(*pdest))-((((XCOL1(color)))* g_m1)>>7); + b=(XCOL2(*pdest))-((((XCOL2(color)))* g_m2)>>7); + g=(XCOL3(*pdest))-((((XCOL3(color)))* g_m3)>>7); + if(r&0x80000000) r=0; + if(b&0x80000000) b=0; + if(g&0x80000000) g=0; + } + else + { +#ifdef HALFBRIGHTMODE3 + r=(XCOL1(*pdest))+((((XCOL1(color))>>2)* g_m1)>>7); + b=(XCOL2(*pdest))+((((XCOL2(color))>>2)* g_m2)>>7); + g=(XCOL3(*pdest))+((((XCOL3(color))>>2)* g_m3)>>7); +#else + r=(XCOL1(*pdest))+((((XCOL1(color))>>1)* g_m1)>>7); + b=(XCOL2(*pdest))+((((XCOL2(color))>>1)* g_m2)>>7); + g=(XCOL3(*pdest))+((((XCOL3(color))>>1)* g_m3)>>7); +#endif + } + } + else + { + r=((XCOL1(color))* g_m1)>>7; + b=((XCOL2(color))* g_m2)>>7; + g=((XCOL3(color))* g_m3)>>7; + } + + if(r&0x7FFFFFE0) r=0x1f; + if(b&0x7FFFFC00) b=0x3e0; + if(g&0x7FFF8000) g=0x7c00; + + *pdest=(XPSXCOL(r,g,b))|l; +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColG32(uint32_t *pdest, uint32_t color) +{ + int r,g,b,l; + + if(color==0) return; + + l=lSetMask|(color&0x80008000); + + if(DrawSemiTrans && (color&0x80008000)) + { + if(GlobalTextABR==0) + { + r=((((X32TCOL1(*pdest))+((X32COL1(color)) * g_m1))&0xFF00FF00)>>8); + b=((((X32TCOL2(*pdest))+((X32COL2(color)) * g_m2))&0xFF00FF00)>>8); + g=((((X32TCOL3(*pdest))+((X32COL3(color)) * g_m3))&0xFF00FF00)>>8); + } + else + if(GlobalTextABR==1) + { + r=(X32COL1(*pdest))+(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(*pdest))+(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(*pdest))+(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); + } + else + if(GlobalTextABR==2) + { + int t; + r=(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); + t=(*pdest&0x001f0000)-(r&0x003f0000); if(t&0x80000000) t=0; + r=(*pdest&0x0000001f)-(r&0x0000003f); if(r&0x80000000) r=0; + r|=t; + + b=(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); + t=((*pdest>>5)&0x001f0000)-(b&0x003f0000); if(t&0x80000000) t=0; + b=((*pdest>>5)&0x0000001f)-(b&0x0000003f); if(b&0x80000000) b=0; + b|=t; + + g=(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); + t=((*pdest>>10)&0x001f0000)-(g&0x003f0000); if(t&0x80000000) t=0; + g=((*pdest>>10)&0x0000001f)-(g&0x0000003f); if(g&0x80000000) g=0; + g|=t; + } + else + { +#ifdef HALFBRIGHTMODE3 + r=(X32COL1(*pdest))+(((((X32BCOL1(color))>>2)* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(*pdest))+(((((X32BCOL2(color))>>2)* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(*pdest))+(((((X32BCOL3(color))>>2)* g_m3)&0xFF80FF80)>>7); +#else + r=(X32COL1(*pdest))+(((((X32ACOL1(color))>>1)* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(*pdest))+(((((X32ACOL2(color))>>1)* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(*pdest))+(((((X32ACOL3(color))>>1)* g_m3)&0xFF80FF80)>>7); +#endif + } + + if(!(color&0x8000)) + { + r=(r&0xffff0000)|((((X32COL1(color))* g_m1)&0x0000FF80)>>7); + b=(b&0xffff0000)|((((X32COL2(color))* g_m2)&0x0000FF80)>>7); + g=(g&0xffff0000)|((((X32COL3(color))* g_m3)&0x0000FF80)>>7); + } + if(!(color&0x80000000)) + { + r=(r&0xffff)|((((X32COL1(color))* g_m1)&0xFF800000)>>7); + b=(b&0xffff)|((((X32COL2(color))* g_m2)&0xFF800000)>>7); + g=(g&0xffff)|((((X32COL3(color))* g_m3)&0xFF800000)>>7); + } + + } + else + { + r=(((X32COL1(color))* g_m1)&0xFF80FF80)>>7; + b=(((X32COL2(color))* g_m2)&0xFF80FF80)>>7; + g=(((X32COL3(color))* 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(bCheckMask) + { + uint32_t ma=*pdest; + + *pdest=(X32PSXCOL(r,g,b))|l; + + if((color&0xffff)==0 ) *pdest=(ma&0xffff)|(*pdest&0xffff0000); + if((color&0xffff0000)==0) *pdest=(ma&0xffff0000)|(*pdest&0xffff); + if(ma&0x80000000) *pdest=(ma&0xFFFF0000)|(*pdest&0xFFFF); + if(ma&0x00008000) *pdest=(ma&0xFFFF) |(*pdest&0xFFFF0000); + + return; + } + if((color&0xffff)==0 ) {*pdest=(*pdest&0xffff)|(((X32PSXCOL(r,g,b))|l)&0xffff0000);return;} + if((color&0xffff0000)==0) {*pdest=(*pdest&0xffff0000)|(((X32PSXCOL(r,g,b))|l)&0xffff);return;} + + *pdest=(X32PSXCOL(r,g,b))|l; +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColG32_S(uint32_t *pdest, uint32_t color) +{ + int r,g,b; + + if(color==0) return; + + r=(((X32COL1(color))* g_m1)&0xFF80FF80)>>7; + b=(((X32COL2(color))* g_m2)&0xFF80FF80)>>7; + g=(((X32COL3(color))* 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) {*pdest=(*pdest&0xffff)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff0000);return;} + if((color&0xffff0000)==0) {*pdest=(*pdest&0xffff0000)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff);return;} + + *pdest=(X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColG32_SPR(uint32_t *pdest, uint32_t color) +{ + int r,g,b; + + if(color==0) return; + + if(DrawSemiTrans && (color&0x80008000)) + { + if(GlobalTextABR==0) + { + r=((((X32TCOL1(*pdest))+((X32COL1(color)) * g_m1))&0xFF00FF00)>>8); + b=((((X32TCOL2(*pdest))+((X32COL2(color)) * g_m2))&0xFF00FF00)>>8); + g=((((X32TCOL3(*pdest))+((X32COL3(color)) * g_m3))&0xFF00FF00)>>8); + } + else + if(GlobalTextABR==1) + { + r=(X32COL1(*pdest))+(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(*pdest))+(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(*pdest))+(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); + } + else + if(GlobalTextABR==2) + { + int t; + r=(((((X32COL1(color)))* g_m1)&0xFF80FF80)>>7); + t=(*pdest&0x001f0000)-(r&0x003f0000); if(t&0x80000000) t=0; + r=(*pdest&0x0000001f)-(r&0x0000003f); if(r&0x80000000) r=0; + r|=t; + + b=(((((X32COL2(color)))* g_m2)&0xFF80FF80)>>7); + t=((*pdest>>5)&0x001f0000)-(b&0x003f0000); if(t&0x80000000) t=0; + b=((*pdest>>5)&0x0000001f)-(b&0x0000003f); if(b&0x80000000) b=0; + b|=t; + + g=(((((X32COL3(color)))* g_m3)&0xFF80FF80)>>7); + t=((*pdest>>10)&0x001f0000)-(g&0x003f0000); if(t&0x80000000) t=0; + g=((*pdest>>10)&0x0000001f)-(g&0x0000003f); if(g&0x80000000) g=0; + g|=t; + } + else + { +#ifdef HALFBRIGHTMODE3 + r=(X32COL1(*pdest))+(((((X32BCOL1(color))>>2)* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(*pdest))+(((((X32BCOL2(color))>>2)* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(*pdest))+(((((X32BCOL3(color))>>2)* g_m3)&0xFF80FF80)>>7); +#else + r=(X32COL1(*pdest))+(((((X32ACOL1(color))>>1)* g_m1)&0xFF80FF80)>>7); + b=(X32COL2(*pdest))+(((((X32ACOL2(color))>>1)* g_m2)&0xFF80FF80)>>7); + g=(X32COL3(*pdest))+(((((X32ACOL3(color))>>1)* g_m3)&0xFF80FF80)>>7); +#endif + } + + if(!(color&0x8000)) + { + r=(r&0xffff0000)|((((X32COL1(color))* g_m1)&0x0000FF80)>>7); + b=(b&0xffff0000)|((((X32COL2(color))* g_m2)&0x0000FF80)>>7); + g=(g&0xffff0000)|((((X32COL3(color))* g_m3)&0x0000FF80)>>7); + } + if(!(color&0x80000000)) + { + r=(r&0xffff)|((((X32COL1(color))* g_m1)&0xFF800000)>>7); + b=(b&0xffff)|((((X32COL2(color))* g_m2)&0xFF800000)>>7); + g=(g&0xffff)|((((X32COL3(color))* g_m3)&0xFF800000)>>7); + } + + } + else + { + r=(((X32COL1(color))* g_m1)&0xFF80FF80)>>7; + b=(((X32COL2(color))* g_m2)&0xFF80FF80)>>7; + g=(((X32COL3(color))* 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(bCheckMask) + { + uint32_t ma=*pdest; + + *pdest=(X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000); + + if((color&0xffff)==0 ) *pdest=(ma&0xffff)|(*pdest&0xffff0000); + if((color&0xffff0000)==0) *pdest=(ma&0xffff0000)|(*pdest&0xffff); + if(ma&0x80000000) *pdest=(ma&0xFFFF0000)|(*pdest&0xFFFF); + if(ma&0x00008000) *pdest=(ma&0xFFFF) |(*pdest&0xFFFF0000); + + return; + } + if((color&0xffff)==0 ) {*pdest=(*pdest&0xffff)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff0000);return;} + if((color&0xffff0000)==0) {*pdest=(*pdest&0xffff0000)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff);return;} + + *pdest=(X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColGX_Dither(unsigned short * pdest, unsigned short color, int m1, int m2, int m3) +{ + int r,g,b; + + if(color==0) return; + + if(bCheckMask && *pdest&0x8000) return; + + m1=(((XCOL1D(color)))*m1)>>4; + m2=(((XCOL2D(color)))*m2)>>4; + m3=(((XCOL3D(color)))*m3)>>4; + + if(DrawSemiTrans && (color&0x8000)) + { + r=((XCOL1D(*pdest))<<3); + b=((XCOL2D(*pdest))<<3); + g=((XCOL3D(*pdest))<<3); + + if(GlobalTextABR==0) + { + r=(r>>1)+(m1>>1); + b=(b>>1)+(m2>>1); + g=(g>>1)+(m3>>1); + } + else + if(GlobalTextABR==1) + { + r+=m1; + b+=m2; + g+=m3; + } + else + if(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,sSetMask|(color&0x8000)); + +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColGX(unsigned short * pdest,unsigned short color,short m1,short m2,short m3) +{ + int r,g,b;unsigned short l; + + if(color==0) return; + + if(bCheckMask && *pdest&0x8000) return; + + l=sSetMask|(color&0x8000); + + if(DrawSemiTrans && (color&0x8000)) + { + if(GlobalTextABR==0) + { + unsigned short d; + d =((*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(GlobalTextABR==1) + { + r=(XCOL1(*pdest))+((((XCOL1(color)))* m1)>>7); + b=(XCOL2(*pdest))+((((XCOL2(color)))* m2)>>7); + g=(XCOL3(*pdest))+((((XCOL3(color)))* m3)>>7); + } + else + if(GlobalTextABR==2) + { + r=(XCOL1(*pdest))-((((XCOL1(color)))* m1)>>7); + b=(XCOL2(*pdest))-((((XCOL2(color)))* m2)>>7); + g=(XCOL3(*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(*pdest))+((((XCOL1(color))>>2)* m1)>>7); + b=(XCOL2(*pdest))+((((XCOL2(color))>>2)* m2)>>7); + g=(XCOL3(*pdest))+((((XCOL3(color))>>2)* m3)>>7); +#else + r=(XCOL1(*pdest))+((((XCOL1(color))>>1)* m1)>>7); + b=(XCOL2(*pdest))+((((XCOL2(color))>>1)* m2)>>7); + g=(XCOL3(*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; + + *pdest=(XPSXCOL(r,g,b))|l; +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColGX_S(unsigned short * pdest,unsigned short color,short m1,short m2,short m3) +{ + int 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; + + *pdest=(XPSXCOL(r,g,b))|sSetMask|(color&0x8000); +} + +//////////////////////////////////////////////////////////////////////// + +__inline void GetTextureTransColGX32_S(uint32_t *pdest, uint32_t color, short m1, short m2, short m3) +{ + int 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) {*pdest=(*pdest&0xffff)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff0000);return;} + if((color&0xffff0000)==0) {*pdest=(*pdest&0xffff0000)|(((X32PSXCOL(r,g,b))|lSetMask|(color&0x80008000))&0xffff);return;} + + *pdest=(X32PSXCOL(r,g,b))|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(x1drawW) return; + if(y0>drawH) return; + + x1=min(x1,drawW+1); + y1=min(y1,drawH+1); + x0=max(x0,drawX); + y0=max(y0,drawY); + + if(y0>=iGPUHeight) return; + if(x0>1023) return; + + if(y1>iGPUHeight) y1=iGPUHeight; + 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 = psxVuw + (1024*y0) + x0; + LineOffset = 1024 - dx; + for(i=0;i>=1; + DSTPtr = (uint32_t *)(psxVuw + (1024*y0) + x0); + LineOffset = 512 - dx; + + if(!bCheckMask && !DrawSemiTrans) + { + for(i=0;iy1) return; + if(x0>x1) return; + + if(y0>=iGPUHeight) return; + if(x0>1023) return; + + if(y1>iGPUHeight) y1=iGPUHeight; + if(x1>1024) x1=1024; + + dx=x1-x0;dy=y1-y0; + if(dx&1) + { + unsigned short *DSTPtr; + unsigned short LineOffset; + + DSTPtr = psxVuw + (1024*y0) + x0; + LineOffset = 1024 - dx; + + for(i=0;i>=1; + DSTPtr = (uint32_t *)(psxVuw + (1024*y0) + x0); + LineOffset = 512 - dx; + + for(i=0;iy - 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 BOOL NextRow_F(void) +{ + if(--left_section_height<=0) + { + if(--left_section <= 0) {return TRUE;} + if(LeftSection_F() <= 0) {return TRUE;} + } + else + { + left_x += delta_left_x; + } + + if(--right_section_height<=0) + { + if(--right_section<=0) {return TRUE;} + if(RightSection_F() <=0) {return TRUE;} + } + else + { + right_x += delta_right_x; + } + return FALSE; +} + +__inline BOOL 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 FALSE;} + longest = (((v2->y - v1->y) << 16) / height) * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + if(longest == 0) {return FALSE;} + + 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 FALSE; + if(RightSection_F() <= 0) + { + right_section--; + if(RightSection_F() <= 0) return FALSE; + } + } + 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 FALSE; + if(LeftSection_F() <= 0) + { + left_section--; + if(LeftSection_F() <= 0) return FALSE; + } + } + + Ymin=v1->y; + Ymax=min(v3->y-1,drawH); + + return TRUE; +} + +__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 BOOL NextRow_G(void) +{ + if(--left_section_height<=0) + { + if(--left_section <= 0) {return TRUE;} + if(LeftSection_G() <= 0) {return TRUE;} + } + 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 TRUE;} + if(RightSection_G() <=0) {return TRUE;} + } + else + { + right_x += delta_right_x; + } + return FALSE; +} + +__inline BOOL SetupSections_G(short x1,short y1,short x2,short y2,short x3,short y3, int rgb1, int rgb2, int 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 FALSE;} + temp=(((v2->y - v1->y) << 16) / height); + longest = temp * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + if(longest == 0) {return FALSE;} + + 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 FALSE; + if(RightSection_G() <= 0) + { + right_section--; + if(RightSection_G() <= 0) return FALSE; + } + 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 FALSE; + if(LeftSection_G() <= 0) + { + left_section--; + if(LeftSection_G() <= 0) return FALSE; + } + if(longest < 0x1000) longest = 0x1000; + } + + Ymin=v1->y; + Ymax=min(v3->y-1,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 TRUE; +} + +__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 BOOL NextRow_FT(void) +{ + if(--left_section_height<=0) + { + if(--left_section <= 0) {return TRUE;} + if(LeftSection_FT() <= 0) {return TRUE;} + } + 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 TRUE;} + if(RightSection_FT() <=0) {return TRUE;} + } + else + { + right_x += delta_right_x; + } + return FALSE; +} + +__inline BOOL 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 FALSE;} + + temp=(((v2->y - v1->y) << 16) / height); + longest = temp * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + + if(longest == 0) {return FALSE;} + + 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 FALSE; + if(RightSection_FT() <= 0) + { + right_section--; + if(RightSection_FT() <= 0) return FALSE; + } + 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 FALSE; + if(LeftSection_FT() <= 0) + { + left_section--; + if(LeftSection_FT() <= 0) return FALSE; + } + if(longest < 0x1000) longest = 0x1000; + } + + Ymin=v1->y; + Ymax=min(v3->y-1,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 TRUE; +} + +__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 BOOL NextRow_GT(void) +{ + if(--left_section_height<=0) + { + if(--left_section <= 0) {return TRUE;} + if(LeftSection_GT() <= 0) {return TRUE;} + } + 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 TRUE;} + if(RightSection_GT() <=0) {return TRUE;} + } + else + { + right_x += delta_right_x; + } + return FALSE; +} + +__inline BOOL 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, int rgb1, int rgb2, int 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 FALSE;} + + temp=(((v2->y - v1->y) << 16) / height); + longest = temp * ((v3->x - v1->x)>>16) + (v1->x - v2->x); + + if(longest == 0) {return FALSE;} + + 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 FALSE; + if(RightSection_GT() <= 0) + { + right_section--; + if(RightSection_GT() <= 0) return FALSE; + } + + 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 FALSE; + if(LeftSection_GT() <= 0) + { + left_section--; + if(LeftSection_GT() <= 0) return FALSE; + } + if(longest < 0x1000) longest = 0x1000; + } + + Ymin=v1->y; + Ymax=min(v3->y-1,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 TRUE; +} + +__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 BOOL 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 FALSE; +} + +__inline BOOL 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; + } + + Ymin=v1->y; + Ymax=min(v4->y-1,drawH); + + return TRUE; +} + +__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 BOOL 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 FALSE; +} + +__inline BOOL 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; + } + + Ymin=v1->y; + Ymax=min(v4->y-1,drawH); + + return TRUE; +} + +__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 BOOL 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 FALSE; +} + +__inline BOOL 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, int rgb1, int rgb2, int rgb3, int 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; + } + + Ymin=v1->y; + Ymax=min(v4->y-1,drawH); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// POLY FUNCS +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// POLY 3/4 FLAT SHADED +//////////////////////////////////////////////////////////////////////// + +__inline void drawPoly3Fi(short x1, short y1, short x2, short y2, short x3, short y3, int rgb) +{ + int i,j,xmin,xmax,ymin,ymax; + unsigned short color; + uint32_t lcolor; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_F(x1,y1,x2,y2,x3,y3)) return; + + ymax=Ymax; + + color = ((rgb & 0x00f80000)>>9) | ((rgb & 0x0000f800)>>6) | ((rgb & 0x000000f8)>>3); + lcolor=lSetMask|(((uint32_t)(color))<<16)|color; + + for(ymin=Ymin;ymin> 16; if(drawX>xmin) xmin=drawX; + xmax=(right_x >> 16)-1; if(drawW> 16; if(drawX>xmin) xmin=drawX; + xmax=(right_x >> 16)-1; if(drawWdrawW && lx1>drawW && lx2>drawW && lx3>drawW) return; + if(ly0>drawH && ly1>drawH && ly2>drawH && ly3>drawH) return; + if(lx0=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_F4(lx0,ly0,lx1,ly1,lx2,ly2,lx3,ly3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin>9) | ((rgb & 0x0000f800)>>6) | ((rgb & 0x000000f8)>>3); + lcolor= lSetMask|(((uint32_t)(color))<<16)|color; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + color |=sSetMask; + for (i=ymin;i<=ymax;i++) + { + xmin=left_x >> 16; if(drawX>xmin) xmin=drawX; + xmax=(right_x >> 16)-1; if(drawW> 16; if(drawX > xmin) xmin = drawX; + xmax = (right_x >> 16) - 1; if(drawW < xmax) xmax = drawW; + + for(j = xmin; j < xmax; j += 2) + { + GetShadeTransCol32((uint32_t *)&psxVuw[(i<<10) + j],lcolor); + } + if(j == xmax) GetShadeTransCol(&psxVuw[(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; + int difX, difY,difX2, difY2; + int posX,posY,YAdjust,XAdjust; + int clutP; + short tC1,tC2; + + if (x1 > drawW && x2 > drawW && x3 > drawW) return; + if (y1 > drawH && y2 > drawH && y3 > drawH) return; + if (x1 < drawX && x2 < drawX && x3 < drawX) return; + if (y1 < drawY && y2 < drawY && y3 < drawY) return; + if (drawY >= drawH) return; + if (drawX >= drawW) return; + + if (!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax = Ymax; + + for (ymin = Ymin; ymin < drawY; ymin++) + if (NextRow_FT()) return; + + clutP = (clY << 10) + clX; + + YAdjust = ((GlobalTextAddrY) << 11) + (GlobalTextAddrX << 1); + + difX = delta_right_u; difX2 = difX << 1; + difY = delta_right_v; difY2 = difY << 1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16); + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16); + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[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; + int difX, difY,difX2, difY2; + int posX,posY,YAdjust,XAdjust; + int clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[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; + int difX, difY,difX2, difY2; + int posX,posY,YAdjust,XAdjust; + int clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin>1); + + difX=delta_right_u;difX2=difX<<1; + difY=delta_right_v;difY2=difY<<1; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16);//-1; //!!!!!!!!!!!!!!!! + if(xmax>xmin) xmax--; + + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i << 10) + j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[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) +{ + int num; + int i,j,xmin,xmax,ymin,ymax; + int difX, difY, difX2, difY2; + int posX,posY,YAdjust,clutP,XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16); + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>16); + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16); + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[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) +{ + int num; + int i,j,xmin,xmax,ymin,ymax,n_xi,n_yi,TXV; + int difX, difY, difX2, difY2; + int posX,posY,YAdjust,clutP,XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[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) +{ + int num; + int i,j,xmin,xmax,ymin,ymax; + int difX, difY, difX2, difY2; + int posX,posY,YAdjust,clutP,XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin>1); + +#ifdef FASTSOLID + + if(!bCheckMask && !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>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[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) +{ + int num; + int i,j,xmin,xmax,ymin,ymax; + int difX, difY, difX2, difY2; + int posX,posY,YAdjust,clutP,XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin>1); + +#ifdef FASTSOLID + + if(!bCheckMask && !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>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColG32_SPR((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + XAdjust=(posX>>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColG_SPR(&psxVuw[(i<<10)+j],psxVuw[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; + int difX, difY,difX2, difY2; + int posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; + tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ + ((posX+difX)>>16)]; + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX+=difX2; + posY+=difY2; + } + + if(j==xmax) + { + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; + tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ + ((posX+difX)>>16)]; + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX+=difX2; + posY+=difY2; + } + + if(j==xmax) + { + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; + GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[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; + int difX, difY,difX2, difY2; + int posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[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; + int difX, difY,difX2, difY2; + int posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16);//-1; //!!!!!!!!!!!!!!!! + if(xmax>xmin) xmax--; + + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX+=difX2; + posY+=difY2; + } + + if(j==xmax) + { + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[clutP+tC1]); + } + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX+=difX2; + posY+=difY2; + } + + if(j==xmax) + { + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[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) +{ + int num; + int i,j,xmin,xmax,ymin,ymax; + int difX, difY, difX2, difY2; + int posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; + tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ + ((posX+difX)>>16)]; + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; + tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ + ((posX+difX)>>16)]; + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; + GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[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) +{ + int num; + int i,j,xmin,xmax,ymin,ymax,n_xi,n_yi,TXV,TXU; + int difX, difY, difX2, difY2; + int posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; + GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[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) +{ + int num; + int i, j, xmin, xmax, ymin, ymax; + int difX, difY, difX2, difY2; + int posX, posY, YAdjust, clutP; + short tC1, tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX += difX2; + posY += difY2; + } + if(j==xmax) + { + tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG(&psxVuw[(i<<10)+j],psxVuw[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) +{ + int num; + int i,j,xmin,xmax,ymin,ymax; + int difX, difY, difX2, difY2; + int posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG_S(&psxVuw[(i<<10)+j],psxVuw[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>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + GetTextureTransColG32_SPR((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[clutP+tC2])<<16); + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + { + tC1 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColG_SPR(&psxVuw[(i<<10)+j],psxVuw[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; + int difX, difY,difX2, difY2; + int posX,posY; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX])<<16)| + psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX]); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_S(&psxVuw[(i<<10)+j], + psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX]); + } + if(NextRow_FT()) + { + return; + } + } + return; + } + +#endif + + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX])<<16)| + psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX]); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG(&psxVuw[(i<<10)+j], + psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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; + int difX, difY,difX2, difY2; + int posX,posY; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])<<16)| + psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_S(&psxVuw[(i<<10)+j], + psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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(drawW=xmin) + { + posX=left_u; + posY=left_v; + + if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])<<16)| + psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG(&psxVuw[(i<<10)+j], + psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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) +{ + int num; + int i,j,xmin,xmax,ymin,ymax; + int difX, difY, difX2, difY2; + int posX,posY; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX])<<16)| + psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX]); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_S(&psxVuw[(i<<10)+j], + psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX])<<16)| + psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+GlobalTextAddrX]); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG(&psxVuw[(i<<10)+j], + psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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) +{ + int num; + int i,j,xmin,xmax,ymin,ymax; + int difX, difY, difX2, difY2; + int posX,posY; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])<<16)| + psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY)<<10)+TWin.Position.y0+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_S(&psxVuw[(i<<10)+j], + psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])<<16)| + psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG(&psxVuw[(i<<10)+j], + psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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) +{ + int num; + int i,j,xmin,xmax,ymin,ymax; + int difX, difY, difX2, difY2; + int posX, posY; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_FT4(x1,y1,x2,y2,x3,y3,x4,y4,tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])<<16)| + psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY)<<10)+TWin.Position.y0+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_S(&psxVuw[(i<<10)+j], + psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])<<16)| + psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0]); + + posX+=difX2; + posY+=difY2; + } + if(j==xmax) + GetTextureTransColG_SPR(&psxVuw[(i<<10)+j], + psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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, int rgb1, int rgb2, int rgb3) +{ + int i,j,xmin,xmax,ymin,ymax; + int cR1,cG1,cB1; + int difR,difB,difG,difR2,difB2,difG2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_G(x1,y1,x2,y2,x3,y3,rgb1,rgb2,rgb3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1;if(drawW=xmin) + { + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>3)&0x001f0000)| + (((cR1) >> 9)&0x7c00)|(((cG1) >> 14)&0x03e0)|(((cB1) >> 19)&0x001f))|lSetMask; + + cR1+=difR2; + cG1+=difG2; + cB1+=difB2; + } + if(j==xmax) + psxVuw[(i<<10)+j]=(((cR1 >> 9)&0x7c00)|((cG1 >> 14)&0x03e0)|((cB1 >> 19)&0x001f))|sSetMask; + } + if(NextRow_G()) return; + } + return; + } + +#endif + + if(iDither==2) + for (i=ymin;i<=ymax;i++) + { + xmin=(left_x >> 16); + xmax=(right_x >> 16)-1;if(drawW=xmin) + { + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>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(drawW=xmin) + { + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin> 9)&0x7c00)|((cG1 >> 14)&0x03e0)|((cB1 >> 19)&0x001f)); + + cR1+=difR; + cG1+=difG; + cB1+=difB; + } + } + if(NextRow_G()) return; + } + +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3G(int rgb1, int rgb2, int rgb3) +{ + drawPoly3Gi(lx0,ly0,lx1,ly1,lx2,ly2,rgb1,rgb2,rgb3); +} + +// draw two g-shaded tris for right psx shading emulation + +void drawPoly4G(int rgb1, int rgb2, int rgb3, int rgb4) +{ + drawPoly3Gi(lx1,ly1,lx3,ly3,lx2,ly2, + rgb2,rgb4,rgb3); + drawPoly3Gi(lx0,ly0,lx1,ly1,lx2,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,int col1, int col2, int col3) +{ + int i,j,xmin,xmax,ymin,ymax; + int cR1,cG1,cB1; + int difR,difB,difG,difR2,difB2,difG2; + int difX, difY,difX2, difY2; + int posX,posY,YAdjust,clutP,XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=((right_x) >> 16)-1; //!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16); + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + psxVuw[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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16); + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1], + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + psxVuw[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,int col1, int col2, int col3) +{ + int i,j,xmin,xmax,ymin,ymax,n_xi,n_yi,TXV; + int cR1,cG1,cB1; + int difR,difB,difG,difR2,difB2,difG2; + int difX, difY,difX2, difY2; + int posX,posY,YAdjust,clutP,XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=((right_x) >> 16)-1; //!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + psxVuw[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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16); + + TXV=posY>>16; + n_xi = ( ( XAdjust >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( XAdjust >> 4 ) & 0xf ); + + tC1= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((XAdjust & 0x03)<<2)) & 0x0f ; + + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1], + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + psxVuw[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, int col1, int col2, int col3) +{ + int i, j, xmin, xmax, ymin, ymax; + int cR1, cG1, cB1; + int difR, difB, difG, difR2, difB2, difG2; + int difX, difY,difX2, difY2; + int posX, posY, YAdjust, clutP, XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin>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(!bCheckMask && !DrawSemiTrans && !iDither) + { + for (i=ymin;i<=ymax;i++) + { + xmin=((left_x) >> 16); + xmax=((right_x) >> 16)-1; //!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16)%TWin.Position.x1; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + psxVuw[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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)%TWin.Position.x1; + tC1 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1], + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + psxVuw[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, + int col1, int col2, int col3, int 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, + int col1, int col2, int col3, int 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, + int col1, int col2, int col4, int col3) +{ + int num; + int i,j,xmin,xmax,ymin,ymax; + int cR1,cG1,cB1; + int difR,difB,difG,difR2,difB2,difG2; + int difX, difY, difX2, difY2; + int posX,posY,YAdjust,clutP,XAdjust; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=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=Ymax; + + for(ymin=Ymin;ymin> 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>16); + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + XAdjust=((posX+difX)>>16); + tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC2=(tC2>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + psxVuw[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>16); + tC1 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+ + (XAdjust>>1)]; + tC1=(tC1>>((XAdjust&1)<<2))&0xf; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1], + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + psxVuw[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, + int col1, int col2, int col3, int 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, int col1, int col2, int col3) +{ + int i,j,xmin,xmax,ymin,ymax; + int cR1,cG1,cB1; + int difR,difB,difG,difR2,difB2,difG2; + int difX, difY,difX2, difY2; + int posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; // !!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>5)&(int)0xFFFFF800)+YAdjust+((posX>>16))]; + tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ + (((posX+difX)>>16))]; + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+((posX>>16))]; + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + psxVuw[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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>5)&(int)0xFFFFF800)+YAdjust+((posX>>16))]; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1], + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + psxVuw[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, int col1, int col2, int col3) +{ + int i,j,xmin,xmax,ymin,ymax,n_xi,n_yi,TXV,TXU; + int cR1,cG1,cB1; + int difR,difB,difG,difR2,difB2,difG2; + int difX, difY,difX2, difY2; + int posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; // !!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (psxVuw[(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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; + + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + psxVuw[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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16; + TXV=posY>>16; + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + tC1= (psxVuw[(n_yi<<10)+YAdjust+n_xi] >> ((TXU & 0x01)<<3)) & 0xff; + + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1], + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + psxVuw[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, int col1, int col2, int col3) +{ + int i,j,xmin,xmax,ymin,ymax; + int cR1,cG1,cB1; + int difR,difB,difG,difR2,difB2,difG2; + int difX, difY,difX2, difY2; + int posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; // !!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + tC2 = psxVub[((((posY+difY)>>16)%TWin.Position.y1)<<11)+ + YAdjust+(((posX+difX)>>16)%TWin.Position.x1)]; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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 = psxVub[(((posY>>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + psxVuw[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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)%TWin.Position.y1)<<11)+ + YAdjust+((posX>>16)%TWin.Position.x1)]; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1], + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + psxVuw[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, + int col1, int col2, int col3, int 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, + int col1, int col2, int col3, int 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, + int col1, int col2, int col4, int col3) +{ + int num; + int i,j,xmin,xmax,ymin,ymax; + int cR1,cG1,cB1; + int difR,difB,difG,difR2,difB2,difG2; + int difX, difY, difX2, difY2; + int posX,posY,YAdjust,clutP; + short tC1,tC2; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=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=Ymax; + + for(ymin=Ymin;ymin> 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>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; + tC2 = psxVub[(((posY+difY)>>5)&(int)0xFFFFF800)+YAdjust+ + ((posX+difX)>>16)]; + + GetTextureTransColGX32_S((uint32_t *)&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1]| + ((int)psxVuw[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 = psxVub[((posY>>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; + GetTextureTransColGX_S(&psxVuw[(i<<10)+j], + psxVuw[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>5)&(int)0xFFFFF800)+YAdjust+(posX>>16)]; + if(iDither) + GetTextureTransColGX_Dither(&psxVuw[(i<<10)+j], + psxVuw[clutP+tC1], + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + psxVuw[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, + int col1, int col2, int col3, int 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, int col1, int col2, int col3) +{ + int i,j,xmin,xmax,ymin,ymax; + int cR1,cG1,cB1; + int difR,difB,difG,difR2,difB2,difG2; + int difX, difY,difX2, difY2; + int posX,posY; + + if(x1>drawW && x2>drawW && x3>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH) return; + if(x1=drawH) return; + if(drawX>=drawW) return; + + if(!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax=Ymax; + + for(ymin=Ymin;ymin> 16); + xmax=(right_x >> 16)-1; //!!!!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX])<<16)| + psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+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(&psxVuw[(i<<10)+j], + psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX], + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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, int col1, int col2, int col3) +{ + int i,j,xmin,xmax,ymin,ymax; + int cR1,cG1,cB1; + int difR,difB,difG,difR2,difB2,difG2; + int difX, difY,difX2, difY2; + int posX,posY; + + if (x1>drawW && x2>drawW && x3>drawW) return; + if (y1>drawH && y2>drawH && y3>drawH) return; + if (x1= drawH) return; + if (drawX >= drawW) return; + + if (!SetupSections_GT(x1,y1,x2,y2,x3,y3,tx1,ty1,tx2,ty2,tx3,ty3,col1,col2,col3)) return; + + ymax = Ymax; + + for(ymin = Ymin; ymin < 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 (!bCheckMask && !DrawSemiTrans && !iDither) + { + for (i = ymin; i <= ymax; i++) + { + xmin = (left_x >> 16); + xmax = (right_x >> 16) - 1; //!!!!!!!!!!!!!!!!!!!! + if(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX+difX)>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0])<<16)| + psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + (((posX)>>16)%TWin.Position.x1)+GlobalTextAddrX+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(&psxVuw[(i<<10)+j], + psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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(drawW=xmin) + { + posX=left_u; + posY=left_v; + cR1=left_R; + cG1=left_G; + cB1=left_B; + + if(xmin>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+TWin.Position.x0], + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + psxVuw[((((posY>>16)%TWin.Position.y1)+GlobalTextAddrY+TWin.Position.y0)<<10)+ + ((posX>>16)%TWin.Position.x1)+GlobalTextAddrX+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, int col1, int col2, int col3, int 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, int col1, int col2, int col4, int col3) +{ + int num; + int i,j,xmin,xmax,ymin,ymax; + int cR1,cG1,cB1; + int difR,difB,difG,difR2,difB2,difG2; + int difX, difY, difX2, difY2; + int posX,posY; + + if(x1>drawW && x2>drawW && x3>drawW && x4>drawW) return; + if(y1>drawH && y2>drawH && y3>drawH && y4>drawH) return; + if(x1=drawH) return; + if(drawX>=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 = Ymax; + + for (ymin = Ymin; ymin < drawY; ymin++) + if (NextRow_GT4()) return; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans && !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>16)+GlobalTextAddrY)<<10)+((posX+difX)>>16)+GlobalTextAddrX])<<16)| + psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+((posX)>>16)+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(&psxVuw[(i<<10)+j], + psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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>16)+GlobalTextAddrY)<<10)+(posX>>16)+GlobalTextAddrX], + (cB1>>16),(cG1>>16),(cR1>>16)); + else + GetTextureTransColGX(&psxVuw[(i<<10)+j], + psxVuw[(((posY>>16)+GlobalTextAddrY)<<10)+(posX>>16)+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, int col1, int col2, int col3, int 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 BOOL IsNoRect(void) +{ + if(lx0==lx1 && lx2==lx3) return FALSE; + if(lx0==lx2 && lx1==lx3) return FALSE; + if(lx0==lx3 && lx1==lx2) return FALSE; + return TRUE; +} +*/ + +// real rect test +__inline BOOL IsNoRect(void) +{ + //if(!(dwActFixes&0x200)) return FALSE; + + if(ly0==ly1) + { + if(lx1==lx3 && ly3==ly2 && lx2==lx0) return FALSE; + if(lx1==lx2 && ly2==ly3 && lx3==lx0) return FALSE; + return TRUE; + } + + if(ly0==ly2) + { + if(lx2==lx3 && ly3==ly1 && lx1==lx0) return FALSE; + if(lx2==lx1 && ly1==ly3 && lx3==lx0) return FALSE; + return TRUE; + } + + if(ly0==ly3) + { + if(lx3==lx2 && ly2==ly1 && lx1==lx0) return FALSE; + if(lx3==lx1 && ly1==ly2 && lx2==lx0) return FALSE; + return TRUE; + } + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3FT(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + + if(GlobalTextIL && GlobalTextTP<2) + { + if(GlobalTextTP==0) + drawPoly3TEx4_IL(lx0,ly0,lx1,ly1,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + else + drawPoly3TEx8_IL(lx0,ly0,lx1,ly1,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + return; + } + + if(!bUsingTWin)// && !(dwActFixes&0x100)) + { + switch(GlobalTextTP) // depending on texture mode + { + case 0: + drawPoly3TEx4(lx0,ly0,lx1,ly1,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + return; + case 1: + drawPoly3TEx8(lx0,ly0,lx1,ly1,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + return; + case 2: + drawPoly3TD(lx0,ly0,lx1,ly1,lx2,ly2,(gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff)); + return; + } + return; + } + + switch(GlobalTextTP) // depending on texture mode + { + case 0: + drawPoly3TEx4_TW(lx0,ly0,lx1,ly1,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + return; + case 1: + drawPoly3TEx8_TW(lx0,ly0,lx1,ly1,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + return; + case 2: + drawPoly3TD_TW(lx0,ly0,lx1,ly1,lx2,ly2,(gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff)); + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4FT(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + + if(GlobalTextIL && GlobalTextTP<2) + { + if(GlobalTextTP==0) + drawPoly4TEx4_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + else + drawPoly4TEx8_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + return; + } + + if(!bUsingTWin) + { +#ifdef POLYQUAD3GT + if(IsNoRect()) + { + switch (GlobalTextTP) + { + case 0: + drawPoly4TEx4_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + return; + case 1: + drawPoly4TEx8_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + return; + case 2: + drawPoly4TD_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff)); + return; + } + return; + } +#endif + + switch (GlobalTextTP) + { + case 0: // grandia investigations needed + drawPoly4TEx4(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + return; + case 1: + drawPoly4TEx8(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + return; + case 2: + drawPoly4TD(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff)); + return; + } + return; + } + + switch (GlobalTextTP) + { + case 0: + drawPoly4TEx4_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + return; + case 1: + drawPoly4TEx8_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff), ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + return; + case 2: + drawPoly4TD_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[4] & 0x000000ff), ((gpuData[4]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),(gpuData[6] & 0x000000ff), ((gpuData[6]>>8) & 0x000000ff)); + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly3GT(unsigned char * baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + + if(GlobalTextIL && GlobalTextTP<2) + { + if(GlobalTextTP==0) + drawPoly3TGEx4_IL(lx0,ly0,lx1,ly1,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask), + gpuData[0],gpuData[3],gpuData[6]); + else + drawPoly3TGEx8_IL(lx0,ly0,lx1,ly1,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask), + gpuData[0],gpuData[3],gpuData[6]); + return; + } + + if(!bUsingTWin) + { + switch (GlobalTextTP) + { + case 0: + drawPoly3TGEx4(lx0,ly0,lx1,ly1,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask), + gpuData[0],gpuData[3],gpuData[6]); + return; + case 1: + drawPoly3TGEx8(lx0,ly0,lx1,ly1,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask), + gpuData[0],gpuData[3],gpuData[6]); + return; + case 2: + drawPoly3TGD(lx0,ly0,lx1,ly1,lx2,ly2,(gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),gpuData[0],gpuData[3],gpuData[6]); + return; + } + return; + } + + switch(GlobalTextTP) + { + case 0: + drawPoly3TGEx4_TW(lx0,ly0,lx1,ly1,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask), + gpuData[0],gpuData[3],gpuData[6]); + return; + case 1: + drawPoly3TGEx8_TW(lx0,ly0,lx1,ly1,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask), + gpuData[0],gpuData[3],gpuData[6]); + return; + case 2: + drawPoly3TGD_TW(lx0,ly0,lx1,ly1,lx2,ly2,(gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),gpuData[0],gpuData[3],gpuData[6]); + return; + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawPoly4GT(unsigned char *baseAddr) +{ + uint32_t *gpuData = ((uint32_t *) baseAddr); + + if(GlobalTextIL && GlobalTextTP<2) + { + if(GlobalTextTP==0) + drawPoly4TGEx4_TRI_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), + gpuData[0],gpuData[3],gpuData[6],gpuData[9]); + else + drawPoly4TGEx8_TRI_IL(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), + gpuData[0],gpuData[3],gpuData[6],gpuData[9]); + return; + } + + if(!bUsingTWin) + { +#ifdef POLYQUAD3GT + if(IsNoRect()) + { + switch (GlobalTextTP) + { + case 0: + drawPoly4TGEx4_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), + gpuData[0],gpuData[3],gpuData[6],gpuData[9]); + + return; + case 1: + drawPoly4TGEx8_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), + gpuData[0],gpuData[3],gpuData[6],gpuData[9]); + return; + case 2: + drawPoly4TGD_TRI(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(gpuData[2] & 0x000000ff),((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),gpuData[0],gpuData[3],gpuData[6],gpuData[9]); + return; + } + return; + } +#endif + + switch (GlobalTextTP) + { + case 0: + drawPoly4TGEx4(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), + gpuData[0],gpuData[3],gpuData[6],gpuData[9]); + + return; + case 1: + drawPoly4TGEx8(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), + gpuData[0],gpuData[3],gpuData[6],gpuData[9]); + return; + case 2: + drawPoly4TGD(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(gpuData[2] & 0x000000ff),((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),gpuData[0],gpuData[3],gpuData[6],gpuData[9]); + return; + } + return; + } + + switch (GlobalTextTP) + { + case 0: + drawPoly4TGEx4_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), + gpuData[0],gpuData[3],gpuData[6],gpuData[9]); + return; + case 1: + drawPoly4TGEx8_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2, + (gpuData[2] & 0x000000ff), ((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff), + ((gpuData[2]>>12) & 0x3f0),((gpuData[2]>>22) & iGPUHeightMask), + gpuData[0],gpuData[3],gpuData[6],gpuData[9]); + return; + case 2: + drawPoly4TGD_TW(lx0,ly0,lx1,ly1,lx3,ly3,lx2,ly2,(gpuData[2] & 0x000000ff),((gpuData[2]>>8) & 0x000000ff), (gpuData[5] & 0x000000ff), ((gpuData[5]>>8) & 0x000000ff),(gpuData[11] & 0x000000ff), ((gpuData[11]>>8) & 0x000000ff),(gpuData[8] & 0x000000ff), ((gpuData[8]>>8) & 0x000000ff),gpuData[0],gpuData[3],gpuData[6],gpuData[9]); + return; + } +} + +//////////////////////////////////////////////////////////////////////// +// SPRITE FUNCS +//////////////////////////////////////////////////////////////////////// + +void DrawSoftwareSpriteTWin(unsigned char * baseAddr, int w, int 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=lx0; + sy0=ly0; + + sx0=sx3=sx0+PSXDisplay.DrawOffset.x; + sx1=sx2=sx0+w; + sy0=sy1=sy0+PSXDisplay.DrawOffset.y; + sy2=sy3=sy0+h; + + tx0=tx3=gpuData[2]&0xff; + tx1=tx2=tx0+w; + ty0=ty1=(gpuData[2]>>8)&0xff; + ty2=ty3=ty0+h; + + switch (GlobalTextTP) + { + case 0: + drawPoly4TEx4_TW_S(sx0,sy0,sx1,sy1,sx2,sy2,sx3,sy3, + tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3, + ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + return; + case 1: + drawPoly4TEx8_TW_S(sx0,sy0,sx1,sy1,sx2,sy2,sx3,sy3, + tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3, + ((gpuData[2]>>12) & 0x3f0), ((gpuData[2]>>22) & iGPUHeightMask)); + 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, int w, int h) +{ + int sprtY,sprtX,sprtW,sprtH,lXDir,lYDir; + int clutY0,clutX0,clutP,textX0,textY0,sprtYa,sprCY,sprCX,sprA; + short tC; + uint32_t *gpuData = (uint32_t *)baseAddr; + sprtY = ly0; + sprtX = lx0; + sprtH = h; + sprtW = w; + clutY0 = (gpuData[2]>>22) & iGPUHeightMask; + clutX0 = (gpuData[2]>>12) & 0x3f0; + clutP = (clutY0<<11) + (clutX0<<1); + textY0 = ((gpuData[2]>>8) & 0x000000ff) + GlobalTextAddrY; + textX0 = (gpuData[2] & 0x000000ff); + + sprtX+=PSXDisplay.DrawOffset.x; + sprtY+=PSXDisplay.DrawOffset.y; + +// while (sprtX>1023) sprtX-=1024; +// while (sprtY>MAXYLINESMIN1) sprtY-=MAXYLINES; + + if(sprtX>drawW) + { +// if((sprtX+sprtW)>1023) sprtX-=1024; +// else return; + return; + } + + if(sprtY>drawH) + { +// if ((sprtY+sprtH)>MAXYLINESMIN1) sprtY-=MAXYLINES; +// else return; + return; + } + + if(sprtYdrawH) sprtH=drawH-sprtY+1; + if((sprtX+sprtW)>drawW) sprtW=drawW-sprtX+1; + + if(usMirror&0x1000) lXDir=-1; else lXDir=1; + if(usMirror&0x2000) lYDir=-1; else lYDir=1; + + switch (GlobalTextTP) + { + case 0: // texture is 4-bit + + sprtW=sprtW/2; + textX0=(GlobalTextAddrX<<1)+(textX0>>1); + sprtYa=(sprtY<<10); + clutP=(clutY0<<10)+clutX0; + for (sprCY=0;sprCY>4)&0xf)]); + GetTextureTransColG_SPR(&psxVuw[sprA+1],psxVuw[clutP+(tC&0xf)]); + } + return; + + case 1: + + clutP>>=1; + for(sprCY=0;sprCYdrawW) return; + if(sprtY>drawH) return; + + tdx=tx+sprtW; + tdy=ty+sprtH; + + sprtW+=sprtX; + sprtH+=sprtY; + + // Pete is too lazy to make a faster version ;) + + if(GlobalTextTP==0) + drawPoly4TEx4_IL(sprtX,sprtY,sprtX,sprtH,sprtW,sprtH,sprtW,sprtY, + tx,ty, tx,tdy, tdx,tdy, tdx,ty, + (gpuData[2]>>12) & 0x3f0, ((gpuData[2]>>22) & iGPUHeightMask)); + + + else + drawPoly4TEx8_IL(sprtX,sprtY,sprtX,sprtH,sprtW,sprtH,sprtW,sprtY, + tx,ty, tx,tdy, tdx,tdy, tdx,ty, + (gpuData[2]>>12) & 0x3f0, ((gpuData[2]>>22) & iGPUHeightMask)); +} + +//////////////////////////////////////////////////////////////////////// + +void DrawSoftwareSprite(unsigned char *baseAddr, short w, short h, int tx, int ty) +{ + int sprtY, sprtX, sprtW, sprtH; + int clutY0, clutX0, clutP, textX0, textY0, sprtYa, sprCY, sprCX, sprA; + short tC, tC2; + uint32_t *gpuData = (uint32_t *)baseAddr; + unsigned char *pV; + BOOL bWT,bWS; + + if(GlobalTextIL && GlobalTextTP<2) + {DrawSoftwareSprite_IL(baseAddr,w,h,tx,ty);return;} + + sprtY = ly0; + sprtX = lx0; + sprtH = h; + sprtW = w; + clutY0 = (gpuData[2]>>22) & iGPUHeightMask; + clutX0 = (gpuData[2]>>12) & 0x3f0; + + clutP = (clutY0<<11) + (clutX0<<1); + + textY0 =ty+ GlobalTextAddrY; + textX0 =tx; + + sprtX+=PSXDisplay.DrawOffset.x; + sprtY+=PSXDisplay.DrawOffset.y; + + //while (sprtX>1023) sprtX-=1024; + //while (sprtY>MAXYLINESMIN1) sprtY-=MAXYLINES; + + if(sprtX>drawW) + { +// if((sprtX+sprtW)>1023) sprtX-=1024; +// else return; + return; + } + + if(sprtY>drawH) + { +// if ((sprtY+sprtH)>MAXYLINESMIN1) sprtY-=MAXYLINES; +// else return; + return; + } + + if(sprtYdrawH) sprtH=drawH-sprtY+1; + if((sprtX+sprtW)>drawW) sprtW=drawW-sprtX+1; + + + bWT=FALSE; + bWS=FALSE; + + switch (GlobalTextTP) + { + case 0: + + if(textX0&1) {bWS=TRUE;sprtW--;} + if(sprtW&1) bWT=TRUE; + + sprtW=sprtW>>1; + textX0=(GlobalTextAddrX<<1)+(textX0>>1)+(textY0<<11); + sprtYa=(sprtY<<10)+sprtX; + clutP=(clutY0<<10)+clutX0; + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for (sprCY=0;sprCY>4)&0xf)]); + } + + for (sprCX=0;sprCX>4)&0xf)])<<16)| + psxVuw[clutP+(tC&0x0f)]); + } + + if(bWT) + { + tC=*pV; + GetTextureTransColG_S(&psxVuw[sprA],psxVuw[clutP+(tC&0x0f)]); + } + } + return; + } + +#endif + + for (sprCY=0;sprCY>4)&0xf)]); + } + + for (sprCX=0;sprCX>4)&0xf)])<<16)| + psxVuw[clutP+(tC&0x0f)]); + } + + if(bWT) + { + tC=*pV; + GetTextureTransColG_SPR(&psxVuw[sprA],psxVuw[clutP+(tC&0x0f)]); + } + } + return; + + case 1: + clutP>>=1;sprtW--; + textX0+=(GlobalTextAddrX<<1) + (textY0<<11); + +#ifdef FASTSOLID + + if(!bCheckMask && !DrawSemiTrans) + { + for(sprCY=0;sprCY 0) + { + dr = ((int)r1 - (int)r0) / dx; + dg = ((int)g1 - (int)g0) / dx; + db = ((int)b1 - (int)b0) / dx; + } + else + { + dr = ((int)r1 - (int)r0); + dg = ((int)g1 - (int)g0); + db = ((int)b1 - (int)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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 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; + int 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 = ((int)r1 - (int)r0) / dy; + dg = ((int)g1 - (int)g0) / dy; + db = ((int)b1 - (int)b0) / dy; + } + else + { + dr = ((int)r1 - (int)r0); + dg = ((int)g1 - (int)g0); + db = ((int)b1 - (int)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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 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; + int 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 = ((uint32_t)r1 - (uint32_t)r0) / dy; + dg = ((uint32_t)g1 - (uint32_t)g0) / dy; + db = ((uint32_t)b1 - (uint32_t)b0) / dy; + } + else + { + dr = ((uint32_t)r1 - (uint32_t)r0); + dg = ((uint32_t)g1 - (uint32_t)g0); + db = ((uint32_t)b1 - (uint32_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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 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; + int 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 = ((int)r1 - (int)r0) / dx; + dg = ((int)g1 - (int)g0) / dx; + db = ((int)b1 - (int)b0) / dx; + } + else + { + dr = ((int)r1 - (int)r0); + dg = ((int)g1 - (int)g0); + db = ((int)b1 - (int)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>=drawX)&&(x0=drawY)&&(y0> 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>=drawX)&&(x0=drawY)&&(y0> 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; + int 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 = ((int)r1 - (int)r0) / dy; + dg = ((int)g1 - (int)g0) / dy; + db = ((int)b1 - (int)b0) / dy; + } + else + { + dr = ((int)r1 - (int)r0); + dg = ((int)g1 - (int)g0); + db = ((int)b1 - (int)b0); + } + + if (y0 < drawY) + { + r0+=dr*(drawY - y0); + g0+=dg*(drawY - y0); + b0+=db*(drawY - y0); + y0 = drawY; + } + + if (y1 > drawH) + y1 = drawH; + + for (y = y0; y <= y1; y++) + { + GetShadeTransCol(&psxVuw[(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; + int 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 = ((int)r1 - (int)r0) / dx; + dg = ((int)g1 - (int)g0) / dx; + db = ((int)b1 - (int)b0) / dx; + } + else + { + dr = ((int)r1 - (int)r0); + dg = ((int)g1 - (int)g0); + db = ((int)b1 - (int)b0); + } + + if (x0 < drawX) + { + r0+=dr*(drawX - x0); + g0+=dg*(drawX - x0); + b0+=db*(drawX - x0); + x0 = drawX; + } + + if (x1 > drawW) + x1 = drawW; + + for (x = x0; x <= x1; x++) + { + GetShadeTransCol(&psxVuw[(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>=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y y1) + { + if (d <= 0) + { + d = d + incrN; /* Choose N */ + y--; + } + else + { + d = d + incrNE; /* Choose NE */ + x++; + y--; + } + if ((x>=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y=drawX)&&(x=drawY)&&(y drawH) + y1 = drawH; + + for (y = y0; y <= y1; y++) + GetShadeTransCol(&psxVuw[(y<<10)+x], colour); +} + +/////////////////////////////////////////////////////////////////////// + +void HorzLineFlat(int y, int x0, int x1, unsigned short colour) +{ + int x; + + if (x0 < drawX) + x0 = drawX; + + if (x1 > drawW) + x1 = drawW; + + for (x = x0; x <= x1; x++) + GetShadeTransCol(&psxVuw[(y<<10)+x], colour); +} + +/////////////////////////////////////////////////////////////////////// + +/* Bresenham Line drawing function */ +void DrawSoftwareLineShade(int rgb0, int rgb1) +{ + short x0, y0, x1, y1, xt, yt; + int rgbt; + double m, dy, dx; + + if(lx0>drawW && lx1>drawW) return; + if(ly0>drawH && ly1>drawH) return; + if(lx0=drawH) return; + if(drawX>=drawW) return; + + x0 = lx0; + y0 = ly0; + x1 = lx1; + y1 = 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(int rgb) +{ + short x0, y0, x1, y1, xt, yt; + double m, dy, dx; + unsigned short colour = 0; + + if(lx0>drawW && lx1>drawW) return; + if(ly0>drawH && ly1>drawH) return; + if(lx0=drawH) return; + if(drawX>=drawW) return; + + colour = ((rgb & 0x00f80000)>>9) | ((rgb & 0x0000f800)>>6) | ((rgb & 0x000000f8)>>3); + + x0 = lx0; + y0 = ly0; + x1 = lx1; + y1 = 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/peopsxgl/texture.c b/plugins/peopsxgl/texture.c index f247175a..90344d58 100644 --- a/plugins/peopsxgl/texture.c +++ b/plugins/peopsxgl/texture.c @@ -1,4925 +1,4917 @@ -/*************************************************************************** - texture.c - description - ------------------- - begin : Sun Mar 08 2009 - copyright : (C) 1999-2009 by Pete Bernert - web : www.pbernert.com - ***************************************************************************/ - -/*************************************************************************** - * * - * 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 "stdafx.h" - -//////////////////////////////////////////////////////////////////////////////////// -// Texture related functions are here ! -// -// The texture handling is heart and soul of this gpu. The plugin was developed -// 1999, by this time no shaders were available. Since the psx gpu is making -// heavy use of CLUT (="color lookup tables", aka palettized textures), it was -// an interesting task to get those emulated at good speed on NV TNT cards -// (which was my major goal when I created the first "gpuPeteTNT"). Later cards -// (Geforce256) supported texture palettes by an OGL extension, but at some point -// this support was dropped again by gfx card vendors. -// Well, at least there is a certain advatage, if no texture palettes extension can -// be used: it is possible to modify the textures in any way, allowing "hi-res" -// textures and other tweaks. -// -// My main texture caching is kinda complex: the plugin is allocating "n" 256x256 textures, -// and it places small psx texture parts inside them. The plugin keeps track what -// part (with what palette) it had placed in which texture, so it can re-use this -// part again. The more ogl textures it can use, the better (of course the managing/ -// searching will be slower, but everything is faster than uploading textures again -// and again to a gfx card). My first card (TNT1) had 16 MB Vram, and it worked -// well with many games, but I recommend nowadays 64 MB Vram to get a good speed. -// -// Sadly, there is also a second kind of texture cache needed, for "psx texture windows". -// Those are "repeated" textures, so a psx "texture window" needs to be put in -// a whole texture to use the GL_TEXTURE_WRAP_ features. This cache can get full very -// fast in games which are having an heavy "texture window" usage, like RRT4. As an -// alternative, this plugin can use the OGL "palette" extension on texture windows, -// if available. Nowadays also a fragment shader can easily be used to emulate -// texture wrapping in a texture atlas, so the main cache could hold the texture -// windows as well (that's what I am doing in the OGL2 plugin). But currently the -// OGL1 plugin is a "shader-free" zone, so heavy "texture window" games will cause -// much texture uploads. -// -// Some final advice: take care if you change things in here. I've removed my ASM -// handlers (they didn't cause much speed gain anyway) for readability/portability, -// but still the functions/data structures used here are easy to mess up. I guess it -// can be a pain in the ass to port the plugin to another byte order :) -// -//////////////////////////////////////////////////////////////////////////////////// - -#define _IN_TEXTURE - -#include "externals.h" -#include "texture.h" -#include "gpu.h" -#include "prim.h" - -#define CLUTCHK 0x00060000 -#define CLUTSHIFT 17 - -//////////////////////////////////////////////////////////////////////// -// texture conversion buffer .. -//////////////////////////////////////////////////////////////////////// - -int iHiResTextures=0; -GLubyte ubPaletteBuffer[256][4]; -GLuint gTexMovieName=0; -GLuint gTexBlurName=0; -GLuint gTexFrameName=0; -int iTexGarbageCollection=1; -uint32_t dwTexPageComp=0; -int iVRamSize=0; -int iClampType=GL_CLAMP; - -void (*LoadSubTexFn) (int,int,short,short); -uint32_t (*PalTexturedColourFn) (uint32_t); - -//////////////////////////////////////////////////////////////////////// -// defines -//////////////////////////////////////////////////////////////////////// - -#define PALCOL(x) PalTexturedColourFn (x) - -#define CSUBSIZE 2048 -#define CSUBSIZEA 8192 -#define CSUBSIZES 4096 - -#define OFFA 0 -#define OFFB 2048 -#define OFFC 4096 -#define OFFD 6144 - -#define XOFFA 0 -#define XOFFB 512 -#define XOFFC 1024 -#define XOFFD 1536 - -#define SOFFA 0 -#define SOFFB 1024 -#define SOFFC 2048 -#define SOFFD 3072 - -#define MAXWNDTEXCACHE 128 - -#define XCHECK(pos1,pos2) ((pos1.c[0]>=pos2.c[1])&&(pos1.c[1]<=pos2.c[0])&&(pos1.c[2]>=pos2.c[3])&&(pos1.c[3]<=pos2.c[2])) -#define INCHECK(pos2,pos1) ((pos1.c[0]<=pos2.c[0]) && (pos1.c[1]>=pos2.c[1]) && (pos1.c[2]<=pos2.c[2]) && (pos1.c[3]>=pos2.c[3])) - -//////////////////////////////////////////////////////////////////////// - -unsigned char * CheckTextureInSubSCache(int TextureMode, uint32_t GivenClutId, unsigned short *pCache); -void LoadSubTexturePageSort(int pageid, int mode, short cx, short cy); -void LoadPackedSubTexturePageSort(int pageid, int mode, short cx, short cy); -void DefineSubTextureSort(void); - -//////////////////////////////////////////////////////////////////////// -// some globals -//////////////////////////////////////////////////////////////////////// - -GLint giWantedRGBA=4; -GLint giWantedFMT=GL_RGBA; -GLint giWantedTYPE=GL_UNSIGNED_BYTE; -int GlobalTexturePage; -GLint XTexS; -GLint YTexS; -GLint DXTexS; -GLint DYTexS; -int iSortTexCnt=32; -BOOL bUseFastMdec=FALSE; -BOOL bUse15bitMdec=FALSE; -int iFrameTexType=0; -int iFrameReadType=0; - -uint32_t (*TCF[2]) (uint32_t); -unsigned short (*PTCF[2]) (unsigned short); - -//////////////////////////////////////////////////////////////////////// -// texture cache implementation -//////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS -#pragma pack(1) -#endif - -// "texture window" cache entry - -typedef struct textureWndCacheEntryTag -{ - uint32_t ClutID; - short pageid; - short textureMode; - short Opaque; - short used; - EXLong pos; - GLuint texname; -} textureWndCacheEntry; - -// "standard texture" cache entry (12 byte per entry, as small as possible... we need lots of them) - -typedef struct textureSubCacheEntryTagS -{ - uint32_t ClutID; - EXLong pos; - unsigned char posTX; - unsigned char posTY; - unsigned char cTexID; - unsigned char Opaque; -} textureSubCacheEntryS; - -#ifdef _WINDOWS -#pragma pack() -#endif - -//--------------------------------------------- - -#define MAXTPAGES_MAX 64 -#define MAXSORTTEX_MAX 196 - -//--------------------------------------------- - -textureWndCacheEntry wcWndtexStore[MAXWNDTEXCACHE]; -textureSubCacheEntryS * pscSubtexStore[3][MAXTPAGES_MAX]; -EXLong * pxSsubtexLeft [MAXSORTTEX_MAX]; -GLuint uiStexturePage[MAXSORTTEX_MAX]; - -unsigned short usLRUTexPage = 0; - -int iMaxTexWnds = 0; -int iTexWndTurn = 0; -int iTexWndLimit = MAXWNDTEXCACHE/2; - -GLubyte * texturepart = NULL; -GLubyte * texturebuffer = NULL; -uint32_t g_x1,g_y1,g_x2,g_y2; -unsigned char ubOpaqueDraw = 0; - -unsigned short MAXTPAGES = 32; -unsigned short CLUTMASK = 0x7fff; -unsigned short CLUTYMASK = 0x1ff; -unsigned short MAXSORTTEX = 196; - -//////////////////////////////////////////////////////////////////////// -// Texture color conversions... all my ASM funcs are removed for easier -// porting... and honestly: nowadays the speed gain would be pointless -//////////////////////////////////////////////////////////////////////// - -uint32_t XP8RGBA(uint32_t BGR) -{ - if(!(BGR&0xffff)) return 0x50000000; - if(DrawSemiTrans && !(BGR&0x8000)) - {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} - return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; -} - -uint32_t XP8RGBAEx(uint32_t BGR) -{ - if(!(BGR&0xffff)) return 0x03000000; - if(DrawSemiTrans && !(BGR&0x8000)) - {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} - return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; -} - -uint32_t CP8RGBA(uint32_t BGR) -{ - uint32_t l; - if(!(BGR&0xffff)) return 0x50000000; - if(DrawSemiTrans && !(BGR&0x8000)) - {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} - l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; - if(l==0xffffff00) l=0xff000000; - return l; -} - -uint32_t CP8RGBAEx(uint32_t BGR) -{ - uint32_t l; - if(!(BGR&0xffff)) return 0x03000000; - if(DrawSemiTrans && !(BGR&0x8000)) - {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} - l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; - if(l==0xffffff00) l=0xff000000; - return l; -} - -uint32_t XP8RGBA_0(uint32_t BGR) -{ - if(!(BGR&0xffff)) return 0x50000000; - return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; -} - -uint32_t XP8RGBAEx_0(uint32_t BGR) -{ - if(!(BGR&0xffff)) return 0x03000000; - return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; -} - -uint32_t XP8BGRA_0(uint32_t BGR) -{ - if(!(BGR&0xffff)) return 0x50000000; - return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; -} - -uint32_t XP8BGRAEx_0(uint32_t BGR) -{ - if(!(BGR&0xffff)) return 0x03000000; - return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; -} - -uint32_t CP8RGBA_0(uint32_t BGR) -{ - uint32_t l; - - if(!(BGR&0xffff)) return 0x50000000; - l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; - if(l==0xfff8f800) l=0xff000000; - return l; -} - -uint32_t CP8RGBAEx_0(uint32_t BGR) -{ - uint32_t l; - - if(!(BGR&0xffff)) return 0x03000000; - l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; - if(l==0xfff8f800) l=0xff000000; - return l; -} - -uint32_t CP8BGRA_0(uint32_t BGR) -{ - uint32_t l; - - if(!(BGR&0xffff)) return 0x50000000; - l=((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; - if(l==0xff00f8f8) l=0xff000000; - return l; -} - -uint32_t CP8BGRAEx_0(uint32_t BGR) -{ - uint32_t l; - - if(!(BGR&0xffff)) return 0x03000000; - l=((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; - if(l==0xff00f8f8) l=0xff000000; - return l; -} - -uint32_t XP8RGBA_1(uint32_t BGR) -{ - if(!(BGR&0xffff)) return 0x50000000; - if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} - return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; -} - -uint32_t XP8RGBAEx_1(uint32_t BGR) -{ - if(!(BGR&0xffff)) return 0x03000000; - if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} - return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; -} - -uint32_t XP8BGRA_1(uint32_t BGR) -{ - if(!(BGR&0xffff)) return 0x50000000; - if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff);} - return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; -} - -uint32_t XP8BGRAEx_1(uint32_t BGR) -{ - if(!(BGR&0xffff)) return 0x03000000; - if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff);} - return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; -} - -uint32_t P8RGBA(uint32_t BGR) -{ - if(!(BGR&0xffff)) return 0; - return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; -} - -uint32_t P8BGRA(uint32_t BGR) -{ - if(!(BGR&0xffff)) return 0; - return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; -} - -unsigned short XP5RGBA(unsigned short BGR) -{ - if(!BGR) return 0; - if(DrawSemiTrans && !(BGR&0x8000)) - {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} - return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; -} - -unsigned short XP5RGBA_0 (unsigned short BGR) -{ - if(!BGR) return 0; - - return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; -} - -unsigned short CP5RGBA_0 (unsigned short BGR) -{ - unsigned short s; - - if(!BGR) return 0; - - s=((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; - if(s==0x07ff) s=1; - return s; -} - -unsigned short XP5RGBA_1(unsigned short BGR) -{ - if(!BGR) return 0; - if(!(BGR&0x8000)) - {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} - return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; -} - -unsigned short P5RGBA(unsigned short BGR) -{ - if(!BGR) return 0; - return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; -} - -unsigned short XP4RGBA(unsigned short BGR) -{ - if(!BGR) return 6; - if(DrawSemiTrans && !(BGR&0x8000)) - {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} - return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; -} - -unsigned short XP4RGBA_0 (unsigned short BGR) -{ - if(!BGR) return 6; - return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; -} - -unsigned short CP4RGBA_0 (unsigned short BGR) -{ - unsigned short s; - if(!BGR) return 6; - s=(((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; - if(s==0x0fff) s=0x000f; - return s; -} - -unsigned short XP4RGBA_1(unsigned short BGR) -{ - if(!BGR) return 6; - if(!(BGR&0x8000)) - {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} - return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; -} - -unsigned short P4RGBA(unsigned short BGR) -{ - if(!BGR) return 0; - return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; -} - -//////////////////////////////////////////////////////////////////////// -// CHECK TEXTURE MEM (on plugin startup) -//////////////////////////////////////////////////////////////////////// - -int iFTexA=512; -int iFTexB=512; - -void CheckTextureMemory(void) -{ - GLboolean b;GLboolean * bDetail; - int i,iCnt,iRam=iVRamSize*1024*1024; - int iTSize;char * p; - - if(iBlurBuffer) - { - char * p; - - if(iResX>1024) iFTexA=2048; - else - if(iResX>512) iFTexA=1024; - else iFTexA=512; - if(iResY>1024) iFTexB=2048; - else - if(iResY>512) iFTexB=1024; - else iFTexB=512; - - glGenTextures(1, &gTexBlurName); - gTexName=gTexBlurName; - glBindTexture(GL_TEXTURE_2D, gTexName); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - p=(char *)malloc(iFTexA*iFTexB*4); - memset(p,0,iFTexA*iFTexB*4); - glTexImage2D(GL_TEXTURE_2D, 0, 3, iFTexA, iFTexB, 0, GL_RGB, GL_UNSIGNED_BYTE, p); - free(p); - glGetError(); - iRam-=iFTexA*iFTexB*3; - iFTexA=(iResX*256)/iFTexA; - iFTexB=(iResY*256)/iFTexB; - } - - if(iVRamSize) - { - int ts; - - iRam-=(iResX*iResY*8); - iRam-=(iResX*iResY*(iZBufferDepth/8)); - - if(iTexQuality==0 || iTexQuality==3) ts=4; - else ts=2; - - if(iHiResTextures) - iSortTexCnt=iRam/(512*512*ts); - else iSortTexCnt=iRam/(256*256*ts); - - if(iSortTexCnt>MAXSORTTEX) - { - iSortTexCnt=MAXSORTTEX-min(1,iHiResTextures); - } - else - { - iSortTexCnt-=3+min(1,iHiResTextures); - if(iSortTexCnt<8) iSortTexCnt=8; - } - - for(i=0;i info for 32*3 - for(j=0;j info 0..511 - { - pxSsubtexLeft[i]=(EXLong *)malloc(CSUBSIZE*sizeof(EXLong)); - memset(pxSsubtexLeft[i],0,CSUBSIZE*sizeof(EXLong)); - uiStexturePage[i]=0; - } -} - -//////////////////////////////////////////////////////////////////////// -// Clean up on exit -//////////////////////////////////////////////////////////////////////// - -void CleanupTextureStore() -{ - int i,j;textureWndCacheEntry * tsx; - //----------------------------------------------------// - glBindTexture(GL_TEXTURE_2D,0); - //----------------------------------------------------// - free(texturepart); // free tex part - texturepart=0; - if(texturebuffer) - { - free(texturebuffer); - texturebuffer=0; - } - //----------------------------------------------------// - tsx=wcWndtexStore; // loop tex window cache - for(i=0;itexname) // -> some tex? - glDeleteTextures(1,&tsx->texname); // --> delete it - } - iMaxTexWnds=0; // no more tex wnds - //----------------------------------------------------// - if(gTexMovieName!=0) // some movie tex? - glDeleteTextures(1, &gTexMovieName); // -> delete it - gTexMovieName=0; // no more movie tex - //----------------------------------------------------// - if(gTexFrameName!=0) // some 15bit framebuffer tex? - glDeleteTextures(1, &gTexFrameName); // -> delete it - gTexFrameName=0; // no more movie tex - //----------------------------------------------------// - if(gTexBlurName!=0) // some 15bit framebuffer tex? - glDeleteTextures(1, &gTexBlurName); // -> delete it - gTexBlurName=0; // no more movie tex - //----------------------------------------------------// - for(i=0;i<3;i++) // -> loop - for(j=0;j clean mem - } - for(i=0;i tex used ? - { - glDeleteTextures(1,&uiStexturePage[i]); - uiStexturePage[i]=0; // --> delete it - } - free(pxSsubtexLeft[i]); // -> clean mem - } - //----------------------------------------------------// -} - -//////////////////////////////////////////////////////////////////////// -// Reset textures in game... -//////////////////////////////////////////////////////////////////////// - -void ResetTextureArea(BOOL bDelTex) -{ - int i,j;textureSubCacheEntryS * tss;EXLong * lu; - textureWndCacheEntry * tsx; - //----------------------------------------------------// - - dwTexPageComp=0; - - //----------------------------------------------------// - if(bDelTex) {glBindTexture(GL_TEXTURE_2D,0);gTexName=0;} - //----------------------------------------------------// - tsx=wcWndtexStore; - for(i=0;iused=0; - if(bDelTex && tsx->texname) - { - glDeleteTextures(1,&tsx->texname); - tsx->texname=0; - } - } - iMaxTexWnds=0; - //----------------------------------------------------// - - for(i=0;i<3;i++) - for(j=0;jpos.l=0; - (tss+SOFFB)->pos.l=0; - (tss+SOFFC)->pos.l=0; - (tss+SOFFD)->pos.l=0; - } - - for(i=0;il=0; - if(bDelTex && uiStexturePage[i]) - {glDeleteTextures(1,&uiStexturePage[i]);uiStexturePage[i]=0;} - } -} - - -//////////////////////////////////////////////////////////////////////// -// Invalidate tex windows -//////////////////////////////////////////////////////////////////////// - -static void InvalidateWndTextureArea(int X, int Y, int W, int H) -{ - int i,px1,px2,py1,py2,iYM=1; - textureWndCacheEntry * tsw=wcWndtexStore; - - W+=X-1; - H+=Y-1; - if(X<0) X=0;if(X>1023) X=1023; - if(W<0) W=0;if(W>1023) W=1023; - if(Y<0) Y=0;if(Y>iGPUHeightMask) Y=iGPUHeightMask; - if(H<0) H=0;if(H>iGPUHeightMask) H=iGPUHeightMask; - W++;H++; - - if(iGPUHeight==1024) iYM=3; - - py1=min(iYM,Y>>8); - py2=min(iYM,H>>8); // y: 0 or 1 - - px1=max(0,(X>>6)); - px2=min(15,(W>>6)); - - if(py1==py2) - { - py1=py1<<4;px1+=py1;px2+=py1; // change to 0-31 - for(i=0;iused) - { - if(tsw->pageid>=px1 && tsw->pageid<=px2) - { - tsw->used=0; - } - } - } - } - else - { - py1=px1+16;py2=px2+16; - for(i=0;iused) - { - if((tsw->pageid>=px1 && tsw->pageid<=px2) || - (tsw->pageid>=py1 && tsw->pageid<=py2)) - { - tsw->used=0; - } - } - } - } - - // adjust tex window count - tsw=wcWndtexStore+iMaxTexWnds-1; - while(iMaxTexWnds && !tsw->used) {iMaxTexWnds--;tsw--;} -} - - - -//////////////////////////////////////////////////////////////////////// -// same for sort textures -//////////////////////////////////////////////////////////////////////// - -static void MarkFree(textureSubCacheEntryS * tsx) -{ - EXLong * ul, * uls; - int j,iMax;unsigned char x1,y1,dx,dy; - - uls=pxSsubtexLeft[tsx->cTexID]; - iMax=uls->l;ul=uls+1; - - if(!iMax) return; - - for(j=0;jl==0xffffffff) break; - - if(jl=uls->l+1; - - x1=tsx->posTX;dx=tsx->pos.c[2]-tsx->pos.c[3]; - if(tsx->posTX) {x1--;dx+=3;} - y1=tsx->posTY;dy=tsx->pos.c[0]-tsx->pos.c[1]; - if(tsx->posTY) {y1--;dy+=3;} - - ul->c[3]=x1; - ul->c[2]=dx; - ul->c[1]=y1; - ul->c[0]=dy; - } -} - -static void InvalidateSubSTextureArea(int X, int Y, int W, int H) -{ - int i,j,k,iMax,px,py,px1,px2,py1,py2,iYM = 1; - EXLong npos; - textureSubCacheEntryS *tsb; - int x1,x2,y1,y2,xa,sw; - - W+=X-1; - H+=Y-1; - if(X<0) X=0;if(X>1023) X=1023; - if(W<0) W=0;if(W>1023) W=1023; - if(Y<0) Y=0;if(Y>iGPUHeightMask) Y=iGPUHeightMask; - if(H<0) H=0;if(H>iGPUHeightMask) H=iGPUHeightMask; - W++;H++; - - if(iGPUHeight==1024) iYM=3; - - py1=min(iYM,Y>>8); - py2=min(iYM,H>>8); // y: 0 or 1 - px1=max(0,(X>>6)-3); - px2=min(15,(W>>6)+3); // x: 0-15 - - for(py=py1;py<=py2;py++) - { - j=(py<<4)+px1; // get page - - y1=py*256;y2=y1+255; - - if(Hy2) continue; - - if(Y>y1) y1=Y; - if(Hx2) continue; - - if(X>x1) x1=X; - if(Wpos.l;tsb++; - for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} - -// if(npos.l & 0x00800000) - { - tsb=pscSubtexStore[k][j]+SOFFB;iMax=tsb->pos.l;tsb++; - for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} - } - -// if(npos.l & 0x00000080) - { - tsb=pscSubtexStore[k][j]+SOFFC;iMax=tsb->pos.l;tsb++; - for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} - } - -// if(npos.l & 0x00800080) - { - tsb=pscSubtexStore[k][j]+SOFFD;iMax=tsb->pos.l;tsb++; - for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} - } - } - } - } - } -} - -//////////////////////////////////////////////////////////////////////// -// Invalidate some parts of cache: main routine -//////////////////////////////////////////////////////////////////////// - -void InvalidateTextureAreaEx(void) -{ - short W=sxmax-sxmin; - short H=symax-symin; - - if (W == 0 && H == 0) return; - - if (iMaxTexWnds) - InvalidateWndTextureArea(sxmin,symin,W,H); - - InvalidateSubSTextureArea(sxmin,symin,W,H); -} - -//////////////////////////////////////////////////////////////////////// - -void InvalidateTextureArea(int X, int Y, int W, int H) -{ - if (W == 0 && H == 0) return; - - if (iMaxTexWnds) InvalidateWndTextureArea(X, Y, W, H); - - InvalidateSubSTextureArea(X, Y, W, H); -} - - -//////////////////////////////////////////////////////////////////////// -// tex window: define -//////////////////////////////////////////////////////////////////////// - -static void DefineTextureWnd(void) -{ - if (gTexName == 0) - glGenTextures(1, &gTexName); - - glBindTexture(GL_TEXTURE_2D, gTexName); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - if(iFilterType && iFilterType<3 && iHiResTextures!=2) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - - glTexImage2D(GL_TEXTURE_2D, 0,giWantedRGBA, - TWin.Position.x1, - TWin.Position.y1, - 0, giWantedFMT, giWantedTYPE, texturepart); -} - -//////////////////////////////////////////////////////////////////////// -// tex window: load packed stretch -//////////////////////////////////////////////////////////////////////// - -static void LoadStretchPackedWndTexturePage(int pageid, int mode, short cx, short cy) -{ - uint32_t start, row, column, j, sxh, sxm, ldx, ldy, ldxo; - unsigned int palstart; - unsigned short *px, *pa, *ta; - unsigned char *cSRCPtr,*cOSRCPtr; - unsigned short *wSRCPtr,*wOSRCPtr; - uint32_t LineOffset; - unsigned short s; - int pmult = pageid / 16; - unsigned short (*LPTCOL)(unsigned short); - - LPTCOL = PTCF[DrawSemiTrans]; - - ldxo = TWin.Position.x1-TWin.OPosition.x1; - ldy = TWin.Position.y1-TWin.OPosition.y1; - - pa = px = (unsigned short *)ubPaletteBuffer; - ta = (unsigned short *)texturepart; - palstart = cx + (cy * 1024); - - ubOpaqueDraw = 0; - - switch (mode) - { - //--------------------------------------------------// - // 4bit texture load .. - case 0: - if(GlobalTextIL) - { - unsigned int TXV,TXU,n_xi,n_yi; - - wSRCPtr=psxVuw+palstart; - for(row=0;row<16;row++) - *px++=LPTCOL(*wSRCPtr++); - - column=g_y2-ldy; - for(TXV=g_y1;TXV<=column;TXV++) - { - ldx=ldxo; - for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) - { - n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); - - s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); - *ta++=s; - - if(ldx) {*ta++=s;ldx--;} - } - - if(ldy) - {ldy--; - for(TXU=g_x1;TXU<=g_x2;TXU++,ta++) - *ta=*(ta-(g_x2-g_x1)); - } - } - - DefineTextureWnd(); - - break; - } - - - start=((pageid-16*pmult)*128)+256*2048*pmult; - - // convert CLUT to 32bits .. and then use THAT as a lookup table - - wSRCPtr=psxVuw+palstart; - for(row=0;row<16;row++) - *px++=LPTCOL(*wSRCPtr++); - - sxm=g_x1&1;sxh=g_x1>>1; - if(sxm) j=g_x1+1; else j=g_x1; - cSRCPtr = psxVub + start + (2048*g_y1) + sxh; - for(column=g_y1;column<=g_y2;column++) - { - cOSRCPtr=cSRCPtr;ldx=ldxo; - if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); - - for(row=j;row<=g_x2-ldxo;row++) - { - s=*(pa+(*cSRCPtr & 0xF)); - *ta++=s; - if(ldx) {*ta++=s;ldx--;} - row++; - if(row<=g_x2-ldxo) - { - s=*(pa+((*cSRCPtr >> 4) & 0xF)); - *ta++=s; - if(ldx) {*ta++=s;ldx--;} - } - cSRCPtr++; - } - - if(ldy && column&1) - {ldy--;cSRCPtr = cOSRCPtr;} - else cSRCPtr = psxVub + start + (2048*(column+1)) + sxh; - } - - DefineTextureWnd(); - break; - //--------------------------------------------------// - // 8bit texture load .. - case 1: - if(GlobalTextIL) - { - unsigned int TXV,TXU,n_xi,n_yi; - - wSRCPtr=psxVuw+palstart; - for(row=0;row<256;row++) - *px++=LPTCOL(*wSRCPtr++); - - column=g_y2-ldy; - for(TXV=g_y1;TXV<=column;TXV++) - { - ldx=ldxo; - for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) - { - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); - - *ta++=s; - if(ldx) {*ta++=s;ldx--;} - } - - if(ldy) - {ldy--; - for(TXU=g_x1;TXU<=g_x2;TXU++,ta++) - *ta=*(ta-(g_x2-g_x1)); - } - - } - - DefineTextureWnd(); - - break; - } - - start=((pageid-16*pmult)*128)+256*2048*pmult; - - // not using a lookup table here... speeds up smaller texture areas - cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; - LineOffset = 2048 - (g_x2-g_x1+1) +ldxo; - - for(column=g_y1;column<=g_y2;column++) - { - cOSRCPtr=cSRCPtr;ldx=ldxo; - for(row=g_x1;row<=g_x2-ldxo;row++) - { - s=LPTCOL(psxVuw[palstart+ *cSRCPtr++]); - *ta++=s; - if(ldx) {*ta++=s;ldx--;} - } - if(ldy && column&1) {ldy--;cSRCPtr=cOSRCPtr;} - else cSRCPtr+=LineOffset; - } - - DefineTextureWnd(); - break; - //--------------------------------------------------// - // 16bit texture load .. - case 2: - start=((pageid-16*pmult)*64)+256*1024*pmult; - wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; - LineOffset = 1024 - (g_x2-g_x1+1) +ldxo; - - for(column=g_y1;column<=g_y2;column++) - { - wOSRCPtr=wSRCPtr;ldx=ldxo; - for(row=g_x1;row<=g_x2-ldxo;row++) - { - s=LPTCOL(*wSRCPtr++); - *ta++=s; - if(ldx) {*ta++=s;ldx--;} - } - if(ldy && column&1) {ldy--;wSRCPtr=wOSRCPtr;} - else wSRCPtr+=LineOffset; - } - - DefineTextureWnd(); - break; - //--------------------------------------------------// - // others are not possible ! - } -} - -//////////////////////////////////////////////////////////////////////// -// tex window: load stretched -//////////////////////////////////////////////////////////////////////// - -static void LoadStretchWndTexturePage(int pageid, int mode, short cx, short cy) -{ - uint32_t start,row,column,j,sxh,sxm,ldx,ldy,ldxo,s; - unsigned int palstart; - uint32_t *px,*pa,*ta; - unsigned char *cSRCPtr,*cOSRCPtr; - unsigned short *wSRCPtr,*wOSRCPtr; - uint32_t LineOffset; - int pmult = pageid / 16; - uint32_t (*LTCOL)(uint32_t); - - LTCOL = TCF[DrawSemiTrans]; - - ldxo=TWin.Position.x1-TWin.OPosition.x1; - ldy =TWin.Position.y1-TWin.OPosition.y1; - - pa = px = (uint32_t *)ubPaletteBuffer; - ta = (uint32_t *)texturepart; - palstart = cx + (cy * 1024); - - ubOpaqueDraw = 0; - - switch (mode) - { - //--------------------------------------------------// - // 4bit texture load .. - case 0: - //------------------- ZN STUFF - - if(GlobalTextIL) - { - unsigned int TXV,TXU,n_xi,n_yi; - - wSRCPtr=psxVuw+palstart; - - row=4;do - { - *px =LTCOL(*wSRCPtr); - *(px+1)=LTCOL(*(wSRCPtr+1)); - *(px+2)=LTCOL(*(wSRCPtr+2)); - *(px+3)=LTCOL(*(wSRCPtr+3)); - row--;px+=4;wSRCPtr+=4; - } - while (row); - - column=g_y2-ldy; - for(TXV=g_y1;TXV<=column;TXV++) - { - ldx=ldxo; - for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) - { - n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); - - s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); - *ta++=s; - - if(ldx) {*ta++=s;ldx--;} - } - - if(ldy) - {ldy--; - for(TXU=g_x1;TXU<=g_x2;TXU++,ta++) - *ta=*(ta-(g_x2-g_x1)); - } - } - - DefineTextureWnd(); - - break; - } - - //------------------- - - start=((pageid-16*pmult)*128)+256*2048*pmult; - // convert CLUT to 32bits .. and then use THAT as a lookup table - - wSRCPtr=psxVuw+palstart; - for(row=0;row<16;row++) - *px++=LTCOL(*wSRCPtr++); - - sxm=g_x1&1;sxh=g_x1>>1; - if(sxm) j=g_x1+1; else j=g_x1; - cSRCPtr = psxVub + start + (2048*g_y1) + sxh; - for(column=g_y1;column<=g_y2;column++) - { - cOSRCPtr=cSRCPtr;ldx=ldxo; - if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); - - for(row=j;row<=g_x2-ldxo;row++) - { - s=*(pa+(*cSRCPtr & 0xF)); - *ta++=s; - if(ldx) {*ta++=s;ldx--;} - row++; - if(row<=g_x2-ldxo) - { - s=*(pa+((*cSRCPtr >> 4) & 0xF)); - *ta++=s; - if(ldx) {*ta++=s;ldx--;} - } - cSRCPtr++; - } - if(ldy && column&1) - {ldy--;cSRCPtr = cOSRCPtr;} - else cSRCPtr = psxVub + start + (2048*(column+1)) + sxh; - } - - DefineTextureWnd(); - break; - //--------------------------------------------------// - // 8bit texture load .. - case 1: - //------------ ZN STUFF - if(GlobalTextIL) - { - unsigned int TXV,TXU,n_xi,n_yi; - - wSRCPtr=psxVuw+palstart; - - row=64;do - { - *px =LTCOL(*wSRCPtr); - *(px+1)=LTCOL(*(wSRCPtr+1)); - *(px+2)=LTCOL(*(wSRCPtr+2)); - *(px+3)=LTCOL(*(wSRCPtr+3)); - row--;px+=4;wSRCPtr+=4; - } - while (row); - - column=g_y2-ldy; - for(TXV=g_y1;TXV<=column;TXV++) - { - ldx=ldxo; - for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) - { - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); - *ta++=s; - if(ldx) {*ta++=s;ldx--;} - } - - if(ldy) - {ldy--; - for(TXU=g_x1;TXU<=g_x2;TXU++,ta++) - *ta=*(ta-(g_x2-g_x1)); - } - - } - - DefineTextureWnd(); - - break; - } - //------------ - - start=((pageid-16*pmult)*128)+256*2048*pmult; - - // not using a lookup table here... speeds up smaller texture areas - cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; - LineOffset = 2048 - (g_x2-g_x1+1) +ldxo; - - for(column=g_y1;column<=g_y2;column++) - { - cOSRCPtr=cSRCPtr;ldx=ldxo; - for(row=g_x1;row<=g_x2-ldxo;row++) - { - s=LTCOL(psxVuw[palstart+ *cSRCPtr++]); - *ta++=s; - if(ldx) {*ta++=s;ldx--;} - } - if(ldy && column&1) {ldy--;cSRCPtr=cOSRCPtr;} - else cSRCPtr+=LineOffset; - } - - DefineTextureWnd(); - break; - //--------------------------------------------------// - // 16bit texture load .. - case 2: - start=((pageid-16*pmult)*64)+256*1024*pmult; - - wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; - LineOffset = 1024 - (g_x2-g_x1+1) +ldxo; - - for(column=g_y1;column<=g_y2;column++) - { - wOSRCPtr=wSRCPtr;ldx=ldxo; - for(row=g_x1;row<=g_x2-ldxo;row++) - { - s=LTCOL(*wSRCPtr++); - *ta++=s; - if(ldx) {*ta++=s;ldx--;} - } - if(ldy && column&1) {ldy--;wSRCPtr=wOSRCPtr;} - else wSRCPtr+=LineOffset; - } - - DefineTextureWnd(); - break; - //--------------------------------------------------// - // others are not possible ! - } -} - -//////////////////////////////////////////////////////////////////////// -// tex window: load packed simple -//////////////////////////////////////////////////////////////////////// - -static void LoadPackedWndTexturePage(int pageid, int mode, short cx, short cy) -{ - uint32_t start,row,column,j,sxh,sxm; - unsigned int palstart; - unsigned short *px,*pa,*ta; - unsigned char *cSRCPtr; - unsigned short *wSRCPtr; - uint32_t LineOffset; - int pmult=pageid/16; - unsigned short (*LPTCOL)(unsigned short); - - LPTCOL=PTCF[DrawSemiTrans]; - - pa=px=(unsigned short *)ubPaletteBuffer; - ta=(unsigned short *)texturepart; - palstart=cx+(cy*1024); - - ubOpaqueDraw=0; - - switch(mode) - { - //--------------------------------------------------// - // 4bit texture load .. - case 0: - if(GlobalTextIL) - { - unsigned int TXV,TXU,n_xi,n_yi; - - wSRCPtr=psxVuw+palstart; - for(row=0;row<16;row++) - *px++=LPTCOL(*wSRCPtr++); - - for(TXV=g_y1;TXV<=g_y2;TXV++) - { - for(TXU=g_x1;TXU<=g_x2;TXU++) - { - n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); - - *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); - } - } - - DefineTextureWnd(); - - break; - } - - start=((pageid-16*pmult)*128)+256*2048*pmult; - - // convert CLUT to 32bits .. and then use THAT as a lookup table - - wSRCPtr=psxVuw+palstart; - for(row=0;row<16;row++) - *px++=LPTCOL(*wSRCPtr++); - - sxm=g_x1&1;sxh=g_x1>>1; - if(sxm) j=g_x1+1; else j=g_x1; - cSRCPtr = psxVub + start + (2048*g_y1) + sxh; - for(column=g_y1;column<=g_y2;column++) - { - cSRCPtr = psxVub + start + (2048*column) + sxh; - - if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); - - for(row=j;row<=g_x2;row++) - { - *ta++=*(pa+(*cSRCPtr & 0xF)); row++; - if(row<=g_x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); - cSRCPtr++; - } - } - - DefineTextureWnd(); - break; - //--------------------------------------------------// - // 8bit texture load .. - case 1: - if(GlobalTextIL) - { - unsigned int TXV,TXU,n_xi,n_yi; - - wSRCPtr=psxVuw+palstart; - for(row=0;row<256;row++) - *px++=LPTCOL(*wSRCPtr++); - - for(TXV=g_y1;TXV<=g_y2;TXV++) - { - for(TXU=g_x1;TXU<=g_x2;TXU++) - { - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); - } - } - - DefineTextureWnd(); - - break; - } - - start=((pageid-16*pmult)*128)+256*2048*pmult; - - // not using a lookup table here... speeds up smaller texture areas - cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; - LineOffset = 2048 - (g_x2-g_x1+1); - - for(column=g_y1;column<=g_y2;column++) - { - for(row=g_x1;row<=g_x2;row++) - *ta++=LPTCOL(psxVuw[palstart+ *cSRCPtr++]); - cSRCPtr+=LineOffset; - } - - DefineTextureWnd(); - break; - //--------------------------------------------------// - // 16bit texture load .. - case 2: - start=((pageid-16*pmult)*64)+256*1024*pmult; - wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; - LineOffset = 1024 - (g_x2-g_x1+1); - - for(column=g_y1;column<=g_y2;column++) - { - for(row=g_x1;row<=g_x2;row++) - *ta++=LPTCOL(*wSRCPtr++); - wSRCPtr+=LineOffset; - } - - DefineTextureWnd(); - break; - //--------------------------------------------------// - // others are not possible ! - } -} - -//////////////////////////////////////////////////////////////////////// -// tex window: load simple -//////////////////////////////////////////////////////////////////////// - -static void LoadWndTexturePage(int pageid, int mode, short cx, short cy) -{ - uint32_t start,row,column,j,sxh,sxm; - unsigned int palstart; - uint32_t *px,*pa,*ta; - unsigned char *cSRCPtr; - unsigned short *wSRCPtr; - uint32_t LineOffset; - int pmult = pageid / 16; - uint32_t (*LTCOL)(uint32_t); - - LTCOL=TCF[DrawSemiTrans]; - - pa = px = (uint32_t *)ubPaletteBuffer; - ta = (uint32_t *)texturepart; - palstart = cx + (cy * 1024); - - ubOpaqueDraw = 0; - - switch (mode) - { - //--------------------------------------------------// - // 4bit texture load .. - case 0: - if(GlobalTextIL) - { - unsigned int TXV,TXU,n_xi,n_yi; - - wSRCPtr=psxVuw+palstart; - - row=4;do - { - *px =LTCOL(*wSRCPtr); - *(px+1)=LTCOL(*(wSRCPtr+1)); - *(px+2)=LTCOL(*(wSRCPtr+2)); - *(px+3)=LTCOL(*(wSRCPtr+3)); - row--;px+=4;wSRCPtr+=4; - } - while (row); - - for(TXV=g_y1;TXV<=g_y2;TXV++) - { - for(TXU=g_x1;TXU<=g_x2;TXU++) - { - n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); - - *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); - } - } - - DefineTextureWnd(); - - break; - } - - start=((pageid-16*pmult)*128)+256*2048*pmult; - - // convert CLUT to 32bits .. and then use THAT as a lookup table - - wSRCPtr=psxVuw+palstart; - for(row=0;row<16;row++) - *px++=LTCOL(*wSRCPtr++); - - sxm=g_x1&1;sxh=g_x1>>1; - if(sxm) j=g_x1+1; else j=g_x1; - cSRCPtr = psxVub + start + (2048*g_y1) + sxh; - for(column=g_y1;column<=g_y2;column++) - { - cSRCPtr = psxVub + start + (2048*column) + sxh; - - if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); - - for(row=j;row<=g_x2;row++) - { - *ta++=*(pa+(*cSRCPtr & 0xF)); row++; - if(row<=g_x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); - cSRCPtr++; - } - } - - DefineTextureWnd(); - break; - //--------------------------------------------------// - // 8bit texture load .. - case 1: - if(GlobalTextIL) - { - unsigned int TXV,TXU,n_xi,n_yi; - - wSRCPtr=psxVuw+palstart; - - row=64;do - { - *px =LTCOL(*wSRCPtr); - *(px+1)=LTCOL(*(wSRCPtr+1)); - *(px+2)=LTCOL(*(wSRCPtr+2)); - *(px+3)=LTCOL(*(wSRCPtr+3)); - row--;px+=4;wSRCPtr+=4; - } - while (row); - - for(TXV=g_y1;TXV<=g_y2;TXV++) - { - for(TXU=g_x1;TXU<=g_x2;TXU++) - { - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); - } - } - - DefineTextureWnd(); - - break; - } - - start=((pageid-16*pmult)*128)+256*2048*pmult; - - // not using a lookup table here... speeds up smaller texture areas - cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; - LineOffset = 2048 - (g_x2-g_x1+1); - - for(column=g_y1;column<=g_y2;column++) - { - for(row=g_x1;row<=g_x2;row++) - *ta++=LTCOL(psxVuw[palstart+ *cSRCPtr++]); - cSRCPtr+=LineOffset; - } - - DefineTextureWnd(); - break; - //--------------------------------------------------// - // 16bit texture load .. - case 2: - start=((pageid-16*pmult)*64)+256*1024*pmult; - - wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; - LineOffset = 1024 - (g_x2-g_x1+1); - - for(column=g_y1;column<=g_y2;column++) - { - for(row=g_x1;row<=g_x2;row++) - *ta++=LTCOL(*wSRCPtr++); - wSRCPtr+=LineOffset; - } - - DefineTextureWnd(); - break; - //--------------------------------------------------// - // others are not possible ! - } -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -static void UploadTexWndPal(int mode,short cx,short cy) -{ - unsigned int i,iSize; - unsigned short *wSrcPtr; - uint32_t *ta = (uint32_t *)texturepart; - - wSrcPtr = psxVuw + cx + (cy * 1024); - if (mode == 0) i = 4; else i = 64; - iSize = i << 2; - ubOpaqueDraw = 0; - - do - { - *ta =PALCOL(*wSrcPtr); - *(ta+1)=PALCOL(*(wSrcPtr+1)); - *(ta+2)=PALCOL(*(wSrcPtr+2)); - *(ta+3)=PALCOL(*(wSrcPtr+3)); - ta+=4;wSrcPtr+=4;i--; - } - while(i); - - (*glColorTableEXTEx)(GL_TEXTURE_2D,GL_RGBA8,iSize, - GL_RGBA,GL_UNSIGNED_BYTE,texturepart); -} - -//////////////////////////////////////////////////////////////////////// - -static void DefinePalTextureWnd(void) -{ - if(gTexName==0) - glGenTextures(1, &gTexName); - - glBindTexture(GL_TEXTURE_2D, gTexName); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - if(iFilterType && iFilterType<3 && iHiResTextures!=2) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - - glTexImage2D(GL_TEXTURE_2D, 0,GL_COLOR_INDEX8_EXT, - TWin.Position.x1, - TWin.Position.y1, - 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE,texturepart); -} - -/////////////////////////////////////////////////////// - -static void LoadPalWndTexturePage(int pageid, int mode, short cx, short cy) -{ - uint32_t start,row,column,j,sxh,sxm; - unsigned char *ta; - unsigned char *cSRCPtr; - uint32_t LineOffset; - int pmult = pageid / 16; - - ta = (unsigned char *)texturepart; - - switch (mode) - { - //--------------------------------------------------// - // 4bit texture load .. - case 0: - start=((pageid-16*pmult)*128)+256*2048*pmult; - - sxm=g_x1&1;sxh=g_x1>>1; - if(sxm) j=g_x1+1; else j=g_x1; - cSRCPtr = psxVub + start + (2048*g_y1) + sxh; - for(column=g_y1;column<=g_y2;column++) - { - cSRCPtr = psxVub + start + (2048*column) + sxh; - - if(sxm) *ta++=((*cSRCPtr++ >> 4) & 0xF); - - for(row=j;row<=g_x2;row++) - { - *ta++=(*cSRCPtr & 0xF); row++; - if(row<=g_x2) *ta++=((*cSRCPtr >> 4) & 0xF); - cSRCPtr++; - } - } - - DefinePalTextureWnd(); - break; - //--------------------------------------------------// - // 8bit texture load .. - case 1: - start=((pageid-16*pmult)*128)+256*2048*pmult; - - // not using a lookup table here... speeds up smaller texture areas - cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; - LineOffset = 2048 - (g_x2-g_x1+1); - - for(column=g_y1;column<=g_y2;column++) - { - for(row=g_x1;row<=g_x2;row++) - *ta++=*cSRCPtr++; - cSRCPtr+=LineOffset; - } - - DefinePalTextureWnd(); - break; - } - UploadTexWndPal(mode,cx,cy); -} - -//////////////////////////////////////////////////////////////////////// - -static void LoadStretchPalWndTexturePage(int pageid, int mode, short cx, short cy) -{ - uint32_t start,row,column,j,sxh,sxm,ldx,ldy,ldxo; - unsigned char *ta,s; - unsigned char *cSRCPtr,*cOSRCPtr; - uint32_t LineOffset; - int pmult = pageid / 16; - - ldxo = TWin.Position.x1-TWin.OPosition.x1; - ldy = TWin.Position.y1-TWin.OPosition.y1; - - ta = (unsigned char *)texturepart; - - switch (mode) - { - //--------------------------------------------------// - // 4bit texture load .. - case 0: - start=((pageid-16*pmult)*128)+256*2048*pmult; - - sxm=g_x1&1;sxh=g_x1>>1; - if(sxm) j=g_x1+1; else j=g_x1; - cSRCPtr = psxVub + start + (2048*g_y1) + sxh; - for(column=g_y1;column<=g_y2;column++) - { - cOSRCPtr=cSRCPtr;ldx=ldxo; - if(sxm) *ta++=((*cSRCPtr++ >> 4) & 0xF); - - for(row=j;row<=g_x2-ldxo;row++) - { - s=(*cSRCPtr & 0xF); - *ta++=s; - if(ldx) {*ta++=s;ldx--;} - row++; - if(row<=g_x2-ldxo) - { - s=((*cSRCPtr >> 4) & 0xF); - *ta++=s; - if(ldx) {*ta++=s;ldx--;} - } - cSRCPtr++; - } - if(ldy && column&1) - {ldy--;cSRCPtr = cOSRCPtr;} - else cSRCPtr = psxVub + start + (2048*(column+1)) + sxh; - } - - DefinePalTextureWnd(); - break; - //--------------------------------------------------// - // 8bit texture load .. - case 1: - start=((pageid-16*pmult)*128)+256*2048*pmult; - - cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; - LineOffset = 2048 - (g_x2-g_x1+1) +ldxo; - - for(column=g_y1;column<=g_y2;column++) - { - cOSRCPtr=cSRCPtr;ldx=ldxo; - for(row=g_x1;row<=g_x2-ldxo;row++) - { - s=*cSRCPtr++; - *ta++=s; - if(ldx) {*ta++=s;ldx--;} - } - if(ldy && column&1) {ldy--;cSRCPtr=cOSRCPtr;} - else cSRCPtr+=LineOffset; - } - - DefinePalTextureWnd(); - break; - } - UploadTexWndPal(mode,cx,cy); -} - -//////////////////////////////////////////////////////////////////////// -// tex window: main selecting, cache handler included -//////////////////////////////////////////////////////////////////////// - -GLuint LoadTextureWnd(int pageid, int TextureMode, uint32_t GivenClutId) -{ - textureWndCacheEntry *ts, *tsx = NULL; - int i; - short cx,cy; - EXLong npos; - - npos.c[3] = TWin.Position.x0; - npos.c[2] = TWin.OPosition.x1; - npos.c[1] = TWin.Position.y0; - npos.c[0] = TWin.OPosition.y1; - - g_x1 = TWin.Position.x0; g_x2 = g_x1 + TWin.Position.x1 - 1; - g_y1 = TWin.Position.y0; g_y2 = g_y1 + TWin.Position.y1 - 1; - - if (TextureMode == 2) { GivenClutId = 0; cx = cy = 0; } - else - { - cx = ((GivenClutId << 4) & 0x3F0); - cy = ((GivenClutId >> 6) & CLUTYMASK); - GivenClutId = (GivenClutId & CLUTMASK) | (DrawSemiTrans << 30); - - // palette check sum - { - uint32_t l = 0,row; - uint32_t *lSRCPtr = (uint32_t *)(psxVuw + cx + (cy * 1024)); - if(TextureMode==1) for(row=1;row<129;row++) l+=((*lSRCPtr++)-1)*row; - else for(row=1;row<9;row++) l+=((*lSRCPtr++)-1)<used) - { - if(ts->pos.l==npos.l && - ts->pageid==pageid && - ts->textureMode==TextureMode) - { - if(ts->ClutID==GivenClutId) - { - ubOpaqueDraw=ts->Opaque; - return ts->texname; - } - else if(glColorTableEXTEx && TextureMode!=2) - { - ts->ClutID=GivenClutId; - if(ts->texname!=gTexName) - { - gTexName=ts->texname; - glBindTexture(GL_TEXTURE_2D, gTexName); - } - UploadTexWndPal(TextureMode,cx,cy); - ts->Opaque=ubOpaqueDraw; - return gTexName; - } - } - } - else tsx=ts; - } - - if(!tsx) - { - if(iMaxTexWnds==iTexWndLimit) - { - tsx=wcWndtexStore+iTexWndTurn; - iTexWndTurn++; - if(iTexWndTurn==iTexWndLimit) iTexWndTurn=0; - } - else - { - tsx=wcWndtexStore+iMaxTexWnds; - iMaxTexWnds++; - } - } - - gTexName=tsx->texname; - - if(TWin.OPosition.y1==TWin.Position.y1 && - TWin.OPosition.x1==TWin.Position.x1) - { - if(glColorTableEXTEx && TextureMode!=2) - LoadPalWndTexturePage(pageid,TextureMode,cx,cy); - else - if(bGLExt) - LoadPackedWndTexturePage(pageid,TextureMode,cx,cy); - else - LoadWndTexturePage(pageid,TextureMode,cx,cy); - } - else - { - if(glColorTableEXTEx && TextureMode!=2) - LoadStretchPalWndTexturePage(pageid,TextureMode,cx,cy); - else - if(bGLExt) - LoadStretchPackedWndTexturePage(pageid,TextureMode,cx,cy); - else - LoadStretchWndTexturePage(pageid,TextureMode,cx,cy); - } - - tsx->Opaque=ubOpaqueDraw; - tsx->pos.l=npos.l; - tsx->ClutID=GivenClutId; - tsx->pageid=pageid; - tsx->textureMode=TextureMode; - tsx->texname=gTexName; - tsx->used=1; - - return gTexName; -} - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -// movie texture: define -//////////////////////////////////////////////////////////////////////// - -static void DefinePackedTextureMovie(void) -{ - if(gTexMovieName==0) - { - glGenTextures(1, &gTexMovieName); - gTexName=gTexMovieName; - glBindTexture(GL_TEXTURE_2D, gTexName); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); - - if(!bUseFastMdec) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - - glTexImage2D(GL_TEXTURE_2D, 0, //giWantedRGBA, - GL_RGB5_A1, - 256, 256, 0, GL_RGBA, giWantedTYPE, texturepart); - } - else - { - gTexName=gTexMovieName;glBindTexture(GL_TEXTURE_2D, gTexName); - } - - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, - (xrMovieArea.x1-xrMovieArea.x0), - (xrMovieArea.y1-xrMovieArea.y0), - GL_RGBA, - GL_UNSIGNED_SHORT_5_5_5_1_EXT, - texturepart); -} - -//////////////////////////////////////////////////////////////////////// - -static void DefineTextureMovie(void) -{ - if(gTexMovieName==0) - { - glGenTextures(1, &gTexMovieName); - gTexName=gTexMovieName; - glBindTexture(GL_TEXTURE_2D, gTexName); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); - - if(!bUseFastMdec) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - - glTexImage2D(GL_TEXTURE_2D, 0, giWantedRGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, texturepart); - } - else - { - gTexName=gTexMovieName;glBindTexture(GL_TEXTURE_2D, gTexName); - } - - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, - (xrMovieArea.x1-xrMovieArea.x0), - (xrMovieArea.y1-xrMovieArea.y0), - GL_RGBA, GL_UNSIGNED_BYTE, texturepart); -} - -//////////////////////////////////////////////////////////////////////// -// movie texture: load -//////////////////////////////////////////////////////////////////////// - -#define MRED(x) ((x>>3) & 0x1f) -#define MGREEN(x) ((x>>6) & 0x3e0) -#define MBLUE(x) ((x>>9) & 0x7c00) - -#define XMGREEN(x) ((x>>5) & 0x07c0) -#define XMRED(x) ((x<<8) & 0xf800) -#define XMBLUE(x) ((x>>18) & 0x003e) - -//////////////////////////////////////////////////////////////////////// -// movie texture: load -//////////////////////////////////////////////////////////////////////// - -unsigned char * LoadDirectMovieFast(void) -{ - int row,column; - unsigned int startxy; - - uint32_t *ta=(uint32_t *)texturepart; - - if(PSXDisplay.RGB24) - { - unsigned char * pD; - - startxy=((1024)*xrMovieArea.y0)+xrMovieArea.x0; - - for(column=xrMovieArea.y0;column>9)|0x00010001; - ta+=2;startxy+=2; - } - if(row==sx0) *ta++=(psxVuw[startxy]<<1)|1; - } - } - DefinePackedTextureMovie(); - } - else - { - if(PSXDisplay.RGB24) - { - unsigned char *pD; - uint32_t *ta = (uint32_t *)texturepart; - - startxy=((1024)*xrMovieArea.y0)+xrMovieArea.x0; - - for(column=xrMovieArea.y0;column>9)|1; - } - - *ta=*(ta-1); - ta++; - } - if(b_Y) - { - dx=xrMovieArea.x1-xrMovieArea.x0+1; - for(row=xrMovieArea.x0;row>9)|1; - } - } - if(b_Y) - { - dx=xrMovieArea.x1-xrMovieArea.x0; - for(row=xrMovieArea.x0;row1280 || iResY>1024) iFTex=2048; - else - if(iResX>640 || iResY>480) iFTex=1024; - else iFTex=512; - - glGenTextures(1, &gTexFrameName); - gTexName=gTexFrameName; - glBindTexture(GL_TEXTURE_2D, gTexName); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - p=(char *)malloc(iFTex*iFTex*4); - memset(p,0,iFTex*iFTex*4); - glTexImage2D(GL_TEXTURE_2D, 0, 3, iFTex, iFTex, 0, GL_RGB, GL_UNSIGNED_BYTE, p); - free(p); - - glGetError(); - } - else - { - gTexName=gTexFrameName; - glBindTexture(GL_TEXTURE_2D, gTexName); - } - - x1+=PreviousPSXDisplay.Range.x0; - y1+=PreviousPSXDisplay.Range.y0; - - if(PSXDisplay.DisplayMode.x) - ScaleX=(float)rRatioRect.right/(float)PSXDisplay.DisplayMode.x; - else ScaleX=1.0f; - if(PSXDisplay.DisplayMode.y) - ScaleY=(float)rRatioRect.bottom/(float)PSXDisplay.DisplayMode.y; - else ScaleY=1.0f; - - rSrc.left =max(x1*ScaleX,0); - rSrc.right =min((x1+x2)*ScaleX+0.99f,iResX-1); - rSrc.top =max(y1*ScaleY,0); - rSrc.bottom=min((y1+y2)*ScaleY+0.99f,iResY-1); - - iYAdjust=(y1+y2)-PSXDisplay.DisplayMode.y; - if(iYAdjust>0) - iYAdjust=(int)((float)iYAdjust*ScaleY)+1; - else iYAdjust=0; - - gl_vy[0]=255-gl_vy[0]; - gl_vy[1]=255-gl_vy[1]; - gl_vy[2]=255-gl_vy[2]; - gl_vy[3]=255-gl_vy[3]; - - y1=min(gl_vy[0],min(gl_vy[1],min(gl_vy[2],gl_vy[3]))); - - gl_vy[0]-=y1; - gl_vy[1]-=y1; - gl_vy[2]-=y1; - gl_vy[3]-=y1; - gl_ux[0]-=gl_ux[7]; - gl_ux[1]-=gl_ux[7]; - gl_ux[2]-=gl_ux[7]; - gl_ux[3]-=gl_ux[7]; - - ScaleX*=256.0f/((float)(iFTex)); - ScaleY*=256.0f/((float)(iFTex)); - - y1=((float)gl_vy[0]*ScaleY); if(y1>255) y1=255; - gl_vy[0]=y1; - y1=((float)gl_vy[1]*ScaleY); if(y1>255) y1=255; - gl_vy[1]=y1; - y1=((float)gl_vy[2]*ScaleY); if(y1>255) y1=255; - gl_vy[2]=y1; - y1=((float)gl_vy[3]*ScaleY); if(y1>255) y1=255; - gl_vy[3]=y1; - - x1=((float)gl_ux[0]*ScaleX); if(x1>255) x1=255; - gl_ux[0]=x1; - x1=((float)gl_ux[1]*ScaleX); if(x1>255) x1=255; - gl_ux[1]=x1; - x1=((float)gl_ux[2]*ScaleX); if(x1>255) x1=255; - gl_ux[2]=x1; - x1=((float)gl_ux[3]*ScaleX); if(x1>255) x1=255; - gl_ux[3]=x1; - - x1=rSrc.right-rSrc.left; - if(x1<=0) x1=1; - if(x1>iFTex) x1=iFTex; - - y1=rSrc.bottom-rSrc.top; - if(y1<=0) y1=1; - if(y1+iYAdjust>iFTex) y1=iFTex-iYAdjust; - - if(bFakeFrontBuffer) glReadBuffer(GL_FRONT); - - glCopyTexSubImage2D( GL_TEXTURE_2D, 0, - 0, - iYAdjust, - rSrc.left+rRatioRect.left, - iResY-rSrc.bottom-rRatioRect.top, - x1,y1); - - if(glGetError()) - { - char * p=(char *)malloc(iFTex*iFTex*4); - memset(p,0,iFTex*iFTex*4); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, iFTex, iFTex, - GL_RGB, GL_UNSIGNED_BYTE, p); - free(p); - } - - if(bFakeFrontBuffer) - {glReadBuffer(GL_BACK);bIgnoreNextTile=TRUE;} - - ubOpaqueDraw=0; - - if(iSpriteTex) - { - sprtW=gl_ux[1]-gl_ux[0]; - sprtH=-(gl_vy[0]-gl_vy[2]); - } - - return (GLuint)gTexName; -} - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// load texture part (unpacked) -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -void LoadSubTexturePageSort(int pageid, int mode, short cx, short cy) -{ - uint32_t start,row,column,j,sxh,sxm; - unsigned int palstart; - uint32_t *px,*pa,*ta; - unsigned char *cSRCPtr; - unsigned short *wSRCPtr; - uint32_t LineOffset; - uint32_t x2a,xalign=0; - uint32_t x1=gl_ux[7]; - uint32_t x2=gl_ux[6]; - uint32_t y1=gl_ux[5]; - uint32_t y2=gl_ux[4]; - uint32_t dx=x2-x1+1; - uint32_t dy=y2-y1+1; - int pmult=pageid/16; - uint32_t (*LTCOL)(uint32_t); - unsigned int a,r,g,b,cnt,h; - uint32_t scol[8]; - - LTCOL=TCF[DrawSemiTrans]; - - pa=px=(uint32_t *)ubPaletteBuffer; - ta=(uint32_t *)texturepart; - palstart=cx+(cy<<10); - - ubOpaqueDraw=0; - - if(YTexS) {ta+=dx;if(XTexS) ta+=2;} - if(XTexS) {ta+=1;xalign=2;} - - switch(mode) - { - //--------------------------------------------------// - // 4bit texture load .. - case 0: - if(GlobalTextIL) - { - unsigned int TXV,TXU,n_xi,n_yi; - - wSRCPtr=psxVuw+palstart; - - row=4;do - { - *px =LTCOL(*wSRCPtr); - *(px+1)=LTCOL(*(wSRCPtr+1)); - *(px+2)=LTCOL(*(wSRCPtr+2)); - *(px+3)=LTCOL(*(wSRCPtr+3)); - row--;px+=4;wSRCPtr+=4; - } - while (row); - - for(TXV=y1;TXV<=y2;TXV++) - { - for(TXU=x1;TXU<=x2;TXU++) - { - n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); - - *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); - } - ta+=xalign; - } - break; - } - - start=((pageid-16*pmult)<<7)+524288*pmult; - // convert CLUT to 32bits .. and then use THAT as a lookup table - - wSRCPtr=psxVuw+palstart; - - row=4;do - { - *px =LTCOL(*wSRCPtr); - *(px+1)=LTCOL(*(wSRCPtr+1)); - *(px+2)=LTCOL(*(wSRCPtr+2)); - *(px+3)=LTCOL(*(wSRCPtr+3)); - row--;px+=4;wSRCPtr+=4; - } - while (row); - - x2a=x2?(x2-1):0;//if(x2) x2a=x2-1; else x2a=0; - sxm=x1&1;sxh=x1>>1; - j=sxm?(x1+1):x1;//if(sxm) j=x1+1; else j=x1; - for(column=y1;column<=y2;column++) - { - cSRCPtr = psxVub + start + (column<<11) + sxh; - - if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); - - for(row=j;row> 4) & 0xF)); - cSRCPtr++;ta+=2; - } - - if(row<=x2) - { - *ta++=*(pa+(*cSRCPtr & 0xF)); row++; - if(row<=x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); - } - - ta+=xalign; - } - - break; - //--------------------------------------------------// - // 8bit texture load .. - case 1: - if(GlobalTextIL) - { - unsigned int TXV,TXU,n_xi,n_yi; - - wSRCPtr=psxVuw+palstart; - - row=64;do - { - *px =LTCOL(*wSRCPtr); - *(px+1)=LTCOL(*(wSRCPtr+1)); - *(px+2)=LTCOL(*(wSRCPtr+2)); - *(px+3)=LTCOL(*(wSRCPtr+3)); - row--;px+=4;wSRCPtr+=4; - } - while (row); - - for(TXV=y1;TXV<=y2;TXV++) - { - for(TXU=x1;TXU<=x2;TXU++) - { - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); - } - ta+=xalign; - } - - break; - } - - start=((pageid-16*pmult)<<7)+524288*pmult; - - cSRCPtr = psxVub + start + (y1<<11) + x1; - LineOffset = 2048 - dx; - - if(dy*dx>384) - { - wSRCPtr=psxVuw+palstart; - - row=64;do - { - *px =LTCOL(*wSRCPtr); - *(px+1)=LTCOL(*(wSRCPtr+1)); - *(px+2)=LTCOL(*(wSRCPtr+2)); - *(px+3)=LTCOL(*(wSRCPtr+3)); - row--;px+=4;wSRCPtr+=4; - } - while (row); - - column=dy;do - { - row=dx; - do {*ta++=*(pa+(*cSRCPtr++));row--;} while(row); - ta+=xalign; - cSRCPtr+=LineOffset;column--; - } - while(column); - } - else - { - wSRCPtr=psxVuw+palstart; - - column=dy;do - { - row=dx; - do {*ta++=LTCOL(*(wSRCPtr+*cSRCPtr++));row--;} while(row); - ta+=xalign; - cSRCPtr+=LineOffset;column--; - } - while(column); - } - - break; - //--------------------------------------------------// - // 16bit texture load .. - case 2: - start=((pageid-16*pmult)<<6)+262144*pmult; - - wSRCPtr = psxVuw + start + (y1<<10) + x1; - LineOffset = 1024 - dx; - - column=dy;do - { - row=dx; - do {*ta++=LTCOL(*wSRCPtr++);row--;} while(row); - ta+=xalign; - wSRCPtr+=LineOffset;column--; - } - while(column); - - break; - //--------------------------------------------------// - // others are not possible ! - } - - x2a=dx+xalign; - - if(YTexS) - { - ta=(uint32_t *)texturepart; - pa=(uint32_t *)texturepart+x2a; - row=x2a;do {*ta++=*pa++;row--;} while(row); - pa=(uint32_t *)texturepart+dy*x2a; - ta=pa+x2a; - row=x2a;do {*ta++=*pa++;row--;} while(row); - YTexS--; - dy+=2; - } - - if(XTexS) - { - ta=(uint32_t *)texturepart; - pa=ta+1; - row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); - pa=(uint32_t *)texturepart+dx; - ta=pa+1; - row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); - XTexS--; - dx+=2; - } - - DXTexS=dx;DYTexS=dy; - - if(!iFilterType) {DefineSubTextureSort();return;} - if(iFilterType!=2 && iFilterType!=4 && iFilterType!=6) {DefineSubTextureSort();return;} - if((iFilterType==4 || iFilterType==6) && ly0==ly1 && ly2==ly3 && lx0==lx3 && lx1==lx2) - {DefineSubTextureSort();return;} - - ta=(uint32_t *)texturepart; - x1=dx-1; - y1=dy-1; - - if(bOpaquePass) - { - if(bSmallAlpha) - { - for(column=0;column>24 !=0x03) scol[cnt++]=*(ta-dx); - if(row && *(ta-1) >>24 !=0x03) scol[cnt++]=*(ta-1); - if(row!=x1 && *(ta+1) >>24 !=0x03) scol[cnt++]=*(ta+1); - if( column!=y1 && *(ta+dx) >>24 !=0x03) scol[cnt++]=*(ta+dx); - - if(row && column && *(ta-dx-1)>>24 !=0x03) scol[cnt++]=*(ta-dx-1); - if(row!=x1 && column && *(ta-dx+1)>>24 !=0x03) scol[cnt++]=*(ta-dx+1); - if(row && column!=y1 && *(ta+dx-1)>>24 !=0x03) scol[cnt++]=*(ta+dx-1); - if(row!=x1 && column!=y1 && *(ta+dx+1)>>24 !=0x03) scol[cnt++]=*(ta+dx+1); - - if(cnt) - { - r=g=b=a=0; - for(h=0;h>16)&0xff; - g+=(scol[h]>>8)&0xff; - b+=scol[h]&0xff; - } - r/=cnt;b/=cnt;g/=cnt; - - *ta=(r<<16)|(g<<8)|b; - *ta|=0x03000000; - } - } - ta++; - } - } - } - else - { - for(column=0;column>24!=1) scol[cnt++]=*(ta-dx); - if(row && *(ta-1) !=0x50000000 && *(ta-1)>>24!=1) scol[cnt++]=*(ta-1); - if(row!=x1 && *(ta+1) !=0x50000000 && *(ta+1)>>24!=1) scol[cnt++]=*(ta+1); - if( column!=y1 && *(ta+dx) !=0x50000000 && *(ta+dx)>>24!=1) scol[cnt++]=*(ta+dx); - - if(row && column && *(ta-dx-1)!=0x50000000 && *(ta-dx-1)>>24!=1) scol[cnt++]=*(ta-dx-1); - if(row!=x1 && column && *(ta-dx+1)!=0x50000000 && *(ta-dx+1)>>24!=1) scol[cnt++]=*(ta-dx+1); - if(row && column!=y1 && *(ta+dx-1)!=0x50000000 && *(ta+dx-1)>>24!=1) scol[cnt++]=*(ta+dx-1); - if(row!=x1 && column!=y1 && *(ta+dx+1)!=0x50000000 && *(ta+dx+1)>>24!=1) scol[cnt++]=*(ta+dx+1); - - if(cnt) - { - r=g=b=a=0; - for(h=0;h>24); - r+=(scol[h]>>16)&0xff; - g+=(scol[h]>>8)&0xff; - b+=scol[h]&0xff; - } - r/=cnt;b/=cnt;g/=cnt; - - *ta=(r<<16)|(g<<8)|b; - if(a) *ta|=0x50000000; - else *ta|=0x01000000; - } - } - ta++; - } - } - } - } - else - for(column=0;column>16)&0xff; - g+=(scol[h]>>8)&0xff; - b+=scol[h]&0xff; - } - r/=cnt;b/=cnt;g/=cnt; - *ta=(r<<16)|(g<<8)|b; - } - } - ta++; - } - } - - DefineSubTextureSort(); -} - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// load texture part (packed) -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -void LoadPackedSubTexturePageSort(int pageid, int mode, short cx, short cy) -{ - uint32_t start,row,column,j,sxh,sxm; - unsigned int palstart; - unsigned short *px,*pa,*ta; - unsigned char *cSRCPtr; - unsigned short *wSRCPtr; - uint32_t LineOffset; - uint32_t x2a,xalign=0; - uint32_t x1=gl_ux[7]; - uint32_t x2=gl_ux[6]; - uint32_t y1=gl_ux[5]; - uint32_t y2=gl_ux[4]; - uint32_t dx=x2-x1+1; - uint32_t dy=y2-y1+1; - int pmult=pageid/16; - unsigned short (*LPTCOL)(unsigned short); - unsigned int a,r,g,b,cnt,h; - unsigned short scol[8]; - - LPTCOL=PTCF[DrawSemiTrans]; - - pa=px=(unsigned short *)ubPaletteBuffer; - ta=(unsigned short *)texturepart; - palstart=cx+(cy<<10); - - ubOpaqueDraw=0; - - if(YTexS) {ta+=dx;if(XTexS) ta+=2;} - if(XTexS) {ta+=1;xalign=2;} - - switch(mode) - { - //--------------------------------------------------// - // 4bit texture load .. - case 0: - if(GlobalTextIL) - { - unsigned int TXV,TXU,n_xi,n_yi; - - wSRCPtr=psxVuw+palstart; - row=4;do - { - *px =LPTCOL(*wSRCPtr); - *(px+1)=LPTCOL(*(wSRCPtr+1)); - *(px+2)=LPTCOL(*(wSRCPtr+2)); - *(px+3)=LPTCOL(*(wSRCPtr+3)); - row--;px+=4;wSRCPtr+=4; - } - while (row); - - for(TXV=y1;TXV<=y2;TXV++) - { - for(TXU=x1;TXU<=x2;TXU++) - { - n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); - n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); - - *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); - } - ta+=xalign; - } - break; - } - - start=((pageid-16*pmult)<<7)+524288*pmult; - - wSRCPtr=psxVuw+palstart; - row=4;do - { - *px =LPTCOL(*wSRCPtr); - *(px+1)=LPTCOL(*(wSRCPtr+1)); - *(px+2)=LPTCOL(*(wSRCPtr+2)); - *(px+3)=LPTCOL(*(wSRCPtr+3)); - row--;px+=4;wSRCPtr+=4; - } - while (row); - - x2a=x2?(x2-1):0;//if(x2) x2a=x2-1; else x2a=0; - sxm=x1&1;sxh=x1>>1; - j=sxm?(x1+1):x1;//if(sxm) j=x1+1; else j=x1; - - for(column=y1;column<=y2;column++) - { - cSRCPtr = psxVub + start + (column<<11) + sxh; - - if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); - - for(row=j;row> 4) & 0xF)); - cSRCPtr++;ta+=2; - } - - if(row<=x2) - { - *ta++=*(pa+(*cSRCPtr & 0xF));row++; - if(row<=x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); - } - - ta+=xalign; - } - break; - //--------------------------------------------------// - // 8bit texture load .. - case 1: - if(GlobalTextIL) - { - unsigned int TXV,TXU,n_xi,n_yi; - - wSRCPtr=psxVuw+palstart; - - row=64;do - { - *px =LPTCOL(*wSRCPtr); - *(px+1)=LPTCOL(*(wSRCPtr+1)); - *(px+2)=LPTCOL(*(wSRCPtr+2)); - *(px+3)=LPTCOL(*(wSRCPtr+3)); - row--;px+=4;wSRCPtr+=4; - } - while (row); - - for(TXV=y1;TXV<=y2;TXV++) - { - for(TXU=x1;TXU<=x2;TXU++) - { - n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); - n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); - - *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); - } - ta+=xalign; - } - - break; - } - - start=((pageid-16*pmult)<<7)+524288*pmult; - - cSRCPtr = psxVub + start + (y1<<11) + x1; - LineOffset = 2048 - dx; - - if(dy*dx>384) // more pix? use lut - { - wSRCPtr=psxVuw+palstart; - - row=64;do - { - *px =LPTCOL(*wSRCPtr); - *(px+1)=LPTCOL(*(wSRCPtr+1)); - *(px+2)=LPTCOL(*(wSRCPtr+2)); - *(px+3)=LPTCOL(*(wSRCPtr+3)); - row--;px+=4;wSRCPtr+=4; - } - while (row); - - column=dy;do - { - row=dx; - do {*ta++=*(pa+(*cSRCPtr++));row--;} while(row); - - ta+=xalign; - - cSRCPtr+=LineOffset;column--; - } - while(column); - } - else // small area? no lut - { - wSRCPtr=psxVuw+palstart; - - column=dy;do - { - row=dx; - do {*ta++=LPTCOL(*(wSRCPtr+*cSRCPtr++));row--;} while(row); - - ta+=xalign; - - cSRCPtr+=LineOffset;column--; - } - while(column); - } - break; - //--------------------------------------------------// - // 16bit texture load .. - case 2: - start=((pageid-16*pmult)<<6)+262144*pmult; - - wSRCPtr = psxVuw + start + (y1<<10) + x1; - LineOffset = 1024 - dx; - - column=dy;do - { - row=dx; - do {*ta++=LPTCOL(*wSRCPtr++);row--;} while(row); - - ta+=xalign; - - wSRCPtr+=LineOffset;column--; - } - while(column); - break; - //--------------------------------------------------// - // others are not possible ! - } - - //////////////////////////////////////////////////////// - - x2a=dx+xalign; - - if(YTexS) - { - ta=(unsigned short *)texturepart; - pa=(unsigned short *)texturepart+x2a; - row=x2a;do {*ta++=*pa++;row--;} while(row); - - pa=(unsigned short *)texturepart+dy*x2a; - ta=pa+x2a; - row=x2a;do {*ta++=*pa++;row--;} while(row); - - YTexS--; - dy+=2; - } - - if(XTexS) - { - ta=(unsigned short *)texturepart; - pa=ta+1; - row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); - - pa=(unsigned short *)texturepart+dx; - ta=pa+1; - row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); - - XTexS--; - dx+=2; - } - - DXTexS=dx;DYTexS=dy; - - if(!iFilterType) {DefineSubTextureSort();return;} - if(iFilterType!=2 && iFilterType!=4 && iFilterType!=6) {DefineSubTextureSort();return;} - if((iFilterType==4 || iFilterType==6) && ly0==ly1 && ly2==ly3 && lx0==lx3 && lx1==lx2) - {DefineSubTextureSort();return;} - - ta=(unsigned short *)texturepart; - x1=dx-1; - y1=dy-1; - - if(iTexQuality==1) - - { - if(bOpaquePass) - for(column=0;column>12; - g+=(scol[h]>>8)&0xf; - b+=(scol[h]>>4)&0xf; - } - r/=cnt;b/=cnt;g/=cnt; - *ta=(r<<12)|(g<<8)|(b<<4); - if(a) *ta|=6; - else *ta=0; - } - } - ta++; - } - } - else - for(column=0;column>12; - g+=(scol[h]>>8)&0xf; - b+=(scol[h]>>4)&0xf; - } - r/=cnt;b/=cnt;g/=cnt; - *ta=(r<<12)|(g<<8)|(b<<4); - } - } - ta++; - } - } - } - else - { - for(column=0;column>11; - g+=(scol[h]>>6)&0x1f; - b+=(scol[h]>>1)&0x1f; - } - r/=cnt;b/=cnt;g/=cnt; - *ta=(r<<11)|(g<<6)|(b<<1); - } - } - ta++; - } - } - } - - DefineSubTextureSort(); -} - -///////////////////////////////////////////////////////////////////////////// - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// hires texture funcs -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - - -#define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D)) - -//////////////////////////////////////////////////////////////////////// - -#define colorMask8 0x00FEFEFE -#define lowPixelMask8 0x00010101 -#define qcolorMask8 0x00FCFCFC -#define qlowpixelMask8 0x00030303 - - -#define INTERPOLATE8_02(A, B) (((((A & colorMask8) >> 1) + ((B & colorMask8) >> 1) + (A & B & lowPixelMask8))|((((A&0xFF000000)==0x03000000)?0x03000000:(((B&0xFF000000)==0x03000000)?0x03000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))) - -#define Q_INTERPOLATE8_02(A, B, C, D) (((((A & qcolorMask8) >> 2) + ((B & qcolorMask8) >> 2) + ((C & qcolorMask8) >> 2) + ((D & qcolorMask8) >> 2) + ((((A & qlowpixelMask8) + (B & qlowpixelMask8) + (C & qlowpixelMask8) + (D & qlowpixelMask8)) >> 2) & qlowpixelMask8))|((((A&0xFF000000)==0x03000000)?0x03000000:(((B&0xFF000000)==0x03000000)?0x03000000:(((C&0xFF000000)==0x03000000)?0x03000000:(((D&0xFF000000)==0x03000000)?0x03000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:(((C&0xFF000000)==0x00000000)?0x00000000:(((D&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))))))) - -#define INTERPOLATE8(A, B) (((((A & colorMask8) >> 1) + ((B & colorMask8) >> 1) + (A & B & lowPixelMask8))|((((A&0xFF000000)==0x50000000)?0x50000000:(((B&0xFF000000)==0x50000000)?0x50000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))) - -#define Q_INTERPOLATE8(A, B, C, D) (((((A & qcolorMask8) >> 2) + ((B & qcolorMask8) >> 2) + ((C & qcolorMask8) >> 2) + ((D & qcolorMask8) >> 2) + ((((A & qlowpixelMask8) + (B & qlowpixelMask8) + (C & qlowpixelMask8) + (D & qlowpixelMask8)) >> 2) & qlowpixelMask8))|((((A&0xFF000000)==0x50000000)?0x50000000:(((B&0xFF000000)==0x50000000)?0x50000000:(((C&0xFF000000)==0x50000000)?0x50000000:(((D&0xFF000000)==0x50000000)?0x50000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:(((C&0xFF000000)==0x00000000)?0x00000000:(((D&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))))))) - -static void Super2xSaI_ex8_Ex(unsigned char *srcPtr, DWORD srcPitch, - unsigned char *dstBitmap, int width, int height) -{ - DWORD dstPitch = srcPitch * 2; - DWORD line; - DWORD *dP; - DWORD *bP; - int width2 = width*2; - int iXA,iXB,iXC,iYA,iYB,iYC,finish; - DWORD color4, color5, color6; - DWORD color1, color2, color3; - DWORD colorA0, colorA1, colorA2, colorA3, - colorB0, colorB1, colorB2, colorB3, - colorS1, colorS2; - DWORD product1a, product1b, - product2a, product2b; - - line = 0; - - { - for (; height; height-=1) - { - bP = (DWORD *)srcPtr; - dP = (DWORD *)(dstBitmap + line*dstPitch); - for (finish = width; finish; finish -= 1 ) - { -//--------------------------------------- B1 B2 -// 4 5 6 S2 -// 1 2 3 S1 -// A1 A2 - if(finish==width) iXA=0; - else iXA=1; - if(finish>4) {iXB=1;iXC=2;} - else - if(finish>3) {iXB=1;iXC=1;} - else {iXB=0;iXC=0;} - if(line==0) iYA=0; - else iYA=width; - if(height>4) {iYB=width;iYC=width2;} - else - if(height>3) {iYB=width;iYC=width;} - else {iYB=0;iYC=0;} - - - colorB0 = *(bP- iYA - iXA); - colorB1 = *(bP- iYA); - colorB2 = *(bP- iYA + iXB); - colorB3 = *(bP- iYA + iXC); - - color4 = *(bP - iXA); - color5 = *(bP); - color6 = *(bP + iXB); - colorS2 = *(bP + iXC); - - color1 = *(bP + iYB - iXA); - color2 = *(bP + iYB); - color3 = *(bP + iYB + iXB); - colorS1= *(bP + iYB + iXC); - - colorA0 = *(bP + iYC - iXA); - colorA1 = *(bP + iYC); - colorA2 = *(bP + iYC + iXB); - colorA3 = *(bP + iYC + iXC); - -//-------------------------------------- - if (color2 == color6 && color5 != color3) - { - product2b = product1b = color2; - } - else - if (color5 == color3 && color2 != color6) - { - product2b = product1b = color5; - } - else - if (color5 == color3 && color2 == color6) - { - register int r = 0; - - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff), (colorA1&0x00ffffff)); - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff), (colorB1&0x00ffffff)); - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff)); - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff)); - - if (r > 0) - product2b = product1b = color6; - else - if (r < 0) - product2b = product1b = color5; - else - { - product2b = product1b = INTERPOLATE8_02(color5, color6); - } - } - else - { - if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) - product2b = Q_INTERPOLATE8_02 (color3, color3, color3, color2); - else - if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) - product2b = Q_INTERPOLATE8_02 (color2, color2, color2, color3); - else - product2b = INTERPOLATE8_02 (color2, color3); - - if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) - product1b = Q_INTERPOLATE8_02 (color6, color6, color6, color5); - else - if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) - product1b = Q_INTERPOLATE8_02 (color6, color5, color5, color5); - else - product1b = INTERPOLATE8_02 (color5, color6); - } - - if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) - product2a = INTERPOLATE8_02(color2, color5); - else - if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) - product2a = INTERPOLATE8_02(color2, color5); - else - product2a = color2; - - if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) - product1a = INTERPOLATE8_02(color2, color5); - else - if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) - product1a = INTERPOLATE8_02(color2, color5); - else - product1a = color5; - - *dP=product1a; - *(dP+1)=product1b; - *(dP+(width2))=product2a; - *(dP+1+(width2))=product2b; - - bP += 1; - dP += 2; - }//end of for ( finish= width etc..) - - line += 2; - srcPtr += srcPitch; - }; //endof: for (; height; height--) - } -} - - -static void Super2xSaI_ex8(unsigned char *srcPtr, DWORD srcPitch, - unsigned char *dstBitmap, int width, int height) -{ - DWORD dstPitch = srcPitch * 2; - DWORD line; - DWORD *dP; - DWORD *bP; - int width2 = width*2; - int iXA,iXB,iXC,iYA,iYB,iYC,finish; - DWORD color4, color5, color6; - DWORD color1, color2, color3; - DWORD colorA0, colorA1, colorA2, colorA3, - colorB0, colorB1, colorB2, colorB3, - colorS1, colorS2; - DWORD product1a, product1b, - product2a, product2b; - - line = 0; - - { - for (; height; height-=1) - { - bP = (DWORD *)srcPtr; - dP = (DWORD *)(dstBitmap + line*dstPitch); - for (finish = width; finish; finish -= 1 ) - { -//--------------------------------------- B1 B2 -// 4 5 6 S2 -// 1 2 3 S1 -// A1 A2 - if(finish==width) iXA=0; - else iXA=1; - if(finish>4) {iXB=1;iXC=2;} - else - if(finish>3) {iXB=1;iXC=1;} - else {iXB=0;iXC=0;} - if(line==0) iYA=0; - else iYA=width; - if(height>4) {iYB=width;iYC=width2;} - else - if(height>3) {iYB=width;iYC=width;} - else {iYB=0;iYC=0;} - - - colorB0 = *(bP- iYA - iXA); - colorB1 = *(bP- iYA); - colorB2 = *(bP- iYA + iXB); - colorB3 = *(bP- iYA + iXC); - - color4 = *(bP - iXA); - color5 = *(bP); - color6 = *(bP + iXB); - colorS2 = *(bP + iXC); - - color1 = *(bP + iYB - iXA); - color2 = *(bP + iYB); - color3 = *(bP + iYB + iXB); - colorS1= *(bP + iYB + iXC); - - colorA0 = *(bP + iYC - iXA); - colorA1 = *(bP + iYC); - colorA2 = *(bP + iYC + iXB); - colorA3 = *(bP + iYC + iXC); - -//-------------------------------------- - if (color2 == color6 && color5 != color3) - { - product2b = product1b = color2; - } - else - if (color5 == color3 && color2 != color6) - { - product2b = product1b = color5; - } - else - if (color5 == color3 && color2 == color6) - { - register int r = 0; - - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff), (colorA1&0x00ffffff)); - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff), (colorB1&0x00ffffff)); - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff)); - r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff)); - - if (r > 0) - product2b = product1b = color6; - else - if (r < 0) - product2b = product1b = color5; - else - { - product2b = product1b = INTERPOLATE8(color5, color6); - } - } - else - { - if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) - product2b = Q_INTERPOLATE8 (color3, color3, color3, color2); - else - if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) - product2b = Q_INTERPOLATE8 (color2, color2, color2, color3); - else - product2b = INTERPOLATE8 (color2, color3); - - if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) - product1b = Q_INTERPOLATE8 (color6, color6, color6, color5); - else - if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) - product1b = Q_INTERPOLATE8 (color6, color5, color5, color5); - else - product1b = INTERPOLATE8 (color5, color6); - } - - if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) - product2a = INTERPOLATE8(color2, color5); - else - if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) - product2a = INTERPOLATE8(color2, color5); - else - product2a = color2; - - if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) - product1a = INTERPOLATE8(color2, color5); - else - if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) - product1a = INTERPOLATE8(color2, color5); - else - product1a = color5; - - *dP=product1a; - *(dP+1)=product1b; - *(dP+(width2))=product2a; - *(dP+1+(width2))=product2b; - - bP += 1; - dP += 2; - }//end of for ( finish= width etc..) - - line += 2; - srcPtr += srcPitch; - }; //endof: for (; height; height--) - } -} -///////////////////////////////////////////////////////////////////////////// - -#define colorMask4 0x0000EEE0 -#define lowPixelMask4 0x00001110 -#define qcolorMask4 0x0000CCC0 -#define qlowpixelMask4 0x00003330 - -#define INTERPOLATE4(A, B) ((((A & colorMask4) >> 1) + ((B & colorMask4) >> 1) + (A & B & lowPixelMask4))|((((A&0x0000000F)==0x00000006)?0x00000006:(((B&0x0000000F)==0x00000006)?0x00000006:(((A&0x0000000F)==0x00000000)?0x00000000:(((B&0x0000000F)==0x00000000)?0x00000000:0x0000000F)))))) - -#define Q_INTERPOLATE4(A, B, C, D) ((((A & qcolorMask4) >> 2) + ((B & qcolorMask4) >> 2) + ((C & qcolorMask4) >> 2) + ((D & qcolorMask4) >> 2) + ((((A & qlowpixelMask4) + (B & qlowpixelMask4) + (C & qlowpixelMask4) + (D & qlowpixelMask4)) >> 2) & qlowpixelMask4))| ((((A&0x0000000F)==0x00000006)?0x00000006:(((B&0x0000000F)==0x00000006)?0x00000006:(((C&0x0000000F)==0x00000006)?0x00000006:(((D&0x0000000F)==0x00000006)?0x00000006:(((A&0x0000000F)==0x00000000)?0x00000000:(((B&0x0000000F)==0x00000000)?0x00000000:(((C&0x0000000F)==0x00000000)?0x00000000:(((D&0x0000000F)==0x00000000)?0x00000000:0x0000000F)))))))))) - -static void Super2xSaI_ex4(unsigned char *srcPtr, DWORD srcPitch, - unsigned char *dstBitmap, int width, int height) -{ - DWORD dstPitch = srcPitch * 2; - DWORD line; - unsigned short *dP; - unsigned short *bP; - int width2 = width*2; - int iXA,iXB,iXC,iYA,iYB,iYC,finish; - DWORD color4, color5, color6; - DWORD color1, color2, color3; - DWORD colorA0, colorA1, colorA2, colorA3, - colorB0, colorB1, colorB2, colorB3, - colorS1, colorS2; - DWORD product1a, product1b, - product2a, product2b; - - line = 0; - - { - for (; height; height-=1) - { - bP = (unsigned short *)srcPtr; - dP = (unsigned short *)(dstBitmap + line*dstPitch); - for (finish = width; finish; finish -= 1 ) - { -//--------------------------------------- B1 B2 -// 4 5 6 S2 -// 1 2 3 S1 -// A1 A2 - if(finish==width) iXA=0; - else iXA=1; - if(finish>4) {iXB=1;iXC=2;} - else - if(finish>3) {iXB=1;iXC=1;} - else {iXB=0;iXC=0;} - if(line==0) iYA=0; - else iYA=width; - if(height>4) {iYB=width;iYC=width2;} - else - if(height>3) {iYB=width;iYC=width;} - else {iYB=0;iYC=0;} - - - colorB0 = *(bP- iYA - iXA); - colorB1 = *(bP- iYA); - colorB2 = *(bP- iYA + iXB); - colorB3 = *(bP- iYA + iXC); - - color4 = *(bP - iXA); - color5 = *(bP); - color6 = *(bP + iXB); - colorS2 = *(bP + iXC); - - color1 = *(bP + iYB - iXA); - color2 = *(bP + iYB); - color3 = *(bP + iYB + iXB); - colorS1= *(bP + iYB + iXC); - - colorA0 = *(bP + iYC - iXA); - colorA1 = *(bP + iYC); - colorA2 = *(bP + iYC + iXB); - colorA3 = *(bP + iYC + iXC); - -//-------------------------------------- - if (color2 == color6 && color5 != color3) - { - product2b = product1b = color2; - } - else - if (color5 == color3 && color2 != color6) - { - product2b = product1b = color5; - } - else - if (color5 == color3 && color2 == color6) - { - register int r = 0; - - r += GET_RESULT ((color6&0xfffffff0), (color5&0xfffffff0), (color1&0xfffffff0), (colorA1&0xfffffff0)); - r += GET_RESULT ((color6&0xfffffff0), (color5&0xfffffff0), (color4&0xfffffff0), (colorB1&0xfffffff0)); - r += GET_RESULT ((color6&0xfffffff0), (color5&0xfffffff0), (colorA2&0xfffffff0), (colorS1&0xfffffff0)); - r += GET_RESULT ((color6&0xfffffff0), (color5&0xfffffff0), (colorB2&0xfffffff0), (colorS2&0xfffffff0)); - - if (r > 0) - product2b = product1b = color6; - else - if (r < 0) - product2b = product1b = color5; - else - { - product2b = product1b = INTERPOLATE4 (color5, color6); - } - } - else - { - if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) - product2b = Q_INTERPOLATE4 (color3, color3, color3, color2); - else - if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) - product2b = Q_INTERPOLATE4 (color2, color2, color2, color3); - else - product2b = INTERPOLATE4 (color2, color3); - - if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) - product1b = Q_INTERPOLATE4 (color6, color6, color6, color5); - else - if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) - product1b = Q_INTERPOLATE4 (color6, color5, color5, color5); - else - product1b = INTERPOLATE4 (color5, color6); - } - - if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) - product2a = INTERPOLATE4 (color2, color5); - else - if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) - product2a = INTERPOLATE4(color2, color5); - else - product2a = color2; - - if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) - product1a = INTERPOLATE4 (color2, color5); - else - if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) - product1a = INTERPOLATE4(color2, color5); - else - product1a = color5; - - *dP=product1a; - *(dP+1)=product1b; - *(dP+(width2))=product2a; - *(dP+1+(width2))=product2b; - - bP += 1; - dP += 2; - }//end of for ( finish= width etc..) - - line += 2; - srcPtr += srcPitch; - }; //endof: for (; height; height--) - } -} - -///////////////////////////////////////////////////////////////////////////// - -#define colorMask5 0x0000F7BC -#define lowPixelMask5 0x00000842 -#define qcolorMask5 0x0000E738 -#define qlowpixelMask5 0x000018C6 - -#define INTERPOLATE5(A, B) ((((A & colorMask5) >> 1) + ((B & colorMask5) >> 1) + (A & B & lowPixelMask5))|((((A&0x00000001)==0x00000000)?0x00000000:(((B&0x00000001)==0x00000000)?0x00000000:0x00000001)))) - -#define Q_INTERPOLATE5(A, B, C, D) ((((A & qcolorMask5) >> 2) + ((B & qcolorMask5) >> 2) + ((C & qcolorMask5) >> 2) + ((D & qcolorMask5) >> 2) + ((((A & qlowpixelMask5) + (B & qlowpixelMask5) + (C & qlowpixelMask5) + (D & qlowpixelMask5)) >> 2) & qlowpixelMask5))| ((((A&0x00000001)==0x00000000)?0x00000000:(((B&0x00000001)==0x00000000)?0x00000000:(((C&0x00000001)==0x00000000)?0x00000000:(((D&0x00000001)==0x00000000)?0x00000000:0x00000001)))))) - -static void Super2xSaI_ex5(unsigned char *srcPtr, DWORD srcPitch, - unsigned char *dstBitmap, int width, int height) -{ - DWORD dstPitch = srcPitch * 2; - DWORD line; - unsigned short *dP; - unsigned short *bP; - int width2 = width*2; - int iXA,iXB,iXC,iYA,iYB,iYC,finish; - DWORD color4, color5, color6; - DWORD color1, color2, color3; - DWORD colorA0, colorA1, colorA2, colorA3, - colorB0, colorB1, colorB2, colorB3, - colorS1, colorS2; - DWORD product1a, product1b, - product2a, product2b; - - line = 0; - - { - for (; height; height-=1) - { - bP = (unsigned short *)srcPtr; - dP = (unsigned short *)(dstBitmap + line*dstPitch); - for (finish = width; finish; finish -= 1 ) - { -//--------------------------------------- B1 B2 -// 4 5 6 S2 -// 1 2 3 S1 -// A1 A2 - if(finish==width) iXA=0; - else iXA=1; - if(finish>4) {iXB=1;iXC=2;} - else - if(finish>3) {iXB=1;iXC=1;} - else {iXB=0;iXC=0;} - if(line==0) iYA=0; - else iYA=width; - if(height>4) {iYB=width;iYC=width2;} - else - if(height>3) {iYB=width;iYC=width;} - else {iYB=0;iYC=0;} - - - colorB0 = *(bP- iYA - iXA); - colorB1 = *(bP- iYA); - colorB2 = *(bP- iYA + iXB); - colorB3 = *(bP- iYA + iXC); - - color4 = *(bP - iXA); - color5 = *(bP); - color6 = *(bP + iXB); - colorS2 = *(bP + iXC); - - color1 = *(bP + iYB - iXA); - color2 = *(bP + iYB); - color3 = *(bP + iYB + iXB); - colorS1= *(bP + iYB + iXC); - - colorA0 = *(bP + iYC - iXA); - colorA1 = *(bP + iYC); - colorA2 = *(bP + iYC + iXB); - colorA3 = *(bP + iYC + iXC); - -//-------------------------------------- - if (color2 == color6 && color5 != color3) - { - product2b = product1b = color2; - } - else - if (color5 == color3 && color2 != color6) - { - product2b = product1b = color5; - } - else - if (color5 == color3 && color2 == color6) - { - register int r = 0; - - r += GET_RESULT ((color6&0xfffffffe), (color5&0xfffffffe), (color1&0xfffffffe), (colorA1&0xfffffffe)); - r += GET_RESULT ((color6&0xfffffffe), (color5&0xfffffffe), (color4&0xfffffffe), (colorB1&0xfffffffe)); - r += GET_RESULT ((color6&0xfffffffe), (color5&0xfffffffe), (colorA2&0xfffffffe), (colorS1&0xfffffffe)); - r += GET_RESULT ((color6&0xfffffffe), (color5&0xfffffffe), (colorB2&0xfffffffe), (colorS2&0xfffffffe)); - - if (r > 0) - product2b = product1b = color6; - else - if (r < 0) - product2b = product1b = color5; - else - { - product2b = product1b = INTERPOLATE5 (color5, color6); - } - } - else - { - if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) - product2b = Q_INTERPOLATE5 (color3, color3, color3, color2); - else - if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) - product2b = Q_INTERPOLATE5 (color2, color2, color2, color3); - else - product2b = INTERPOLATE5 (color2, color3); - - if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) - product1b = Q_INTERPOLATE5 (color6, color6, color6, color5); - else - if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) - product1b = Q_INTERPOLATE5 (color6, color5, color5, color5); - else - product1b = INTERPOLATE5 (color5, color6); - } - - if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) - product2a = INTERPOLATE5 (color2, color5); - else - if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) - product2a = INTERPOLATE5(color2, color5); - else - product2a = color2; - - if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) - product1a = INTERPOLATE5(color2, color5); - else - if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) - product1a = INTERPOLATE5(color2, color5); - else - product1a = color5; - - *dP=product1a; - *(dP+1)=product1b; - *(dP+(width2))=product2a; - *(dP+1+(width2))=product2b; - - bP += 1; - dP += 2; - }//end of for ( finish= width etc..) - - line += 2; - srcPtr += srcPitch; - }; //endof: for (; height; height--) - } -} - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// ogl texture defines -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -static void DefineSubTextureSortHiRes(void) -{ - int x,y,dx2; - - if(!gTexName) - { - glGenTextures(1, &gTexName); - glBindTexture(GL_TEXTURE_2D, gTexName); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); - - if(iFilterType) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - glTexImage2D(GL_TEXTURE_2D, 0, giWantedRGBA, 512, 512, 0, giWantedFMT, giWantedTYPE, texturebuffer); - } - else glBindTexture(GL_TEXTURE_2D, gTexName); - - if(bGLExt && (iTexQuality==1 || iTexQuality==2)) - { - if(DXTexS < 4 || DYTexS < 4 || iHiResTextures==2) - { - unsigned short * pS,*pD1,*pD2; - dx2=(DXTexS<<1); - pS=(unsigned short *)texturepart; - pD1=(unsigned short *)texturebuffer; - pD2=(unsigned short *)texturebuffer; - pD2+=dx2; - for(y=0;y=iSortTexCnt) LRUCleaned=0; // wrap? wrap! - iC1=LRUCleaned; // range of textures to clean - iC2=LRUCleaned+iC; - - for(iC=iC1;iCl=0; - } - - for(i=0;i<3;i++) // remove all references to that textures - for(j=0;jpos.l; - if(iMax) - do - { - tsb++; - if(tsb->cTexID>=iC1 && tsb->cTexIDClutID=0; - } - while(--iMax); - } - - usLRUTexPage=LRUCleaned; -} - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// search cache for existing (already used) parts -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -unsigned char * CheckTextureInSubSCache(int TextureMode, uint32_t GivenClutId, unsigned short * pCache) -{ - textureSubCacheEntryS * tsx, * tsb, *tsg;//, *tse=NULL; - int i,iMax;EXLong npos; - unsigned char cx,cy; - int iC,j,k;uint32_t rx,ry,mx,my; - EXLong * ul=0, * uls; - EXLong rfree; - unsigned char cXAdj,cYAdj; - - npos.l=*((uint32_t *)&gl_ux[4]); - - //--------------------------------------------------------------// - // find matching texturepart first... speed up... - //--------------------------------------------------------------// - - tsg=pscSubtexStore[TextureMode][GlobalTexturePage]; - tsg+=((GivenClutId&CLUTCHK)>>CLUTSHIFT)*SOFFB; - - iMax=tsg->pos.l; - if(iMax) - { - i=iMax; - tsb=tsg+1; - do - { - if(GivenClutId==tsb->ClutID && - (INCHECK(tsb->pos,npos))) - { - { - cx=tsb->pos.c[3]-tsb->posTX; - cy=tsb->pos.c[1]-tsb->posTY; - - gl_ux[0]-=cx; - gl_ux[1]-=cx; - gl_ux[2]-=cx; - gl_ux[3]-=cx; - gl_vy[0]-=cy; - gl_vy[1]-=cy; - gl_vy[2]-=cy; - gl_vy[3]-=cy; - - ubOpaqueDraw=tsb->Opaque; - *pCache=tsb->cTexID; - return NULL; - } - } - tsb++; - } - while(--i); - } - - //----------------------------------------------------// - - cXAdj=1;cYAdj=1; - - rx=(int)gl_ux[6]-(int)gl_ux[7]; - ry=(int)gl_ux[4]-(int)gl_ux[5]; - - tsx=NULL;tsb=tsg+1; - for(i=0;iClutID) {tsx=tsb;break;} - } - - if(!tsx) - { - iMax++; - if(iMax>=SOFFB-2) - { - if(iTexGarbageCollection) // gc mode? - { - if(*pCache==0) - { - dwTexPageComp|=(1<ClutID) - { - if(!tsx) {tsx=tsb;rfree.l=npos.l;} // - else tsb->ClutID=0; - rfree.c[3]=min(rfree.c[3],tsb->pos.c[3]); - rfree.c[2]=max(rfree.c[2],tsb->pos.c[2]); - rfree.c[1]=min(rfree.c[1],tsb->pos.c[1]); - rfree.c[0]=max(rfree.c[0],tsb->pos.c[0]); - MarkFree(tsb); - } - - if(tsx) // 3. if one or more found, create a new rect with bigger size - { - *((uint32_t *)&gl_ux[4])=npos.l=rfree.l; - rx=(int)rfree.c[2]-(int)rfree.c[3]; - ry=(int)rfree.c[0]-(int)rfree.c[1]; - DoTexGarbageCollection(); - - goto ENDLOOP3; - } - } - - iMax=1; - } - tsx=tsg+iMax; - tsg->pos.l=iMax; - } - - //----------------------------------------------------// - // now get a free texture space - //----------------------------------------------------// - - if(iTexGarbageCollection) usLRUTexPage=0; - -ENDLOOP3: - - rx+=3;if(rx>255) {cXAdj=0;rx=255;} - ry+=3;if(ry>255) {cYAdj=0;ry=255;} - - iC=usLRUTexPage; - - for(k=0;kl;ul=uls+1; - - //--------------------------------------------------// - // first time - - if(!iMax) - { - rfree.l=0; - - if(rx>252 && ry>252) - {uls->l=1;ul->l=0xffffffff;ul=0;goto ENDLOOP;} - - if(rx<253) - { - uls->l=uls->l+1; - ul->c[3]=rx; - ul->c[2]=255-rx; - ul->c[1]=0; - ul->c[0]=ry; - ul++; - } - - if(ry<253) - { - uls->l=uls->l+1; - ul->c[3]=0; - ul->c[2]=255; - ul->c[1]=ry; - ul->c[0]=255-ry; - } - ul=0; - goto ENDLOOP; - } - - //--------------------------------------------------// - for(i=0;il!=0xffffffff && - ry<=ul->c[0] && - rx<=ul->c[2]) - { - rfree=*ul; - mx=ul->c[2]-2; - my=ul->c[0]-2; - if(rxc[3]+=rx; - ul->c[2]-=rx; - ul->c[0]=ry; - - for(ul=uls+1,j=0;jl==0xffffffff) break; - - if(jl=uls->l+1; - - ul->c[3]=rfree.c[3]; - ul->c[2]=rfree.c[2]; - ul->c[1]=rfree.c[1]+ry; - ul->c[0]=rfree.c[0]-ry; - } - } - else if(rxc[3]+=rx; - ul->c[2]-=rx; - } - else if(ryc[1]+=ry; - ul->c[0]-=ry; - } - else - { - ul->l=0xffffffff; - } - ul=0; - goto ENDLOOP; - } - } - - //--------------------------------------------------// - - iC++; if(iC>=iSortTexCnt) iC=0; - } - - //----------------------------------------------------// - // check, if free space got - //----------------------------------------------------// - -ENDLOOP: - if(ul) - { - ////////////////////////////////////////////////////// - - { - dwTexPageComp=0; - - for(i=0;i<3;i++) // cleaning up - for(j=0;jpos.l=0; - (tsb+SOFFB)->pos.l=0; - (tsb+SOFFC)->pos.l=0; - (tsb+SOFFD)->pos.l=0; - } - for(i=0;il=0;} - usLRUTexPage=0; - } - - ////////////////////////////////////////////////////// - iC=usLRUTexPage; - uls=pxSsubtexLeft[usLRUTexPage]; - uls->l=0;ul=uls+1; - rfree.l=0; - - if(rx>252 && ry>252) - {uls->l=1;ul->l=0xffffffff;} - else - { - if(rx<253) - { - uls->l=uls->l+1; - ul->c[3]=rx; - ul->c[2]=255-rx; - ul->c[1]=0; - ul->c[0]=ry; - ul++; - } - if(ry<253) - { - uls->l=uls->l+1; - ul->c[3]=0; - ul->c[2]=255; - ul->c[1]=ry; - ul->c[0]=255-ry; - } - } - tsg->pos.l=1;tsx=tsg+1; - } - - rfree.c[3]+=cXAdj; - rfree.c[1]+=cYAdj; - - tsx->cTexID =*pCache=iC; - tsx->pos = npos; - tsx->ClutID = GivenClutId; - tsx->posTX = rfree.c[3]; - tsx->posTY = rfree.c[1]; - - cx=gl_ux[7]-rfree.c[3]; - cy=gl_ux[5]-rfree.c[1]; - - gl_ux[0]-=cx; - gl_ux[1]-=cx; - gl_ux[2]-=cx; - gl_ux[3]-=cx; - gl_vy[0]-=cy; - gl_vy[1]-=cy; - gl_vy[2]-=cy; - gl_vy[3]-=cy; - - XTexS=rfree.c[3]; - YTexS=rfree.c[1]; - - return &tsx->Opaque; -} - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// search cache for free place (on compress) -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -static BOOL GetCompressTexturePlace(textureSubCacheEntryS * tsx) -{ - int i,j,k,iMax,iC;uint32_t rx,ry,mx,my; - EXLong * ul=0, * uls, rfree; - unsigned char cXAdj=1,cYAdj=1; - - rx=(int)tsx->pos.c[2]-(int)tsx->pos.c[3]; - ry=(int)tsx->pos.c[0]-(int)tsx->pos.c[1]; - - rx+=3;if(rx>255) {cXAdj=0;rx=255;} - ry+=3;if(ry>255) {cYAdj=0;ry=255;} - - iC=usLRUTexPage; - - for(k=0;kl;ul=uls+1; - - //--------------------------------------------------// - // first time - - if(!iMax) - { - rfree.l=0; - - if(rx>252 && ry>252) - {uls->l=1;ul->l=0xffffffff;ul=0;goto TENDLOOP;} - - if(rx<253) - { - uls->l=uls->l+1; - ul->c[3]=rx; - ul->c[2]=255-rx; - ul->c[1]=0; - ul->c[0]=ry; - ul++; - } - - if(ry<253) - { - uls->l=uls->l+1; - ul->c[3]=0; - ul->c[2]=255; - ul->c[1]=ry; - ul->c[0]=255-ry; - } - ul=0; - goto TENDLOOP; - } - - //--------------------------------------------------// - for(i=0;il!=0xffffffff && - ry<=ul->c[0] && - rx<=ul->c[2]) - { - rfree=*ul; - mx=ul->c[2]-2; - my=ul->c[0]-2; - - if(rxc[3]+=rx; - ul->c[2]-=rx; - ul->c[0]=ry; - - for(ul=uls+1,j=0;jl==0xffffffff) break; - - if(jl=uls->l+1; - - ul->c[3]=rfree.c[3]; - ul->c[2]=rfree.c[2]; - ul->c[1]=rfree.c[1]+ry; - ul->c[0]=rfree.c[0]-ry; - } - } - else if(rxc[3]+=rx; - ul->c[2]-=rx; - } - else if(ryc[1]+=ry; - ul->c[0]-=ry; - } - else - { - ul->l=0xffffffff; - } - ul=0; - goto TENDLOOP; - } - } - - //--------------------------------------------------// - - iC++; if(iC>=iSortTexCnt) iC=0; - } - - //----------------------------------------------------// - // check, if free space got - //----------------------------------------------------// - -TENDLOOP: - if(ul) return FALSE; - - rfree.c[3]+=cXAdj; - rfree.c[1]+=cYAdj; - - tsx->cTexID = iC; - tsx->posTX = rfree.c[3]; - tsx->posTY = rfree.c[1]; - - XTexS=rfree.c[3]; - YTexS=rfree.c[1]; - - return TRUE; -} - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// compress texture cache (to make place for new texture part, if needed) -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -static void CompressTextureSpace(void) -{ - textureSubCacheEntryS * tsx, * tsg, * tsb; - int i,j,k,m,n,iMax;EXLong * ul, r,opos; - short sOldDST=DrawSemiTrans,cx,cy; - int lOGTP=GlobalTexturePage; - uint32_t l,row; - uint32_t *lSRCPtr; - - opos.l=*((uint32_t *)&gl_ux[4]); - - // 1. mark all textures as free - for(i=0;il=0;} - usLRUTexPage=0; - - // 2. compress - for(j=0;j<3;j++) - { - for(k=0;kpos.l=0; - (tsg+SOFFB)->pos.l=0; - (tsg+SOFFC)->pos.l=0; - (tsg+SOFFD)->pos.l=0; - continue; - } - - for(m=0;m<4;m++,tsg+=SOFFB) - { - iMax=tsg->pos.l; - - tsx=tsg+1; - for(i=0;iClutID) - { - r.l=tsx->pos.l; - for(n=i+1,tsb=tsx+1;nClutID==tsb->ClutID) - { - r.c[3]=min(r.c[3],tsb->pos.c[3]); - r.c[2]=max(r.c[2],tsb->pos.c[2]); - r.c[1]=min(r.c[1],tsb->pos.c[1]); - r.c[0]=max(r.c[0],tsb->pos.c[0]); - tsb->ClutID=0; - } - } - -// if(r.l!=tsx->pos.l) - { - cx=((tsx->ClutID << 4) & 0x3F0); - cy=((tsx->ClutID >> 6) & CLUTYMASK); - - if(j!=2) - { - // palette check sum - l=0;lSRCPtr=(uint32_t *)(psxVuw+cx+(cy*1024)); - if(j==1) for(row=1;row<129;row++) l+=((*lSRCPtr++)-1)*row; - else for(row=1;row<9;row++) l+=((*lSRCPtr++)-1)<ClutID&(0x00003fff<<16))) - { - tsx->ClutID=0;continue; - } - } - - tsx->pos.l=r.l; - if(!GetCompressTexturePlace(tsx)) // no place? - { - for(i=0;i<3;i++) // -> clean up everything - for(j=0;jpos.l=0; - (tsb+SOFFB)->pos.l=0; - (tsb+SOFFC)->pos.l=0; - (tsb+SOFFD)->pos.l=0; - } - for(i=0;il=0;} - usLRUTexPage=0; - DrawSemiTrans=sOldDST; - GlobalTexturePage=lOGTP; - *((uint32_t *)&gl_ux[4])=opos.l; - dwTexPageComp=0; - - return; - } - - if(tsx->ClutID&(1<<30)) DrawSemiTrans=1; - else DrawSemiTrans=0; - *((uint32_t *)&gl_ux[4])=r.l; - - gTexName=uiStexturePage[tsx->cTexID]; - LoadSubTexFn(k,j,cx,cy); - uiStexturePage[tsx->cTexID]=gTexName; - tsx->Opaque=ubOpaqueDraw; - } - } - } - - if(iMax) - { - tsx=tsg+iMax; - while(!tsx->ClutID && iMax) {tsx--;iMax--;} - tsg->pos.l=iMax; - } - - } - } - } - - if(dwTexPageComp==0xffffffff) dwTexPageComp=0; - - *((uint32_t *)&gl_ux[4])=opos.l; - GlobalTexturePage=lOGTP; - DrawSemiTrans=sOldDST; -} - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// main entry for searching/creating textures, called from prim.c -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -GLuint SelectSubTextureS(int TextureMode, uint32_t GivenClutId) -{ - unsigned char * OPtr;unsigned short iCache;short cx,cy; - - // sort sow/tow infos for fast access - - unsigned char ma1,ma2,mi1,mi2; - if(gl_ux[0]>gl_ux[1]) {mi1=gl_ux[1];ma1=gl_ux[0];} - else {mi1=gl_ux[0];ma1=gl_ux[1];} - if(gl_ux[2]>gl_ux[3]) {mi2=gl_ux[3];ma2=gl_ux[2];} - else {mi2=gl_ux[2];ma2=gl_ux[3];} - if(mi1>mi2) gl_ux[7]=mi2; - else gl_ux[7]=mi1; - if(ma1>ma2) gl_ux[6]=ma1; - else gl_ux[6]=ma2; - - if(gl_vy[0]>gl_vy[1]) {mi1=gl_vy[1];ma1=gl_vy[0];} - else {mi1=gl_vy[0];ma1=gl_vy[1];} - if(gl_vy[2]>gl_vy[3]) {mi2=gl_vy[3];ma2=gl_vy[2];} - else {mi2=gl_vy[2];ma2=gl_vy[3];} - if(mi1>mi2) gl_ux[5]=mi2; - else gl_ux[5]=mi1; - if(ma1>ma2) gl_ux[4]=ma1; - else gl_ux[4]=ma2; - - // get clut infos in one 32 bit val - - if(TextureMode==2) // no clut here - { - GivenClutId=CLUTUSED|(DrawSemiTrans<<30);cx=cy=0; - - if(iFrameTexType && Fake15BitTexture()) - return (GLuint)gTexName; - } - else - { - cx=((GivenClutId << 4) & 0x3F0); // but here - cy=((GivenClutId >> 6) & CLUTYMASK); - GivenClutId=(GivenClutId&CLUTMASK)|(DrawSemiTrans<<30)|CLUTUSED; - - // palette check sum.. removed MMX asm, this easy func works as well - { - uint32_t l=0,row; - - uint32_t *lSRCPtr = (uint32_t *)(psxVuw+cx+(cy*1024)); - if(TextureMode==1) for(row=1;row<129;row++) l+=((*lSRCPtr++)-1)*row; - else for(row=1;row<9;row++) l+=((*lSRCPtr++)-1)<=pos2.c[1])&&(pos1.c[1]<=pos2.c[0])&&(pos1.c[2]>=pos2.c[3])&&(pos1.c[3]<=pos2.c[2])) +#define INCHECK(pos2,pos1) ((pos1.c[0]<=pos2.c[0]) && (pos1.c[1]>=pos2.c[1]) && (pos1.c[2]<=pos2.c[2]) && (pos1.c[3]>=pos2.c[3])) + +//////////////////////////////////////////////////////////////////////// + +unsigned char * CheckTextureInSubSCache(int TextureMode, uint32_t GivenClutId, unsigned short *pCache); +void LoadSubTexturePageSort(int pageid, int mode, short cx, short cy); +void LoadPackedSubTexturePageSort(int pageid, int mode, short cx, short cy); +void DefineSubTextureSort(void); + +//////////////////////////////////////////////////////////////////////// +// some globals +//////////////////////////////////////////////////////////////////////// + +GLint giWantedRGBA=4; +GLint giWantedFMT=GL_RGBA; +GLint giWantedTYPE=GL_UNSIGNED_BYTE; +int GlobalTexturePage; +GLint XTexS; +GLint YTexS; +GLint DXTexS; +GLint DYTexS; +int iSortTexCnt=32; +BOOL bUseFastMdec=FALSE; +BOOL bUse15bitMdec=FALSE; +int iFrameTexType=0; +int iFrameReadType=0; + +uint32_t (*TCF[2]) (uint32_t); +unsigned short (*PTCF[2]) (unsigned short); + +//////////////////////////////////////////////////////////////////////// +// texture cache implementation +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +#pragma pack(1) +#endif + +// "texture window" cache entry + +typedef struct textureWndCacheEntryTag +{ + uint32_t ClutID; + short pageid; + short textureMode; + short Opaque; + short used; + EXLong pos; + GLuint texname; +} textureWndCacheEntry; + +// "standard texture" cache entry (12 byte per entry, as small as possible... we need lots of them) + +typedef struct textureSubCacheEntryTagS +{ + uint32_t ClutID; + EXLong pos; + unsigned char posTX; + unsigned char posTY; + unsigned char cTexID; + unsigned char Opaque; +} textureSubCacheEntryS; + +#ifdef _WINDOWS +#pragma pack() +#endif + +//--------------------------------------------- + +#define MAXTPAGES_MAX 64 +#define MAXSORTTEX_MAX 196 + +//--------------------------------------------- + +textureWndCacheEntry wcWndtexStore[MAXWNDTEXCACHE]; +textureSubCacheEntryS * pscSubtexStore[3][MAXTPAGES_MAX]; +EXLong * pxSsubtexLeft [MAXSORTTEX_MAX]; +GLuint uiStexturePage[MAXSORTTEX_MAX]; + +unsigned short usLRUTexPage = 0; + +int iMaxTexWnds = 0; +int iTexWndTurn = 0; +int iTexWndLimit = MAXWNDTEXCACHE/2; + +GLubyte * texturepart = NULL; +GLubyte * texturebuffer = NULL; +uint32_t g_x1,g_y1,g_x2,g_y2; +unsigned char ubOpaqueDraw = 0; + +unsigned short MAXTPAGES = 32; +unsigned short CLUTMASK = 0x7fff; +unsigned short CLUTYMASK = 0x1ff; +unsigned short MAXSORTTEX = 196; + +//////////////////////////////////////////////////////////////////////// +// Texture color conversions... all my ASM funcs are removed for easier +// porting... and honestly: nowadays the speed gain would be pointless +//////////////////////////////////////////////////////////////////////// + +uint32_t XP8RGBA(uint32_t BGR) +{ + if(!(BGR&0xffff)) return 0x50000000; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +uint32_t XP8RGBAEx(uint32_t BGR) +{ + if(!(BGR&0xffff)) return 0x03000000; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +uint32_t CP8RGBA(uint32_t BGR) +{ + uint32_t l; + if(!(BGR&0xffff)) return 0x50000000; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; + if(l==0xffffff00) l=0xff000000; + return l; +} + +uint32_t CP8RGBAEx(uint32_t BGR) +{ + uint32_t l; + if(!(BGR&0xffff)) return 0x03000000; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; + if(l==0xffffff00) l=0xff000000; + return l; +} + +uint32_t XP8RGBA_0(uint32_t BGR) +{ + if(!(BGR&0xffff)) return 0x50000000; + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +uint32_t XP8RGBAEx_0(uint32_t BGR) +{ + if(!(BGR&0xffff)) return 0x03000000; + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +uint32_t XP8BGRA_0(uint32_t BGR) +{ + if(!(BGR&0xffff)) return 0x50000000; + return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; +} + +uint32_t XP8BGRAEx_0(uint32_t BGR) +{ + if(!(BGR&0xffff)) return 0x03000000; + return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; +} + +uint32_t CP8RGBA_0(uint32_t BGR) +{ + uint32_t l; + + if(!(BGR&0xffff)) return 0x50000000; + l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; + if(l==0xfff8f800) l=0xff000000; + return l; +} + +uint32_t CP8RGBAEx_0(uint32_t BGR) +{ + uint32_t l; + + if(!(BGR&0xffff)) return 0x03000000; + l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; + if(l==0xfff8f800) l=0xff000000; + return l; +} + +uint32_t CP8BGRA_0(uint32_t BGR) +{ + uint32_t l; + + if(!(BGR&0xffff)) return 0x50000000; + l=((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; + if(l==0xff00f8f8) l=0xff000000; + return l; +} + +uint32_t CP8BGRAEx_0(uint32_t BGR) +{ + uint32_t l; + + if(!(BGR&0xffff)) return 0x03000000; + l=((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; + if(l==0xff00f8f8) l=0xff000000; + return l; +} + +uint32_t XP8RGBA_1(uint32_t BGR) +{ + if(!(BGR&0xffff)) return 0x50000000; + if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +uint32_t XP8RGBAEx_1(uint32_t BGR) +{ + if(!(BGR&0xffff)) return 0x03000000; + if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +uint32_t XP8BGRA_1(uint32_t BGR) +{ + if(!(BGR&0xffff)) return 0x50000000; + if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff);} + return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; +} + +uint32_t XP8BGRAEx_1(uint32_t BGR) +{ + if(!(BGR&0xffff)) return 0x03000000; + if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff);} + return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; +} + +uint32_t P8RGBA(uint32_t BGR) +{ + if(!(BGR&0xffff)) return 0; + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +uint32_t P8BGRA(uint32_t BGR) +{ + if(!(BGR&0xffff)) return 0; + return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned short XP5RGBA(unsigned short BGR) +{ + if(!BGR) return 0; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} + return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; +} + +unsigned short XP5RGBA_0 (unsigned short BGR) +{ + if(!BGR) return 0; + + return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; +} + +unsigned short CP5RGBA_0 (unsigned short BGR) +{ + unsigned short s; + + if(!BGR) return 0; + + s=((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; + if(s==0x07ff) s=1; + return s; +} + +unsigned short XP5RGBA_1(unsigned short BGR) +{ + if(!BGR) return 0; + if(!(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} + return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; +} + +unsigned short P5RGBA(unsigned short BGR) +{ + if(!BGR) return 0; + return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; +} + +unsigned short XP4RGBA(unsigned short BGR) +{ + if(!BGR) return 6; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} + return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; +} + +unsigned short XP4RGBA_0 (unsigned short BGR) +{ + if(!BGR) return 6; + return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; +} + +unsigned short CP4RGBA_0 (unsigned short BGR) +{ + unsigned short s; + if(!BGR) return 6; + s=(((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; + if(s==0x0fff) s=0x000f; + return s; +} + +unsigned short XP4RGBA_1(unsigned short BGR) +{ + if(!BGR) return 6; + if(!(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} + return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; +} + +unsigned short P4RGBA(unsigned short BGR) +{ + if(!BGR) return 0; + return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; +} + +//////////////////////////////////////////////////////////////////////// +// CHECK TEXTURE MEM (on plugin startup) +//////////////////////////////////////////////////////////////////////// + +int iFTexA=512; +int iFTexB=512; + +void CheckTextureMemory(void) +{ + GLboolean b;GLboolean * bDetail; + int i,iCnt,iRam=iVRamSize*1024*1024; + int iTSize;char * p; + + if(iBlurBuffer) + { + char * p; + + if(iResX>1024) iFTexA=2048; + else + if(iResX>512) iFTexA=1024; + else iFTexA=512; + if(iResY>1024) iFTexB=2048; + else + if(iResY>512) iFTexB=1024; + else iFTexB=512; + + glGenTextures(1, &gTexBlurName); + gTexName=gTexBlurName; + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + p=(char *)malloc(iFTexA*iFTexB*4); + memset(p,0,iFTexA*iFTexB*4); + glTexImage2D(GL_TEXTURE_2D, 0, 3, iFTexA, iFTexB, 0, GL_RGB, GL_UNSIGNED_BYTE, p); + free(p); + glGetError(); + iRam-=iFTexA*iFTexB*3; + iFTexA=(iResX*256)/iFTexA; + iFTexB=(iResY*256)/iFTexB; + } + + if(iVRamSize) + { + int ts; + + iRam-=(iResX*iResY*8); + iRam-=(iResX*iResY*(iZBufferDepth/8)); + + if(iTexQuality==0 || iTexQuality==3) ts=4; + else ts=2; + + if(iHiResTextures) + iSortTexCnt=iRam/(512*512*ts); + else iSortTexCnt=iRam/(256*256*ts); + + if(iSortTexCnt>MAXSORTTEX) + { + iSortTexCnt=MAXSORTTEX-min(1,iHiResTextures); + } + else + { + iSortTexCnt-=3+min(1,iHiResTextures); + if(iSortTexCnt<8) iSortTexCnt=8; + } + + for(i=0;i info for 32*3 + for(j=0;j info 0..511 + { + pxSsubtexLeft[i]=(EXLong *)malloc(CSUBSIZE*sizeof(EXLong)); + memset(pxSsubtexLeft[i],0,CSUBSIZE*sizeof(EXLong)); + uiStexturePage[i]=0; + } +} + +//////////////////////////////////////////////////////////////////////// +// Clean up on exit +//////////////////////////////////////////////////////////////////////// + +void CleanupTextureStore() +{ + int i,j;textureWndCacheEntry * tsx; + //----------------------------------------------------// + glBindTexture(GL_TEXTURE_2D,0); + //----------------------------------------------------// + free(texturepart); // free tex part + texturepart=0; + if(texturebuffer) + { + free(texturebuffer); + texturebuffer=0; + } + //----------------------------------------------------// + tsx=wcWndtexStore; // loop tex window cache + for(i=0;itexname) // -> some tex? + glDeleteTextures(1,&tsx->texname); // --> delete it + } + iMaxTexWnds=0; // no more tex wnds + //----------------------------------------------------// + if(gTexMovieName!=0) // some movie tex? + glDeleteTextures(1, &gTexMovieName); // -> delete it + gTexMovieName=0; // no more movie tex + //----------------------------------------------------// + if(gTexFrameName!=0) // some 15bit framebuffer tex? + glDeleteTextures(1, &gTexFrameName); // -> delete it + gTexFrameName=0; // no more movie tex + //----------------------------------------------------// + if(gTexBlurName!=0) // some 15bit framebuffer tex? + glDeleteTextures(1, &gTexBlurName); // -> delete it + gTexBlurName=0; // no more movie tex + //----------------------------------------------------// + for(i=0;i<3;i++) // -> loop + for(j=0;j clean mem + } + for(i=0;i tex used ? + { + glDeleteTextures(1,&uiStexturePage[i]); + uiStexturePage[i]=0; // --> delete it + } + free(pxSsubtexLeft[i]); // -> clean mem + } + //----------------------------------------------------// +} + +//////////////////////////////////////////////////////////////////////// +// Reset textures in game... +//////////////////////////////////////////////////////////////////////// + +void ResetTextureArea(BOOL bDelTex) +{ + int i,j;textureSubCacheEntryS * tss;EXLong * lu; + textureWndCacheEntry * tsx; + //----------------------------------------------------// + + dwTexPageComp=0; + + //----------------------------------------------------// + if(bDelTex) {glBindTexture(GL_TEXTURE_2D,0);gTexName=0;} + //----------------------------------------------------// + tsx=wcWndtexStore; + for(i=0;iused=0; + if(bDelTex && tsx->texname) + { + glDeleteTextures(1,&tsx->texname); + tsx->texname=0; + } + } + iMaxTexWnds=0; + //----------------------------------------------------// + + for(i=0;i<3;i++) + for(j=0;jpos.l=0; + (tss+SOFFB)->pos.l=0; + (tss+SOFFC)->pos.l=0; + (tss+SOFFD)->pos.l=0; + } + + for(i=0;il=0; + if(bDelTex && uiStexturePage[i]) + {glDeleteTextures(1,&uiStexturePage[i]);uiStexturePage[i]=0;} + } +} + + +//////////////////////////////////////////////////////////////////////// +// Invalidate tex windows +//////////////////////////////////////////////////////////////////////// + +void InvalidateWndTextureArea(int X, int Y, int W, int H) +{ + int i,px1,px2,py1,py2,iYM=1; + textureWndCacheEntry * tsw=wcWndtexStore; + + W+=X-1; + H+=Y-1; + if(X<0) X=0;if(X>1023) X=1023; + if(W<0) W=0;if(W>1023) W=1023; + if(Y<0) Y=0;if(Y>iGPUHeightMask) Y=iGPUHeightMask; + if(H<0) H=0;if(H>iGPUHeightMask) H=iGPUHeightMask; + W++;H++; + + if(iGPUHeight==1024) iYM=3; + + py1=min(iYM,Y>>8); + py2=min(iYM,H>>8); // y: 0 or 1 + + px1=max(0,(X>>6)); + px2=min(15,(W>>6)); + + if(py1==py2) + { + py1=py1<<4;px1+=py1;px2+=py1; // change to 0-31 + for(i=0;iused) + { + if(tsw->pageid>=px1 && tsw->pageid<=px2) + { + tsw->used=0; + } + } + } + } + else + { + py1=px1+16;py2=px2+16; + for(i=0;iused) + { + if((tsw->pageid>=px1 && tsw->pageid<=px2) || + (tsw->pageid>=py1 && tsw->pageid<=py2)) + { + tsw->used=0; + } + } + } + } + + // adjust tex window count + tsw=wcWndtexStore+iMaxTexWnds-1; + while(iMaxTexWnds && !tsw->used) {iMaxTexWnds--;tsw--;} +} + + + +//////////////////////////////////////////////////////////////////////// +// same for sort textures +//////////////////////////////////////////////////////////////////////// + +void MarkFree(textureSubCacheEntryS * tsx) +{ + EXLong * ul, * uls; + int j,iMax;unsigned char x1,y1,dx,dy; + + uls=pxSsubtexLeft[tsx->cTexID]; + iMax=uls->l;ul=uls+1; + + if(!iMax) return; + + for(j=0;jl==0xffffffff) break; + + if(jl=uls->l+1; + + x1=tsx->posTX;dx=tsx->pos.c[2]-tsx->pos.c[3]; + if(tsx->posTX) {x1--;dx+=3;} + y1=tsx->posTY;dy=tsx->pos.c[0]-tsx->pos.c[1]; + if(tsx->posTY) {y1--;dy+=3;} + + ul->c[3]=x1; + ul->c[2]=dx; + ul->c[1]=y1; + ul->c[0]=dy; + } +} + +void InvalidateSubSTextureArea(int X, int Y, int W, int H) +{ + int i,j,k,iMax,px,py,px1,px2,py1,py2,iYM = 1; + EXLong npos; + textureSubCacheEntryS *tsb; + int x1,x2,y1,y2,xa,sw; + + W+=X-1; + H+=Y-1; + if(X<0) X=0;if(X>1023) X=1023; + if(W<0) W=0;if(W>1023) W=1023; + if(Y<0) Y=0;if(Y>iGPUHeightMask) Y=iGPUHeightMask; + if(H<0) H=0;if(H>iGPUHeightMask) H=iGPUHeightMask; + W++;H++; + + if(iGPUHeight==1024) iYM=3; + + py1=min(iYM,Y>>8); + py2=min(iYM,H>>8); // y: 0 or 1 + px1=max(0,(X>>6)-3); + px2=min(15,(W>>6)+3); // x: 0-15 + + for(py=py1;py<=py2;py++) + { + j=(py<<4)+px1; // get page + + y1=py*256;y2=y1+255; + + if(Hy2) continue; + + if(Y>y1) y1=Y; + if(Hx2) continue; + + if(X>x1) x1=X; + if(Wpos.l;tsb++; + for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} + +// if(npos.l & 0x00800000) + { + tsb=pscSubtexStore[k][j]+SOFFB;iMax=tsb->pos.l;tsb++; + for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} + } + +// if(npos.l & 0x00000080) + { + tsb=pscSubtexStore[k][j]+SOFFC;iMax=tsb->pos.l;tsb++; + for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} + } + +// if(npos.l & 0x00800080) + { + tsb=pscSubtexStore[k][j]+SOFFD;iMax=tsb->pos.l;tsb++; + for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} + } + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////// +// Invalidate some parts of cache: main routine +//////////////////////////////////////////////////////////////////////// + +void InvalidateTextureAreaEx(void) +{ + short W=sxmax-sxmin; + short H=symax-symin; + + if (W == 0 && H == 0) return; + + if (iMaxTexWnds) + InvalidateWndTextureArea(sxmin,symin,W,H); + + InvalidateSubSTextureArea(sxmin,symin,W,H); +} + +//////////////////////////////////////////////////////////////////////// + +void InvalidateTextureArea(int X, int Y, int W, int H) +{ + if (W == 0 && H == 0) return; + + if (iMaxTexWnds) InvalidateWndTextureArea(X, Y, W, H); + + InvalidateSubSTextureArea(X, Y, W, H); +} + + +//////////////////////////////////////////////////////////////////////// +// tex window: define +//////////////////////////////////////////////////////////////////////// + +void DefineTextureWnd(void) +{ + if (gTexName == 0) + glGenTextures(1, &gTexName); + + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + if(iFilterType && iFilterType<3 && iHiResTextures!=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + + glTexImage2D(GL_TEXTURE_2D, 0,giWantedRGBA, + TWin.Position.x1, + TWin.Position.y1, + 0, giWantedFMT, giWantedTYPE, texturepart); +} + +//////////////////////////////////////////////////////////////////////// +// tex window: load packed stretch +//////////////////////////////////////////////////////////////////////// + +void LoadStretchPackedWndTexturePage(int pageid, int mode, short cx, short cy) +{ + uint32_t start, row, column, j, sxh, sxm, ldx, ldy, ldxo; + unsigned int palstart; + unsigned short *px, *pa, *ta; + unsigned char *cSRCPtr,*cOSRCPtr; + unsigned short *wSRCPtr,*wOSRCPtr; + uint32_t LineOffset; + unsigned short s; + int pmult = pageid / 16; + unsigned short (*LPTCOL)(unsigned short); + + LPTCOL = PTCF[DrawSemiTrans]; + + ldxo = TWin.Position.x1-TWin.OPosition.x1; + ldy = TWin.Position.y1-TWin.OPosition.y1; + + pa = px = (unsigned short *)ubPaletteBuffer; + ta = (unsigned short *)texturepart; + palstart = cx + (cy * 1024); + + ubOpaqueDraw = 0; + + switch (mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LPTCOL(*wSRCPtr++); + + column=g_y2-ldy; + for(TXV=g_y1;TXV<=column;TXV++) + { + ldx=ldxo; + for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + *ta++=s; + + if(ldx) {*ta++=s;ldx--;} + } + + if(ldy) + {ldy--; + for(TXU=g_x1;TXU<=g_x2;TXU++) + *ta++=*(ta-(g_x2-g_x1)); + } + } + + DefineTextureWnd(); + + break; + } + + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // convert CLUT to 32bits .. and then use THAT as a lookup table + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LPTCOL(*wSRCPtr++); + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row<=g_x2-ldxo;row++) + { + s=*(pa+(*cSRCPtr & 0xF)); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + row++; + if(row<=g_x2-ldxo) + { + s=*(pa+((*cSRCPtr >> 4) & 0xF)); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + cSRCPtr++; + } + + if(ldy && column&1) + {ldy--;cSRCPtr = cOSRCPtr;} + else cSRCPtr = psxVub + start + (2048*(column+1)) + sxh; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + for(row=0;row<256;row++) + *px++=LPTCOL(*wSRCPtr++); + + column=g_y2-ldy; + for(TXV=g_y1;TXV<=column;TXV++) + { + ldx=ldxo; + for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + + if(ldy) + {ldy--; + for(TXU=g_x1;TXU<=g_x2;TXU++) + *ta++=*(ta-(g_x2-g_x1)); + } + + } + + DefineTextureWnd(); + + break; + } + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // not using a lookup table here... speeds up smaller texture areas + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1) +ldxo; + + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + for(row=g_x1;row<=g_x2-ldxo;row++) + { + s=LPTCOL(psxVuw[palstart+ *cSRCPtr++]); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + if(ldy && column&1) {ldy--;cSRCPtr=cOSRCPtr;} + else cSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)*64)+256*1024*pmult; + wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; + LineOffset = 1024 - (g_x2-g_x1+1) +ldxo; + + for(column=g_y1;column<=g_y2;column++) + { + wOSRCPtr=wSRCPtr;ldx=ldxo; + for(row=g_x1;row<=g_x2-ldxo;row++) + { + s=LPTCOL(*wSRCPtr++); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + if(ldy && column&1) {ldy--;wSRCPtr=wOSRCPtr;} + else wSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // others are not possible ! + } +} + +//////////////////////////////////////////////////////////////////////// +// tex window: load stretched +//////////////////////////////////////////////////////////////////////// + +void LoadStretchWndTexturePage(int pageid, int mode, short cx, short cy) +{ + uint32_t start,row,column,j,sxh,sxm,ldx,ldy,ldxo,s; + unsigned int palstart; + uint32_t *px,*pa,*ta; + unsigned char *cSRCPtr,*cOSRCPtr; + unsigned short *wSRCPtr,*wOSRCPtr; + uint32_t LineOffset; + int pmult = pageid / 16; + uint32_t (*LTCOL)(uint32_t); + + LTCOL = TCF[DrawSemiTrans]; + + ldxo=TWin.Position.x1-TWin.OPosition.x1; + ldy =TWin.Position.y1-TWin.OPosition.y1; + + pa = px = (uint32_t *)ubPaletteBuffer; + ta = (uint32_t *)texturepart; + palstart = cx + (cy * 1024); + + ubOpaqueDraw = 0; + + switch (mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + //------------------- ZN STUFF + + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=4;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + column=g_y2-ldy; + for(TXV=g_y1;TXV<=column;TXV++) + { + ldx=ldxo; + for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + *ta++=s; + + if(ldx) {*ta++=s;ldx--;} + } + + if(ldy) + {ldy--; + for(TXU=g_x1;TXU<=g_x2;TXU++) + *ta++=*(ta-(g_x2-g_x1)); + } + } + + DefineTextureWnd(); + + break; + } + + //------------------- + + start=((pageid-16*pmult)*128)+256*2048*pmult; + // convert CLUT to 32bits .. and then use THAT as a lookup table + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LTCOL(*wSRCPtr++); + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row<=g_x2-ldxo;row++) + { + s=*(pa+(*cSRCPtr & 0xF)); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + row++; + if(row<=g_x2-ldxo) + { + s=*(pa+((*cSRCPtr >> 4) & 0xF)); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + cSRCPtr++; + } + if(ldy && column&1) + {ldy--;cSRCPtr = cOSRCPtr;} + else cSRCPtr = psxVub + start + (2048*(column+1)) + sxh; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + //------------ ZN STUFF + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + column=g_y2-ldy; + for(TXV=g_y1;TXV<=column;TXV++) + { + ldx=ldxo; + for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + + if(ldy) + {ldy--; + for(TXU=g_x1;TXU<=g_x2;TXU++) + *ta++=*(ta-(g_x2-g_x1)); + } + + } + + DefineTextureWnd(); + + break; + } + //------------ + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // not using a lookup table here... speeds up smaller texture areas + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1) +ldxo; + + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + for(row=g_x1;row<=g_x2-ldxo;row++) + { + s=LTCOL(psxVuw[palstart+ *cSRCPtr++]); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + if(ldy && column&1) {ldy--;cSRCPtr=cOSRCPtr;} + else cSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)*64)+256*1024*pmult; + + wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; + LineOffset = 1024 - (g_x2-g_x1+1) +ldxo; + + for(column=g_y1;column<=g_y2;column++) + { + wOSRCPtr=wSRCPtr;ldx=ldxo; + for(row=g_x1;row<=g_x2-ldxo;row++) + { + s=LTCOL(*wSRCPtr++); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + if(ldy && column&1) {ldy--;wSRCPtr=wOSRCPtr;} + else wSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // others are not possible ! + } +} + +//////////////////////////////////////////////////////////////////////// +// tex window: load packed simple +//////////////////////////////////////////////////////////////////////// + +void LoadPackedWndTexturePage(int pageid, int mode, short cx, short cy) +{ + uint32_t start,row,column,j,sxh,sxm; + unsigned int palstart; + unsigned short *px,*pa,*ta; + unsigned char *cSRCPtr; + unsigned short *wSRCPtr; + uint32_t LineOffset; + int pmult=pageid/16; + unsigned short (*LPTCOL)(unsigned short); + + LPTCOL=PTCF[DrawSemiTrans]; + + pa=px=(unsigned short *)ubPaletteBuffer; + ta=(unsigned short *)texturepart; + palstart=cx+(cy*1024); + + ubOpaqueDraw=0; + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LPTCOL(*wSRCPtr++); + + for(TXV=g_y1;TXV<=g_y2;TXV++) + { + for(TXU=g_x1;TXU<=g_x2;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + } + } + + DefineTextureWnd(); + + break; + } + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // convert CLUT to 32bits .. and then use THAT as a lookup table + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LPTCOL(*wSRCPtr++); + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cSRCPtr = psxVub + start + (2048*column) + sxh; + + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row<=g_x2;row++) + { + *ta++=*(pa+(*cSRCPtr & 0xF)); row++; + if(row<=g_x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); + cSRCPtr++; + } + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + for(row=0;row<256;row++) + *px++=LPTCOL(*wSRCPtr++); + + for(TXV=g_y1;TXV<=g_y2;TXV++) + { + for(TXU=g_x1;TXU<=g_x2;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + } + } + + DefineTextureWnd(); + + break; + } + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // not using a lookup table here... speeds up smaller texture areas + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1); + + for(column=g_y1;column<=g_y2;column++) + { + for(row=g_x1;row<=g_x2;row++) + *ta++=LPTCOL(psxVuw[palstart+ *cSRCPtr++]); + cSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)*64)+256*1024*pmult; + wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; + LineOffset = 1024 - (g_x2-g_x1+1); + + for(column=g_y1;column<=g_y2;column++) + { + for(row=g_x1;row<=g_x2;row++) + *ta++=LPTCOL(*wSRCPtr++); + wSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // others are not possible ! + } +} + +//////////////////////////////////////////////////////////////////////// +// tex window: load simple +//////////////////////////////////////////////////////////////////////// + +void LoadWndTexturePage(int pageid, int mode, short cx, short cy) +{ + uint32_t start,row,column,j,sxh,sxm; + unsigned int palstart; + uint32_t *px,*pa,*ta; + unsigned char *cSRCPtr; + unsigned short *wSRCPtr; + uint32_t LineOffset; + int pmult = pageid / 16; + uint32_t (*LTCOL)(uint32_t); + + LTCOL=TCF[DrawSemiTrans]; + + pa = px = (uint32_t *)ubPaletteBuffer; + ta = (uint32_t *)texturepart; + palstart = cx + (cy * 1024); + + ubOpaqueDraw = 0; + + switch (mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=4;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=g_y1;TXV<=g_y2;TXV++) + { + for(TXU=g_x1;TXU<=g_x2;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + } + } + + DefineTextureWnd(); + + break; + } + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // convert CLUT to 32bits .. and then use THAT as a lookup table + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LTCOL(*wSRCPtr++); + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cSRCPtr = psxVub + start + (2048*column) + sxh; + + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row<=g_x2;row++) + { + *ta++=*(pa+(*cSRCPtr & 0xF)); row++; + if(row<=g_x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); + cSRCPtr++; + } + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=g_y1;TXV<=g_y2;TXV++) + { + for(TXU=g_x1;TXU<=g_x2;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + } + } + + DefineTextureWnd(); + + break; + } + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // not using a lookup table here... speeds up smaller texture areas + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1); + + for(column=g_y1;column<=g_y2;column++) + { + for(row=g_x1;row<=g_x2;row++) + *ta++=LTCOL(psxVuw[palstart+ *cSRCPtr++]); + cSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)*64)+256*1024*pmult; + + wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; + LineOffset = 1024 - (g_x2-g_x1+1); + + for(column=g_y1;column<=g_y2;column++) + { + for(row=g_x1;row<=g_x2;row++) + *ta++=LTCOL(*wSRCPtr++); + wSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // others are not possible ! + } +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +void UploadTexWndPal(int mode,short cx,short cy) +{ + unsigned int i,iSize; + unsigned short *wSrcPtr; + uint32_t *ta = (uint32_t *)texturepart; + + wSrcPtr = psxVuw + cx + (cy * 1024); + if (mode == 0) i = 4; else i = 64; + iSize = i << 2; + ubOpaqueDraw = 0; + + do + { + *ta =PALCOL(*wSrcPtr); + *(ta+1)=PALCOL(*(wSrcPtr+1)); + *(ta+2)=PALCOL(*(wSrcPtr+2)); + *(ta+3)=PALCOL(*(wSrcPtr+3)); + ta+=4;wSrcPtr+=4;i--; + } + while(i); + + (*glColorTableEXTEx)(GL_TEXTURE_2D,GL_RGBA8,iSize, + GL_RGBA,GL_UNSIGNED_BYTE,texturepart); +} + +//////////////////////////////////////////////////////////////////////// + +void DefinePalTextureWnd(void) +{ + if(gTexName==0) + glGenTextures(1, &gTexName); + + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + if(iFilterType && iFilterType<3 && iHiResTextures!=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + + glTexImage2D(GL_TEXTURE_2D, 0,GL_COLOR_INDEX8_EXT, + TWin.Position.x1, + TWin.Position.y1, + 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE,texturepart); +} + +/////////////////////////////////////////////////////// + +void LoadPalWndTexturePage(int pageid, int mode, short cx, short cy) +{ + uint32_t start,row,column,j,sxh,sxm; + unsigned char *ta; + unsigned char *cSRCPtr; + uint32_t LineOffset; + int pmult = pageid / 16; + + ta = (unsigned char *)texturepart; + + switch (mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + start=((pageid-16*pmult)*128)+256*2048*pmult; + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cSRCPtr = psxVub + start + (2048*column) + sxh; + + if(sxm) *ta++=((*cSRCPtr++ >> 4) & 0xF); + + for(row=j;row<=g_x2;row++) + { + *ta++=(*cSRCPtr & 0xF); row++; + if(row<=g_x2) *ta++=((*cSRCPtr >> 4) & 0xF); + cSRCPtr++; + } + } + + DefinePalTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // not using a lookup table here... speeds up smaller texture areas + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1); + + for(column=g_y1;column<=g_y2;column++) + { + for(row=g_x1;row<=g_x2;row++) + *ta++=*cSRCPtr++; + cSRCPtr+=LineOffset; + } + + DefinePalTextureWnd(); + break; + } + UploadTexWndPal(mode,cx,cy); +} + +//////////////////////////////////////////////////////////////////////// + +void LoadStretchPalWndTexturePage(int pageid, int mode, short cx, short cy) +{ + uint32_t start,row,column,j,sxh,sxm,ldx,ldy,ldxo; + unsigned char *ta,s; + unsigned char *cSRCPtr,*cOSRCPtr; + uint32_t LineOffset; + int pmult = pageid / 16; + + ldxo = TWin.Position.x1-TWin.OPosition.x1; + ldy = TWin.Position.y1-TWin.OPosition.y1; + + ta = (unsigned char *)texturepart; + + switch (mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + start=((pageid-16*pmult)*128)+256*2048*pmult; + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + if(sxm) *ta++=((*cSRCPtr++ >> 4) & 0xF); + + for(row=j;row<=g_x2-ldxo;row++) + { + s=(*cSRCPtr & 0xF); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + row++; + if(row<=g_x2-ldxo) + { + s=((*cSRCPtr >> 4) & 0xF); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + cSRCPtr++; + } + if(ldy && column&1) + {ldy--;cSRCPtr = cOSRCPtr;} + else cSRCPtr = psxVub + start + (2048*(column+1)) + sxh; + } + + DefinePalTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + start=((pageid-16*pmult)*128)+256*2048*pmult; + + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1) +ldxo; + + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + for(row=g_x1;row<=g_x2-ldxo;row++) + { + s=*cSRCPtr++; + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + if(ldy && column&1) {ldy--;cSRCPtr=cOSRCPtr;} + else cSRCPtr+=LineOffset; + } + + DefinePalTextureWnd(); + break; + } + UploadTexWndPal(mode,cx,cy); +} + +//////////////////////////////////////////////////////////////////////// +// tex window: main selecting, cache handler included +//////////////////////////////////////////////////////////////////////// + +GLuint LoadTextureWnd(int pageid, int TextureMode, uint32_t GivenClutId) +{ + textureWndCacheEntry *ts, *tsx = NULL; + int i; + short cx,cy; + EXLong npos; + + npos.c[3] = TWin.Position.x0; + npos.c[2] = TWin.OPosition.x1; + npos.c[1] = TWin.Position.y0; + npos.c[0] = TWin.OPosition.y1; + + g_x1 = TWin.Position.x0; g_x2 = g_x1 + TWin.Position.x1 - 1; + g_y1 = TWin.Position.y0; g_y2 = g_y1 + TWin.Position.y1 - 1; + + if (TextureMode == 2) { GivenClutId = 0; cx = cy = 0; } + else + { + cx = ((GivenClutId << 4) & 0x3F0); + cy = ((GivenClutId >> 6) & CLUTYMASK); + GivenClutId = (GivenClutId & CLUTMASK) | (DrawSemiTrans << 30); + + // palette check sum + { + uint32_t l = 0,row; + uint32_t *lSRCPtr = (uint32_t *)(psxVuw + cx + (cy * 1024)); + if(TextureMode==1) for(row=1;row<129;row++) l+=((*lSRCPtr++)-1)*row; + else for(row=1;row<9;row++) l+=((*lSRCPtr++)-1)<used) + { + if(ts->pos.l==npos.l && + ts->pageid==pageid && + ts->textureMode==TextureMode) + { + if(ts->ClutID==GivenClutId) + { + ubOpaqueDraw=ts->Opaque; + return ts->texname; + } + else if(glColorTableEXTEx && TextureMode!=2) + { + ts->ClutID=GivenClutId; + if(ts->texname!=gTexName) + { + gTexName=ts->texname; + glBindTexture(GL_TEXTURE_2D, gTexName); + } + UploadTexWndPal(TextureMode,cx,cy); + ts->Opaque=ubOpaqueDraw; + return gTexName; + } + } + } + else tsx=ts; + } + + if(!tsx) + { + if(iMaxTexWnds==iTexWndLimit) + { + tsx=wcWndtexStore+iTexWndTurn; + iTexWndTurn++; + if(iTexWndTurn==iTexWndLimit) iTexWndTurn=0; + } + else + { + tsx=wcWndtexStore+iMaxTexWnds; + iMaxTexWnds++; + } + } + + gTexName=tsx->texname; + + if(TWin.OPosition.y1==TWin.Position.y1 && + TWin.OPosition.x1==TWin.Position.x1) + { + if(glColorTableEXTEx && TextureMode!=2) + LoadPalWndTexturePage(pageid,TextureMode,cx,cy); + else + if(bGLExt) + LoadPackedWndTexturePage(pageid,TextureMode,cx,cy); + else + LoadWndTexturePage(pageid,TextureMode,cx,cy); + } + else + { + if(glColorTableEXTEx && TextureMode!=2) + LoadStretchPalWndTexturePage(pageid,TextureMode,cx,cy); + else + if(bGLExt) + LoadStretchPackedWndTexturePage(pageid,TextureMode,cx,cy); + else + LoadStretchWndTexturePage(pageid,TextureMode,cx,cy); + } + + tsx->Opaque=ubOpaqueDraw; + tsx->pos.l=npos.l; + tsx->ClutID=GivenClutId; + tsx->pageid=pageid; + tsx->textureMode=TextureMode; + tsx->texname=gTexName; + tsx->used=1; + + return gTexName; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// movie texture: define +//////////////////////////////////////////////////////////////////////// + +void DefinePackedTextureMovie(void) +{ + if(gTexMovieName==0) + { + glGenTextures(1, &gTexMovieName); + gTexName=gTexMovieName; + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); + + if(!bUseFastMdec) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + + glTexImage2D(GL_TEXTURE_2D, 0, //giWantedRGBA, + GL_RGB5_A1, + 256, 256, 0, GL_RGBA, giWantedTYPE, texturepart); + } + else + { + gTexName=gTexMovieName;glBindTexture(GL_TEXTURE_2D, gTexName); + } + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, + (xrMovieArea.x1-xrMovieArea.x0), + (xrMovieArea.y1-xrMovieArea.y0), + GL_RGBA, + GL_UNSIGNED_SHORT_5_5_5_1_EXT, + texturepart); +} + +//////////////////////////////////////////////////////////////////////// + +void DefineTextureMovie(void) +{ + if(gTexMovieName==0) + { + glGenTextures(1, &gTexMovieName); + gTexName=gTexMovieName; + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); + + if(!bUseFastMdec) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + + glTexImage2D(GL_TEXTURE_2D, 0, giWantedRGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, texturepart); + } + else + { + gTexName=gTexMovieName;glBindTexture(GL_TEXTURE_2D, gTexName); + } + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, + (xrMovieArea.x1-xrMovieArea.x0), + (xrMovieArea.y1-xrMovieArea.y0), + GL_RGBA, GL_UNSIGNED_BYTE, texturepart); +} + +//////////////////////////////////////////////////////////////////////// +// movie texture: load +//////////////////////////////////////////////////////////////////////// + +#define MRED(x) ((x>>3) & 0x1f) +#define MGREEN(x) ((x>>6) & 0x3e0) +#define MBLUE(x) ((x>>9) & 0x7c00) + +#define XMGREEN(x) ((x>>5) & 0x07c0) +#define XMRED(x) ((x<<8) & 0xf800) +#define XMBLUE(x) ((x>>18) & 0x003e) + +//////////////////////////////////////////////////////////////////////// +// movie texture: load +//////////////////////////////////////////////////////////////////////// + +unsigned char * LoadDirectMovieFast(void) +{ + int row,column; + unsigned int startxy; + + uint32_t *ta=(uint32_t *)texturepart; + + if(PSXDisplay.RGB24) + { + unsigned char * pD; + + startxy=((1024)*xrMovieArea.y0)+xrMovieArea.x0; + + for(column=xrMovieArea.y0;column>9)|0x00010001; + ta+=2;startxy+=2; + } + if(row==sx0) *ta++=(psxVuw[startxy]<<1)|1; + } + } + DefinePackedTextureMovie(); + } + else + { + if(PSXDisplay.RGB24) + { + unsigned char *pD; + uint32_t *ta = (uint32_t *)texturepart; + + startxy=((1024)*xrMovieArea.y0)+xrMovieArea.x0; + + for(column=xrMovieArea.y0;column>9)|1; + } + + *ta++=*(ta-1); + } + if(b_Y) + { + dx=xrMovieArea.x1-xrMovieArea.x0+1; + for(row=xrMovieArea.x0;row>9)|1; + } + } + if(b_Y) + { + dx=xrMovieArea.x1-xrMovieArea.x0; + for(row=xrMovieArea.x0;row1280 || iResY>1024) iFTex=2048; + else + if(iResX>640 || iResY>480) iFTex=1024; + else iFTex=512; + + glGenTextures(1, &gTexFrameName); + gTexName=gTexFrameName; + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + p=(char *)malloc(iFTex*iFTex*4); + memset(p,0,iFTex*iFTex*4); + glTexImage2D(GL_TEXTURE_2D, 0, 3, iFTex, iFTex, 0, GL_RGB, GL_UNSIGNED_BYTE, p); + free(p); + + glGetError(); + } + else + { + gTexName=gTexFrameName; + glBindTexture(GL_TEXTURE_2D, gTexName); + } + + x1+=PreviousPSXDisplay.Range.x0; + y1+=PreviousPSXDisplay.Range.y0; + + if(PSXDisplay.DisplayMode.x) + ScaleX=(float)rRatioRect.right/(float)PSXDisplay.DisplayMode.x; + else ScaleX=1.0f; + if(PSXDisplay.DisplayMode.y) + ScaleY=(float)rRatioRect.bottom/(float)PSXDisplay.DisplayMode.y; + else ScaleY=1.0f; + + rSrc.left =max(x1*ScaleX,0); + rSrc.right =min((x1+x2)*ScaleX+0.99f,iResX-1); + rSrc.top =max(y1*ScaleY,0); + rSrc.bottom=min((y1+y2)*ScaleY+0.99f,iResY-1); + + iYAdjust=(y1+y2)-PSXDisplay.DisplayMode.y; + if(iYAdjust>0) + iYAdjust=(int)((float)iYAdjust*ScaleY)+1; + else iYAdjust=0; + + gl_vy[0]=255-gl_vy[0]; + gl_vy[1]=255-gl_vy[1]; + gl_vy[2]=255-gl_vy[2]; + gl_vy[3]=255-gl_vy[3]; + + y1=min(gl_vy[0],min(gl_vy[1],min(gl_vy[2],gl_vy[3]))); + + gl_vy[0]-=y1; + gl_vy[1]-=y1; + gl_vy[2]-=y1; + gl_vy[3]-=y1; + gl_ux[0]-=gl_ux[7]; + gl_ux[1]-=gl_ux[7]; + gl_ux[2]-=gl_ux[7]; + gl_ux[3]-=gl_ux[7]; + + ScaleX*=256.0f/((float)(iFTex)); + ScaleY*=256.0f/((float)(iFTex)); + + y1=((float)gl_vy[0]*ScaleY); if(y1>255) y1=255; + gl_vy[0]=y1; + y1=((float)gl_vy[1]*ScaleY); if(y1>255) y1=255; + gl_vy[1]=y1; + y1=((float)gl_vy[2]*ScaleY); if(y1>255) y1=255; + gl_vy[2]=y1; + y1=((float)gl_vy[3]*ScaleY); if(y1>255) y1=255; + gl_vy[3]=y1; + + x1=((float)gl_ux[0]*ScaleX); if(x1>255) x1=255; + gl_ux[0]=x1; + x1=((float)gl_ux[1]*ScaleX); if(x1>255) x1=255; + gl_ux[1]=x1; + x1=((float)gl_ux[2]*ScaleX); if(x1>255) x1=255; + gl_ux[2]=x1; + x1=((float)gl_ux[3]*ScaleX); if(x1>255) x1=255; + gl_ux[3]=x1; + + x1=rSrc.right-rSrc.left; + if(x1<=0) x1=1; + if(x1>iFTex) x1=iFTex; + + y1=rSrc.bottom-rSrc.top; + if(y1<=0) y1=1; + if(y1+iYAdjust>iFTex) y1=iFTex-iYAdjust; + + if(bFakeFrontBuffer) glReadBuffer(GL_FRONT); + + glCopyTexSubImage2D( GL_TEXTURE_2D, 0, + 0, + iYAdjust, + rSrc.left+rRatioRect.left, + iResY-rSrc.bottom-rRatioRect.top, + x1,y1); + + if(glGetError()) + { + char * p=(char *)malloc(iFTex*iFTex*4); + memset(p,0,iFTex*iFTex*4); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, iFTex, iFTex, + GL_RGB, GL_UNSIGNED_BYTE, p); + free(p); + } + + if(bFakeFrontBuffer) + {glReadBuffer(GL_BACK);bIgnoreNextTile=TRUE;} + + ubOpaqueDraw=0; + + if(iSpriteTex) + { + sprtW=gl_ux[1]-gl_ux[0]; + sprtH=-(gl_vy[0]-gl_vy[2]); + } + + return (GLuint)gTexName; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// load texture part (unpacked) +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +void LoadSubTexturePageSort(int pageid, int mode, short cx, short cy) +{ + uint32_t start,row,column,j,sxh,sxm; + unsigned int palstart; + uint32_t *px,*pa,*ta; + unsigned char *cSRCPtr; + unsigned short *wSRCPtr; + uint32_t LineOffset; + uint32_t x2a,xalign=0; + uint32_t x1=gl_ux[7]; + uint32_t x2=gl_ux[6]; + uint32_t y1=gl_ux[5]; + uint32_t y2=gl_ux[4]; + uint32_t dx=x2-x1+1; + uint32_t dy=y2-y1+1; + int pmult=pageid/16; + uint32_t (*LTCOL)(uint32_t); + unsigned int a,r,g,b,cnt,h; + uint32_t scol[8]; + + LTCOL=TCF[DrawSemiTrans]; + + pa=px=(uint32_t *)ubPaletteBuffer; + ta=(uint32_t *)texturepart; + palstart=cx+(cy<<10); + + ubOpaqueDraw=0; + + if(YTexS) {ta+=dx;if(XTexS) ta+=2;} + if(XTexS) {ta+=1;xalign=2;} + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=4;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=y1;TXV<=y2;TXV++) + { + for(TXU=x1;TXU<=x2;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + } + ta+=xalign; + } + break; + } + + start=((pageid-16*pmult)<<7)+524288*pmult; + // convert CLUT to 32bits .. and then use THAT as a lookup table + + wSRCPtr=psxVuw+palstart; + + row=4;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + x2a=x2?(x2-1):0;//if(x2) x2a=x2-1; else x2a=0; + sxm=x1&1;sxh=x1>>1; + j=sxm?(x1+1):x1;//if(sxm) j=x1+1; else j=x1; + for(column=y1;column<=y2;column++) + { + cSRCPtr = psxVub + start + (column<<11) + sxh; + + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row> 4) & 0xF)); + cSRCPtr++;ta+=2; + } + + if(row<=x2) + { + *ta++=*(pa+(*cSRCPtr & 0xF)); row++; + if(row<=x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); + } + + ta+=xalign; + } + + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=y1;TXV<=y2;TXV++) + { + for(TXU=x1;TXU<=x2;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + } + ta+=xalign; + } + + break; + } + + start=((pageid-16*pmult)<<7)+524288*pmult; + + cSRCPtr = psxVub + start + (y1<<11) + x1; + LineOffset = 2048 - dx; + + if(dy*dx>384) + { + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + column=dy;do + { + row=dx; + do {*ta++=*(pa+(*cSRCPtr++));row--;} while(row); + ta+=xalign; + cSRCPtr+=LineOffset;column--; + } + while(column); + } + else + { + wSRCPtr=psxVuw+palstart; + + column=dy;do + { + row=dx; + do {*ta++=LTCOL(*(wSRCPtr+*cSRCPtr++));row--;} while(row); + ta+=xalign; + cSRCPtr+=LineOffset;column--; + } + while(column); + } + + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)<<6)+262144*pmult; + + wSRCPtr = psxVuw + start + (y1<<10) + x1; + LineOffset = 1024 - dx; + + column=dy;do + { + row=dx; + do {*ta++=LTCOL(*wSRCPtr++);row--;} while(row); + ta+=xalign; + wSRCPtr+=LineOffset;column--; + } + while(column); + + break; + //--------------------------------------------------// + // others are not possible ! + } + + x2a=dx+xalign; + + if(YTexS) + { + ta=(uint32_t *)texturepart; + pa=(uint32_t *)texturepart+x2a; + row=x2a;do {*ta++=*pa++;row--;} while(row); + pa=(uint32_t *)texturepart+dy*x2a; + ta=pa+x2a; + row=x2a;do {*ta++=*pa++;row--;} while(row); + YTexS--; + dy+=2; + } + + if(XTexS) + { + ta=(uint32_t *)texturepart; + pa=ta+1; + row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); + pa=(uint32_t *)texturepart+dx; + ta=pa+1; + row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); + XTexS--; + dx+=2; + } + + DXTexS=dx;DYTexS=dy; + + if(!iFilterType) {DefineSubTextureSort();return;} + if(iFilterType!=2 && iFilterType!=4 && iFilterType!=6) {DefineSubTextureSort();return;} + if((iFilterType==4 || iFilterType==6) && ly0==ly1 && ly2==ly3 && lx0==lx3 && lx1==lx2) + {DefineSubTextureSort();return;} + + ta=(uint32_t *)texturepart; + x1=dx-1; + y1=dy-1; + + if(bOpaquePass) + { + if(bSmallAlpha) + { + for(column=0;column>24 !=0x03) scol[cnt++]=*(ta-dx); + if(row && *(ta-1) >>24 !=0x03) scol[cnt++]=*(ta-1); + if(row!=x1 && *(ta+1) >>24 !=0x03) scol[cnt++]=*(ta+1); + if( column!=y1 && *(ta+dx) >>24 !=0x03) scol[cnt++]=*(ta+dx); + + if(row && column && *(ta-dx-1)>>24 !=0x03) scol[cnt++]=*(ta-dx-1); + if(row!=x1 && column && *(ta-dx+1)>>24 !=0x03) scol[cnt++]=*(ta-dx+1); + if(row && column!=y1 && *(ta+dx-1)>>24 !=0x03) scol[cnt++]=*(ta+dx-1); + if(row!=x1 && column!=y1 && *(ta+dx+1)>>24 !=0x03) scol[cnt++]=*(ta+dx+1); + + if(cnt) + { + r=g=b=a=0; + for(h=0;h>16)&0xff; + g+=(scol[h]>>8)&0xff; + b+=scol[h]&0xff; + } + r/=cnt;b/=cnt;g/=cnt; + + *ta=(r<<16)|(g<<8)|b; + *ta|=0x03000000; + } + } + ta++; + } + } + } + else + { + for(column=0;column>24!=1) scol[cnt++]=*(ta-dx); + if(row && *(ta-1) !=0x50000000 && *(ta-1)>>24!=1) scol[cnt++]=*(ta-1); + if(row!=x1 && *(ta+1) !=0x50000000 && *(ta+1)>>24!=1) scol[cnt++]=*(ta+1); + if( column!=y1 && *(ta+dx) !=0x50000000 && *(ta+dx)>>24!=1) scol[cnt++]=*(ta+dx); + + if(row && column && *(ta-dx-1)!=0x50000000 && *(ta-dx-1)>>24!=1) scol[cnt++]=*(ta-dx-1); + if(row!=x1 && column && *(ta-dx+1)!=0x50000000 && *(ta-dx+1)>>24!=1) scol[cnt++]=*(ta-dx+1); + if(row && column!=y1 && *(ta+dx-1)!=0x50000000 && *(ta+dx-1)>>24!=1) scol[cnt++]=*(ta+dx-1); + if(row!=x1 && column!=y1 && *(ta+dx+1)!=0x50000000 && *(ta+dx+1)>>24!=1) scol[cnt++]=*(ta+dx+1); + + if(cnt) + { + r=g=b=a=0; + for(h=0;h>24); + r+=(scol[h]>>16)&0xff; + g+=(scol[h]>>8)&0xff; + b+=scol[h]&0xff; + } + r/=cnt;b/=cnt;g/=cnt; + + *ta=(r<<16)|(g<<8)|b; + if(a) *ta|=0x50000000; + else *ta|=0x01000000; + } + } + ta++; + } + } + } + } + else + for(column=0;column>16)&0xff; + g+=(scol[h]>>8)&0xff; + b+=scol[h]&0xff; + } + r/=cnt;b/=cnt;g/=cnt; + *ta=(r<<16)|(g<<8)|b; + } + } + ta++; + } + } + + DefineSubTextureSort(); +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// load texture part (packed) +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +void LoadPackedSubTexturePageSort(int pageid, int mode, short cx, short cy) +{ + uint32_t start,row,column,j,sxh,sxm; + unsigned int palstart; + unsigned short *px,*pa,*ta; + unsigned char *cSRCPtr; + unsigned short *wSRCPtr; + uint32_t LineOffset; + uint32_t x2a,xalign=0; + uint32_t x1=gl_ux[7]; + uint32_t x2=gl_ux[6]; + uint32_t y1=gl_ux[5]; + uint32_t y2=gl_ux[4]; + uint32_t dx=x2-x1+1; + uint32_t dy=y2-y1+1; + int pmult=pageid/16; + unsigned short (*LPTCOL)(unsigned short); + unsigned int a,r,g,b,cnt,h; + unsigned short scol[8]; + + LPTCOL=PTCF[DrawSemiTrans]; + + pa=px=(unsigned short *)ubPaletteBuffer; + ta=(unsigned short *)texturepart; + palstart=cx+(cy<<10); + + ubOpaqueDraw=0; + + if(YTexS) {ta+=dx;if(XTexS) ta+=2;} + if(XTexS) {ta+=1;xalign=2;} + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + row=4;do + { + *px =LPTCOL(*wSRCPtr); + *(px+1)=LPTCOL(*(wSRCPtr+1)); + *(px+2)=LPTCOL(*(wSRCPtr+2)); + *(px+3)=LPTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=y1;TXV<=y2;TXV++) + { + for(TXU=x1;TXU<=x2;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + } + ta+=xalign; + } + break; + } + + start=((pageid-16*pmult)<<7)+524288*pmult; + + wSRCPtr=psxVuw+palstart; + row=4;do + { + *px =LPTCOL(*wSRCPtr); + *(px+1)=LPTCOL(*(wSRCPtr+1)); + *(px+2)=LPTCOL(*(wSRCPtr+2)); + *(px+3)=LPTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + x2a=x2?(x2-1):0;//if(x2) x2a=x2-1; else x2a=0; + sxm=x1&1;sxh=x1>>1; + j=sxm?(x1+1):x1;//if(sxm) j=x1+1; else j=x1; + + for(column=y1;column<=y2;column++) + { + cSRCPtr = psxVub + start + (column<<11) + sxh; + + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row> 4) & 0xF)); + cSRCPtr++;ta+=2; + } + + if(row<=x2) + { + *ta++=*(pa+(*cSRCPtr & 0xF));row++; + if(row<=x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); + } + + ta+=xalign; + } + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LPTCOL(*wSRCPtr); + *(px+1)=LPTCOL(*(wSRCPtr+1)); + *(px+2)=LPTCOL(*(wSRCPtr+2)); + *(px+3)=LPTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=y1;TXV<=y2;TXV++) + { + for(TXU=x1;TXU<=x2;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + } + ta+=xalign; + } + + break; + } + + start=((pageid-16*pmult)<<7)+524288*pmult; + + cSRCPtr = psxVub + start + (y1<<11) + x1; + LineOffset = 2048 - dx; + + if(dy*dx>384) // more pix? use lut + { + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LPTCOL(*wSRCPtr); + *(px+1)=LPTCOL(*(wSRCPtr+1)); + *(px+2)=LPTCOL(*(wSRCPtr+2)); + *(px+3)=LPTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + column=dy;do + { + row=dx; + do {*ta++=*(pa+(*cSRCPtr++));row--;} while(row); + + ta+=xalign; + + cSRCPtr+=LineOffset;column--; + } + while(column); + } + else // small area? no lut + { + wSRCPtr=psxVuw+palstart; + + column=dy;do + { + row=dx; + do {*ta++=LPTCOL(*(wSRCPtr+*cSRCPtr++));row--;} while(row); + + ta+=xalign; + + cSRCPtr+=LineOffset;column--; + } + while(column); + } + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)<<6)+262144*pmult; + + wSRCPtr = psxVuw + start + (y1<<10) + x1; + LineOffset = 1024 - dx; + + column=dy;do + { + row=dx; + do {*ta++=LPTCOL(*wSRCPtr++);row--;} while(row); + + ta+=xalign; + + wSRCPtr+=LineOffset;column--; + } + while(column); + break; + //--------------------------------------------------// + // others are not possible ! + } + + //////////////////////////////////////////////////////// + + x2a=dx+xalign; + + if(YTexS) + { + ta=(unsigned short *)texturepart; + pa=(unsigned short *)texturepart+x2a; + row=x2a;do {*ta++=*pa++;row--;} while(row); + + pa=(unsigned short *)texturepart+dy*x2a; + ta=pa+x2a; + row=x2a;do {*ta++=*pa++;row--;} while(row); + + YTexS--; + dy+=2; + } + + if(XTexS) + { + ta=(unsigned short *)texturepart; + pa=ta+1; + row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); + + pa=(unsigned short *)texturepart+dx; + ta=pa+1; + row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); + + XTexS--; + dx+=2; + } + + DXTexS=dx;DYTexS=dy; + + if(!iFilterType) {DefineSubTextureSort();return;} + if(iFilterType!=2 && iFilterType!=4 && iFilterType!=6) {DefineSubTextureSort();return;} + if((iFilterType==4 || iFilterType==6) && ly0==ly1 && ly2==ly3 && lx0==lx3 && lx1==lx2) + {DefineSubTextureSort();return;} + + ta=(unsigned short *)texturepart; + x1=dx-1; + y1=dy-1; + + if(iTexQuality==1) + + { + if(bOpaquePass) + for(column=0;column>12; + g+=(scol[h]>>8)&0xf; + b+=(scol[h]>>4)&0xf; + } + r/=cnt;b/=cnt;g/=cnt; + *ta=(r<<12)|(g<<8)|(b<<4); + if(a) *ta|=6; + else *ta=0; + } + } + ta++; + } + } + else + for(column=0;column>12; + g+=(scol[h]>>8)&0xf; + b+=(scol[h]>>4)&0xf; + } + r/=cnt;b/=cnt;g/=cnt; + *ta=(r<<12)|(g<<8)|(b<<4); + } + } + ta++; + } + } + } + else + { + for(column=0;column>11; + g+=(scol[h]>>6)&0x1f; + b+=(scol[h]>>1)&0x1f; + } + r/=cnt;b/=cnt;g/=cnt; + *ta=(r<<11)|(g<<6)|(b<<1); + } + } + ta++; + } + } + } + + DefineSubTextureSort(); +} + +///////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// hires texture funcs +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +#define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D)) + +//////////////////////////////////////////////////////////////////////// + +#define colorMask8 0x00FEFEFE +#define lowPixelMask8 0x00010101 +#define qcolorMask8 0x00FCFCFC +#define qlowpixelMask8 0x00030303 + + +#define INTERPOLATE8_02(A, B) (((((A & colorMask8) >> 1) + ((B & colorMask8) >> 1) + (A & B & lowPixelMask8))|((((A&0xFF000000)==0x03000000)?0x03000000:(((B&0xFF000000)==0x03000000)?0x03000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))) + +#define Q_INTERPOLATE8_02(A, B, C, D) (((((A & qcolorMask8) >> 2) + ((B & qcolorMask8) >> 2) + ((C & qcolorMask8) >> 2) + ((D & qcolorMask8) >> 2) + ((((A & qlowpixelMask8) + (B & qlowpixelMask8) + (C & qlowpixelMask8) + (D & qlowpixelMask8)) >> 2) & qlowpixelMask8))|((((A&0xFF000000)==0x03000000)?0x03000000:(((B&0xFF000000)==0x03000000)?0x03000000:(((C&0xFF000000)==0x03000000)?0x03000000:(((D&0xFF000000)==0x03000000)?0x03000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:(((C&0xFF000000)==0x00000000)?0x00000000:(((D&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))))))) + +#define INTERPOLATE8(A, B) (((((A & colorMask8) >> 1) + ((B & colorMask8) >> 1) + (A & B & lowPixelMask8))|((((A&0xFF000000)==0x50000000)?0x50000000:(((B&0xFF000000)==0x50000000)?0x50000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))) + +#define Q_INTERPOLATE8(A, B, C, D) (((((A & qcolorMask8) >> 2) + ((B & qcolorMask8) >> 2) + ((C & qcolorMask8) >> 2) + ((D & qcolorMask8) >> 2) + ((((A & qlowpixelMask8) + (B & qlowpixelMask8) + (C & qlowpixelMask8) + (D & qlowpixelMask8)) >> 2) & qlowpixelMask8))|((((A&0xFF000000)==0x50000000)?0x50000000:(((B&0xFF000000)==0x50000000)?0x50000000:(((C&0xFF000000)==0x50000000)?0x50000000:(((D&0xFF000000)==0x50000000)?0x50000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:(((C&0xFF000000)==0x00000000)?0x00000000:(((D&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))))))) + +void Super2xSaI_ex8_Ex(unsigned char *srcPtr, DWORD srcPitch, + unsigned char *dstBitmap, int width, int height) +{ + DWORD dstPitch = srcPitch * 2; + DWORD line; + DWORD *dP; + DWORD *bP; + int width2 = width*2; + int iXA,iXB,iXC,iYA,iYB,iYC,finish; + DWORD color4, color5, color6; + DWORD color1, color2, color3; + DWORD colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, + colorS1, colorS2; + DWORD product1a, product1b, + product2a, product2b; + + line = 0; + + { + for (; height; height-=1) + { + bP = (DWORD *)srcPtr; + dP = (DWORD *)(dstBitmap + line*dstPitch); + for (finish = width; finish; finish -= 1 ) + { +//--------------------------------------- B1 B2 +// 4 5 6 S2 +// 1 2 3 S1 +// A1 A2 + if(finish==width) iXA=0; + else iXA=1; + if(finish>4) {iXB=1;iXC=2;} + else + if(finish>3) {iXB=1;iXC=1;} + else {iXB=0;iXC=0;} + if(line==0) iYA=0; + else iYA=width; + if(height>4) {iYB=width;iYC=width2;} + else + if(height>3) {iYB=width;iYC=width;} + else {iYB=0;iYC=0;} + + + colorB0 = *(bP- iYA - iXA); + colorB1 = *(bP- iYA); + colorB2 = *(bP- iYA + iXB); + colorB3 = *(bP- iYA + iXC); + + color4 = *(bP - iXA); + color5 = *(bP); + color6 = *(bP + iXB); + colorS2 = *(bP + iXC); + + color1 = *(bP + iYB - iXA); + color2 = *(bP + iYB); + color3 = *(bP + iYB + iXB); + colorS1= *(bP + iYB + iXC); + + colorA0 = *(bP + iYC - iXA); + colorA1 = *(bP + iYC); + colorA2 = *(bP + iYC + iXB); + colorA3 = *(bP + iYC + iXC); + +//-------------------------------------- + if (color2 == color6 && color5 != color3) + { + product2b = product1b = color2; + } + else + if (color5 == color3 && color2 != color6) + { + product2b = product1b = color5; + } + else + if (color5 == color3 && color2 == color6) + { + register int r = 0; + + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff), (colorA1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff), (colorB1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff)); + + if (r > 0) + product2b = product1b = color6; + else + if (r < 0) + product2b = product1b = color5; + else + { + product2b = product1b = INTERPOLATE8_02(color5, color6); + } + } + else + { + if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) + product2b = Q_INTERPOLATE8_02 (color3, color3, color3, color2); + else + if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) + product2b = Q_INTERPOLATE8_02 (color2, color2, color2, color3); + else + product2b = INTERPOLATE8_02 (color2, color3); + + if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) + product1b = Q_INTERPOLATE8_02 (color6, color6, color6, color5); + else + if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) + product1b = Q_INTERPOLATE8_02 (color6, color5, color5, color5); + else + product1b = INTERPOLATE8_02 (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) + product2a = INTERPOLATE8_02(color2, color5); + else + if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE8_02(color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) + product1a = INTERPOLATE8_02(color2, color5); + else + if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE8_02(color2, color5); + else + product1a = color5; + + *dP=product1a; + *(dP+1)=product1b; + *(dP+(width2))=product2a; + *(dP+1+(width2))=product2b; + + bP += 1; + dP += 2; + }//end of for ( finish= width etc..) + + line += 2; + srcPtr += srcPitch; + }; //endof: for (; height; height--) + } +} + + +void Super2xSaI_ex8(unsigned char *srcPtr, DWORD srcPitch, + unsigned char *dstBitmap, int width, int height) +{ + DWORD dstPitch = srcPitch * 2; + DWORD line; + DWORD *dP; + DWORD *bP; + int width2 = width*2; + int iXA,iXB,iXC,iYA,iYB,iYC,finish; + DWORD color4, color5, color6; + DWORD color1, color2, color3; + DWORD colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, + colorS1, colorS2; + DWORD product1a, product1b, + product2a, product2b; + + line = 0; + + { + for (; height; height-=1) + { + bP = (DWORD *)srcPtr; + dP = (DWORD *)(dstBitmap + line*dstPitch); + for (finish = width; finish; finish -= 1 ) + { +//--------------------------------------- B1 B2 +// 4 5 6 S2 +// 1 2 3 S1 +// A1 A2 + if(finish==width) iXA=0; + else iXA=1; + if(finish>4) {iXB=1;iXC=2;} + else + if(finish>3) {iXB=1;iXC=1;} + else {iXB=0;iXC=0;} + if(line==0) iYA=0; + else iYA=width; + if(height>4) {iYB=width;iYC=width2;} + else + if(height>3) {iYB=width;iYC=width;} + else {iYB=0;iYC=0;} + + + colorB0 = *(bP- iYA - iXA); + colorB1 = *(bP- iYA); + colorB2 = *(bP- iYA + iXB); + colorB3 = *(bP- iYA + iXC); + + color4 = *(bP - iXA); + color5 = *(bP); + color6 = *(bP + iXB); + colorS2 = *(bP + iXC); + + color1 = *(bP + iYB - iXA); + color2 = *(bP + iYB); + color3 = *(bP + iYB + iXB); + colorS1= *(bP + iYB + iXC); + + colorA0 = *(bP + iYC - iXA); + colorA1 = *(bP + iYC); + colorA2 = *(bP + iYC + iXB); + colorA3 = *(bP + iYC + iXC); + +//-------------------------------------- + if (color2 == color6 && color5 != color3) + { + product2b = product1b = color2; + } + else + if (color5 == color3 && color2 != color6) + { + product2b = product1b = color5; + } + else + if (color5 == color3 && color2 == color6) + { + register int r = 0; + + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff), (colorA1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff), (colorB1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff)); + + if (r > 0) + product2b = product1b = color6; + else + if (r < 0) + product2b = product1b = color5; + else + { + product2b = product1b = INTERPOLATE8(color5, color6); + } + } + else + { + if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) + product2b = Q_INTERPOLATE8 (color3, color3, color3, color2); + else + if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) + product2b = Q_INTERPOLATE8 (color2, color2, color2, color3); + else + product2b = INTERPOLATE8 (color2, color3); + + if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) + product1b = Q_INTERPOLATE8 (color6, color6, color6, color5); + else + if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) + product1b = Q_INTERPOLATE8 (color6, color5, color5, color5); + else + product1b = INTERPOLATE8 (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) + product2a = INTERPOLATE8(color2, color5); + else + if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE8(color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) + product1a = INTERPOLATE8(color2, color5); + else + if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE8(color2, color5); + else + product1a = color5; + + *dP=product1a; + *(dP+1)=product1b; + *(dP+(width2))=product2a; + *(dP+1+(width2))=product2b; + + bP += 1; + dP += 2; + }//end of for ( finish= width etc..) + + line += 2; + srcPtr += srcPitch; + }; //endof: for (; height; height--) + } +} +///////////////////////////////////////////////////////////////////////////// + +#define colorMask4 0x0000EEE0 +#define lowPixelMask4 0x00001110 +#define qcolorMask4 0x0000CCC0 +#define qlowpixelMask4 0x00003330 + +#define INTERPOLATE4(A, B) ((((A & colorMask4) >> 1) + ((B & colorMask4) >> 1) + (A & B & lowPixelMask4))|((((A&0x0000000F)==0x00000006)?0x00000006:(((B&0x0000000F)==0x00000006)?0x00000006:(((A&0x0000000F)==0x00000000)?0x00000000:(((B&0x0000000F)==0x00000000)?0x00000000:0x0000000F)))))) + +#define Q_INTERPOLATE4(A, B, C, D) ((((A & qcolorMask4) >> 2) + ((B & qcolorMask4) >> 2) + ((C & qcolorMask4) >> 2) + ((D & qcolorMask4) >> 2) + ((((A & qlowpixelMask4) + (B & qlowpixelMask4) + (C & qlowpixelMask4) + (D & qlowpixelMask4)) >> 2) & qlowpixelMask4))| ((((A&0x0000000F)==0x00000006)?0x00000006:(((B&0x0000000F)==0x00000006)?0x00000006:(((C&0x0000000F)==0x00000006)?0x00000006:(((D&0x0000000F)==0x00000006)?0x00000006:(((A&0x0000000F)==0x00000000)?0x00000000:(((B&0x0000000F)==0x00000000)?0x00000000:(((C&0x0000000F)==0x00000000)?0x00000000:(((D&0x0000000F)==0x00000000)?0x00000000:0x0000000F)))))))))) + +void Super2xSaI_ex4(unsigned char *srcPtr, DWORD srcPitch, + unsigned char *dstBitmap, int width, int height) +{ + DWORD dstPitch = srcPitch * 2; + DWORD line; + unsigned short *dP; + unsigned short *bP; + int width2 = width*2; + int iXA,iXB,iXC,iYA,iYB,iYC,finish; + DWORD color4, color5, color6; + DWORD color1, color2, color3; + DWORD colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, + colorS1, colorS2; + DWORD product1a, product1b, + product2a, product2b; + + line = 0; + + { + for (; height; height-=1) + { + bP = (unsigned short *)srcPtr; + dP = (unsigned short *)(dstBitmap + line*dstPitch); + for (finish = width; finish; finish -= 1 ) + { +//--------------------------------------- B1 B2 +// 4 5 6 S2 +// 1 2 3 S1 +// A1 A2 + if(finish==width) iXA=0; + else iXA=1; + if(finish>4) {iXB=1;iXC=2;} + else + if(finish>3) {iXB=1;iXC=1;} + else {iXB=0;iXC=0;} + if(line==0) iYA=0; + else iYA=width; + if(height>4) {iYB=width;iYC=width2;} + else + if(height>3) {iYB=width;iYC=width;} + else {iYB=0;iYC=0;} + + + colorB0 = *(bP- iYA - iXA); + colorB1 = *(bP- iYA); + colorB2 = *(bP- iYA + iXB); + colorB3 = *(bP- iYA + iXC); + + color4 = *(bP - iXA); + color5 = *(bP); + color6 = *(bP + iXB); + colorS2 = *(bP + iXC); + + color1 = *(bP + iYB - iXA); + color2 = *(bP + iYB); + color3 = *(bP + iYB + iXB); + colorS1= *(bP + iYB + iXC); + + colorA0 = *(bP + iYC - iXA); + colorA1 = *(bP + iYC); + colorA2 = *(bP + iYC + iXB); + colorA3 = *(bP + iYC + iXC); + +//-------------------------------------- + if (color2 == color6 && color5 != color3) + { + product2b = product1b = color2; + } + else + if (color5 == color3 && color2 != color6) + { + product2b = product1b = color5; + } + else + if (color5 == color3 && color2 == color6) + { + register int r = 0; + + r += GET_RESULT ((color6&0xfffffff0), (color5&0xfffffff0), (color1&0xfffffff0), (colorA1&0xfffffff0)); + r += GET_RESULT ((color6&0xfffffff0), (color5&0xfffffff0), (color4&0xfffffff0), (colorB1&0xfffffff0)); + r += GET_RESULT ((color6&0xfffffff0), (color5&0xfffffff0), (colorA2&0xfffffff0), (colorS1&0xfffffff0)); + r += GET_RESULT ((color6&0xfffffff0), (color5&0xfffffff0), (colorB2&0xfffffff0), (colorS2&0xfffffff0)); + + if (r > 0) + product2b = product1b = color6; + else + if (r < 0) + product2b = product1b = color5; + else + { + product2b = product1b = INTERPOLATE4 (color5, color6); + } + } + else + { + if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) + product2b = Q_INTERPOLATE4 (color3, color3, color3, color2); + else + if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) + product2b = Q_INTERPOLATE4 (color2, color2, color2, color3); + else + product2b = INTERPOLATE4 (color2, color3); + + if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) + product1b = Q_INTERPOLATE4 (color6, color6, color6, color5); + else + if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) + product1b = Q_INTERPOLATE4 (color6, color5, color5, color5); + else + product1b = INTERPOLATE4 (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) + product2a = INTERPOLATE4 (color2, color5); + else + if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE4(color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) + product1a = INTERPOLATE4 (color2, color5); + else + if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE4(color2, color5); + else + product1a = color5; + + *dP=product1a; + *(dP+1)=product1b; + *(dP+(width2))=product2a; + *(dP+1+(width2))=product2b; + + bP += 1; + dP += 2; + }//end of for ( finish= width etc..) + + line += 2; + srcPtr += srcPitch; + }; //endof: for (; height; height--) + } +} + +///////////////////////////////////////////////////////////////////////////// + +#define colorMask5 0x0000F7BC +#define lowPixelMask5 0x00000842 +#define qcolorMask5 0x0000E738 +#define qlowpixelMask5 0x000018C6 + +#define INTERPOLATE5(A, B) ((((A & colorMask5) >> 1) + ((B & colorMask5) >> 1) + (A & B & lowPixelMask5))|((((A&0x00000001)==0x00000000)?0x00000000:(((B&0x00000001)==0x00000000)?0x00000000:0x00000001)))) + +#define Q_INTERPOLATE5(A, B, C, D) ((((A & qcolorMask5) >> 2) + ((B & qcolorMask5) >> 2) + ((C & qcolorMask5) >> 2) + ((D & qcolorMask5) >> 2) + ((((A & qlowpixelMask5) + (B & qlowpixelMask5) + (C & qlowpixelMask5) + (D & qlowpixelMask5)) >> 2) & qlowpixelMask5))| ((((A&0x00000001)==0x00000000)?0x00000000:(((B&0x00000001)==0x00000000)?0x00000000:(((C&0x00000001)==0x00000000)?0x00000000:(((D&0x00000001)==0x00000000)?0x00000000:0x00000001)))))) + +void Super2xSaI_ex5(unsigned char *srcPtr, DWORD srcPitch, + unsigned char *dstBitmap, int width, int height) +{ + DWORD dstPitch = srcPitch * 2; + DWORD line; + unsigned short *dP; + unsigned short *bP; + int width2 = width*2; + int iXA,iXB,iXC,iYA,iYB,iYC,finish; + DWORD color4, color5, color6; + DWORD color1, color2, color3; + DWORD colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, + colorS1, colorS2; + DWORD product1a, product1b, + product2a, product2b; + + line = 0; + + { + for (; height; height-=1) + { + bP = (unsigned short *)srcPtr; + dP = (unsigned short *)(dstBitmap + line*dstPitch); + for (finish = width; finish; finish -= 1 ) + { +//--------------------------------------- B1 B2 +// 4 5 6 S2 +// 1 2 3 S1 +// A1 A2 + if(finish==width) iXA=0; + else iXA=1; + if(finish>4) {iXB=1;iXC=2;} + else + if(finish>3) {iXB=1;iXC=1;} + else {iXB=0;iXC=0;} + if(line==0) iYA=0; + else iYA=width; + if(height>4) {iYB=width;iYC=width2;} + else + if(height>3) {iYB=width;iYC=width;} + else {iYB=0;iYC=0;} + + + colorB0 = *(bP- iYA - iXA); + colorB1 = *(bP- iYA); + colorB2 = *(bP- iYA + iXB); + colorB3 = *(bP- iYA + iXC); + + color4 = *(bP - iXA); + color5 = *(bP); + color6 = *(bP + iXB); + colorS2 = *(bP + iXC); + + color1 = *(bP + iYB - iXA); + color2 = *(bP + iYB); + color3 = *(bP + iYB + iXB); + colorS1= *(bP + iYB + iXC); + + colorA0 = *(bP + iYC - iXA); + colorA1 = *(bP + iYC); + colorA2 = *(bP + iYC + iXB); + colorA3 = *(bP + iYC + iXC); + +//-------------------------------------- + if (color2 == color6 && color5 != color3) + { + product2b = product1b = color2; + } + else + if (color5 == color3 && color2 != color6) + { + product2b = product1b = color5; + } + else + if (color5 == color3 && color2 == color6) + { + register int r = 0; + + r += GET_RESULT ((color6&0xfffffffe), (color5&0xfffffffe), (color1&0xfffffffe), (colorA1&0xfffffffe)); + r += GET_RESULT ((color6&0xfffffffe), (color5&0xfffffffe), (color4&0xfffffffe), (colorB1&0xfffffffe)); + r += GET_RESULT ((color6&0xfffffffe), (color5&0xfffffffe), (colorA2&0xfffffffe), (colorS1&0xfffffffe)); + r += GET_RESULT ((color6&0xfffffffe), (color5&0xfffffffe), (colorB2&0xfffffffe), (colorS2&0xfffffffe)); + + if (r > 0) + product2b = product1b = color6; + else + if (r < 0) + product2b = product1b = color5; + else + { + product2b = product1b = INTERPOLATE5 (color5, color6); + } + } + else + { + if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) + product2b = Q_INTERPOLATE5 (color3, color3, color3, color2); + else + if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) + product2b = Q_INTERPOLATE5 (color2, color2, color2, color3); + else + product2b = INTERPOLATE5 (color2, color3); + + if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) + product1b = Q_INTERPOLATE5 (color6, color6, color6, color5); + else + if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) + product1b = Q_INTERPOLATE5 (color6, color5, color5, color5); + else + product1b = INTERPOLATE5 (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) + product2a = INTERPOLATE5 (color2, color5); + else + if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE5(color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) + product1a = INTERPOLATE5(color2, color5); + else + if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE5(color2, color5); + else + product1a = color5; + + *dP=product1a; + *(dP+1)=product1b; + *(dP+(width2))=product2a; + *(dP+1+(width2))=product2b; + + bP += 1; + dP += 2; + }//end of for ( finish= width etc..) + + line += 2; + srcPtr += srcPitch; + }; //endof: for (; height; height--) + } +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// ogl texture defines +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +void DefineSubTextureSortHiRes(void) +{ + int x,y,dx2; + + if(!gTexName) + { + glGenTextures(1, &gTexName); + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); + + if(iFilterType) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + glTexImage2D(GL_TEXTURE_2D, 0, giWantedRGBA, 512, 512, 0, giWantedFMT, giWantedTYPE, texturebuffer); + } + else glBindTexture(GL_TEXTURE_2D, gTexName); + + if(bGLExt && (iTexQuality==1 || iTexQuality==2)) + { + if(DXTexS < 4 || DYTexS < 4 || iHiResTextures==2) + { + unsigned short * pS,*pD1,*pD2; + dx2=(DXTexS<<1); + pS=(unsigned short *)texturepart; + pD1=(unsigned short *)texturebuffer; + pD2=(unsigned short *)texturebuffer; + pD2+=dx2; + for(y=0;y=iSortTexCnt) LRUCleaned=0; // wrap? wrap! + iC1=LRUCleaned; // range of textures to clean + iC2=LRUCleaned+iC; + + for(iC=iC1;iCl=0; + } + + for(i=0;i<3;i++) // remove all references to that textures + for(j=0;jpos.l; + if(iMax) + do + { + tsb++; + if(tsb->cTexID>=iC1 && tsb->cTexIDClutID=0; + } + while(--iMax); + } + + usLRUTexPage=LRUCleaned; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// search cache for existing (already used) parts +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +unsigned char * CheckTextureInSubSCache(int TextureMode, uint32_t GivenClutId, unsigned short * pCache) +{ + textureSubCacheEntryS * tsx, * tsb, *tsg;//, *tse=NULL; + int i,iMax;EXLong npos; + unsigned char cx,cy; + int iC,j,k;uint32_t rx,ry,mx,my; + EXLong * ul=0, * uls; + EXLong rfree; + unsigned char cXAdj,cYAdj; + + npos.l=*((uint32_t *)&gl_ux[4]); + + //--------------------------------------------------------------// + // find matching texturepart first... speed up... + //--------------------------------------------------------------// + + tsg=pscSubtexStore[TextureMode][GlobalTexturePage]; + tsg+=((GivenClutId&CLUTCHK)>>CLUTSHIFT)*SOFFB; + + iMax=tsg->pos.l; + if(iMax) + { + i=iMax; + tsb=tsg+1; + do + { + if(GivenClutId==tsb->ClutID && + (INCHECK(tsb->pos,npos))) + { + { + cx=tsb->pos.c[3]-tsb->posTX; + cy=tsb->pos.c[1]-tsb->posTY; + + gl_ux[0]-=cx; + gl_ux[1]-=cx; + gl_ux[2]-=cx; + gl_ux[3]-=cx; + gl_vy[0]-=cy; + gl_vy[1]-=cy; + gl_vy[2]-=cy; + gl_vy[3]-=cy; + + ubOpaqueDraw=tsb->Opaque; + *pCache=tsb->cTexID; + return NULL; + } + } + tsb++; + } + while(--i); + } + + //----------------------------------------------------// + + cXAdj=1;cYAdj=1; + + rx=(int)gl_ux[6]-(int)gl_ux[7]; + ry=(int)gl_ux[4]-(int)gl_ux[5]; + + tsx=NULL;tsb=tsg+1; + for(i=0;iClutID) {tsx=tsb;break;} + } + + if(!tsx) + { + iMax++; + if(iMax>=SOFFB-2) + { + if(iTexGarbageCollection) // gc mode? + { + if(*pCache==0) + { + dwTexPageComp|=(1<ClutID) + { + if(!tsx) {tsx=tsb;rfree.l=npos.l;} // + else tsb->ClutID=0; + rfree.c[3]=min(rfree.c[3],tsb->pos.c[3]); + rfree.c[2]=max(rfree.c[2],tsb->pos.c[2]); + rfree.c[1]=min(rfree.c[1],tsb->pos.c[1]); + rfree.c[0]=max(rfree.c[0],tsb->pos.c[0]); + MarkFree(tsb); + } + + if(tsx) // 3. if one or more found, create a new rect with bigger size + { + *((uint32_t *)&gl_ux[4])=npos.l=rfree.l; + rx=(int)rfree.c[2]-(int)rfree.c[3]; + ry=(int)rfree.c[0]-(int)rfree.c[1]; + DoTexGarbageCollection(); + + goto ENDLOOP3; + } + } + + iMax=1; + } + tsx=tsg+iMax; + tsg->pos.l=iMax; + } + + //----------------------------------------------------// + // now get a free texture space + //----------------------------------------------------// + + if(iTexGarbageCollection) usLRUTexPage=0; + +ENDLOOP3: + + rx+=3;if(rx>255) {cXAdj=0;rx=255;} + ry+=3;if(ry>255) {cYAdj=0;ry=255;} + + iC=usLRUTexPage; + + for(k=0;kl;ul=uls+1; + + //--------------------------------------------------// + // first time + + if(!iMax) + { + rfree.l=0; + + if(rx>252 && ry>252) + {uls->l=1;ul->l=0xffffffff;ul=0;goto ENDLOOP;} + + if(rx<253) + { + uls->l=uls->l+1; + ul->c[3]=rx; + ul->c[2]=255-rx; + ul->c[1]=0; + ul->c[0]=ry; + ul++; + } + + if(ry<253) + { + uls->l=uls->l+1; + ul->c[3]=0; + ul->c[2]=255; + ul->c[1]=ry; + ul->c[0]=255-ry; + } + ul=0; + goto ENDLOOP; + } + + //--------------------------------------------------// + for(i=0;il!=0xffffffff && + ry<=ul->c[0] && + rx<=ul->c[2]) + { + rfree=*ul; + mx=ul->c[2]-2; + my=ul->c[0]-2; + if(rxc[3]+=rx; + ul->c[2]-=rx; + ul->c[0]=ry; + + for(ul=uls+1,j=0;jl==0xffffffff) break; + + if(jl=uls->l+1; + + ul->c[3]=rfree.c[3]; + ul->c[2]=rfree.c[2]; + ul->c[1]=rfree.c[1]+ry; + ul->c[0]=rfree.c[0]-ry; + } + } + else if(rxc[3]+=rx; + ul->c[2]-=rx; + } + else if(ryc[1]+=ry; + ul->c[0]-=ry; + } + else + { + ul->l=0xffffffff; + } + ul=0; + goto ENDLOOP; + } + } + + //--------------------------------------------------// + + iC++; if(iC>=iSortTexCnt) iC=0; + } + + //----------------------------------------------------// + // check, if free space got + //----------------------------------------------------// + +ENDLOOP: + if(ul) + { + ////////////////////////////////////////////////////// + + { + dwTexPageComp=0; + + for(i=0;i<3;i++) // cleaning up + for(j=0;jpos.l=0; + (tsb+SOFFB)->pos.l=0; + (tsb+SOFFC)->pos.l=0; + (tsb+SOFFD)->pos.l=0; + } + for(i=0;il=0;} + usLRUTexPage=0; + } + + ////////////////////////////////////////////////////// + iC=usLRUTexPage; + uls=pxSsubtexLeft[usLRUTexPage]; + uls->l=0;ul=uls+1; + rfree.l=0; + + if(rx>252 && ry>252) + {uls->l=1;ul->l=0xffffffff;} + else + { + if(rx<253) + { + uls->l=uls->l+1; + ul->c[3]=rx; + ul->c[2]=255-rx; + ul->c[1]=0; + ul->c[0]=ry; + ul++; + } + if(ry<253) + { + uls->l=uls->l+1; + ul->c[3]=0; + ul->c[2]=255; + ul->c[1]=ry; + ul->c[0]=255-ry; + } + } + tsg->pos.l=1;tsx=tsg+1; + } + + rfree.c[3]+=cXAdj; + rfree.c[1]+=cYAdj; + + tsx->cTexID =*pCache=iC; + tsx->pos = npos; + tsx->ClutID = GivenClutId; + tsx->posTX = rfree.c[3]; + tsx->posTY = rfree.c[1]; + + cx=gl_ux[7]-rfree.c[3]; + cy=gl_ux[5]-rfree.c[1]; + + gl_ux[0]-=cx; + gl_ux[1]-=cx; + gl_ux[2]-=cx; + gl_ux[3]-=cx; + gl_vy[0]-=cy; + gl_vy[1]-=cy; + gl_vy[2]-=cy; + gl_vy[3]-=cy; + + XTexS=rfree.c[3]; + YTexS=rfree.c[1]; + + return &tsx->Opaque; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// search cache for free place (on compress) +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +BOOL GetCompressTexturePlace(textureSubCacheEntryS * tsx) +{ + int i,j,k,iMax,iC;uint32_t rx,ry,mx,my; + EXLong * ul=0, * uls, rfree; + unsigned char cXAdj=1,cYAdj=1; + + rx=(int)tsx->pos.c[2]-(int)tsx->pos.c[3]; + ry=(int)tsx->pos.c[0]-(int)tsx->pos.c[1]; + + rx+=3;if(rx>255) {cXAdj=0;rx=255;} + ry+=3;if(ry>255) {cYAdj=0;ry=255;} + + iC=usLRUTexPage; + + for(k=0;kl;ul=uls+1; + + //--------------------------------------------------// + // first time + + if(!iMax) + { + rfree.l=0; + + if(rx>252 && ry>252) + {uls->l=1;ul->l=0xffffffff;ul=0;goto TENDLOOP;} + + if(rx<253) + { + uls->l=uls->l+1; + ul->c[3]=rx; + ul->c[2]=255-rx; + ul->c[1]=0; + ul->c[0]=ry; + ul++; + } + + if(ry<253) + { + uls->l=uls->l+1; + ul->c[3]=0; + ul->c[2]=255; + ul->c[1]=ry; + ul->c[0]=255-ry; + } + ul=0; + goto TENDLOOP; + } + + //--------------------------------------------------// + for(i=0;il!=0xffffffff && + ry<=ul->c[0] && + rx<=ul->c[2]) + { + rfree=*ul; + mx=ul->c[2]-2; + my=ul->c[0]-2; + + if(rxc[3]+=rx; + ul->c[2]-=rx; + ul->c[0]=ry; + + for(ul=uls+1,j=0;jl==0xffffffff) break; + + if(jl=uls->l+1; + + ul->c[3]=rfree.c[3]; + ul->c[2]=rfree.c[2]; + ul->c[1]=rfree.c[1]+ry; + ul->c[0]=rfree.c[0]-ry; + } + } + else if(rxc[3]+=rx; + ul->c[2]-=rx; + } + else if(ryc[1]+=ry; + ul->c[0]-=ry; + } + else + { + ul->l=0xffffffff; + } + ul=0; + goto TENDLOOP; + } + } + + //--------------------------------------------------// + + iC++; if(iC>=iSortTexCnt) iC=0; + } + + //----------------------------------------------------// + // check, if free space got + //----------------------------------------------------// + +TENDLOOP: + if(ul) return FALSE; + + rfree.c[3]+=cXAdj; + rfree.c[1]+=cYAdj; + + tsx->cTexID = iC; + tsx->posTX = rfree.c[3]; + tsx->posTY = rfree.c[1]; + + XTexS=rfree.c[3]; + YTexS=rfree.c[1]; + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// compress texture cache (to make place for new texture part, if needed) +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +void CompressTextureSpace(void) +{ + textureSubCacheEntryS * tsx, * tsg, * tsb; + int i,j,k,m,n,iMax;EXLong * ul, r,opos; + short sOldDST=DrawSemiTrans,cx,cy; + int lOGTP=GlobalTexturePage; + uint32_t l,row; + uint32_t *lSRCPtr; + + opos.l=*((uint32_t *)&gl_ux[4]); + + // 1. mark all textures as free + for(i=0;il=0;} + usLRUTexPage=0; + + // 2. compress + for(j=0;j<3;j++) + { + for(k=0;kpos.l=0; + (tsg+SOFFB)->pos.l=0; + (tsg+SOFFC)->pos.l=0; + (tsg+SOFFD)->pos.l=0; + continue; + } + + for(m=0;m<4;m++,tsg+=SOFFB) + { + iMax=tsg->pos.l; + + tsx=tsg+1; + for(i=0;iClutID) + { + r.l=tsx->pos.l; + for(n=i+1,tsb=tsx+1;nClutID==tsb->ClutID) + { + r.c[3]=min(r.c[3],tsb->pos.c[3]); + r.c[2]=max(r.c[2],tsb->pos.c[2]); + r.c[1]=min(r.c[1],tsb->pos.c[1]); + r.c[0]=max(r.c[0],tsb->pos.c[0]); + tsb->ClutID=0; + } + } + +// if(r.l!=tsx->pos.l) + { + cx=((tsx->ClutID << 4) & 0x3F0); + cy=((tsx->ClutID >> 6) & CLUTYMASK); + + if(j!=2) + { + // palette check sum + l=0;lSRCPtr=(uint32_t *)(psxVuw+cx+(cy*1024)); + if(j==1) for(row=1;row<129;row++) l+=((*lSRCPtr++)-1)*row; + else for(row=1;row<9;row++) l+=((*lSRCPtr++)-1)<ClutID&(0x00003fff<<16))) + { + tsx->ClutID=0;continue; + } + } + + tsx->pos.l=r.l; + if(!GetCompressTexturePlace(tsx)) // no place? + { + for(i=0;i<3;i++) // -> clean up everything + for(j=0;jpos.l=0; + (tsb+SOFFB)->pos.l=0; + (tsb+SOFFC)->pos.l=0; + (tsb+SOFFD)->pos.l=0; + } + for(i=0;il=0;} + usLRUTexPage=0; + DrawSemiTrans=sOldDST; + GlobalTexturePage=lOGTP; + *((uint32_t *)&gl_ux[4])=opos.l; + dwTexPageComp=0; + + return; + } + + if(tsx->ClutID&(1<<30)) DrawSemiTrans=1; + else DrawSemiTrans=0; + *((uint32_t *)&gl_ux[4])=r.l; + + gTexName=uiStexturePage[tsx->cTexID]; + LoadSubTexFn(k,j,cx,cy); + uiStexturePage[tsx->cTexID]=gTexName; + tsx->Opaque=ubOpaqueDraw; + } + } + } + + if(iMax) + { + tsx=tsg+iMax; + while(!tsx->ClutID && iMax) {tsx--;iMax--;} + tsg->pos.l=iMax; + } + + } + } + } + + if(dwTexPageComp==0xffffffff) dwTexPageComp=0; + + *((uint32_t *)&gl_ux[4])=opos.l; + GlobalTexturePage=lOGTP; + DrawSemiTrans=sOldDST; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// main entry for searching/creating textures, called from prim.c +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +GLuint SelectSubTextureS(int TextureMode, uint32_t GivenClutId) +{ + unsigned char * OPtr;unsigned short iCache;short cx,cy; + + // sort sow/tow infos for fast access + + unsigned char ma1,ma2,mi1,mi2; + if(gl_ux[0]>gl_ux[1]) {mi1=gl_ux[1];ma1=gl_ux[0];} + else {mi1=gl_ux[0];ma1=gl_ux[1];} + if(gl_ux[2]>gl_ux[3]) {mi2=gl_ux[3];ma2=gl_ux[2];} + else {mi2=gl_ux[2];ma2=gl_ux[3];} + if(mi1>mi2) gl_ux[7]=mi2; + else gl_ux[7]=mi1; + if(ma1>ma2) gl_ux[6]=ma1; + else gl_ux[6]=ma2; + + if(gl_vy[0]>gl_vy[1]) {mi1=gl_vy[1];ma1=gl_vy[0];} + else {mi1=gl_vy[0];ma1=gl_vy[1];} + if(gl_vy[2]>gl_vy[3]) {mi2=gl_vy[3];ma2=gl_vy[2];} + else {mi2=gl_vy[2];ma2=gl_vy[3];} + if(mi1>mi2) gl_ux[5]=mi2; + else gl_ux[5]=mi1; + if(ma1>ma2) gl_ux[4]=ma1; + else gl_ux[4]=ma2; + + // get clut infos in one 32 bit val + + if(TextureMode==2) // no clut here + { + GivenClutId=CLUTUSED|(DrawSemiTrans<<30);cx=cy=0; + + if(iFrameTexType && Fake15BitTexture()) + return (GLuint)gTexName; + } + else + { + cx=((GivenClutId << 4) & 0x3F0); // but here + cy=((GivenClutId >> 6) & CLUTYMASK); + GivenClutId=(GivenClutId&CLUTMASK)|(DrawSemiTrans<<30)|CLUTUSED; + + // palette check sum.. removed MMX asm, this easy func works as well + { + uint32_t l=0,row; + + uint32_t *lSRCPtr = (uint32_t *)(psxVuw+cx+(cy*1024)); + if(TextureMode==1) for(row=1;row<129;row++) l+=((*lSRCPtr++)-1)*row; + else for(row=1;row<9;row++) l+=((*lSRCPtr++)-1)<