mirror of https://github.com/PCSX2/pcsx2.git
Merge the changes in the GregsMisc branch back into trunk.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4049 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
commit
bd7fee3be3
|
@ -39,7 +39,7 @@ set(SoundTouchSources
|
|||
RateTransposer.cpp
|
||||
SoundTouch.cpp
|
||||
TDStretch.cpp
|
||||
WavFile.cpp
|
||||
# WavFile.cpp # directly include in spu2x
|
||||
cpu_detect_x86_gcc.cpp
|
||||
mmx_optimized.cpp
|
||||
sse_optimized.cpp)
|
||||
|
@ -55,7 +55,7 @@ set(SoundTouchHeaders
|
|||
STTypes.h
|
||||
SoundTouch.h
|
||||
TDStretch.h
|
||||
WavFile.h
|
||||
# WavFile.h # directly include in spu2x
|
||||
cpu_detect.h)
|
||||
|
||||
# add library
|
||||
|
|
|
@ -23,9 +23,6 @@ if(Linux)
|
|||
endif(GTK2_FOUND)
|
||||
|
||||
find_package(X11)
|
||||
# Manually find Xxf86vm because it is not done in the module...
|
||||
FIND_LIBRARY(X11_Xxf86vm_LIB Xxf86vm ${X11_LIB_SEARCH_PATH})
|
||||
MARK_AS_ADVANCED(X11_Xxf86vm_LIB)
|
||||
endif(Linux)
|
||||
|
||||
## Use cmake package to find module
|
||||
|
|
|
@ -183,11 +183,11 @@ __fi void memcpy_vibes(void * dest, const void * src, int size) {
|
|||
__asm__ __volatile__
|
||||
(
|
||||
".intel_syntax noprefix\n"
|
||||
"mov eax, %[qwc]\n" // keep a copy of count for looping
|
||||
"shr eax, 1\n"
|
||||
"jz memcpy_qwc_1_%=\n" // only one 16 byte block to copy?
|
||||
"sub %[qwc], 1\n" // dec the counter to ease the count of 16bytes block later (optimization)
|
||||
// Note after this line, real value of the counter is %[qwc] + 1
|
||||
"jle memcpy_qwc_1_%=\n" // only one 16 byte block to copy? Or nothing.
|
||||
|
||||
"cmp eax, 64\n" // "IN_CACHE_COPY/32"
|
||||
"cmp %[qwc], 127\n" // "IN_CACHE_COPY/16"
|
||||
"jb memcpy_qwc_loop1_%=\n" // small copies should be cached (definite speedup --air)
|
||||
|
||||
"memcpy_qwc_loop2_%=:\n" // 32-byte blocks, uncached copy
|
||||
|
@ -204,8 +204,8 @@ __fi void memcpy_vibes(void * dest, const void * src, int size) {
|
|||
|
||||
"add %[src],32\n" // update source pointer
|
||||
"add %[dest],32\n" // update destination pointer
|
||||
"sub eax,1\n"
|
||||
"jnz memcpy_qwc_loop2_%=\n" // last 64-byte block?
|
||||
"sub %[qwc],2\n"
|
||||
"jg memcpy_qwc_loop2_%=\n" // last 64-byte block?
|
||||
"sfence\n" // flush the write buffer
|
||||
"jmp memcpy_qwc_1_%=\n"
|
||||
|
||||
|
@ -227,12 +227,12 @@ __fi void memcpy_vibes(void * dest, const void * src, int size) {
|
|||
|
||||
"add %[src],32\n" // update source pointer
|
||||
"add %[dest],32\n" // update destination pointer
|
||||
"sub eax,1\n"
|
||||
"jnz memcpy_qwc_loop1_%=\n" // last 64-byte block?
|
||||
"sub %[qwc],2\n"
|
||||
"jg memcpy_qwc_loop2_%=\n" // last 64-byte block?
|
||||
|
||||
"memcpy_qwc_1_%=:\n"
|
||||
"test %[qwc],1\n"
|
||||
"jz memcpy_qwc_final_%=\n"
|
||||
"cmp %[qwc],0\n"
|
||||
"jne memcpy_qwc_final_%=\n"
|
||||
"movq mm0,[%[src]]\n"
|
||||
"movq mm1,[%[src]+8]\n"
|
||||
"movq [%[dest]], mm0\n"
|
||||
|
@ -243,7 +243,7 @@ __fi void memcpy_vibes(void * dest, const void * src, int size) {
|
|||
".att_syntax\n"
|
||||
: "=&r"(dest), "=&r"(src), "=&r"(qwc)
|
||||
: [dest]"0"(dest), [src]"1"(src), [qwc]"2"(qwc)
|
||||
: "memory", "eax", "mm0", "mm1", "mm2", "mm3"
|
||||
: "memory", "mm0", "mm1", "mm2", "mm3"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "cpudetect_internal.h"
|
||||
#include <wx/thread.h>
|
||||
|
||||
// Note: Apparently this solution is Linux/Solaris only.
|
||||
// FreeBSD/OsX need something far more complicated (apparently)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</Compiler>
|
||||
</Target>
|
||||
<Target title="Release">
|
||||
<Option output="../../../bin/patches/libFWnull.so.0.5.0" prefix_auto="0" extension_auto="0" />
|
||||
<Option output="../../../bin/plugins/libFWnull.so.0.5.0" prefix_auto="0" extension_auto="0" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
|
|
|
@ -57,8 +57,9 @@ set(spu2xSources
|
|||
Spu2replay.cpp
|
||||
spu2sys.cpp
|
||||
Timestretcher.cpp
|
||||
#utf8.cpp
|
||||
Wavedump_wav.cpp)
|
||||
Wavedump_wav.cpp
|
||||
WavFile.cpp
|
||||
)
|
||||
|
||||
# spu2x headers
|
||||
set(spu2xHeaders
|
||||
|
@ -75,7 +76,7 @@ set(spu2xHeaders
|
|||
SndOut.h
|
||||
spdif.h
|
||||
Spu2replay.h
|
||||
#utf8.h
|
||||
WavFile.h
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2
|
||||
* Developed and maintained by the Pcsx2 Development Team.
|
||||
*
|
||||
* The file is based on WavFile.h from SoundTouch library.
|
||||
* Original portions are (c) 2009 by Olli Parviainen (oparviai 'at' iki.fi)
|
||||
*
|
||||
* SPU2-X is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Note the file is mostly a copy paste of the WavFile.h from SoundTouch library. It was
|
||||
// shrunken to support only output 16 bits wav files
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "WavFile.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const char riffStr[] = "RIFF";
|
||||
static const char waveStr[] = "WAVE";
|
||||
static const char fmtStr[] = "fmt ";
|
||||
static const char dataStr[] = "data";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Class WavOutFile
|
||||
//
|
||||
|
||||
WavOutFile::WavOutFile(const char *fileName, int sampleRate, int bits, int channels)
|
||||
{
|
||||
bytesWritten = 0;
|
||||
fptr = fopen(fileName, "wb");
|
||||
if (fptr == NULL)
|
||||
{
|
||||
string msg = "Error : Unable to open file \"";
|
||||
msg += fileName;
|
||||
msg += "\" for writing.";
|
||||
//pmsg = msg.c_str;
|
||||
throw runtime_error(msg);
|
||||
}
|
||||
|
||||
fillInHeader(sampleRate, bits, channels);
|
||||
writeHeader();
|
||||
}
|
||||
|
||||
|
||||
WavOutFile::~WavOutFile()
|
||||
{
|
||||
finishHeader();
|
||||
if (fptr) fclose(fptr);
|
||||
fptr = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void WavOutFile::fillInHeader(uint sampleRate, uint bits, uint channels)
|
||||
{
|
||||
// fill in the 'riff' part..
|
||||
|
||||
// copy string 'RIFF' to riff_char
|
||||
memcpy(&(header.riff.riff_char), riffStr, 4);
|
||||
// package_len unknown so far
|
||||
header.riff.package_len = 0;
|
||||
// copy string 'WAVE' to wave
|
||||
memcpy(&(header.riff.wave), waveStr, 4);
|
||||
|
||||
|
||||
// fill in the 'format' part..
|
||||
|
||||
// copy string 'fmt ' to fmt
|
||||
memcpy(&(header.format.fmt), fmtStr, 4);
|
||||
|
||||
header.format.format_len = 0x10;
|
||||
header.format.fixed = 1;
|
||||
header.format.channel_number = (short)channels;
|
||||
header.format.sample_rate = (int)sampleRate;
|
||||
header.format.bits_per_sample = (short)bits;
|
||||
header.format.byte_per_sample = (short)(bits * channels / 8);
|
||||
header.format.byte_rate = header.format.byte_per_sample * (int)sampleRate;
|
||||
header.format.sample_rate = (int)sampleRate;
|
||||
|
||||
// fill in the 'data' part..
|
||||
|
||||
// copy string 'data' to data_field
|
||||
memcpy(&(header.data.data_field), dataStr, 4);
|
||||
// data_len unknown so far
|
||||
header.data.data_len = 0;
|
||||
}
|
||||
|
||||
|
||||
void WavOutFile::finishHeader()
|
||||
{
|
||||
// supplement the file length into the header structure
|
||||
header.riff.package_len = bytesWritten + 36;
|
||||
header.data.data_len = bytesWritten;
|
||||
|
||||
writeHeader();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void WavOutFile::writeHeader()
|
||||
{
|
||||
int res;
|
||||
|
||||
// write the supplemented header in the beginning of the file
|
||||
fseek(fptr, 0, SEEK_SET);
|
||||
res = fwrite(&header, sizeof(header), 1, fptr);
|
||||
if (res != 1)
|
||||
{
|
||||
throw runtime_error("Error while writing to a wav file.");
|
||||
}
|
||||
|
||||
// jump back to the end of the file
|
||||
fseek(fptr, 0, SEEK_END);
|
||||
}
|
||||
|
||||
|
||||
void WavOutFile::write(const short *buffer, int numElems)
|
||||
{
|
||||
int res;
|
||||
|
||||
// 16bit format & 16 bit samples
|
||||
|
||||
assert(header.format.bits_per_sample == 16);
|
||||
if (numElems < 1) return; // nothing to do
|
||||
|
||||
res = fwrite(buffer, 2, numElems, fptr);
|
||||
|
||||
if (res != numElems)
|
||||
{
|
||||
throw runtime_error("Error while writing to a wav file.");
|
||||
}
|
||||
bytesWritten += 2 * numElems;
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2
|
||||
* Developed and maintained by the Pcsx2 Development Team.
|
||||
*
|
||||
* The file is based on WavFile.h from SoundTouch library.
|
||||
* Original portions are (c) 2009 by Olli Parviainen (oparviai 'at' iki.fi)
|
||||
*
|
||||
* SPU2-X is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Note the file is mostly a copy paste of the WavFile.h from SoundTouch library. It was
|
||||
// shrunken to support only output 16 bits wav files
|
||||
|
||||
#ifndef WAVFILE_H
|
||||
#define WAVFILE_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef uint
|
||||
typedef unsigned int uint;
|
||||
#endif
|
||||
|
||||
|
||||
/// WAV audio file 'riff' section header
|
||||
typedef struct
|
||||
{
|
||||
char riff_char[4];
|
||||
int package_len;
|
||||
char wave[4];
|
||||
} WavRiff;
|
||||
|
||||
/// WAV audio file 'format' section header
|
||||
typedef struct
|
||||
{
|
||||
char fmt[4];
|
||||
int format_len;
|
||||
short fixed;
|
||||
short channel_number;
|
||||
int sample_rate;
|
||||
int byte_rate;
|
||||
short byte_per_sample;
|
||||
short bits_per_sample;
|
||||
} WavFormat;
|
||||
|
||||
/// WAV audio file 'data' section header
|
||||
typedef struct
|
||||
{
|
||||
char data_field[4];
|
||||
uint data_len;
|
||||
} WavData;
|
||||
|
||||
|
||||
/// WAV audio file header
|
||||
typedef struct
|
||||
{
|
||||
WavRiff riff;
|
||||
WavFormat format;
|
||||
WavData data;
|
||||
} WavHeader;
|
||||
|
||||
|
||||
/// Class for writing WAV audio files.
|
||||
class WavOutFile
|
||||
{
|
||||
private:
|
||||
/// Pointer to the WAV file
|
||||
FILE *fptr;
|
||||
|
||||
/// WAV file header data.
|
||||
WavHeader header;
|
||||
|
||||
/// Counter of how many bytes have been written to the file so far.
|
||||
int bytesWritten;
|
||||
|
||||
/// Fills in WAV file header information.
|
||||
void fillInHeader(const uint sampleRate, const uint bits, const uint channels);
|
||||
|
||||
/// Finishes the WAV file header by supplementing information of amount of
|
||||
/// data written to file etc
|
||||
void finishHeader();
|
||||
|
||||
/// Writes the WAV file header.
|
||||
void writeHeader();
|
||||
|
||||
public:
|
||||
/// Constructor: Creates a new WAV file. Throws a 'runtime_error' exception
|
||||
/// if file creation fails.
|
||||
WavOutFile(const char *fileName, ///< Filename
|
||||
int sampleRate, ///< Sample rate (e.g. 44100 etc)
|
||||
int bits, ///< Bits per sample (8 or 16 bits)
|
||||
int channels ///< Number of channels (1=mono, 2=stereo)
|
||||
);
|
||||
|
||||
/// Destructor: Finalizes & closes the WAV file.
|
||||
~WavOutFile();
|
||||
|
||||
/// Write data to WAV file. Throws a 'runtime_error' exception if writing to
|
||||
/// file fails.
|
||||
void write(const short *buffer, ///< Pointer to sample data buffer.
|
||||
int numElems ///< How many array items are to be written to file.
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -16,7 +16,11 @@
|
|||
*/
|
||||
|
||||
#include "Global.h"
|
||||
#ifdef __LINUX__
|
||||
#include "WavFile.h"
|
||||
#else
|
||||
#include "soundtouch/WavFile.h"
|
||||
#endif
|
||||
|
||||
static WavOutFile* _new_WavOutFile( const char* destfile )
|
||||
{
|
||||
|
|
|
@ -855,4 +855,5 @@ public:
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -63,6 +63,11 @@ set(zzoglSources
|
|||
x86.cpp
|
||||
zerogs.cpp
|
||||
zpipe.cpp
|
||||
ZZClut.cpp
|
||||
ZZHacks.cpp
|
||||
ZZKeyboard.cpp
|
||||
ZZoglDrawing.cpp
|
||||
ZZLog.cpp
|
||||
ZZoglCreate.cpp
|
||||
ZZoglCRTC.cpp
|
||||
ZZoglFlush.cpp
|
||||
|
@ -71,8 +76,7 @@ set(zzoglSources
|
|||
ZZoglShaders.cpp
|
||||
ZZoglShoots.cpp
|
||||
ZZoglVB.cpp
|
||||
ZZKeyboard.cpp
|
||||
ZZLog.cpp)
|
||||
)
|
||||
|
||||
# zzogl headers
|
||||
set(zzoglHeaders
|
||||
|
@ -81,6 +85,7 @@ set(zzoglHeaders
|
|||
GifTransfer.h
|
||||
# glprocs.h
|
||||
GS.h
|
||||
HostMemory.h
|
||||
Mem.h
|
||||
Mem_Swizzle.h
|
||||
Mem_Transmit.h
|
||||
|
@ -93,11 +98,17 @@ set(zzoglHeaders
|
|||
x86.h
|
||||
zerogs.h
|
||||
zpipe.h
|
||||
ZZClut.h
|
||||
ZZGl.h
|
||||
ZZHacks.h
|
||||
ZZoglDrawing.h
|
||||
ZZLog.h
|
||||
ZZoglCRTC.h
|
||||
ZZoglMath.h
|
||||
ZZoglShaders.h
|
||||
ZZGl.h
|
||||
ZZLog.h)
|
||||
ZZoglShoots.h
|
||||
ZZoglVB.h
|
||||
)
|
||||
|
||||
# zzogl S sources
|
||||
set(zzoglSSources
|
||||
|
|
|
@ -20,44 +20,7 @@
|
|||
#ifndef CRC_H_INCLUDED
|
||||
#define CRC_H_INCLUDED
|
||||
|
||||
// don't change these values!
|
||||
enum GAME_HACK_OPTIONS
|
||||
{
|
||||
GAME_TEXTURETARGS = 0x00000001,
|
||||
GAME_AUTORESET = 0x00000002,
|
||||
GAME_INTERLACE2X = 0x00000004,
|
||||
GAME_TEXAHACK = 0x00000008, // apply texa to non textured polys
|
||||
GAME_NOTARGETRESOLVE = 0x00000010,
|
||||
GAME_EXACTCOLOR = 0x00000020,
|
||||
GAME_NOCOLORCLAMP = 0x00000040,
|
||||
GAME_FFXHACK = 0x00000080,
|
||||
GAME_NOALPHAFAIL = 0x00000100,
|
||||
GAME_NODEPTHUPDATE = 0x00000200,
|
||||
GAME_QUICKRESOLVE1 = 0x00000400,
|
||||
GAME_NOQUICKRESOLVE = 0x00000800,
|
||||
GAME_NOTARGETCLUT = 0x00001000, // full 16 bit resolution
|
||||
GAME_NOSTENCIL = 0x00002000,
|
||||
GAME_VSSHACKOFF = 0x00004000, // vertical stripe syndrome
|
||||
GAME_NODEPTHRESOLVE = 0x00008000,
|
||||
GAME_FULL16BITRES = 0x00010000,
|
||||
GAME_RESOLVEPROMOTED = 0x00020000,
|
||||
GAME_FASTUPDATE = 0x00040000,
|
||||
GAME_NOALPHATEST = 0x00080000,
|
||||
GAME_DISABLEMRTDEPTH = 0x00100000,
|
||||
GAME_32BITTARGS = 0x00200000,
|
||||
GAME_PATH3HACK = 0x00400000,
|
||||
GAME_DOPARALLELCTX = 0x00800000, // tries to parallelize both contexts so that render calls are reduced (xenosaga)
|
||||
// makes the game faster, but can be buggy
|
||||
GAME_XENOSPECHACK = 0x01000000, // xenosaga specularity hack (ignore any zmask=1 draws)
|
||||
GAME_PARTIALPOINTERS = 0x02000000, // whenver the texture or render target are small, tries to look for bigger ones to read from
|
||||
GAME_PARTIALDEPTH = 0x04000000, // tries to save depth targets as much as possible across height changes
|
||||
GAME_REGETHACK = 0x08000000, // some sort of weirdness in ReGet() code
|
||||
GAME_GUSTHACK = 0x10000000, // Needed for Gustgames fast update.
|
||||
GAME_NOLOGZ = 0x20000000, // Intended for linux -- not logarithmic Z.
|
||||
GAME_AUTOSKIPDRAW = 0x40000000 // Remove blur effect on some games
|
||||
};
|
||||
|
||||
#define USEALPHATESTING (!(conf.settings().no_alpha_test))
|
||||
#include "ZZHacks.h"
|
||||
|
||||
// CRC Information
|
||||
enum Title_Info
|
||||
|
@ -374,8 +337,10 @@ static const Game_Info crc_game_list[] =
|
|||
//{0x4437F4B1, ArTonelico1, US, GAME_GUSTHACK, -1, -1},
|
||||
{0xF95F37EE, ArTonelico2, US, GAME_GUSTHACK, -1, -1},
|
||||
{0xF46142D3, ArTonelico2, JPUNDUB, GAME_GUSTHACK, -1, -1},
|
||||
{0x77b0236f, ManaKhemia1, US, GAME_GUSTHACK , -1, -1},
|
||||
{0x433951e7, ManaKhemia2, US, GAME_GUSTHACK, -1, -1},
|
||||
|
||||
// According to Zeydlitz, Mana Khemia no longer needs the Gust Hack.
|
||||
//{0x77b0236f, ManaKhemia1, US, GAME_GUSTHACK, -1, -1},
|
||||
//{0x433951e7, ManaKhemia2, US, GAME_GUSTHACK, -1, -1},
|
||||
//{0xda11c6d4, AtelierJudie, JP, GAME_GUSTHACK, -1, -1},
|
||||
//{0x3e72c085, AtelierLilie, JP, GAME_GUSTHACK, -1, -1},
|
||||
//{0x6eac076b, AtelierViorate, JP, GAME_GUSTHACK, -1, -1},
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
|
||||
#undef CreateWindow // Undo Windows.h global namespace pollution
|
||||
|
||||
extern void SetDeviceSize(int nNewWidth, int nNewHeight);
|
||||
extern void OnFKey(int key, int shift);
|
||||
|
||||
class GLWindow
|
||||
{
|
||||
private:
|
||||
|
@ -51,6 +54,9 @@ class GLWindow
|
|||
u32 width, height, depth;
|
||||
|
||||
public:
|
||||
char title[256];
|
||||
Size backbuffer;
|
||||
|
||||
void SwapGLBuffers();
|
||||
bool ReleaseContext();
|
||||
|
||||
|
@ -63,8 +69,21 @@ class GLWindow
|
|||
bool DisplayWindow(int _width, int _height);
|
||||
void SetTitle(char *strtitle);
|
||||
void ResizeCheck();
|
||||
};
|
||||
void ProcessEvents();
|
||||
|
||||
void UpdateWindowSize(int nNewWidth, int nNewHeight)
|
||||
{
|
||||
FUNCLOG
|
||||
backbuffer.w = std::max(nNewWidth, 16);
|
||||
backbuffer.h = std::max(nNewHeight, 16);
|
||||
|
||||
if (!(conf.fullscreen()))
|
||||
{
|
||||
conf.width = nNewWidth;
|
||||
conf.height = nNewHeight;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
extern GLWindow GLWin;
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
*/
|
||||
|
||||
#include "GS.h"
|
||||
#include "zerogs.h"
|
||||
#include "GLWin.h"
|
||||
|
||||
#ifdef GL_WIN32_WINDOW
|
||||
|
||||
HWND GShwnd = NULL;
|
||||
HDC hDC = NULL; // Private GDI Device Context
|
||||
HGLRC hRC = NULL; // Permanent Rendering Context
|
||||
|
||||
|
@ -47,14 +47,14 @@ LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
case WM_SIZE:
|
||||
nWindowWidth = lParam & 0xffff;
|
||||
nWindowHeight = lParam >> 16;
|
||||
ZeroGS::ChangeWindowSize(nWindowWidth, nWindowHeight);
|
||||
GLWin.UpdateWindowSize(nWindowWidth, nWindowHeight);
|
||||
break;
|
||||
|
||||
case WM_SIZING:
|
||||
// if button is 0, then just released so can resize
|
||||
if (GetSystemMetrics(SM_SWAPBUTTON) ? !GetAsyncKeyState(VK_RBUTTON) : !GetAsyncKeyState(VK_LBUTTON))
|
||||
{
|
||||
ZeroGS::SetChangeDeviceSize(nWindowWidth, nWindowHeight);
|
||||
SetDeviceSize(nWindowWidth, nWindowHeight);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -122,7 +122,11 @@ bool GLWindow::CreateWindow(void *pDisplay)
|
|||
hInstance, // Instance
|
||||
NULL); // Don't Pass Anything To WM_CREATE
|
||||
|
||||
if (GShwnd == NULL) return false;
|
||||
if (GShwnd == NULL)
|
||||
{
|
||||
ZZLog::Error_Log("Failed to create window. Exiting...");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pDisplay != NULL) *(HWND*)pDisplay = GShwnd;
|
||||
|
||||
|
@ -135,6 +139,7 @@ bool GLWindow::CreateWindow(void *pDisplay)
|
|||
|
||||
SetFocus(GShwnd);
|
||||
|
||||
if (pDisplay == NULL) ZZLog::Error_Log("Failed to create window. Exiting...");
|
||||
return (pDisplay != NULL);
|
||||
}
|
||||
|
||||
|
@ -184,8 +189,8 @@ bool GLWindow::DisplayWindow(int _width, int _height)
|
|||
|
||||
if (conf.fullscreen())
|
||||
{
|
||||
nBackbufferWidth = rcdesktop.right - rcdesktop.left;
|
||||
nBackbufferHeight = rcdesktop.bottom - rcdesktop.top;
|
||||
backbuffer.w = rcdesktop.right - rcdesktop.left;
|
||||
backbuffer.h = rcdesktop.bottom - rcdesktop.top;
|
||||
|
||||
dwExStyle = WS_EX_APPWINDOW;
|
||||
dwStyle = WS_POPUP;
|
||||
|
@ -195,6 +200,8 @@ bool GLWindow::DisplayWindow(int _width, int _height)
|
|||
{
|
||||
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
|
||||
dwStyle = WS_OVERLAPPEDWINDOW;
|
||||
backbuffer.w = _width;
|
||||
backbuffer.h = _height;
|
||||
}
|
||||
dwStyle |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
|
||||
|
||||
|
@ -202,8 +209,8 @@ bool GLWindow::DisplayWindow(int _width, int _height)
|
|||
|
||||
rc.left = 0;
|
||||
rc.top = 0;
|
||||
rc.right = nBackbufferWidth;
|
||||
rc.bottom = nBackbufferHeight;
|
||||
rc.right = backbuffer.h;
|
||||
rc.bottom = backbuffer.h;
|
||||
AdjustWindowRectEx(&rc, dwStyle, false, dwExStyle);
|
||||
int X = (rcdesktop.right - rcdesktop.left) / 2 - (rc.right - rc.left) / 2;
|
||||
int Y = (rcdesktop.bottom - rcdesktop.top) / 2 - (rc.bottom - rc.top) / 2;
|
||||
|
@ -218,8 +225,8 @@ bool GLWindow::DisplayWindow(int _width, int _height)
|
|||
DEVMODE dmScreenSettings;
|
||||
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
|
||||
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
|
||||
dmScreenSettings.dmPelsWidth = nBackbufferWidth;
|
||||
dmScreenSettings.dmPelsHeight = nBackbufferHeight;
|
||||
dmScreenSettings.dmPelsWidth = backbuffer.w;
|
||||
dmScreenSettings.dmPelsHeight = backbuffer.h;
|
||||
dmScreenSettings.dmBitsPerPel = 32;
|
||||
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
|
||||
|
||||
|
@ -300,8 +307,10 @@ bool GLWindow::DisplayWindow(int _width, int _height)
|
|||
void GLWindow::SwapGLBuffers()
|
||||
{
|
||||
static u32 lastswaptime = 0;
|
||||
|
||||
if (glGetError() != GL_NO_ERROR) ZZLog::Debug_Log("glError before swap!");
|
||||
|
||||
SwapBuffers(hDC);
|
||||
//glClear(GL_COLOR_BUFFER_BIT);
|
||||
lastswaptime = timeGetTime();
|
||||
}
|
||||
|
||||
|
@ -315,4 +324,74 @@ void GLWindow::ResizeCheck()
|
|||
|
||||
}
|
||||
|
||||
|
||||
extern void ChangeDeviceSize(int nNewWidth, int nNewHeight);
|
||||
|
||||
void GLWindow::ProcessEvents()
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
ZeroMemory(&msg, sizeof(msg));
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
||||
{
|
||||
switch (msg.message)
|
||||
{
|
||||
case WM_KEYDOWN :
|
||||
int my_KeyEvent = msg.wParam;
|
||||
bool my_bShift = !!(GetKeyState(VK_SHIFT) & 0x8000);
|
||||
|
||||
switch (msg.wParam)
|
||||
{
|
||||
case VK_F5:
|
||||
case VK_F6:
|
||||
case VK_F7:
|
||||
case VK_F9:
|
||||
OnFKey(msg.wParam - VK_F1 + 1, my_bShift);
|
||||
break;
|
||||
|
||||
case VK_ESCAPE:
|
||||
|
||||
if (conf.fullscreen())
|
||||
{
|
||||
// destroy that msg
|
||||
conf.setFullscreen(false);
|
||||
ChangeDeviceSize(conf.width, conf.height);
|
||||
UpdateWindow(GShwnd);
|
||||
continue; // so that msg doesn't get sent
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessage(GShwnd, WM_DESTROY, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((GetKeyState(VK_MENU) & 0x8000) && (GetKeyState(VK_RETURN) & 0x8000))
|
||||
{
|
||||
conf.zz_options.fullscreen = !conf.zz_options.fullscreen;
|
||||
|
||||
SetDeviceSize(
|
||||
(conf.fullscreen()) ? 1280 : conf.width,
|
||||
(conf.fullscreen()) ? 960 : conf.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
#include "Util.h"
|
||||
#include "GLWin.h"
|
||||
#include "zerogs.h"
|
||||
|
||||
#ifdef GL_X11_WINDOW
|
||||
|
||||
|
@ -35,7 +34,11 @@ bool GLWindow::CreateWindow(void *pDisplay)
|
|||
glDisplay = XOpenDisplay(0);
|
||||
glScreen = DefaultScreen(glDisplay);
|
||||
|
||||
if (pDisplay == NULL) return false;
|
||||
if (pDisplay == NULL)
|
||||
{
|
||||
ZZLog::Error_Log("Failed to create window. Exiting...");
|
||||
return false;
|
||||
}
|
||||
|
||||
*(Display**)pDisplay = glDisplay;
|
||||
|
||||
|
@ -135,9 +138,9 @@ void GLWindow::GetWindowSize()
|
|||
XUnlockDisplay(glDisplay);
|
||||
|
||||
// update the gl buffer size
|
||||
ZeroGS::ChangeWindowSize(width, height);
|
||||
UpdateWindowSize(width, height);
|
||||
|
||||
ZZLog::Error_Log("Resolution %dx%d. Depth %d bpp. Position (%d,%d)", width, height, depth, conf.x, conf.y);
|
||||
ZZLog::Dev_Log("Resolution %dx%d. Depth %d bpp. Position (%d,%d)", width, height, depth, conf.x, conf.y);
|
||||
}
|
||||
|
||||
void GLWindow::GetGLXVersion()
|
||||
|
@ -252,6 +255,9 @@ void GLWindow::ToggleFullscreen()
|
|||
|
||||
bool GLWindow::DisplayWindow(int _width, int _height)
|
||||
{
|
||||
backbuffer.w = _width;
|
||||
backbuffer.h = _height;
|
||||
|
||||
if (!CreateVisual()) return false;
|
||||
|
||||
/* create a GLX context */
|
||||
|
@ -301,8 +307,8 @@ bool GLWindow::DisplayWindow(int _width, int _height)
|
|||
|
||||
void GLWindow::SwapGLBuffers()
|
||||
{
|
||||
if (glGetError() != GL_NO_ERROR) ZZLog::Debug_Log("glError before swap!");
|
||||
glXSwapBuffers(glDisplay, glWindow);
|
||||
//glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void GLWindow::SetTitle(char *strtitle)
|
||||
|
@ -336,7 +342,7 @@ void GLWindow::ResizeCheck()
|
|||
width = event.xconfigure.width;
|
||||
height = event.xconfigure.height;
|
||||
Force43Ratio();
|
||||
ZeroGS::ChangeWindowSize(width, height);
|
||||
UpdateWindowSize(width, height);
|
||||
}
|
||||
|
||||
if (!fullScreen) {
|
||||
|
@ -352,4 +358,32 @@ void GLWindow::ResizeCheck()
|
|||
XUnlockDisplay(glDisplay);
|
||||
}
|
||||
|
||||
u32 THR_KeyEvent = 0; // Value for key event processing between threads
|
||||
bool THR_bShift = false;
|
||||
|
||||
void GLWindow::ProcessEvents()
|
||||
{
|
||||
FUNCLOG
|
||||
|
||||
// check resizing
|
||||
ResizeCheck();
|
||||
|
||||
if (THR_KeyEvent) // This value was passed from GSKeyEvents which could be in another thread
|
||||
{
|
||||
int my_KeyEvent = THR_KeyEvent;
|
||||
bool my_bShift = THR_bShift;
|
||||
THR_KeyEvent = 0;
|
||||
|
||||
switch (my_KeyEvent)
|
||||
{
|
||||
case XK_F5:
|
||||
case XK_F6:
|
||||
case XK_F7:
|
||||
case XK_F9:
|
||||
OnFKey(my_KeyEvent - XK_F1 + 1, my_bShift);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,39 +25,13 @@
|
|||
|
||||
#include "Util.h"
|
||||
#include "GifTransfer.h"
|
||||
#include "HostMemory.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern float fFPS;
|
||||
|
||||
#define MEMORY_END 0x00400000
|
||||
|
||||
extern int g_LastCRC;
|
||||
extern u8* g_pBasePS2Mem;
|
||||
|
||||
extern u8* g_pbyGSMemory;
|
||||
|
||||
class GSMemory
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
void destroy();
|
||||
u8* get();
|
||||
u8* get(u32 addr);
|
||||
u8* get_raw(u32 addr);
|
||||
};
|
||||
|
||||
extern u8* g_pbyGSClut; // the temporary clut buffer
|
||||
|
||||
class GSClut
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
void destroy();
|
||||
u8* get();
|
||||
u8* get(u32 addr);
|
||||
u8* get_raw(u32 addr);
|
||||
};
|
||||
|
||||
struct Vector_16F
|
||||
{
|
||||
|
@ -66,22 +40,7 @@ struct Vector_16F
|
|||
|
||||
// PS2 vertex
|
||||
|
||||
struct VertexGPU
|
||||
{
|
||||
// gained from XYZ2, XYZ3, XYZF2, XYZF3,
|
||||
// X -- bits 0-15, Y-16-31. Z - 32-63 if no F used, 32-55 otherwise, F (fog) - 56-63
|
||||
// X, Y stored in 12d3 format,
|
||||
s16 x, y, f, resv0; // note: xy is 12d3
|
||||
// Vertex color settings. RGB -- luminance of red/green/blue, A -- alpha. 1.0 == 0x80.
|
||||
// Goes grom RGBAQ register, bits 0-7, 8-15, 16-23 and 24-31 accordingly
|
||||
u32 rgba;
|
||||
u32 z;
|
||||
// Texture coordinates. S & T going from ST register (bits 0-31, and 32-63).
|
||||
// Q goes from RGBAQ register, bits 32-63
|
||||
float s, t, q;
|
||||
};
|
||||
|
||||
// Almost same as previous, controlled by prim.fst flags
|
||||
// Almost same as VertexGPU, controlled by prim.fst flags
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
|
@ -94,6 +53,75 @@ struct Vertex
|
|||
u16 u, v;
|
||||
};
|
||||
|
||||
struct VertexGPU
|
||||
{
|
||||
// gained from XYZ2, XYZ3, XYZF2, XYZF3,
|
||||
// X -- bits 0-15, Y-16-31. Z - 32-63 if no F used, 32-55 otherwise, F (fog) - 56-63
|
||||
// X, Y stored in 12d3 format,
|
||||
s16 x, y;
|
||||
s16 f, resv0;
|
||||
|
||||
// Vertex color settings. RGB -- luminance of red/green/blue, A -- alpha. 1.0 == 0x80.
|
||||
// Goes grom RGBAQ register, bits 0-7, 8-15, 16-23 and 24-31 accordingly
|
||||
u32 rgba;
|
||||
u32 z;
|
||||
// Texture coordinates. S & T going from ST register (bits 0-31, and 32-63).
|
||||
// Q goes from RGBAQ register, bits 32-63
|
||||
float s, t, q;
|
||||
|
||||
void move_x(Vertex v, int offset)
|
||||
{
|
||||
x = ((((int)v.x - offset) >> 1) & 0xffff);
|
||||
}
|
||||
|
||||
void move_y(Vertex v, int offset)
|
||||
{
|
||||
y = ((((int)v.y - offset) >> 1) & 0xffff);
|
||||
}
|
||||
|
||||
void move_z(Vertex v, int mask)
|
||||
{
|
||||
z = (mask == 0xffff) ? min((u32)0xffff, v.z) : v.z;
|
||||
}
|
||||
|
||||
void move_fog(Vertex v)
|
||||
{
|
||||
f = ((s16)(v).f << 7) | 0x7f;
|
||||
}
|
||||
|
||||
void set_xy(s16 x1, s16 y1)
|
||||
{
|
||||
x = x1;
|
||||
y = y1;
|
||||
}
|
||||
void set_xyz(s16 x1, s16 y1, u32 z1)
|
||||
{
|
||||
x = x1;
|
||||
y = y1;
|
||||
z = z1;
|
||||
}
|
||||
|
||||
void set_st(float s1, float t1)
|
||||
{
|
||||
s = s1;
|
||||
t = t1;
|
||||
}
|
||||
|
||||
void set_stq(float s1, float t1, float q1)
|
||||
{
|
||||
s = s1;
|
||||
t = t1;
|
||||
q = q1;
|
||||
}
|
||||
|
||||
void set_xyzst(s16 x1, s16 y1, u32 z1, float s1, float t1)
|
||||
{
|
||||
set_xyz(x1, y1, z1);
|
||||
set_st(s1, t1);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
extern GSconf conf;
|
||||
|
||||
// PSM values
|
||||
|
@ -346,7 +374,7 @@ union tex_0_info
|
|||
|
||||
u32 psm_fix()
|
||||
{
|
||||
// printf ("psm %d\n", psm);
|
||||
// ZZLog::Debug_Log("psm %d\n", psm);
|
||||
if (psm == 9) return 1;
|
||||
|
||||
return psm;
|
||||
|
@ -385,6 +413,10 @@ union tex_0_info
|
|||
#define TEX_HIGHLIGHT 2
|
||||
#define TEX_HIGHLIGHT2 3
|
||||
|
||||
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height);
|
||||
extern void SaveTex(tex0Info* ptex, int usevid);
|
||||
extern char* NamedSaveTex(tex0Info* ptex, int usevid);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int lcm;
|
||||
|
@ -471,14 +503,16 @@ typedef struct
|
|||
|
||||
typedef struct
|
||||
{
|
||||
Vertex gsvertex[3];
|
||||
u32 rgba;
|
||||
Vertex gsvertex[4]; // circular buffer that contains the vertex
|
||||
Vertex gsTriFanVertex; // Base of triangle fan primitive vertex
|
||||
u32 rgba; // global color for flat shading texture
|
||||
float q;
|
||||
Vertex vertexregs;
|
||||
Vertex vertexregs; // accumulation buffer that collect current vertex data
|
||||
|
||||
int primC; // number of verts current storing
|
||||
int primIndex; // current prim index
|
||||
int nTriFanVert;
|
||||
int nTriFanVert; // remember the index of the base of triangle fan
|
||||
int new_tri_fan; // 1 if we process a new triangle fan primitive. 0 otherwise
|
||||
|
||||
int prac;
|
||||
int dthe;
|
||||
|
@ -512,9 +546,17 @@ typedef struct
|
|||
GSClut clut_buffer;
|
||||
int primNext(int inc = 1)
|
||||
{
|
||||
return ((primIndex + inc) % ARRAY_SIZE(gsvertex));
|
||||
// Note: ArraySize(gsvertex) == 2^n => modulo is replaced by an and instruction
|
||||
return ((primIndex + inc) % ArraySize(gsvertex));
|
||||
}
|
||||
|
||||
int primPrev(int dec = 1)
|
||||
{
|
||||
// Note: assert( dec <= ArraySize(gsvertex) );
|
||||
// Note: ArraySize(gsvertex) == 2^n => modulo is replaced by an and instruction
|
||||
return ((primIndex + (ArraySize(gsvertex) - dec)) % ArraySize(gsvertex));
|
||||
}
|
||||
|
||||
void setRGBA(u32 r, u32 g, u32 b, u32 a)
|
||||
{
|
||||
rgba = (r & 0xff) |
|
||||
|
@ -523,29 +565,39 @@ typedef struct
|
|||
((a & 0xff) << 24);
|
||||
}
|
||||
|
||||
void add_vertex(u16 x, u16 y, u32 z, u16 f)
|
||||
inline void add_vertex(u16 x, u16 y, u32 z, u16 f)
|
||||
{
|
||||
vertexregs.x = x;
|
||||
vertexregs.y = y;
|
||||
vertexregs.z = z;
|
||||
vertexregs.f = f;
|
||||
gsvertex[primIndex] = vertexregs;
|
||||
primIndex = primNext();
|
||||
if (likely(!new_tri_fan)) {
|
||||
gsvertex[primIndex] = vertexregs;
|
||||
} else {
|
||||
gsTriFanVertex = vertexregs;
|
||||
new_tri_fan = false;
|
||||
}
|
||||
}
|
||||
|
||||
void add_vertex(u16 x, u16 y, u32 z)
|
||||
inline void add_vertex(u16 x, u16 y, u32 z)
|
||||
{
|
||||
vertexregs.x = x;
|
||||
vertexregs.y = y;
|
||||
vertexregs.z = z;
|
||||
gsvertex[primIndex] = vertexregs;
|
||||
primIndex = primNext();
|
||||
if (likely(!new_tri_fan)) {
|
||||
gsvertex[primIndex] = vertexregs;
|
||||
} else {
|
||||
gsTriFanVertex = vertexregs;
|
||||
new_tri_fan = false;
|
||||
}
|
||||
}
|
||||
} GSinternal;
|
||||
|
||||
extern GSinternal gs;
|
||||
|
||||
static __forceinline u16 RGBA32to16(u32 c)
|
||||
// Note the function is used in a template parameter so it must be declared extern
|
||||
// Note2: In this case extern is not compatible with __forceinline so just inline it...
|
||||
extern inline u16 RGBA32to16(u32 c)
|
||||
{
|
||||
return (u16)((((c) & 0x000000f8) >> 3) |
|
||||
(((c) & 0x0000f800) >> 6) |
|
||||
|
@ -673,7 +725,7 @@ static __forceinline int ZZOglGet_psm_TexBitsFix(u32 data)
|
|||
{
|
||||
//return tex_0_info(data).psm_fix();
|
||||
int result = ZZOglGet_psm_TexBits(data) ;
|
||||
// printf ("result %d\n", result);
|
||||
// ZZLog::Debug_Log("result %d", result);
|
||||
|
||||
if (result == 9) result = 1;
|
||||
|
||||
|
@ -910,6 +962,21 @@ inline bool ZZOglClutStorageUnchanged(const u32* oldtex, const u32* newtex)
|
|||
return ((oldtex[1] & 0x1ff10000) == (newtex[1] & 0x1ff10000));
|
||||
}
|
||||
|
||||
// call to load CLUT data (depending on CLD)
|
||||
void texClutWrite(int ctx);
|
||||
|
||||
// Perform clutting for flushed texture. Better check if it needs a prior call.
|
||||
inline void CluttingForFlushedTex(tex0Info* tex0, u32 Data, int ictx)
|
||||
{
|
||||
tex0->cbp = ZZOglGet_cbp_TexBits(Data);
|
||||
tex0->cpsm = ZZOglGet_cpsm_TexBits(Data);
|
||||
tex0->csm = ZZOglGet_csm_TexBits(Data);
|
||||
tex0->csa = ZZOglGet_csa_TexBits(Data);
|
||||
tex0->cld = ZZOglGet_cld_TexBits(Data);
|
||||
|
||||
texClutWrite(ictx);
|
||||
};
|
||||
|
||||
// CSA and CPSM bitmask 0001 1111 0111 1000 ...
|
||||
// 60 56 52
|
||||
#define CPSM_CSA_BITMASK 0x1f780000
|
||||
|
|
|
@ -16,29 +16,17 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include "Win32.h"
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include "Util.h"
|
||||
#include "GS.h"
|
||||
#include "Profile.h"
|
||||
#include "GLWin.h"
|
||||
#include "ZZoglFlushHack.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "GS.h"
|
||||
#include "Mem.h"
|
||||
#include "Regs.h"
|
||||
#include "Profile.h"
|
||||
#include "GLWin.h"
|
||||
|
||||
#include "zerogs.h"
|
||||
#include "targets.h"
|
||||
#include "ZZoglShaders.h"
|
||||
#include "ZZoglFlushHack.h"
|
||||
#include "ZZoglFlushHack.h"
|
||||
extern void SaveSnapshot(const char* filename);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4244)
|
||||
|
@ -46,7 +34,6 @@ using namespace std;
|
|||
|
||||
GLWindow GLWin;
|
||||
GSinternal gs;
|
||||
char GStitle[256];
|
||||
GSconf conf;
|
||||
|
||||
int ppf, g_GSMultiThreaded, CurrentSavestate = 0;
|
||||
|
@ -59,7 +46,7 @@ float fFPS = 0;
|
|||
|
||||
void (*GSirq)();
|
||||
u8* g_pBasePS2Mem = NULL;
|
||||
std::string s_strIniPath("inis/"); // Air's new ini path (r2361)
|
||||
string s_strIniPath("inis/"); // Air's new ini path (r2361)
|
||||
|
||||
bool SaveStateExists = true; // We could not know save slot status before first change occured
|
||||
const char* SaveStateFile = NULL; // Name of SaveFile for access check.
|
||||
|
@ -85,21 +72,24 @@ char *libraryName = "ZZ Ogl PG ";
|
|||
|
||||
extern int g_nPixelShaderVer, g_nFrameRender, g_nFramesSkipped;
|
||||
|
||||
extern void ProcessEvents();
|
||||
extern void WriteAA();
|
||||
extern void WriteBilinear();
|
||||
extern void ZZDestroy();
|
||||
extern bool ZZCreate(int width, int height);
|
||||
extern void ZZGSStateReset();
|
||||
extern int ZZSave(s8* pbydata);
|
||||
extern bool ZZLoad(s8* pbydata);
|
||||
|
||||
// switches the render target to the real target, flushes the current render targets and renders the real image
|
||||
extern void RenderCRTC(int interlace);
|
||||
|
||||
#if defined(_WIN32) && defined(_DEBUG)
|
||||
HANDLE g_hCurrentThread = NULL;
|
||||
#endif
|
||||
|
||||
extern int VALIDATE_THRESH;
|
||||
extern u32 TEXDESTROY_THRESH;
|
||||
|
||||
#ifdef _WIN32
|
||||
HWND GShwnd = NULL;
|
||||
#endif
|
||||
|
||||
u32 THR_KeyEvent = 0; // Value for key event processing between threads
|
||||
bool THR_bShift = false;
|
||||
|
||||
|
||||
u32 CALLBACK PS2EgetLibType()
|
||||
{
|
||||
return PS2E_LT_GS;
|
||||
|
@ -130,55 +120,6 @@ void CALLBACK GSsetLogDir(const char* dir)
|
|||
ZZLog::SetDir(dir);
|
||||
}
|
||||
|
||||
void ReportHacks(gameHacks hacks)
|
||||
{
|
||||
if (hacks.texture_targs) ZZLog::WriteLn("'Texture targs' hack enabled.");
|
||||
if (hacks.auto_reset) ZZLog::WriteLn("'Auto reset' hack enabled.");
|
||||
if (hacks.interlace_2x) ZZLog::WriteLn("'Interlace 2x' hack enabled.");
|
||||
if (hacks.texa) ZZLog::WriteLn("'Texa' hack enabled.");
|
||||
if (hacks.no_target_resolve) ZZLog::WriteLn("'No target resolve' hack enabled.");
|
||||
if (hacks.exact_color) ZZLog::WriteLn("Exact color hack enabled.");
|
||||
if (hacks.no_color_clamp) ZZLog::WriteLn("'No color clamp' hack enabled.");
|
||||
if (hacks.no_alpha_fail) ZZLog::WriteLn("'No alpha fail' hack enabled.");
|
||||
if (hacks.no_depth_update) ZZLog::WriteLn("'No depth update' hack enabled.");
|
||||
if (hacks.quick_resolve_1) ZZLog::WriteLn("'Quick resolve 1' enabled.");
|
||||
if (hacks.no_quick_resolve) ZZLog::WriteLn("'No Quick resolve' hack enabled.");
|
||||
if (hacks.no_target_clut) ZZLog::WriteLn("'No target clut' hack enabled.");
|
||||
if (hacks.no_stencil) ZZLog::WriteLn("'No stencil' hack enabled.");
|
||||
if (hacks.vss_hack_off) ZZLog::WriteLn("VSS hack enabled.");
|
||||
if (hacks.no_depth_resolve) ZZLog::WriteLn("'No depth resolve' hack enabled.");
|
||||
if (hacks.full_16_bit_res) ZZLog::WriteLn("'Full 16 bit resolution' hack enabled.");
|
||||
if (hacks.resolve_promoted) ZZLog::WriteLn("'Resolve promoted' hack enabled.");
|
||||
if (hacks.fast_update) ZZLog::WriteLn("'Fast update' hack enabled.");
|
||||
if (hacks.no_alpha_test) ZZLog::WriteLn("'No alpha test' hack enabled.");
|
||||
if (hacks.disable_mrt_depth) ZZLog::WriteLn("'Disable mrt depth' hack enabled.");
|
||||
if (hacks.args_32_bit) ZZLog::WriteLn("'Args 32 bit' hack enabled.");
|
||||
//if (hacks.path3) ZZLog::WriteLn("'Path3' hack enabled.");
|
||||
if (hacks.parallel_context) ZZLog::WriteLn("'Parallel context' hack enabled.");
|
||||
if (hacks.xenosaga_spec) ZZLog::WriteLn("'Xenosaga spec' hack enabled.");
|
||||
if (hacks.partial_pointers) ZZLog::WriteLn("'Partial pointers' hack enabled.");
|
||||
if (hacks.partial_depth) ZZLog::WriteLn("'Partial depth' hack enabled.");
|
||||
if (hacks.reget) ZZLog::WriteLn("Reget hack enabled.");
|
||||
if (hacks.gust) ZZLog::WriteLn("Gust hack enabled.");
|
||||
if (hacks.no_logz) ZZLog::WriteLn("'No logz' hack enabled.");
|
||||
if (hacks.automatic_skip_draw) ZZLog::WriteLn("'Automatic skip draw' hack enabled.");
|
||||
}
|
||||
|
||||
void ListHacks()
|
||||
{
|
||||
if ((!conf.disableHacks) && (conf.def_hacks._u32 != 0))
|
||||
{
|
||||
ZZLog::WriteLn("AutoEnabling these hacks:");
|
||||
ReportHacks(conf.def_hacks);
|
||||
}
|
||||
|
||||
if (conf.hacks._u32 != 0)
|
||||
{
|
||||
ZZLog::WriteLn("You've manually enabled these hacks:");
|
||||
ReportHacks(conf.hacks);
|
||||
}
|
||||
}
|
||||
|
||||
void CALLBACK GSsetGameCRC(int crc, int options)
|
||||
{
|
||||
// build a list of function pointer for GetSkipCount (SkipDraw)
|
||||
|
@ -190,10 +131,6 @@ void CALLBACK GSsetGameCRC(int crc, int options)
|
|||
inited = true;
|
||||
|
||||
memset(GSC_list, 0, sizeof(GSC_list));
|
||||
// for(int i = 0; i < NUMBER_OF_TITLES; i++)
|
||||
// {
|
||||
// GSC_list[i] = GSC_Null;
|
||||
// }
|
||||
|
||||
GSC_list[Okami] = GSC_Okami;
|
||||
GSC_list[MetalGearSolid3] = GSC_MetalGearSolid3;
|
||||
|
@ -207,7 +144,7 @@ void CALLBACK GSsetGameCRC(int crc, int options)
|
|||
GSC_list[OnePieceGrandBattle] = GSC_OnePieceGrandBattle;
|
||||
GSC_list[ICO] = GSC_ICO;
|
||||
GSC_list[GT4] = GSC_GT4;
|
||||
//FIXME GSC_list[WildArms4] = GSC_WildArms4;
|
||||
GSC_list[WildArms4] = GSC_WildArms4;
|
||||
GSC_list[WildArms5] = GSC_WildArms5;
|
||||
GSC_list[Manhunt2] = GSC_Manhunt2;
|
||||
GSC_list[CrashBandicootWoC] = GSC_CrashBandicootWoC;
|
||||
|
@ -296,12 +233,28 @@ void CALLBACK GSsetFrameSkip(int frameskip)
|
|||
|
||||
void CALLBACK GSreset()
|
||||
{
|
||||
ZeroGS::GSReset();
|
||||
FUNCLOG
|
||||
|
||||
memset(&gs, 0, sizeof(gs));
|
||||
|
||||
ZZGSStateReset();
|
||||
|
||||
gs.prac = 1;
|
||||
prim = &gs._prim[0];
|
||||
gs.imageTransfer = -1;
|
||||
gs.q = 1;
|
||||
}
|
||||
|
||||
void CALLBACK GSgifSoftReset(u32 mask)
|
||||
{
|
||||
ZeroGS::GSSoftReset(mask);
|
||||
FUNCLOG
|
||||
|
||||
if (mask & 1) memset(&gs.path[0], 0, sizeof(gs.path[0]));
|
||||
if (mask & 2) memset(&gs.path[1], 0, sizeof(gs.path[1]));
|
||||
if (mask & 4) memset(&gs.path[2], 0, sizeof(gs.path[2]));
|
||||
|
||||
gs.imageTransfer = -1;
|
||||
gs.q = 1;
|
||||
}
|
||||
|
||||
s32 CALLBACK GSinit()
|
||||
|
@ -318,60 +271,73 @@ s32 CALLBACK GSinit()
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifdef _DEBUG
|
||||
HANDLE g_hCurrentThread = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
extern LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
extern HINSTANCE hInst;
|
||||
#endif
|
||||
|
||||
|
||||
s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread)
|
||||
__forceinline void InitMisc()
|
||||
{
|
||||
FUNCLOG
|
||||
|
||||
bool err;
|
||||
|
||||
g_GSMultiThreaded = multithread;
|
||||
|
||||
ZZLog::WriteLn("Calling GSopen.");
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _DEBUG
|
||||
g_hCurrentThread = GetCurrentThread();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
LoadConfig();
|
||||
strcpy(GStitle, Title);
|
||||
|
||||
err = GLWin.CreateWindow(pDsp);
|
||||
if (!err)
|
||||
{
|
||||
ZZLog::Error_Log("Failed to create window. Exiting...");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ZZLog::GS_Log("Using %s:%d.%d.%d.", libraryName, zgsrevision, zgsbuild, zgsminor);
|
||||
ZZLog::WriteLn("Creating ZZOgl window.");
|
||||
|
||||
if (!ZeroGS::Create(conf.width, conf.height)) return -1;
|
||||
|
||||
ZZLog::WriteLn("Initialization successful.");
|
||||
|
||||
WriteBilinear();
|
||||
WriteAA();
|
||||
InitProfile();
|
||||
InitPath();
|
||||
ResetRegs();
|
||||
}
|
||||
|
||||
s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread)
|
||||
{
|
||||
FUNCLOG
|
||||
|
||||
g_GSMultiThreaded = multithread;
|
||||
|
||||
ZZLog::WriteLn("Calling GSopen.");
|
||||
|
||||
#if defined(_WIN32) && defined(_DEBUG)
|
||||
g_hCurrentThread = GetCurrentThread();
|
||||
#endif
|
||||
|
||||
LoadConfig();
|
||||
strcpy(GLWin.title, Title);
|
||||
|
||||
ZZLog::GS_Log("Using %s:%d.%d.%d.", libraryName, zgsrevision, zgsbuild, zgsminor);
|
||||
|
||||
ZZLog::WriteLn("Creating ZZOgl window.");
|
||||
if ((!GLWin.CreateWindow(pDsp)) || (!ZZCreate(conf.width, conf.height))) return -1;
|
||||
|
||||
ZZLog::WriteLn("Initialization successful.");
|
||||
|
||||
InitMisc();
|
||||
ZZLog::GS_Log("GSopen finished.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USE_GOPEN2
|
||||
s32 CALLBACK GSopen2( void* pDsp, INT32 flags )
|
||||
{
|
||||
FUNCLOG
|
||||
|
||||
bool err;
|
||||
|
||||
g_GSMultiThreaded = true;
|
||||
|
||||
ZZLog::WriteLn("Calling GSopen2.");
|
||||
|
||||
#if defined(_WIN32) && defined(_DEBUG)
|
||||
g_hCurrentThread = GetCurrentThread();
|
||||
#endif
|
||||
|
||||
LoadConfig();
|
||||
|
||||
ZZLog::GS_Log("Using %s:%d.%d.%d.", libraryName, zgsrevision, zgsbuild, zgsminor);
|
||||
|
||||
ZZLog::WriteLn("Capturing ZZOgl window.");
|
||||
if ((!GLWin.GetWindow(pDsp)) || (!ZZCreate2(conf.width, conf.height))) return -1;// Needs to be added.
|
||||
|
||||
ZZLog::WriteLn("Initialization successful.");
|
||||
|
||||
InitMisc();
|
||||
ZZLog::GS_Log("GSopen2 finished.");
|
||||
return 0;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void CALLBACK GSshutdown()
|
||||
{
|
||||
FUNCLOG
|
||||
|
@ -382,7 +348,7 @@ void CALLBACK GSclose()
|
|||
{
|
||||
FUNCLOG
|
||||
|
||||
ZeroGS::Destroy(1);
|
||||
ZZDestroy();
|
||||
GLWin.CloseWindow();
|
||||
|
||||
SaveStateFile = NULL;
|
||||
|
@ -414,7 +380,7 @@ void CALLBACK GSchangeSaveState(int newstate, const char* filename)
|
|||
|
||||
char str[255];
|
||||
sprintf(str, "save state %d", newstate);
|
||||
ZeroGS::AddMessage(str);
|
||||
ZZAddMessage(str);
|
||||
CurrentSavestate = newstate;
|
||||
|
||||
SaveStateFile = filename;
|
||||
|
@ -448,13 +414,12 @@ void CALLBACK GSmakeSnapshot(char *path)
|
|||
if ((bmpfile = fopen(filename, "wb")) == NULL)
|
||||
{
|
||||
char strdir[255];
|
||||
sprintf(strdir, "%s", path);
|
||||
|
||||
#ifdef _WIN32
|
||||
sprintf(strdir, "%s", path);
|
||||
CreateDirectory(strdir, NULL);
|
||||
#else
|
||||
sprintf(strdir, "mkdir %s", path);
|
||||
system(strdir);
|
||||
mkdir(path, 0777);
|
||||
#endif
|
||||
|
||||
if ((bmpfile = fopen(filename, "wb")) == NULL) return;
|
||||
|
@ -463,7 +428,7 @@ void CALLBACK GSmakeSnapshot(char *path)
|
|||
fclose(bmpfile);
|
||||
|
||||
// get the bits
|
||||
ZeroGS::SaveSnapshot(filename);
|
||||
SaveSnapshot(filename);
|
||||
}
|
||||
|
||||
// I'll probably move this somewhere else later, but it's got a ton of dependencies.
|
||||
|
@ -491,7 +456,7 @@ static __forceinline void SetGSTitle()
|
|||
100*g_nFramesSkipped / g_nFrame,
|
||||
g_nGenVars / (float)UPDATE_FRAMES, g_nTexVars / (float)UPDATE_FRAMES, g_nAlphaVars / (float)UPDATE_FRAMES,
|
||||
g_nResolve / (float)UPDATE_FRAMES, (ppf&0xfffff) / (float)UPDATE_FRAMES,
|
||||
ZeroGS::g_MemTargs.listTargets.size(), ZeroGS::g_MemTargs.listClearedTargets.size(), g_TransferredToGPU >> 10);
|
||||
g_MemTargs.listTargets.size(), g_MemTargs.listClearedTargets.size(), g_TransferredToGPU >> 10);
|
||||
|
||||
//_snprintf(strtitle, 512, "%x %x", *(int*)(g_pbyGSMemory + 256 * 0x3e0c + 4), *(int*)(g_pbyGSMemory + 256 * 0x3e04 + 4));
|
||||
#endif
|
||||
|
@ -517,14 +482,14 @@ void CALLBACK GSvsync(int interlace)
|
|||
g_nRealFrame++;
|
||||
|
||||
// !interlace? Hmmm... Fixme.
|
||||
ZeroGS::RenderCRTC(!interlace);
|
||||
RenderCRTC(!interlace);
|
||||
|
||||
ProcessEvents();
|
||||
GLWin.ProcessEvents();
|
||||
|
||||
if (--nToNextUpdate <= 0)
|
||||
{
|
||||
u32 d = timeGetTime();
|
||||
fFPS = UPDATE_FRAMES * 1000.0f / (float)max(d - dwTime, 1);
|
||||
fFPS = UPDATE_FRAMES * 1000.0f / (float)max(d - dwTime, (u32)1);
|
||||
dwTime = d;
|
||||
g_nFrame += UPDATE_FRAMES;
|
||||
SetGSTitle();
|
||||
|
@ -571,7 +536,7 @@ void CALLBACK GSreadFIFO(u64 *pMem)
|
|||
|
||||
//ZZLog::GS_Log("Calling GSreadFIFO.");
|
||||
|
||||
ZeroGS::TransferLocalHost((u32*)pMem, 1);
|
||||
TransferLocalHost((u32*)pMem, 1);
|
||||
}
|
||||
|
||||
void CALLBACK GSreadFIFO2(u64 *pMem, int qwc)
|
||||
|
@ -580,7 +545,7 @@ void CALLBACK GSreadFIFO2(u64 *pMem, int qwc)
|
|||
|
||||
//ZZLog::GS_Log("Calling GSreadFIFO2.");
|
||||
|
||||
ZeroGS::TransferLocalHost((u32*)pMem, qwc);
|
||||
TransferLocalHost((u32*)pMem, qwc);
|
||||
}
|
||||
|
||||
int CALLBACK GSsetupRecording(int start, void* pData)
|
||||
|
@ -588,9 +553,9 @@ int CALLBACK GSsetupRecording(int start, void* pData)
|
|||
FUNCLOG
|
||||
|
||||
if (start)
|
||||
ZeroGS::StartCapture();
|
||||
StartCapture();
|
||||
else
|
||||
ZeroGS::StopCapture();
|
||||
StopCapture();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -602,16 +567,16 @@ s32 CALLBACK GSfreeze(int mode, freezeData *data)
|
|||
switch (mode)
|
||||
{
|
||||
case FREEZE_LOAD:
|
||||
if (!ZeroGS::Load(data->data)) ZZLog::Error_Log("GS: Bad load format!");
|
||||
if (!ZZLoad(data->data)) ZZLog::Error_Log("GS: Bad load format!");
|
||||
g_nRealFrame += 100;
|
||||
break;
|
||||
|
||||
case FREEZE_SAVE:
|
||||
ZeroGS::Save(data->data);
|
||||
ZZSave(data->data);
|
||||
break;
|
||||
|
||||
case FREEZE_SIZE:
|
||||
data->size = ZeroGS::Save(NULL);
|
||||
data->size = ZZSave(NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
#include "GS.h"
|
||||
#include "Mem.h"
|
||||
#include "zerogs.h"
|
||||
#include "GifTransfer.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
@ -168,7 +167,7 @@ template<int index> void _GSgifTransfer(const u32 *pMem, u32 size)
|
|||
switch (gs.imageTransfer)
|
||||
{
|
||||
case 0:
|
||||
ZeroGS::TransferHostLocal(pMem, len * 4);
|
||||
TransferHostLocal(pMem, len * 4);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
@ -176,11 +175,11 @@ template<int index> void _GSgifTransfer(const u32 *pMem, u32 size)
|
|||
// a GIFtag operation. They're an entirely separate process that can only be
|
||||
// done through the ReverseFIFO transfer (aka ReadFIFO). --air
|
||||
assert(0);
|
||||
//ZeroGS::TransferLocalHost(pMem, len);
|
||||
//TransferLocalHost(pMem, len);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
//ZeroGS::TransferLocalLocal();
|
||||
//TransferLocalLocal();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
#ifndef GIFTRANSFER_H_INCLUDED
|
||||
#define GIFTRANSFER_H_INCLUDED
|
||||
|
||||
#include "Util.h"
|
||||
#include "GS.h"
|
||||
#include "Regs.h"
|
||||
#include "Util.h"
|
||||
|
||||
enum GIF_FLG
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,114 @@
|
|||
/* ZZ Open GL graphics plugin
|
||||
* Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
|
||||
* Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef HOSTMEMORY_H_INCLUDED
|
||||
#define HOSTMEMORY_H_INCLUDED
|
||||
|
||||
#include "GLWin.h"
|
||||
|
||||
#define MEMORY_END 0x00400000
|
||||
|
||||
extern int GPU_TEXWIDTH;
|
||||
|
||||
extern u8* g_pBasePS2Mem;
|
||||
extern u8* g_pbyGSMemory;
|
||||
|
||||
class GSMemory
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
void destroy();
|
||||
u8* get();
|
||||
u8* get(u32 addr);
|
||||
u8* get_raw(u32 addr);
|
||||
};
|
||||
|
||||
extern u8* g_pbyGSClut; // the temporary clut buffer
|
||||
|
||||
class GSClut
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
void destroy();
|
||||
u8* get();
|
||||
u8* get(u32 addr);
|
||||
u8* get_raw(u32 addr);
|
||||
};
|
||||
|
||||
class ZeroGSInit
|
||||
{
|
||||
|
||||
public:
|
||||
ZeroGSInit()
|
||||
{
|
||||
const u32 mem_size = MEMORY_END + 0x10000; // leave some room for out of range accesses (saves on the checks)
|
||||
// clear
|
||||
g_pbyGSMemory = (u8*)_aligned_malloc(mem_size, 1024);
|
||||
memset(g_pbyGSMemory, 0, mem_size);
|
||||
|
||||
g_pbyGSClut = (u8*)_aligned_malloc(256 * 8, 1024); // need 512 alignment!
|
||||
memset(g_pbyGSClut, 0, 256*8);
|
||||
memset(&GLWin, 0, sizeof(GLWin));
|
||||
}
|
||||
|
||||
~ZeroGSInit()
|
||||
{
|
||||
_aligned_free(g_pbyGSMemory);
|
||||
g_pbyGSMemory = NULL;
|
||||
|
||||
_aligned_free(g_pbyGSClut);
|
||||
g_pbyGSClut = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
// The size in bytes of x strings (of texture).
|
||||
inline int MemorySize(int x)
|
||||
{
|
||||
return 4 * GPU_TEXWIDTH * x;
|
||||
}
|
||||
|
||||
// Return the address in memory of data block for string x.
|
||||
inline u8* MemoryAddress(int x)
|
||||
{
|
||||
return g_pbyGSMemory + MemorySize(x);
|
||||
}
|
||||
|
||||
template <u32 mult>
|
||||
inline u8* _MemoryAddress(int x)
|
||||
{
|
||||
return g_pbyGSMemory + mult * x;
|
||||
}
|
||||
|
||||
extern void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw);
|
||||
|
||||
|
||||
// called when trxdir is accessed. If host is involved, transfers memory to temp buffer byTransferBuf.
|
||||
// Otherwise performs the transfer. TODO: Perhaps divide the transfers into chunks?
|
||||
extern void InitTransferHostLocal();
|
||||
extern void TransferHostLocal(const void* pbyMem, u32 nQWordSize);
|
||||
|
||||
extern void InitTransferLocalHost();
|
||||
extern void TransferLocalHost(void* pbyMem, u32 nQWordSize);
|
||||
|
||||
extern void TransferLocalLocal();
|
||||
|
||||
extern void TerminateLocalHost();
|
||||
extern void TerminateHostLocal();
|
||||
|
||||
#endif // HOSTMEMORY_H_INCLUDED
|
|
@ -40,7 +40,7 @@ void SaveConfig()
|
|||
|
||||
fprintf(f, "mrtdepth = %hhx\n", conf.mrtdepth);
|
||||
fprintf(f, "zzoptions = %x\n", conf.zz_options._u32);
|
||||
fprintf(f, "options = %x\n", conf.hacks);
|
||||
fprintf(f, "options = %x\n", conf.hacks._u32);
|
||||
fprintf(f, "bilinear = %hhx\n", conf.bilinear);
|
||||
fprintf(f, "aliasing = %hhx\n", conf.aa);
|
||||
fprintf(f, "width = %x\n", conf.width);
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include "GS.h"
|
||||
#include "Linux.h"
|
||||
#include "zerogs.h"
|
||||
#include "GLWin.h"
|
||||
|
||||
#include <map>
|
||||
|
@ -495,7 +494,7 @@ void *SysLoadSym(void *lib, char *sym)
|
|||
{
|
||||
void *ret = dlsym(lib, sym);
|
||||
|
||||
if (ret == NULL) printf("null: %s\n", sym);
|
||||
if (ret == NULL) ZZLog::Debug_Log("null: %s", sym);
|
||||
|
||||
return dlsym(lib, sym);
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
</Build>
|
||||
<Compiler>
|
||||
<Add option="`pkg-config gtk+-2.0 --cflags`" />
|
||||
<Add option="`wx-config --version=2.8 --static=no --unicode=yes --cflags`" />
|
||||
<Add option="-Wno-format" />
|
||||
<Add option="-Wno-unused-parameter" />
|
||||
<Add option="-Wno-unused-value" />
|
||||
|
@ -106,6 +107,7 @@
|
|||
<Unit filename="../../GifTransfer.cpp" />
|
||||
<Unit filename="../../GifTransfer.h" />
|
||||
<Unit filename="../../HostMemory.cpp" />
|
||||
<Unit filename="../../HostMemory.h" />
|
||||
<Unit filename="../Conf.cpp" />
|
||||
<Unit filename="../Linux.cpp" />
|
||||
<Unit filename="../Linux.h" />
|
||||
|
@ -139,8 +141,14 @@
|
|||
<Option compile="0" />
|
||||
<Option link="0" />
|
||||
</Unit>
|
||||
<Unit filename="../../ZZClut.cpp" />
|
||||
<Unit filename="../../ZZClut.h" />
|
||||
<Unit filename="../../ZZGl.h" />
|
||||
<Unit filename="../../ZZHacks.cpp" />
|
||||
<Unit filename="../../ZZHacks.h" />
|
||||
<Unit filename="../../ZZKeyboard.cpp" />
|
||||
<Unit filename="../../ZZoglDrawing.cpp" />
|
||||
<Unit filename="../../ZZoglDrawing.h" />
|
||||
<Unit filename="../../ZZLog.cpp" />
|
||||
<Unit filename="../../ZZLog.h" />
|
||||
<Unit filename="../../ZZoglCRTC.cpp" />
|
||||
|
@ -154,7 +162,9 @@
|
|||
<Unit filename="../../ZZoglShaders.cpp" />
|
||||
<Unit filename="../../ZZoglShaders.h" />
|
||||
<Unit filename="../../ZZoglShoots.cpp" />
|
||||
<Unit filename="../../ZZoglShoots.h" />
|
||||
<Unit filename="../../ZZoglVB.cpp" />
|
||||
<Unit filename="../../ZZoglVB.h" />
|
||||
<Unit filename="../../common.h" />
|
||||
<Unit filename="../../glprocs.c">
|
||||
<Option compilerVar="CC" />
|
||||
|
|
|
@ -19,12 +19,14 @@
|
|||
|
||||
#include "GS.h"
|
||||
#include "Mem.h"
|
||||
#include "zerogs.h"
|
||||
#include "targets.h"
|
||||
#include "x86.h"
|
||||
|
||||
#include "Mem_Transmit.h"
|
||||
#include "Mem_Swizzle.h"
|
||||
#ifdef ZEROGS_SSE2
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
BLOCK m_Blocks[0x40]; // do so blocks are indexable
|
||||
|
||||
|
@ -128,8 +130,14 @@ static __forceinline const T* TransferAligningToBlocks(TransferData data, Transf
|
|||
for (int tempj = gs.trxpos.dx; tempj < alignedPt.x; tempj += data.blockwidth, pbuf += TransPitch(data.blockwidth, data.transfersize) / TSize)
|
||||
{
|
||||
u8 *temp = pstart + fun.gp(tempj, tempY, gs.dstbuf.bw) * data.blockbits / 8;
|
||||
swizzle(temp, (u8*)pbuf, TransPitch(pitch, data.transfersize), 0xffffffff);
|
||||
swizzle(temp, (u8*)pbuf, TransPitch(pitch, data.transfersize));
|
||||
}
|
||||
#ifdef ZEROGS_SSE2
|
||||
// Note: swizzle function uses some non temporal move (mm_stream) instruction.
|
||||
// store fence insures that previous store are finish before execute new one.
|
||||
_mm_sfence();
|
||||
|
||||
#endif
|
||||
|
||||
/* transfer the rest */
|
||||
if (alignedPt.x < gs.imageEndX)
|
||||
|
@ -158,8 +166,8 @@ static __forceinline int FinishTransfer(TransferData data, int nLeftOver)
|
|||
assert(gs.imageTransfer == -1 || tempY == gs.imageEndY);
|
||||
gs.imageTransfer = -1;
|
||||
/*int start, end;
|
||||
ZeroGS::GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw);
|
||||
ZeroGS::g_MemTargs.ClearRange(start, end);*/
|
||||
GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw);
|
||||
g_MemTargs.ClearRange(start, end);*/
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -42,7 +42,7 @@ typedef u32(*_readPixel)(const void* pmem, int x, int y, u32 bp, u32 bw);
|
|||
typedef u32(*_readPixel_0)(const void* pmem, int x, int y, u32 bw);
|
||||
typedef int (*_TransferHostLocal)(const void* pbyMem, u32 nQWordSize);
|
||||
typedef void (*_TransferLocalHost)(void* pbyMem, u32 nQWordSize);
|
||||
typedef void (*_SwizzleBlock)(u8 *dst, u8 *src, int pitch, u32 WriteMask);
|
||||
typedef void (*_SwizzleBlock)(u8 *dst, u8 *src, int pitch);
|
||||
|
||||
extern _getPixelAddress_0 getPixelFun_0[64];
|
||||
extern _writePixel_0 writePixelFun_0[64];
|
||||
|
|
|
@ -24,109 +24,54 @@
|
|||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
// WARNING a sfence instruction must be call after SwizzleBlock sse2 function
|
||||
|
||||
// Current port of the ASM function to intrinsic
|
||||
#define INTRINSIC_PORT_32
|
||||
#define INTRINSIC_PORT_16
|
||||
#define INTRINSIC_PORT_8
|
||||
#define INTRINSIC_PORT_4
|
||||
#ifdef ZEROGS_SSE2
|
||||
static const __aligned16 u32 mask_24b_H[4] = {0xFF000000, 0x0000FFFF, 0xFF000000, 0x0000FFFF};
|
||||
static const __aligned16 u32 mask_24b_L[4] = {0x00FFFFFF, 0x00000000, 0x00FFFFFF, 0x00000000};
|
||||
|
||||
template<bool aligned>
|
||||
__forceinline void SwizzleBlock32_sse2_I(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock32_sse2_I(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
__m128i src_0;
|
||||
__m128i src_1;
|
||||
__m128i src_2;
|
||||
__m128i src_3;
|
||||
|
||||
if (WriteMask == 0xffffffff) {
|
||||
for (int i=3 ; i >= 0 ; --i) {
|
||||
// load
|
||||
if (aligned) {
|
||||
src_0 = _mm_load_si128((__m128i*)src); // 5 4 1 0
|
||||
src_1 = _mm_load_si128((__m128i*)(src+16)); // 13 12 9 8
|
||||
src_2 = _mm_load_si128((__m128i*)(src+pitch)); // 7 6 3 2
|
||||
src_3 = _mm_load_si128((__m128i*)(src+16+pitch)); // 15 14 11 10
|
||||
} else {
|
||||
src_0 = _mm_loadu_si128((__m128i*)src); // 5 4 1 0
|
||||
src_1 = _mm_loadu_si128((__m128i*)(src+16)); // 13 12 9 8
|
||||
src_2 = _mm_loadu_si128((__m128i*)(src+pitch)); // 7 6 3 2
|
||||
src_3 = _mm_loadu_si128((__m128i*)(src+16+pitch)); // 15 14 11 10
|
||||
}
|
||||
|
||||
// Reorder
|
||||
__m128i dst_0 = _mm_unpacklo_epi64(src_0, src_2); // 3 2 1 0
|
||||
__m128i dst_1 = _mm_unpackhi_epi64(src_0, src_2); // 7 6 5 4
|
||||
__m128i dst_2 = _mm_unpacklo_epi64(src_1, src_3); // 11 10 9 8
|
||||
__m128i dst_3 = _mm_unpackhi_epi64(src_1, src_3); // 15 14 13 12
|
||||
|
||||
// store
|
||||
_mm_stream_si128((__m128i*)dst, dst_0);
|
||||
_mm_stream_si128(((__m128i*)dst)+1, dst_1);
|
||||
_mm_stream_si128(((__m128i*)dst)+2, dst_2);
|
||||
_mm_stream_si128(((__m128i*)dst)+3, dst_3);
|
||||
|
||||
// update the pointer
|
||||
dst += 64;
|
||||
src += 2*pitch;
|
||||
for (int i=3 ; i >= 0 ; --i) {
|
||||
// load
|
||||
if (aligned) {
|
||||
src_0 = _mm_load_si128((__m128i*)src); // 5 4 1 0
|
||||
src_1 = _mm_load_si128((__m128i*)(src+16)); // 13 12 9 8
|
||||
src_2 = _mm_load_si128((__m128i*)(src+pitch)); // 7 6 3 2
|
||||
src_3 = _mm_load_si128((__m128i*)(src+16+pitch)); // 15 14 11 10
|
||||
} else {
|
||||
src_0 = _mm_loadu_si128((__m128i*)src); // 5 4 1 0
|
||||
src_1 = _mm_loadu_si128((__m128i*)(src+16)); // 13 12 9 8
|
||||
src_2 = _mm_loadu_si128((__m128i*)(src+pitch)); // 7 6 3 2
|
||||
src_3 = _mm_loadu_si128((__m128i*)(src+16+pitch)); // 15 14 11 10
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Build the mask (tranform a u32 to a 4 packets u32)
|
||||
__m128i mask = _mm_cvtsi32_si128(WriteMask);
|
||||
mask = _mm_shuffle_epi32(mask, 0);
|
||||
|
||||
for (int i=3 ; i >= 0 ; --i) {
|
||||
// load
|
||||
if (aligned) {
|
||||
src_0 = _mm_load_si128((__m128i*)src); // 5 4 1 0
|
||||
src_1 = _mm_load_si128((__m128i*)(src+16)); // 13 12 9 8
|
||||
src_2 = _mm_load_si128((__m128i*)(src+pitch)); // 7 6 3 2
|
||||
src_3 = _mm_load_si128((__m128i*)(src+16+pitch)); // 15 14 11 10
|
||||
} else {
|
||||
src_0 = _mm_loadu_si128((__m128i*)src); // 5 4 1 0
|
||||
src_1 = _mm_loadu_si128((__m128i*)(src+16)); // 13 12 9 8
|
||||
src_2 = _mm_loadu_si128((__m128i*)(src+pitch)); // 7 6 3 2
|
||||
src_3 = _mm_loadu_si128((__m128i*)(src+16+pitch)); // 15 14 11 10
|
||||
}
|
||||
// Reorder
|
||||
__m128i dst_0 = _mm_unpacklo_epi64(src_0, src_2); // 3 2 1 0
|
||||
__m128i dst_1 = _mm_unpackhi_epi64(src_0, src_2); // 7 6 5 4
|
||||
__m128i dst_2 = _mm_unpacklo_epi64(src_1, src_3); // 11 10 9 8
|
||||
__m128i dst_3 = _mm_unpackhi_epi64(src_1, src_3); // 15 14 13 12
|
||||
|
||||
// Apply the WriteMask before reordering
|
||||
src_0 = _mm_and_si128(src_0, mask);
|
||||
src_1 = _mm_and_si128(src_1, mask);
|
||||
src_2 = _mm_and_si128(src_2, mask);
|
||||
src_3 = _mm_and_si128(src_3, mask);
|
||||
// store
|
||||
_mm_stream_si128((__m128i*)dst, dst_0);
|
||||
_mm_stream_si128(((__m128i*)dst)+1, dst_1);
|
||||
_mm_stream_si128(((__m128i*)dst)+2, dst_2);
|
||||
_mm_stream_si128(((__m128i*)dst)+3, dst_3);
|
||||
|
||||
// Reorder
|
||||
__m128i dst_0 = _mm_unpacklo_epi64(src_0, src_2); // 3 2 1 0
|
||||
__m128i dst_1 = _mm_unpackhi_epi64(src_0, src_2); // 7 6 5 4
|
||||
__m128i dst_2 = _mm_unpacklo_epi64(src_1, src_3); // 11 10 9 8
|
||||
__m128i dst_3 = _mm_unpackhi_epi64(src_1, src_3); // 15 14 13 12
|
||||
|
||||
// Load previous value and apply the ~mask
|
||||
__m128i old_dst_0 = _mm_andnot_si128(mask, _mm_load_si128((__m128i*)dst));
|
||||
__m128i old_dst_1 = _mm_andnot_si128(mask, _mm_load_si128(((__m128i*)dst)+1));
|
||||
__m128i old_dst_2 = _mm_andnot_si128(mask, _mm_load_si128(((__m128i*)dst)+2));
|
||||
__m128i old_dst_3 = _mm_andnot_si128(mask, _mm_load_si128(((__m128i*)dst)+3));
|
||||
|
||||
// Build the final value
|
||||
dst_0 = _mm_or_si128(dst_0, old_dst_0);
|
||||
dst_1 = _mm_or_si128(dst_1, old_dst_1);
|
||||
dst_2 = _mm_or_si128(dst_2, old_dst_2);
|
||||
dst_3 = _mm_or_si128(dst_3, old_dst_3);
|
||||
|
||||
// store
|
||||
_mm_stream_si128((__m128i*)dst, dst_0);
|
||||
_mm_stream_si128(((__m128i*)dst)+1, dst_1);
|
||||
_mm_stream_si128(((__m128i*)dst)+2, dst_2);
|
||||
_mm_stream_si128(((__m128i*)dst)+3, dst_3);
|
||||
|
||||
// update the pointer
|
||||
dst += 64;
|
||||
src += 2*pitch;
|
||||
}
|
||||
}
|
||||
// FIXME normally you must use a sfence but it would impact perf to do here
|
||||
// the function is in a loop and it would have a better place after the loop...
|
||||
// update the pointer
|
||||
dst += 64;
|
||||
src += 2*pitch;
|
||||
}
|
||||
}
|
||||
|
||||
template<bool aligned>
|
||||
|
@ -173,8 +118,6 @@ __forceinline void SwizzleBlock16_sse2_I(u8 *dst, u8 *src, int pitch)
|
|||
dst += 64;
|
||||
src += 2*pitch;
|
||||
}
|
||||
// FIXME normally you must use a sfence but it would impact perf to do here
|
||||
// the function is in a loop and it would have a better place after the loop...
|
||||
}
|
||||
|
||||
// Template the code to improve reuse of code
|
||||
|
@ -256,9 +199,6 @@ __forceinline void SwizzleBlock8_sse2_I(u8 *dst, u8 *src, int pitch)
|
|||
dst += 64;
|
||||
src += 4*pitch;
|
||||
SwizzleColumn8_sse2_I<aligned, 3>(dst, src, pitch);
|
||||
|
||||
// FIXME normally you must use a sfence but it would impact perf to do here
|
||||
// the function is in a loop and it would have a better place after the loop...
|
||||
}
|
||||
|
||||
// Template the code to improve reuse of code
|
||||
|
@ -372,130 +312,310 @@ __forceinline void SwizzleBlock4_sse2_I(u8 *dst, u8 *src, int pitch)
|
|||
dst += 64;
|
||||
src += 4*pitch;
|
||||
SwizzleColumn4_sse2_I<aligned, 3>(dst, src, pitch);
|
||||
|
||||
// FIXME normally you must use a sfence but it would impact perf to do here
|
||||
// the function is in a loop and it would have a better place after the loop...
|
||||
}
|
||||
#endif
|
||||
|
||||
template<bool FOUR_BIT, bool UPPER>
|
||||
__forceinline void SwizzleBlock8H_4H(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
__m128i zero_128 = _mm_setzero_si128();
|
||||
__m128i src_0;
|
||||
__m128i src_1;
|
||||
__m128i src_2;
|
||||
__m128i src_3;
|
||||
__m128i src_0_init_H;
|
||||
__m128i src_0_init_L;
|
||||
__m128i src_2_init_H;
|
||||
__m128i src_2_init_L;
|
||||
__m128i src_0_init;
|
||||
__m128i src_2_init;
|
||||
|
||||
__m128i upper_mask = _mm_cvtsi32_si128(0xF0F0F0F0);
|
||||
// Build the write_mask (tranform a u32 to a 4 packets u32)
|
||||
__m128i write_mask;
|
||||
if (FOUR_BIT) {
|
||||
if (UPPER) write_mask = _mm_cvtsi32_si128(0xF0000000);
|
||||
else write_mask = _mm_cvtsi32_si128(0x0F000000);
|
||||
} else {
|
||||
write_mask = _mm_cvtsi32_si128(0xFF000000);
|
||||
}
|
||||
write_mask = _mm_shuffle_epi32(write_mask, 0);
|
||||
|
||||
for (int i=3 ; i >= 0 ; --i) {
|
||||
if (FOUR_BIT) {
|
||||
src_0_init = _mm_cvtsi32_si128(*(u32*)src);
|
||||
src_2_init = _mm_cvtsi32_si128(*(u32*)(src + pitch));
|
||||
} else {
|
||||
src_0_init = _mm_loadl_epi64((__m128i*)src);
|
||||
src_2_init = _mm_loadl_epi64((__m128i*)(src + pitch));
|
||||
}
|
||||
|
||||
// Convert to 8 bits
|
||||
if (FOUR_BIT) {
|
||||
src_0_init_H = _mm_and_si128(upper_mask, src_0_init);
|
||||
src_0_init_L = _mm_andnot_si128(upper_mask, src_0_init);
|
||||
src_2_init_H = _mm_and_si128(upper_mask, src_2_init);
|
||||
src_2_init_L = _mm_andnot_si128(upper_mask, src_2_init);
|
||||
|
||||
if (UPPER) {
|
||||
src_0_init_L = _mm_slli_epi32(src_0_init_L, 4);
|
||||
src_2_init_L = _mm_slli_epi32(src_2_init_L, 4);
|
||||
} else {
|
||||
src_0_init_H = _mm_srli_epi32(src_0_init_H, 4);
|
||||
src_2_init_H = _mm_srli_epi32(src_2_init_H, 4);
|
||||
}
|
||||
|
||||
// Repack the src to keep HByte order
|
||||
src_0_init = _mm_unpacklo_epi8(src_0_init_L, src_0_init_H);
|
||||
src_2_init = _mm_unpacklo_epi8(src_2_init_L, src_2_init_H);
|
||||
}
|
||||
|
||||
// transform to 16 bits (add 0 in low bits)
|
||||
src_0_init = _mm_unpacklo_epi8(zero_128, src_0_init);
|
||||
src_2_init = _mm_unpacklo_epi8(zero_128, src_2_init);
|
||||
|
||||
// transform to 32 bits (add 0 in low bits)
|
||||
src_0 = _mm_unpacklo_epi16(zero_128, src_0_init);
|
||||
src_1 = _mm_unpackhi_epi16(zero_128, src_0_init);
|
||||
src_2 = _mm_unpacklo_epi16(zero_128, src_2_init);
|
||||
src_3 = _mm_unpackhi_epi16(zero_128, src_2_init);
|
||||
|
||||
// Reorder the data (same as 32 bits format)
|
||||
__m128i dst_0 = _mm_unpacklo_epi64(src_0, src_2);
|
||||
__m128i dst_1 = _mm_unpackhi_epi64(src_0, src_2);
|
||||
__m128i dst_2 = _mm_unpacklo_epi64(src_1, src_3);
|
||||
__m128i dst_3 = _mm_unpackhi_epi64(src_1, src_3);
|
||||
|
||||
// Load previous value and apply the ~write_mask
|
||||
__m128i old_dst_0 = _mm_andnot_si128(write_mask, _mm_load_si128((__m128i*)dst));
|
||||
dst_0 = _mm_or_si128(dst_0, old_dst_0);
|
||||
|
||||
__m128i old_dst_1 = _mm_andnot_si128(write_mask, _mm_load_si128(((__m128i*)dst)+1));
|
||||
dst_1 = _mm_or_si128(dst_1, old_dst_1);
|
||||
|
||||
__m128i old_dst_2 = _mm_andnot_si128(write_mask, _mm_load_si128(((__m128i*)dst)+2));
|
||||
dst_2 = _mm_or_si128(dst_2, old_dst_2);
|
||||
|
||||
__m128i old_dst_3 = _mm_andnot_si128(write_mask, _mm_load_si128(((__m128i*)dst)+3));
|
||||
dst_3 = _mm_or_si128(dst_3, old_dst_3);
|
||||
|
||||
// store
|
||||
_mm_stream_si128((__m128i*)dst, dst_0);
|
||||
_mm_stream_si128(((__m128i*)dst)+1, dst_1);
|
||||
_mm_stream_si128(((__m128i*)dst)+2, dst_2);
|
||||
_mm_stream_si128(((__m128i*)dst)+3, dst_3);
|
||||
|
||||
// update the pointer
|
||||
dst += 64;
|
||||
src += 2*pitch;
|
||||
}
|
||||
}
|
||||
|
||||
// special swizzle macros - which I converted to functions.
|
||||
#ifdef ZEROGS_SSE2
|
||||
|
||||
__forceinline void SwizzleBlock32(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock32(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
#ifdef INTRINSIC_PORT_32
|
||||
SwizzleBlock32_sse2_I<true>(dst, src, pitch, WriteMask);
|
||||
#else
|
||||
SwizzleBlock32_sse2(dst, src, pitch, WriteMask);
|
||||
#endif
|
||||
SwizzleBlock32_sse2_I<true>(dst, src, pitch);
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock16(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock24(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
__m128i mask_H = _mm_load_si128((__m128i*)mask_24b_H);
|
||||
__m128i mask_L = _mm_load_si128((__m128i*)mask_24b_L);
|
||||
// Build the write_mask (tranform a u32 to a 4 packets u32)
|
||||
__m128i write_mask = _mm_cvtsi32_si128(0x00FFFFFF);
|
||||
write_mask = _mm_shuffle_epi32(write_mask, 0);
|
||||
|
||||
for (int i=3 ; i >= 0 ; --i) {
|
||||
// Note src can be out of bound of GS memory (but there is some spare allocation
|
||||
// to avoid a tricky corner case)
|
||||
__m128i src_0 = _mm_loadu_si128((__m128i*)src);
|
||||
__m128i src_1 = _mm_loadu_si128((__m128i*)(src+12));
|
||||
__m128i src_2 = _mm_loadu_si128((__m128i*)(src+pitch));
|
||||
__m128i src_3 = _mm_loadu_si128((__m128i*)(src+pitch+12));
|
||||
|
||||
// transform 24 bits value to 32 bits one
|
||||
// 1/ Align a little the data
|
||||
src_0 = _mm_slli_si128(src_0, 2);
|
||||
src_0 = _mm_shufflelo_epi16(src_0, 0x39);
|
||||
|
||||
src_1 = _mm_slli_si128(src_1, 2);
|
||||
src_1 = _mm_shufflelo_epi16(src_1, 0x39);
|
||||
|
||||
src_2 = _mm_slli_si128(src_2, 2);
|
||||
src_2 = _mm_shufflelo_epi16(src_2, 0x39);
|
||||
|
||||
src_3 = _mm_slli_si128(src_3, 2);
|
||||
src_3 = _mm_shufflelo_epi16(src_3, 0x39);
|
||||
|
||||
// 2/ Filter the 24 bits pixels & do the conversion
|
||||
__m128i src_0_H = _mm_and_si128(src_0, mask_H);
|
||||
__m128i src_0_L = _mm_and_si128(src_0, mask_L);
|
||||
src_0_H = _mm_slli_si128(src_0_H, 1);
|
||||
src_0 = _mm_or_si128(src_0_H, src_0_L);
|
||||
|
||||
__m128i src_1_H = _mm_and_si128(src_1, mask_H);
|
||||
__m128i src_1_L = _mm_and_si128(src_1, mask_L);
|
||||
src_1_H = _mm_slli_si128(src_1_H, 1);
|
||||
src_1 = _mm_or_si128(src_1_H, src_1_L);
|
||||
|
||||
__m128i src_2_H = _mm_and_si128(src_2, mask_H);
|
||||
__m128i src_2_L = _mm_and_si128(src_2, mask_L);
|
||||
src_2_H = _mm_slli_si128(src_2_H, 1);
|
||||
src_2 = _mm_or_si128(src_2_H, src_2_L);
|
||||
|
||||
__m128i src_3_H = _mm_and_si128(src_3, mask_H);
|
||||
__m128i src_3_L = _mm_and_si128(src_3, mask_L);
|
||||
src_3_H = _mm_slli_si128(src_3_H, 1);
|
||||
src_3 = _mm_or_si128(src_3_H, src_3_L);
|
||||
|
||||
// Reorder the data (same as 32 bits format)
|
||||
__m128i dst_0 = _mm_unpacklo_epi64(src_0, src_2);
|
||||
__m128i dst_1 = _mm_unpackhi_epi64(src_0, src_2);
|
||||
__m128i dst_2 = _mm_unpacklo_epi64(src_1, src_3);
|
||||
__m128i dst_3 = _mm_unpackhi_epi64(src_1, src_3);
|
||||
|
||||
// Load previous value and apply the ~write_mask
|
||||
__m128i old_dst_0 = _mm_andnot_si128(write_mask, _mm_load_si128((__m128i*)dst));
|
||||
dst_0 = _mm_or_si128(dst_0, old_dst_0);
|
||||
|
||||
__m128i old_dst_1 = _mm_andnot_si128(write_mask, _mm_load_si128(((__m128i*)dst)+1));
|
||||
dst_1 = _mm_or_si128(dst_1, old_dst_1);
|
||||
|
||||
__m128i old_dst_2 = _mm_andnot_si128(write_mask, _mm_load_si128(((__m128i*)dst)+2));
|
||||
dst_2 = _mm_or_si128(dst_2, old_dst_2);
|
||||
|
||||
__m128i old_dst_3 = _mm_andnot_si128(write_mask, _mm_load_si128(((__m128i*)dst)+3));
|
||||
dst_3 = _mm_or_si128(dst_3, old_dst_3);
|
||||
|
||||
// store
|
||||
_mm_stream_si128((__m128i*)dst, dst_0);
|
||||
_mm_stream_si128(((__m128i*)dst)+1, dst_1);
|
||||
_mm_stream_si128(((__m128i*)dst)+2, dst_2);
|
||||
_mm_stream_si128(((__m128i*)dst)+3, dst_3);
|
||||
|
||||
// update the pointer
|
||||
dst += 64;
|
||||
src += 2*pitch;
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock16(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
#ifdef INTRINSIC_PORT_16
|
||||
SwizzleBlock16_sse2_I<true>(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock16_sse2_I<true>(dst, src, pitch);
|
||||
#else
|
||||
SwizzleBlock16_sse2(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock16_sse2(dst, src, pitch);
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock8(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock8(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
#ifdef INTRINSIC_PORT_8
|
||||
SwizzleBlock8_sse2_I<true>(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock8_sse2_I<true>(dst, src, pitch);
|
||||
#else
|
||||
SwizzleBlock8_sse2(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock8_sse2(dst, src, pitch);
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock4(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock4(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
#ifdef INTRINSIC_PORT_4
|
||||
SwizzleBlock4_sse2_I<true>(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock4_sse2_I<true>(dst, src, pitch);
|
||||
#else
|
||||
SwizzleBlock4_sse2(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock4_sse2(dst, src, pitch);
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock32u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock32u(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
#ifdef INTRINSIC_PORT_32
|
||||
SwizzleBlock32_sse2_I<false>(dst, src, pitch, WriteMask);
|
||||
#else
|
||||
SwizzleBlock32u_sse2(dst, src, pitch, WriteMask);
|
||||
#endif
|
||||
SwizzleBlock32_sse2_I<false>(dst, src, pitch);
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock16u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock16u(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
#ifdef INTRINSIC_PORT_16
|
||||
SwizzleBlock16_sse2_I<false>(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock16_sse2_I<false>(dst, src, pitch);
|
||||
#else
|
||||
SwizzleBlock16u_sse2(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock16u_sse2(dst, src, pitch);
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock8u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock8u(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
#ifdef INTRINSIC_PORT_8
|
||||
SwizzleBlock8_sse2_I<false>(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock8_sse2_I<false>(dst, src, pitch);
|
||||
#else
|
||||
SwizzleBlock8u_sse2(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock8u_sse2(dst, src, pitch);
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock4u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock4u(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
#ifdef INTRINSIC_PORT_4
|
||||
SwizzleBlock4_sse2_I<false>(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock4_sse2_I<false>(dst, src, pitch);
|
||||
#else
|
||||
SwizzleBlock4u_sse2(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock4u_sse2(dst, src, pitch);
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock8H(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
SwizzleBlock8H_4H<false, false>(dst, src, pitch);
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock4HH(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
SwizzleBlock8H_4H<true, true>(dst, src, pitch);
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock4HL(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
SwizzleBlock8H_4H<true, false>(dst, src, pitch);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
__forceinline void SwizzleBlock32(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock32(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
SwizzleBlock32_c(dst, src, pitch, WriteMask);
|
||||
SwizzleBlock32_c(dst, src, pitch);
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock16(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock16(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
SwizzleBlock16_c(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock16_c(dst, src, pitch);
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock8(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock8(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
SwizzleBlock8_c(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock8_c(dst, src, pitch);
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock4(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock4(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
SwizzleBlock4_c(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock4_c(dst, src, pitch);
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock32u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock32u(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
SwizzleBlock32_c(dst, src, pitch, WriteMask);
|
||||
SwizzleBlock32_c(dst, src, pitch);
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock16u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock16u(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
SwizzleBlock16_c(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock16_c(dst, src, pitch);
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock8u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock8u(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
SwizzleBlock8_c(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock8_c(dst, src, pitch);
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock4u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock4u(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
SwizzleBlock4_c(dst, src, pitch/*, WriteMask*/);
|
||||
SwizzleBlock4_c(dst, src, pitch);
|
||||
}
|
||||
|
||||
__forceinline void __fastcall SwizzleBlock32_c(u8* dst, u8* src, int srcpitch, u32 WriteMask)
|
||||
__forceinline void __fastcall SwizzleBlock32_mask(u8* dst, u8* src, int srcpitch, u32 WriteMask)
|
||||
{
|
||||
u32* d = &g_columnTable32[0][0];
|
||||
|
||||
|
@ -513,26 +633,12 @@ __forceinline void __fastcall SwizzleBlock32_c(u8* dst, u8* src, int srcpitch, u
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
__forceinline void __fastcall SwizzleBlock24_c(u8* dst, u8* src, int srcpitch, u32 WriteMask)
|
||||
__forceinline void __fastcall SwizzleBlock32_c(u8* dst, u8* src, int srcpitch)
|
||||
{
|
||||
u32* d = &g_columnTable32[0][0];
|
||||
|
||||
if (WriteMask == 0x00ffffff)
|
||||
{
|
||||
for (int j = 0; j < 8; j++, d += 8, src += srcpitch)
|
||||
for (int i = 0; i < 8; i++)
|
||||
((u32*)dst)[d[i]] = ((u32*)src)[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < 8; j++, d += 8, src += srcpitch)
|
||||
for (int i = 0; i < 8; i++)
|
||||
((u32*)dst)[d[i]] = (((u32*)dst)[d[i]] & ~WriteMask) | (((u32*)src)[i] & WriteMask);
|
||||
}
|
||||
SwizzleBlock32_mask(dst, src, srcpitch, 0xffffffff);
|
||||
}
|
||||
|
||||
__forceinline void __fastcall SwizzleBlock16_c(u8* dst, u8* src, int srcpitch, u32 WriteMask)
|
||||
__forceinline void __fastcall SwizzleBlock16_c(u8* dst, u8* src, int srcpitch)
|
||||
{
|
||||
u32* d = &g_columnTable16[0][0];
|
||||
|
||||
|
@ -541,7 +647,7 @@ __forceinline void __fastcall SwizzleBlock16_c(u8* dst, u8* src, int srcpitch, u
|
|||
((u16*)dst)[d[i]] = ((u16*)src)[i];
|
||||
}
|
||||
|
||||
__forceinline void __fastcall SwizzleBlock8_c(u8* dst, u8* src, int srcpitch, u32 WriteMask)
|
||||
__forceinline void __fastcall SwizzleBlock8_c(u8* dst, u8* src, int srcpitch)
|
||||
{
|
||||
u32* d = &g_columnTable8[0][0];
|
||||
|
||||
|
@ -550,7 +656,7 @@ __forceinline void __fastcall SwizzleBlock8_c(u8* dst, u8* src, int srcpitch, u3
|
|||
dst[d[i]] = src[i];
|
||||
}
|
||||
|
||||
__forceinline void __fastcall SwizzleBlock4_c(u8* dst, u8* src, int srcpitch, u32 WriteMask)
|
||||
__forceinline void __fastcall SwizzleBlock4_c(u8* dst, u8* src, int srcpitch)
|
||||
{
|
||||
u32* d = &g_columnTable4[0][0];
|
||||
|
||||
|
@ -566,13 +672,14 @@ __forceinline void __fastcall SwizzleBlock4_c(u8* dst, u8* src, int srcpitch, u3
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
__forceinline void SwizzleBlock24(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock24(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
u8* pnewsrc = src;
|
||||
u32* pblock = tempblock;
|
||||
|
||||
for (int by = 0; by < 7; ++by, pblock += 8, pnewsrc += pitch - 24)
|
||||
// Note src can be out of bound of GS memory (but there is some spare allocation
|
||||
// to avoid a tricky corner case)
|
||||
for (int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch - 24)
|
||||
{
|
||||
for (int bx = 0; bx < 8; ++bx, pnewsrc += 3)
|
||||
{
|
||||
|
@ -580,23 +687,10 @@ __forceinline void SwizzleBlock24(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
|||
}
|
||||
}
|
||||
|
||||
for (int bx = 0; bx < 7; ++bx, pnewsrc += 3)
|
||||
{
|
||||
/* might be 1 byte out of bounds of GS memory */
|
||||
pblock[bx] = *(u32*)pnewsrc;
|
||||
}
|
||||
|
||||
/* do 3 bytes for the last copy */
|
||||
*((u8*)pblock + 28) = pnewsrc[0];
|
||||
|
||||
*((u8*)pblock + 29) = pnewsrc[1];
|
||||
|
||||
*((u8*)pblock + 30) = pnewsrc[2];
|
||||
|
||||
SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0x00ffffff);
|
||||
SwizzleBlock32_mask((u8*)dst, (u8*)tempblock, 32, 0x00ffffff);
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock8H(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock8H(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
u8* pnewsrc = src;
|
||||
u32* pblock = tempblock;
|
||||
|
@ -615,10 +709,10 @@ __forceinline void SwizzleBlock8H(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
|||
pblock[7] = u;
|
||||
}
|
||||
|
||||
SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0xff000000);
|
||||
SwizzleBlock32_mask((u8*)dst, (u8*)tempblock, 32, 0xff000000);
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock4HH(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock4HH(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
u8* pnewsrc = src;
|
||||
u32* pblock = tempblock;
|
||||
|
@ -636,10 +730,10 @@ __forceinline void SwizzleBlock4HH(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
|||
pblock[7] = u;
|
||||
}
|
||||
|
||||
SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0xf0000000);
|
||||
SwizzleBlock32_mask((u8*)dst, (u8*)tempblock, 32, 0xf0000000);
|
||||
}
|
||||
|
||||
__forceinline void SwizzleBlock4HL(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
||||
__forceinline void SwizzleBlock4HL(u8 *dst, u8 *src, int pitch)
|
||||
{
|
||||
u8* pnewsrc = src;
|
||||
u32* pblock = tempblock;
|
||||
|
@ -657,6 +751,6 @@ __forceinline void SwizzleBlock4HL(u8 *dst, u8 *src, int pitch, u32 WriteMask)
|
|||
pblock[7] = u >> 4;
|
||||
}
|
||||
|
||||
SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0x0f000000);
|
||||
SwizzleBlock32_mask((u8*)dst, (u8*)tempblock, 32, 0x0f000000);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,26 +24,25 @@
|
|||
#include "Mem.h"
|
||||
#include "x86.h"
|
||||
|
||||
extern __forceinline void SwizzleBlock32(u8 *dst, u8 *src, int pitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void SwizzleBlock16(u8 *dst, u8 *src, int pitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void SwizzleBlock8(u8 *dst, u8 *src, int pitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void SwizzleBlock4(u8 *dst, u8 *src, int pitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void SwizzleBlock32u(u8 *dst, u8 *src, int pitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void SwizzleBlock16u(u8 *dst, u8 *src, int pitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void SwizzleBlock8u(u8 *dst, u8 *src, int pitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void SwizzleBlock4u(u8 *dst, u8 *src, int pitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void SwizzleBlock32(u8 *dst, u8 *src, int pitch);
|
||||
extern __forceinline void SwizzleBlock16(u8 *dst, u8 *src, int pitch);
|
||||
extern __forceinline void SwizzleBlock8(u8 *dst, u8 *src, int pitch);
|
||||
extern __forceinline void SwizzleBlock4(u8 *dst, u8 *src, int pitch);
|
||||
extern __forceinline void SwizzleBlock32u(u8 *dst, u8 *src, int pitch);
|
||||
extern __forceinline void SwizzleBlock16u(u8 *dst, u8 *src, int pitch);
|
||||
extern __forceinline void SwizzleBlock8u(u8 *dst, u8 *src, int pitch);
|
||||
extern __forceinline void SwizzleBlock4u(u8 *dst, u8 *src, int pitch);
|
||||
|
||||
extern __forceinline void __fastcall SwizzleBlock32_c(u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void __fastcall SwizzleBlock24_c(u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void __fastcall SwizzleBlock16_c(u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void __fastcall SwizzleBlock8_c(u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void __fastcall SwizzleBlock4_c(u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void __fastcall SwizzleBlock32_c(u8* dst, u8* src, int srcpitch);
|
||||
extern __forceinline void __fastcall SwizzleBlock16_c(u8* dst, u8* src, int srcpitch);
|
||||
extern __forceinline void __fastcall SwizzleBlock8_c(u8* dst, u8* src, int srcpitch);
|
||||
extern __forceinline void __fastcall SwizzleBlock4_c(u8* dst, u8* src, int srcpitch);
|
||||
|
||||
// special swizzle macros - which I converted to functions.
|
||||
extern __forceinline void SwizzleBlock24(u8 *dst, u8 *src, int pitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void SwizzleBlock8H(u8 *dst, u8 *src, int pitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void SwizzleBlock4HH(u8 *dst, u8 *src, int pitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void SwizzleBlock4HL(u8 *dst, u8 *src, int pitch, u32 WriteMask = 0xffffffff);
|
||||
extern __forceinline void SwizzleBlock24(u8 *dst, u8 *src, int pitch);
|
||||
extern __forceinline void SwizzleBlock8H(u8 *dst, u8 *src, int pitch);
|
||||
extern __forceinline void SwizzleBlock4HH(u8 *dst, u8 *src, int pitch);
|
||||
extern __forceinline void SwizzleBlock4HL(u8 *dst, u8 *src, int pitch);
|
||||
#define SwizzleBlock24u SwizzleBlock24
|
||||
#define SwizzleBlock8Hu SwizzleBlock8H
|
||||
#define SwizzleBlock4HHu SwizzleBlock4HH
|
||||
|
|
|
@ -22,15 +22,13 @@
|
|||
#include "NewRegs.h"
|
||||
#include "PS2Etypes.h"
|
||||
|
||||
#include "zerogs.h"
|
||||
#include "targets.h"
|
||||
|
||||
#ifdef USE_OLD_REGS
|
||||
#include "Regs.h"
|
||||
#else
|
||||
|
||||
const u32 g_primmult[8] = { 1, 2, 2, 3, 3, 3, 2, 0xff };
|
||||
const u32 g_primsub[8] = { 1, 2, 1, 3, 1, 1, 2, 0 };
|
||||
#include "ZZoglVB.h"
|
||||
#include "ZZoglDrawing.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4244)
|
||||
|
@ -46,28 +44,6 @@ u32 s_uClampData[2] = {0, };
|
|||
|
||||
//u32 results[65535] = {0, };
|
||||
|
||||
// return true if triangle SHOULD be painted.
|
||||
// My brain hurts. --arcum42
|
||||
|
||||
// return true if triangle SHOULD be painted.
|
||||
inline bool NoHighlights(int i)
|
||||
{
|
||||
// This is hack-code, I still in search of correct reason, why some triangles should not be drawn.
|
||||
|
||||
int dummy = 0;
|
||||
|
||||
u32 resultA = prim->iip + (2 * (prim->tme)) + (4 * (prim->fge)) + (8 * (prim->abe)) + (16 * (prim->aa1)) + (32 * (prim->fst)) + (64 * (prim->ctxt)) + (128 * (prim->fix));
|
||||
|
||||
const pixTest curtest = ZeroGS::vb[i].test;
|
||||
|
||||
u32 result = curtest.ate + ((curtest.atst) << 1) +((curtest.afail) << 4) + ((curtest.date) << 6) + ((curtest.datm) << 7) + ((curtest.zte) << 8) + ((curtest.ztst)<< 9);
|
||||
|
||||
if ((resultA == 0x310a) && (result == 0x0)) return false; // Radiata Stories
|
||||
|
||||
//Old code
|
||||
return (!(conf.settings().xenosaga_spec) || !ZeroGS::vb[i].zbuf.zmsk || prim->iip) ;
|
||||
}
|
||||
|
||||
void __gifCall GIFPackedRegHandlerNull(const u32* data)
|
||||
{
|
||||
FUNCLOG
|
||||
|
@ -127,24 +103,6 @@ void __gifCall GIFPackedRegHandlerUV(const u32* data)
|
|||
ZZLog::Greg_Log("Packed UV: 0x%x, 0x%x", r->U, r->V);
|
||||
}
|
||||
|
||||
void __gifCall KickVertex(bool adc)
|
||||
{
|
||||
FUNCLOG
|
||||
if (++gs.primC >= (int)g_primmult[prim->prim])
|
||||
{
|
||||
if (!adc && NoHighlights(prim->ctxt)) (*ZeroGS::drawfn[prim->prim])();
|
||||
|
||||
gs.primC -= g_primsub[prim->prim];
|
||||
|
||||
if (adc && prim->prim == 5)
|
||||
{
|
||||
/* tri fans need special processing */
|
||||
if (gs.nTriFanVert == gs.primIndex)
|
||||
gs.primIndex = gs.primNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __gifCall GIFPackedRegHandlerXYZF2(const u32* data)
|
||||
{
|
||||
FUNCLOG
|
||||
|
@ -152,7 +110,7 @@ void __gifCall GIFPackedRegHandlerXYZF2(const u32* data)
|
|||
gs.add_vertex(r->X, r->Y,r->Z, r->F);
|
||||
|
||||
// Fix Vertexes up later.
|
||||
KickVertex(!!(r->ADC));
|
||||
ZZKick->KickVertex(!!(r->ADC));
|
||||
ZZLog::Greg_Log("Packed XYZF2: 0x%x, 0x%x, 0x%x, %f", r->X, r->Y, r->Z, r->F);
|
||||
}
|
||||
|
||||
|
@ -163,7 +121,7 @@ void __gifCall GIFPackedRegHandlerXYZ2(const u32* data)
|
|||
gs.add_vertex(r->X, r->Y,r->Z);
|
||||
|
||||
// Fix Vertexes up later.
|
||||
KickVertex(!!(r->ADC));
|
||||
ZZKick->KickVertex(!!(r->ADC));
|
||||
ZZLog::Greg_Log("Packed XYZ2: 0x%x, 0x%x, 0x%x", r->X, r->Y, r->Z);
|
||||
}
|
||||
|
||||
|
@ -240,7 +198,7 @@ void __gifCall GIFRegHandlerXYZF2(const u32* data)
|
|||
GIFRegXYZF* r = (GIFRegXYZF*)(data);
|
||||
gs.add_vertex(r->X, r->Y,r->Z, r->F);
|
||||
|
||||
KickVertex(false);
|
||||
ZZKick->KickVertex(false);
|
||||
ZZLog::Greg_Log("XYZF2: 0x%x, 0x%x, 0x%x, %f", r->X, r->Y, r->Z, r->F);
|
||||
}
|
||||
|
||||
|
@ -250,7 +208,7 @@ void __gifCall GIFRegHandlerXYZ2(const u32* data)
|
|||
GIFRegXYZ* r = (GIFRegXYZ*)(data);
|
||||
gs.add_vertex(r->X, r->Y,r->Z);
|
||||
|
||||
KickVertex(false);
|
||||
ZZKick->KickVertex(false);
|
||||
ZZLog::Greg_Log("XYZF2: 0x%x, 0x%x, 0x%x", r->X, r->Y, r->Z);
|
||||
}
|
||||
|
||||
|
@ -275,22 +233,22 @@ void __gifCall GIFRegHandlerTEX0(const u32* data)
|
|||
}
|
||||
|
||||
// Order is important.
|
||||
ZeroGS::vb[i].uNextTex0Data[0] = r->ai32[0];
|
||||
ZeroGS::vb[i].uNextTex0Data[1] = r->ai32[1];
|
||||
ZeroGS::vb[i].bNeedTexCheck = 1;
|
||||
vb[i].uNextTex0Data[0] = r->ai32[0];
|
||||
vb[i].uNextTex0Data[1] = r->ai32[1];
|
||||
vb[i].bNeedTexCheck = 1;
|
||||
|
||||
// don't update unless necessary
|
||||
if (PSMT_ISCLUT(psm))
|
||||
{
|
||||
if (ZeroGS::CheckChangeInClut(data[1], psm))
|
||||
if (CheckChangeInClut(data[1], psm))
|
||||
{
|
||||
// loading clut, so flush whole texture
|
||||
ZeroGS::vb[i].FlushTexData();
|
||||
vb[i].FlushTexData();
|
||||
}
|
||||
else if (r->CSA != (ZeroGS::vb[i].uCurTex0.CSA))
|
||||
else if (r->CSA != (vb[i].uCurTex0.CSA))
|
||||
{
|
||||
// check if csa is the same!! (ffx bisaid island, grass)
|
||||
ZeroGS::Flush(i); // flush any previous entries
|
||||
Flush(i); // flush any previous entries
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -299,7 +257,7 @@ template <u32 i>
|
|||
void __gifCall GIFRegHandlerCLAMP(const u32* data)
|
||||
{
|
||||
FUNCLOG
|
||||
clampInfo& clamp = ZeroGS::vb[i].clamp;
|
||||
clampInfo& clamp = vb[i].clamp;
|
||||
GIFRegCLAMP* r = (GIFRegCLAMP*)(data);
|
||||
|
||||
// Worry about this later.
|
||||
|
@ -307,9 +265,9 @@ void __gifCall GIFRegHandlerCLAMP(const u32* data)
|
|||
|
||||
if ((s_uClampData[i] != data[0]) || (((clamp.minv >> 8) | (clamp.maxv << 2)) != (data[1]&0x0fff)))
|
||||
{
|
||||
ZeroGS::Flush(i);
|
||||
Flush(i);
|
||||
|
||||
ZeroGS::vb[i].bTexConstsSync = false;
|
||||
vb[i].bTexConstsSync = false;
|
||||
}
|
||||
|
||||
s_uClampData[i] = data[0];
|
||||
|
@ -337,7 +295,7 @@ void __gifCall GIFRegHandlerXYZF3(const u32* data)
|
|||
GIFRegXYZF* r = (GIFRegXYZF*)(data);
|
||||
gs.add_vertex(r->X, r->Y,r->Z, r->F);
|
||||
|
||||
KickVertex(true);
|
||||
ZZKick->KickVertex(true);
|
||||
ZZLog::Greg_Log("XYZF3: 0x%x, 0x%x, 0x%x, %f", r->X, r->Y, r->Z, r->F);
|
||||
}
|
||||
|
||||
|
@ -347,7 +305,7 @@ void __gifCall GIFRegHandlerXYZ3(const u32* data)
|
|||
GIFRegXYZ* r = (GIFRegXYZ*)(data);
|
||||
gs.add_vertex(r->X, r->Y,r->Z);
|
||||
|
||||
KickVertex(true);
|
||||
ZZKick->KickVertex(true);
|
||||
ZZLog::Greg_Log("XYZ3: 0x%x, 0x%x, 0x%x", r->X, r->Y, r->Z);
|
||||
}
|
||||
|
||||
|
@ -361,15 +319,15 @@ void __fastcall GIFRegHandlerTEX1(const u32* data)
|
|||
{
|
||||
FUNCLOG
|
||||
GIFRegTEX1* r = (GIFRegTEX1*)(data);
|
||||
tex1Info& tex1 = ZeroGS::vb[i].tex1;
|
||||
tex1Info& tex1 = vb[i].tex1;
|
||||
|
||||
// Worry about this later.
|
||||
if (!NoHighlights(i)) return;
|
||||
|
||||
if (conf.bilinear == 1 && (tex1.mmag != r->MMAG || tex1.mmin != r->MMIN))
|
||||
{
|
||||
ZeroGS::Flush(i);
|
||||
ZeroGS::vb[i].bVarsTexSync = false;
|
||||
Flush(i);
|
||||
vb[i].bVarsTexSync = false;
|
||||
}
|
||||
|
||||
tex1.lcm = r->LCM;
|
||||
|
@ -387,13 +345,13 @@ template <u32 i>
|
|||
void __gifCall GIFRegHandlerTEX2(const u32* data)
|
||||
{
|
||||
FUNCLOG
|
||||
tex0Info& tex0 = ZeroGS::vb[i].tex0;
|
||||
tex0Info& tex0 = vb[i].tex0;
|
||||
|
||||
ZeroGS::vb[i].FlushTexData();
|
||||
vb[i].FlushTexData();
|
||||
|
||||
u32 psm = ZZOglGet_psm_TexBitsFix(data[0]);
|
||||
|
||||
u32* s_uTex0Data = ZeroGS::vb[i].uCurTex0Data;
|
||||
u32* s_uTex0Data = vb[i].uCurTex0Data;
|
||||
|
||||
// don't update unless necessary
|
||||
// if( ZZOglGet_psm_TexBitsFix(*s_uTex0Data) == ZZOglGet_psm_TexBitsFix(data[0]) ) { // psm is the same
|
||||
|
@ -408,26 +366,26 @@ void __gifCall GIFRegHandlerTEX2(const u32* data)
|
|||
|
||||
if (tex0.cld != 0)
|
||||
{
|
||||
ZeroGS::texClutWrite(i);
|
||||
texClutWrite(i);
|
||||
// invalidate to make sure target didn't change!
|
||||
ZeroGS::vb[i].bVarsTexSync = false;
|
||||
vb[i].bVarsTexSync = false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ZeroGS::Flush(i);
|
||||
Flush(i);
|
||||
|
||||
ZeroGS::vb[i].bVarsTexSync = false;
|
||||
ZeroGS::vb[i].bTexConstsSync = false;
|
||||
vb[i].bVarsTexSync = false;
|
||||
vb[i].bTexConstsSync = false;
|
||||
|
||||
s_uTex0Data[0] = (s_uTex0Data[0] & ~0x03f00000) | (psm << 20);
|
||||
s_uTex0Data[1] = (s_uTex0Data[1] & 0x1f) | (data[1] & ~0x1f);
|
||||
|
||||
tex0.psm = ZZOglGet_psm_TexBitsFix(data[0]);
|
||||
|
||||
if (PSMT_ISCLUT(tex0.psm)) ZeroGS::CluttingForFlushedTex(&tex0, data[1], i);
|
||||
if (PSMT_ISCLUT(tex0.psm)) CluttingForFlushedTex(&tex0, data[1], i);
|
||||
ZZLog::Greg_Log("TEX2_%d: 0x%x", i, data);
|
||||
}
|
||||
|
||||
|
@ -437,8 +395,8 @@ void __gifCall GIFRegHandlerXYOFFSET(const u32* data)
|
|||
FUNCLOG
|
||||
// Affects that Mana Khemia opening dialog (when i == 0).
|
||||
GIFRegXYOFFSET* r = (GIFRegXYOFFSET*)(data);
|
||||
ZeroGS::vb[i].offset.x = r->OFX;
|
||||
ZeroGS::vb[i].offset.y = r->OFY;
|
||||
vb[i].offset.x = r->OFX;
|
||||
vb[i].offset.y = r->OFY;
|
||||
ZZLog::Greg_Log("XYOFFSET_%d: 0x%x, 0x%x", i, r->OFX, r->OFY);
|
||||
}
|
||||
|
||||
|
@ -453,16 +411,16 @@ void __gifCall GIFRegHandlerPRIM(const u32 *data)
|
|||
//ZZLog::Warn_Log("Warning: unknown bits in prim %8.8lx_%8.8lx", data[1], data[0]);
|
||||
//}
|
||||
|
||||
// Come back to this one...
|
||||
gs.nTriFanVert = gs.primIndex;
|
||||
|
||||
gs.primC = 0;
|
||||
prim->prim = r->PRIM;
|
||||
gs._prim[0].prim = r->PRIM;
|
||||
gs._prim[1].prim = r->PRIM;
|
||||
gs._prim[1]._val = (data[0] >> 3) & 0xff; // Setting the next 8 flags after prim at once.
|
||||
|
||||
ZeroGS::Prim();
|
||||
gs.new_tri_fan = !(r->PRIM ^ PRIM_TRIANGLE_FAN);
|
||||
ZZKick->DirtyValidPrevPrim();
|
||||
|
||||
Prim();
|
||||
ZZLog::Greg_Log("PRIM");
|
||||
}
|
||||
|
||||
|
@ -474,7 +432,7 @@ void __gifCall GIFRegHandlerPRMODE(const u32* data)
|
|||
// Re-examine all code dealing with PRIMs in a bit.
|
||||
gs._prim[0]._val = (data[0] >> 3) & 0xff;
|
||||
|
||||
if (gs.prac == 0) ZeroGS::Prim();
|
||||
if (gs.prac == 0) Prim();
|
||||
ZZLog::Greg_Log("PRMODE");
|
||||
}
|
||||
|
||||
|
@ -487,7 +445,7 @@ void __gifCall GIFRegHandlerPRMODECONT(const u32* data)
|
|||
gs.prac = r->AC;
|
||||
prim = &gs._prim[gs.prac];
|
||||
|
||||
ZeroGS::Prim();
|
||||
Prim();
|
||||
ZZLog::Greg_Log("PRMODECONT");
|
||||
}
|
||||
|
||||
|
@ -497,8 +455,8 @@ void __gifCall GIFRegHandlerTEXCLUT(const u32* data)
|
|||
// Affects background coloration of initial Mana Khemia dialog.
|
||||
GIFRegTEXCLUT* r = (GIFRegTEXCLUT*)(data);
|
||||
|
||||
ZeroGS::vb[0].FlushTexData();
|
||||
ZeroGS::vb[1].FlushTexData();
|
||||
vb[0].FlushTexData();
|
||||
vb[1].FlushTexData();
|
||||
|
||||
// Fixme.
|
||||
gs.clut.cbw = r->CBW << 6;
|
||||
|
@ -514,9 +472,9 @@ void __gifCall GIFRegHandlerSCANMSK(const u32* data)
|
|||
|
||||
if(r->MSK != gs.smask)
|
||||
{
|
||||
ZeroGS::FlushBoth();
|
||||
// ZeroGS::ResolveC(&ZeroGS::vb[0]);
|
||||
// ZeroGS::ResolveZ(&ZeroGS::vb[0]);
|
||||
FlushBoth();
|
||||
// ResolveC(&vb[0]);
|
||||
// ResolveZ(&vb[0]);
|
||||
}
|
||||
|
||||
gs.smask = r->MSK;
|
||||
|
@ -533,7 +491,7 @@ void __gifCall GIFRegHandlerMIPTBP1(const u32* data)
|
|||
Flush();
|
||||
}*/
|
||||
|
||||
miptbpInfo& miptbp0 = ZeroGS::vb[i].miptbp0;
|
||||
miptbpInfo& miptbp0 = vb[i].miptbp0;
|
||||
miptbp0.tbp[0] = r->TBP1;
|
||||
miptbp0.tbw[0] = r->TBW1;
|
||||
miptbp0.tbp[1] = r->TBP2;
|
||||
|
@ -550,7 +508,7 @@ void __gifCall GIFRegHandlerMIPTBP2(const u32* data)
|
|||
GIFRegMIPTBP2* r = (GIFRegMIPTBP2*)(data);
|
||||
// Yep.
|
||||
|
||||
miptbpInfo& miptbp1 = ZeroGS::vb[i].miptbp1;
|
||||
miptbpInfo& miptbp1 = vb[i].miptbp1;
|
||||
miptbp1.tbp[0] = r->TBP4;
|
||||
miptbp1.tbw[0] = r->TBW4;
|
||||
miptbp1.tbp[1] = r->TBP5;
|
||||
|
@ -568,10 +526,10 @@ void __gifCall GIFRegHandlerTEXA(const u32* data)
|
|||
|
||||
if ((r->AEM != gs.texa.aem) || (r->TA0 != gs.texa.ta[0]) || (r->TA1 != gs.texa.ta[1]))
|
||||
{
|
||||
ZeroGS::FlushBoth();
|
||||
FlushBoth();
|
||||
|
||||
ZeroGS::vb[0].bTexConstsSync = false;
|
||||
ZeroGS::vb[1].bTexConstsSync = false;
|
||||
vb[0].bTexConstsSync = false;
|
||||
vb[1].bTexConstsSync = false;
|
||||
}
|
||||
|
||||
gs.texa.aem = r->AEM;
|
||||
|
@ -589,10 +547,10 @@ void __gifCall GIFRegHandlerFOGCOL(const u32* data)
|
|||
|
||||
if (gs.fogcol != r->ai32[0])
|
||||
{
|
||||
ZeroGS::FlushBoth();
|
||||
FlushBoth();
|
||||
}
|
||||
|
||||
ZeroGS::SetFogColor(r);
|
||||
SetFogColor(r);
|
||||
gs.fogcol = r->ai32[0];
|
||||
ZZLog::Greg_Log("FOGCOL: 0x%x", r->ai32[0]);
|
||||
}
|
||||
|
@ -601,7 +559,7 @@ void __gifCall GIFRegHandlerTEXFLUSH(const u32* data)
|
|||
{
|
||||
FUNCLOG
|
||||
// GSdx doesn't even do anything here.
|
||||
ZeroGS::SetTexFlush();
|
||||
SetTexFlush();
|
||||
ZZLog::Greg_Log("TEXFLUSH");
|
||||
}
|
||||
|
||||
|
@ -610,7 +568,7 @@ void __gifCall GIFRegHandlerSCISSOR(const u32* data)
|
|||
{
|
||||
FUNCLOG
|
||||
GIFRegSCISSOR* r = (GIFRegSCISSOR*)(data);
|
||||
Rect2& scissor = ZeroGS::vb[i].scissor;
|
||||
Rect2& scissor = vb[i].scissor;
|
||||
|
||||
Rect2 newscissor;
|
||||
|
||||
|
@ -623,10 +581,10 @@ void __gifCall GIFRegHandlerSCISSOR(const u32* data)
|
|||
if (newscissor.x1 != scissor.x1 || newscissor.y1 != scissor.y1 ||
|
||||
newscissor.x0 != scissor.x0 || newscissor.y0 != scissor.y0)
|
||||
{
|
||||
ZeroGS::Flush(i);
|
||||
Flush(i);
|
||||
|
||||
// flush everything
|
||||
ZeroGS::vb[i].bNeedFrameCheck = 1;
|
||||
vb[i].bNeedFrameCheck = 1;
|
||||
}
|
||||
|
||||
scissor = newscissor;
|
||||
|
@ -663,12 +621,12 @@ void __gifCall GIFRegHandlerALPHA(const u32* data)
|
|||
if (newalpha.c == 3) newalpha.c = 0;
|
||||
if (newalpha.d == 3) newalpha.d = 0;
|
||||
|
||||
if ((newalpha.abcd != ZeroGS::vb[i].alpha.abcd) || (newalpha.fix != ZeroGS::vb[i].alpha.fix))
|
||||
if ((newalpha.abcd != vb[i].alpha.abcd) || (newalpha.fix != vb[i].alpha.fix))
|
||||
{
|
||||
ZeroGS::Flush(i);
|
||||
Flush(i);
|
||||
}
|
||||
|
||||
ZeroGS::vb[i].alpha = newalpha;
|
||||
vb[i].alpha = newalpha;
|
||||
ZZLog::Greg_Log("ALPHA%d: A:0x%x B:0x%x C:0x%x D:0x%x FIX:0x%x ", i, r->A, r->B, r->C, r->D, r->FIX);
|
||||
}
|
||||
|
||||
|
@ -682,7 +640,7 @@ void __gifCall GIFRegHandlerDIMX(const u32* data)
|
|||
|
||||
if (r->i64 != gs.dimx.i64)
|
||||
{
|
||||
ZeroGS::FlushBoth();
|
||||
FlushBoth();
|
||||
|
||||
update = true;
|
||||
}
|
||||
|
@ -703,7 +661,7 @@ void __gifCall GIFRegHandlerDTHE(const u32* data)
|
|||
|
||||
if (r->DTHE != gs.dthe)
|
||||
{
|
||||
ZeroGS::FlushBoth();
|
||||
FlushBoth();
|
||||
}
|
||||
|
||||
gs.dthe = r->DTHE;
|
||||
|
@ -717,7 +675,7 @@ void __gifCall GIFRegHandlerCOLCLAMP(const u32* data)
|
|||
|
||||
if (r->CLAMP != gs.colclamp)
|
||||
{
|
||||
ZeroGS::FlushBoth();
|
||||
FlushBoth();
|
||||
}
|
||||
|
||||
gs.colclamp = r->CLAMP;
|
||||
|
@ -728,12 +686,12 @@ template <u32 i>
|
|||
void __gifCall GIFRegHandlerTEST(const u32* data)
|
||||
{
|
||||
FUNCLOG
|
||||
pixTest* test = &ZeroGS::vb[i].test;
|
||||
pixTest* test = &vb[i].test;
|
||||
GIFRegTEST* r = (GIFRegTEST*)(data);
|
||||
|
||||
if (test->_val != r->ai32[0])
|
||||
{
|
||||
ZeroGS::Flush(i);
|
||||
Flush(i);
|
||||
}
|
||||
|
||||
test->_val = r->ai32[0];
|
||||
|
@ -747,9 +705,9 @@ void __gifCall GIFRegHandlerPABE(const u32* data)
|
|||
|
||||
if (gs.pabe != r->PABE)
|
||||
{
|
||||
ZeroGS::FlushBoth();
|
||||
// ZeroGS::SetAlphaChanged(0, GPUREG_PABE);
|
||||
// ZeroGS::SetAlphaChanged(1, GPUREG_PABE);
|
||||
FlushBoth();
|
||||
// SetAlphaChanged(0, GPUREG_PABE);
|
||||
// SetAlphaChanged(1, GPUREG_PABE);
|
||||
}
|
||||
|
||||
gs.pabe = r->PABE;
|
||||
|
@ -762,12 +720,12 @@ void __gifCall GIFRegHandlerFBA(const u32* data)
|
|||
FUNCLOG
|
||||
GIFRegFBA* r = (GIFRegFBA*)(data);
|
||||
|
||||
if (r->FBA != ZeroGS::vb[i].fba.fba)
|
||||
if (r->FBA != vb[i].fba.fba)
|
||||
{
|
||||
ZeroGS::FlushBoth();
|
||||
FlushBoth();
|
||||
}
|
||||
|
||||
ZeroGS::vb[i].fba.fba = r->FBA;
|
||||
vb[i].fba.fba = r->FBA;
|
||||
ZZLog::Greg_Log("FBA%d: 0x%x ", i, r->FBA);
|
||||
}
|
||||
|
||||
|
@ -778,7 +736,7 @@ void __gifCall GIFRegHandlerFRAME(const u32* data)
|
|||
// Affects opening dialogs, movie, and menu on Mana Khemia.
|
||||
|
||||
GIFRegFRAME* r = (GIFRegFRAME*)(data);
|
||||
frameInfo& gsfb = ZeroGS::vb[i].gsfb;
|
||||
frameInfo& gsfb = vb[i].gsfb;
|
||||
|
||||
int fbw = r->FBW * 64;
|
||||
int fbp = r->FBP * 32;
|
||||
|
@ -798,7 +756,7 @@ void __gifCall GIFRegHandlerFRAME(const u32* data)
|
|||
return;
|
||||
}
|
||||
|
||||
ZeroGS::FlushBoth();
|
||||
FlushBoth();
|
||||
if (r->FBW > 0) fbh = ZZOgl_fbh_Calc(r->FBP, r->FBW, r->PSM);
|
||||
|
||||
gsfb.fbp = fbp;
|
||||
|
@ -808,7 +766,7 @@ void __gifCall GIFRegHandlerFRAME(const u32* data)
|
|||
gsfb.fbm = ZZOglGet_fbm_FrameBitsFix(data[0], data[1]);
|
||||
|
||||
|
||||
ZeroGS::vb[i].bNeedFrameCheck = 1;
|
||||
vb[i].bNeedFrameCheck = 1;
|
||||
ZZLog::Greg_Log("FRAME_%d", i);
|
||||
}
|
||||
|
||||
|
@ -820,7 +778,7 @@ void __gifCall GIFRegHandlerZBUF(const u32* data)
|
|||
GIFRegZBUF* r = (GIFRegZBUF*)(data);
|
||||
ZZLog::Greg_Log("ZBUF_1");
|
||||
|
||||
zbufInfo& zbuf = ZeroGS::vb[i].zbuf;
|
||||
zbufInfo& zbuf = vb[i].zbuf;
|
||||
int psm = (0x30 | r->PSM);
|
||||
int zbp = r->ZBP * 32;
|
||||
|
||||
|
@ -834,17 +792,17 @@ void __gifCall GIFRegHandlerZBUF(const u32* data)
|
|||
// error detection
|
||||
if (m_Blocks[psm].bpp == 0) return;
|
||||
|
||||
ZeroGS::FlushBoth();
|
||||
FlushBoth();
|
||||
|
||||
zbuf.zbp = zbp;
|
||||
zbuf.psm = psm;
|
||||
zbuf.zmsk = r->ZMSK;
|
||||
|
||||
ZeroGS::vb[i].zprimmask = 0xffffffff;
|
||||
vb[i].zprimmask = 0xffffffff;
|
||||
|
||||
if (zbuf.psm > 0x31) ZeroGS::vb[i].zprimmask = 0xffff;
|
||||
if (zbuf.psm > 0x31) vb[i].zprimmask = 0xffff;
|
||||
|
||||
ZeroGS::vb[i].bNeedZCheck = 1;
|
||||
vb[i].bNeedZCheck = 1;
|
||||
}
|
||||
|
||||
void __gifCall GIFRegHandlerBITBLTBUF(const u32* data)
|
||||
|
@ -911,11 +869,11 @@ void __gifCall GIFRegHandlerTRXDIR(const u32* data)
|
|||
switch (gs.imageTransfer)
|
||||
{
|
||||
case 0: // host->loc
|
||||
gs.imageTransfer = -1;
|
||||
TerminateHostLocal();
|
||||
break;
|
||||
|
||||
case 1: // loc->host
|
||||
ZeroGS::TerminateLocalHost();
|
||||
TerminateLocalHost();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -932,15 +890,15 @@ void __gifCall GIFRegHandlerTRXDIR(const u32* data)
|
|||
switch (gs.imageTransfer)
|
||||
{
|
||||
case 0: // host->loc
|
||||
ZeroGS::InitTransferHostLocal();
|
||||
InitTransferHostLocal();
|
||||
break;
|
||||
|
||||
case 1: // loc->host
|
||||
ZeroGS::InitTransferLocalHost();
|
||||
InitTransferLocalHost();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ZeroGS::TransferLocalLocal();
|
||||
TransferLocalLocal();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
|
@ -967,7 +925,7 @@ void __gifCall GIFRegHandlerHWREG(const u32* data)
|
|||
|
||||
if (gs.imageTransfer == 0)
|
||||
{
|
||||
ZeroGS::TransferHostLocal(data, 2);
|
||||
TransferHostLocal(data, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -25,6 +25,7 @@
|
|||
#include <string>
|
||||
#include <map>
|
||||
#include "Profile.h"
|
||||
#include "Util.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -59,7 +60,7 @@ struct DVPROFSTRUCT
|
|||
|
||||
while (it != listpChild.end())
|
||||
{
|
||||
SAFE_DELETE(*it);
|
||||
safe_delete(*it);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,149 +1,172 @@
|
|||
/* ZZ Open GL graphics plugin
|
||||
* Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
|
||||
* Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/* ZZ Open GL graphics plugin
|
||||
* Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
|
||||
* Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef PROFILE_H_INCLUDED
|
||||
#define PROFILE_H_INCLUDED
|
||||
|
||||
#include "zerogs.h"
|
||||
|
||||
#if !defined(ZEROGS_DEVBUILD)
|
||||
#define g_bWriteProfile 0
|
||||
#else
|
||||
extern bool g_bWriteProfile;
|
||||
#endif
|
||||
|
||||
extern u64 luPerfFreq;
|
||||
|
||||
|
||||
// Copied from Utilities; remove later.
|
||||
#ifdef __LINUX__
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
static __forceinline void InitCPUTicks()
|
||||
{
|
||||
}
|
||||
|
||||
static __forceinline u64 GetTickFrequency()
|
||||
{
|
||||
return 1000000; // unix measures in microseconds
|
||||
}
|
||||
|
||||
static __forceinline u64 GetCPUTicks()
|
||||
{
|
||||
|
||||
struct timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
return ((u64)t.tv_sec*GetTickFrequency()) + t.tv_usec;
|
||||
}
|
||||
|
||||
#else
|
||||
static __aligned16 LARGE_INTEGER lfreq;
|
||||
|
||||
static __forceinline void InitCPUTicks()
|
||||
{
|
||||
QueryPerformanceFrequency(&lfreq);
|
||||
}
|
||||
|
||||
static __forceinline u64 GetTickFrequency()
|
||||
{
|
||||
return lfreq.QuadPart;
|
||||
}
|
||||
|
||||
static __forceinline u64 GetCPUTicks()
|
||||
{
|
||||
LARGE_INTEGER count;
|
||||
QueryPerformanceCounter(&count);
|
||||
return count.QuadPart;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// IMPORTANT: For every Register there must be an End
|
||||
void DVProfRegister(char* pname); // first checks if this profiler exists in g_listProfilers
|
||||
void DVProfEnd(u32 dwUserData);
|
||||
void DVProfWrite(char* pfilename, u32 frames = 0);
|
||||
void DVProfClear(); // clears all the profilers
|
||||
|
||||
#define DVPROFILE
|
||||
#ifdef DVPROFILE
|
||||
|
||||
class DVProfileFunc
|
||||
{
|
||||
public:
|
||||
u32 dwUserData;
|
||||
DVProfileFunc(char* pname) { DVProfRegister(pname); dwUserData = 0; }
|
||||
DVProfileFunc(char* pname, u32 dwUserData) : dwUserData(dwUserData) { DVProfRegister(pname); }
|
||||
~DVProfileFunc() { DVProfEnd(dwUserData); }
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class DVProfileFunc
|
||||
{
|
||||
|
||||
public:
|
||||
u32 dwUserData;
|
||||
static __forceinline DVProfileFunc(char* pname) {}
|
||||
static __forceinline DVProfileFunc(char* pname, u32 dwUserData) { }
|
||||
~DVProfileFunc() {}
|
||||
};
|
||||
|
||||
#define PROFILE_H_INCLUDED
|
||||
|
||||
#include "Util.h"
|
||||
|
||||
#if !defined(ZEROGS_DEVBUILD)
|
||||
#define g_bWriteProfile 0
|
||||
#else
|
||||
extern bool g_bWriteProfile;
|
||||
#endif
|
||||
|
||||
|
||||
template <typename T>
|
||||
class CInterfacePtr
|
||||
{
|
||||
|
||||
public:
|
||||
inline CInterfacePtr() : ptr(NULL) {}
|
||||
inline explicit CInterfacePtr(T* newptr) : ptr(newptr) { if (ptr != NULL) ptr->AddRef(); }
|
||||
inline ~CInterfacePtr() { if (ptr != NULL) ptr->Release(); }
|
||||
inline T* operator*() { assert(ptr != NULL); return *ptr; }
|
||||
inline T* operator->() { return ptr; }
|
||||
inline T* get() { return ptr; }
|
||||
|
||||
inline void release()
|
||||
{
|
||||
if (ptr != NULL) { ptr->Release(); ptr = NULL; }
|
||||
}
|
||||
|
||||
inline operator T*() { return ptr; }
|
||||
inline bool operator==(T* rhs) { return ptr == rhs; }
|
||||
inline bool operator!=(T* rhs) { return ptr != rhs; }
|
||||
|
||||
inline CInterfacePtr& operator= (T* newptr)
|
||||
{
|
||||
if (ptr != NULL) ptr->Release();
|
||||
|
||||
ptr = newptr;
|
||||
|
||||
if (ptr != NULL) ptr->AddRef();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
T* ptr;
|
||||
};
|
||||
|
||||
extern void InitProfile();
|
||||
|
||||
extern u64 luPerfFreq;
|
||||
|
||||
|
||||
// Copied from Utilities; remove later.
|
||||
#ifdef __LINUX__
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/timeb.h> // ftime(), struct timeb
|
||||
|
||||
inline unsigned long timeGetTime()
|
||||
{
|
||||
timeb t;
|
||||
ftime(&t);
|
||||
|
||||
return (unsigned long)(t.time*1000 + t.millitm);
|
||||
}
|
||||
|
||||
inline unsigned long timeGetPreciseTime()
|
||||
{
|
||||
timespec t;
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t);
|
||||
|
||||
return t.tv_nsec;
|
||||
}
|
||||
|
||||
static __forceinline void InitCPUTicks()
|
||||
{
|
||||
}
|
||||
|
||||
static __forceinline u64 GetTickFrequency()
|
||||
{
|
||||
return 1000000; // unix measures in microseconds
|
||||
}
|
||||
|
||||
static __forceinline u64 GetCPUTicks()
|
||||
{
|
||||
|
||||
struct timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
return ((u64)t.tv_sec*GetTickFrequency()) + t.tv_usec;
|
||||
}
|
||||
|
||||
#else
|
||||
static __aligned16 LARGE_INTEGER lfreq;
|
||||
|
||||
inline unsigned long timeGetPreciseTime()
|
||||
{
|
||||
// Implement later.
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __forceinline void InitCPUTicks()
|
||||
{
|
||||
QueryPerformanceFrequency(&lfreq);
|
||||
}
|
||||
|
||||
static __forceinline u64 GetTickFrequency()
|
||||
{
|
||||
return lfreq.QuadPart;
|
||||
}
|
||||
|
||||
static __forceinline u64 GetCPUTicks()
|
||||
{
|
||||
LARGE_INTEGER count;
|
||||
QueryPerformanceCounter(&count);
|
||||
return count.QuadPart;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// IMPORTANT: For every Register there must be an End
|
||||
void DVProfRegister(char* pname); // first checks if this profiler exists in g_listProfilers
|
||||
void DVProfEnd(u32 dwUserData);
|
||||
void DVProfWrite(char* pfilename, u32 frames = 0);
|
||||
void DVProfClear(); // clears all the profilers
|
||||
|
||||
#define DVPROFILE
|
||||
#ifdef DVPROFILE
|
||||
|
||||
class DVProfileFunc
|
||||
{
|
||||
public:
|
||||
u32 dwUserData;
|
||||
DVProfileFunc(char* pname) { DVProfRegister(pname); dwUserData = 0; }
|
||||
DVProfileFunc(char* pname, u32 dwUserData) : dwUserData(dwUserData) { DVProfRegister(pname); }
|
||||
~DVProfileFunc() { DVProfEnd(dwUserData); }
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class DVProfileFunc
|
||||
{
|
||||
|
||||
public:
|
||||
u32 dwUserData;
|
||||
static __forceinline DVProfileFunc(char* pname) {}
|
||||
static __forceinline DVProfileFunc(char* pname, u32 dwUserData) { }
|
||||
~DVProfileFunc() {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
template <typename T>
|
||||
class CInterfacePtr
|
||||
{
|
||||
|
||||
public:
|
||||
inline CInterfacePtr() : ptr(NULL) {}
|
||||
inline explicit CInterfacePtr(T* newptr) : ptr(newptr) { if (ptr != NULL) ptr->AddRef(); }
|
||||
inline ~CInterfacePtr() { if (ptr != NULL) ptr->Release(); }
|
||||
inline T* operator*() { assert(ptr != NULL); return *ptr; }
|
||||
inline T* operator->() { return ptr; }
|
||||
inline T* get() { return ptr; }
|
||||
|
||||
inline void release()
|
||||
{
|
||||
if (ptr != NULL) { ptr->Release(); ptr = NULL; }
|
||||
}
|
||||
|
||||
inline operator T*() { return ptr; }
|
||||
inline bool operator==(T* rhs) { return ptr == rhs; }
|
||||
inline bool operator!=(T* rhs) { return ptr != rhs; }
|
||||
|
||||
inline CInterfacePtr& operator= (T* newptr)
|
||||
{
|
||||
if (ptr != NULL) ptr->Release();
|
||||
|
||||
ptr = newptr;
|
||||
|
||||
if (ptr != NULL) ptr->AddRef();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
T* ptr;
|
||||
};
|
||||
|
||||
extern void InitProfile();
|
||||
|
||||
#endif // PROFILE_H_INCLUDED
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -116,13 +116,7 @@ extern FnType_GIFRegHandler GIFPackedRegHandlerXYZ2;
|
|||
extern FnType_GIFRegHandler GIFPackedRegHandlerFOG;
|
||||
extern FnType_GIFRegHandler GIFPackedRegHandlerA_D;
|
||||
extern FnType_GIFRegHandler GIFPackedRegHandlerNOP;
|
||||
|
||||
// These are unimplemented, and fall back on the non-packed versions.
|
||||
extern FnType_GIFRegHandler GIFPackedRegHandlerPRIM;
|
||||
extern FnType_GIFRegHandler GIFPackedRegHandlerTEX0_1;
|
||||
extern FnType_GIFRegHandler GIFPackedRegHandlerTEX0_2;
|
||||
extern FnType_GIFRegHandler GIFPackedRegHandlerCLAMP_1;
|
||||
extern FnType_GIFRegHandler GIFPackedRegHandlerCLAMP_2;
|
||||
extern FnType_GIFRegHandler GIFPackedRegHandlerXYZF3;
|
||||
extern FnType_GIFRegHandler GIFPackedRegHandlerXYZ3;
|
||||
|
||||
|
@ -133,47 +127,21 @@ extern FnType_GIFRegHandler GIFRegHandlerST;
|
|||
extern FnType_GIFRegHandler GIFRegHandlerUV;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerXYZF2;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerXYZ2;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTEX0_1;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTEX0_2;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerCLAMP_1;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerCLAMP_2;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerFOG;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerXYZF3;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerXYZ3;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerNOP;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTEX1_1;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTEX1_2;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTEX2_1;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTEX2_2;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerXYOFFSET_1;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerXYOFFSET_2;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerPRMODECONT;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerPRMODE;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTEXCLUT;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerSCANMSK;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerMIPTBP1_1;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerMIPTBP1_2;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerMIPTBP2_1;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerMIPTBP2_2;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTEXA;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerFOGCOL;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTEXFLUSH;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerSCISSOR_1;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerSCISSOR_2;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerALPHA_1;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerALPHA_2;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerDIMX;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerDTHE;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerCOLCLAMP;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTEST_1;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTEST_2;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerPABE;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerFBA_1;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerFBA_2;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerFRAME_1;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerFRAME_2;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerZBUF_1;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerZBUF_2;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerBITBLTBUF;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTRXPOS;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTRXREG;
|
||||
|
@ -183,8 +151,39 @@ extern FnType_GIFRegHandler GIFRegHandlerSIGNAL;
|
|||
extern FnType_GIFRegHandler GIFRegHandlerFINISH;
|
||||
extern FnType_GIFRegHandler GIFRegHandlerLABEL;
|
||||
|
||||
// GifReg & GifPackedReg structs from GSdx, slightly modified
|
||||
template<u32 ctxt>
|
||||
extern FnType_GIFRegHandler GIFPackedRegHandlerTEX0;
|
||||
template<u32 ctxt>
|
||||
extern FnType_GIFRegHandler GIFPackedRegHandlerCLAMP;
|
||||
template<u32 ctxt>
|
||||
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTEX0;
|
||||
template<u32 ctxt>
|
||||
extern FnType_GIFRegHandler GIFRegHandlerCLAMP;
|
||||
template<u32 ctxt>
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTEX1;
|
||||
template<u32 ctxt>
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTEX2;
|
||||
template<u32 ctxt>
|
||||
extern FnType_GIFRegHandler GIFRegHandlerXYOFFSET;
|
||||
template<u32 ctxt>
|
||||
extern FnType_GIFRegHandler GIFRegHandlerMIPTBP1;
|
||||
template<u32 ctxt>
|
||||
extern FnType_GIFRegHandler GIFRegHandlerMIPTBP2;
|
||||
template<u32 ctxt>
|
||||
extern FnType_GIFRegHandler GIFRegHandlerSCISSOR;
|
||||
template<u32 ctxt>
|
||||
extern FnType_GIFRegHandler GIFRegHandlerALPHA;
|
||||
template<u32 ctxt>
|
||||
extern FnType_GIFRegHandler GIFRegHandlerTEST;
|
||||
template<u32 ctxt>
|
||||
extern FnType_GIFRegHandler GIFRegHandlerFBA;
|
||||
template<u32 ctxt>
|
||||
extern FnType_GIFRegHandler GIFRegHandlerFRAME;
|
||||
template<u32 ctxt>
|
||||
extern FnType_GIFRegHandler GIFRegHandlerZBUF;
|
||||
|
||||
// GifReg & GifPackedReg structs from GSdx, slightly modified.
|
||||
enum GS_ATST
|
||||
{
|
||||
ATST_NEVER = 0,
|
||||
|
@ -946,6 +945,19 @@ REG_END
|
|||
extern void WriteTempRegs();
|
||||
extern void SetFrameSkip(bool skip);
|
||||
extern void ResetRegs();
|
||||
|
||||
extern void SetTexFlush();
|
||||
extern void SetFogColor(u32 fog);
|
||||
extern void SetFogColor(GIFRegFOGCOL* fog);
|
||||
extern bool CheckChangeInClut(u32 highdword, u32 psm); // returns true if clut will change after this tex0 op
|
||||
|
||||
// flush current vertices, call before setting new registers (the main render method)
|
||||
void Flush(int context);
|
||||
void FlushBoth();
|
||||
|
||||
// called on a primitive switch
|
||||
void Prim();
|
||||
|
||||
#else
|
||||
#include "NewRegs.h"
|
||||
#endif
|
||||
|
|
|
@ -23,16 +23,20 @@
|
|||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <io.h>
|
||||
#include "Utilities/RedtapeWindows.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#include "glprocs.h"
|
||||
|
||||
extern HWND GShwnd;
|
||||
|
||||
#else // linux basic definitions
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
|
@ -41,9 +45,11 @@ extern HWND GShwnd;
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
#define GSdefs
|
||||
#include "PS2Edefs.h"
|
||||
|
||||
//Pcsx2Defs is included in Dependencies.h.
|
||||
#include "Utilities/Dependencies.h"
|
||||
|
||||
#include "CRC.h"
|
||||
#include "ZZLog.h"
|
||||
|
||||
|
@ -53,75 +59,13 @@ extern "C" u32 CALLBACK PS2EgetLibVersion2(u32 type);
|
|||
extern "C" char* CALLBACK PS2EgetLibName(void);
|
||||
|
||||
#include "ZZoglMath.h"
|
||||
#include "Profile.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include "Utilities/MemcpyFast.h"
|
||||
#define memcpy_amd memcpy_fast
|
||||
|
||||
extern std::string s_strIniPath; // Air's new (r2361) new constant for ini file path
|
||||
|
||||
#if !defined(_MSC_VER) && !defined(HAVE_ALIGNED_MALLOC)
|
||||
#include <malloc.h>
|
||||
|
||||
// declare linux equivalents
|
||||
static __forceinline void* pcsx2_aligned_malloc(size_t size, size_t align)
|
||||
{
|
||||
assert(align < 0x10000);
|
||||
char* p = (char*)malloc(size + align);
|
||||
int off = 2 + align - ((int)(uptr)(p + 2) % align);
|
||||
|
||||
p += off;
|
||||
*(u16*)(p - 2) = off;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static __forceinline void pcsx2_aligned_free(void* pmem)
|
||||
{
|
||||
if (pmem != NULL)
|
||||
{
|
||||
char* p = (char*)pmem;
|
||||
free(p - (int)*(u16*)(p - 2));
|
||||
}
|
||||
}
|
||||
|
||||
#define _aligned_malloc pcsx2_aligned_malloc
|
||||
#define _aligned_free pcsx2_aligned_free
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __LINUX__
|
||||
#include <sys/timeb.h> // ftime(), struct timeb
|
||||
|
||||
inline unsigned long timeGetTime()
|
||||
{
|
||||
timeb t;
|
||||
ftime(&t);
|
||||
|
||||
return (unsigned long)(t.time*1000 + t.millitm);
|
||||
}
|
||||
|
||||
#include <time.h>
|
||||
inline unsigned long timeGetPreciseTime()
|
||||
{
|
||||
timespec t;
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t);
|
||||
|
||||
return t.tv_nsec;
|
||||
}
|
||||
|
||||
struct RECT
|
||||
{
|
||||
int left, top;
|
||||
int right, bottom;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x, y, w, h;
|
||||
|
@ -132,6 +76,11 @@ typedef struct
|
|||
int x, y;
|
||||
} Point;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int w, h;
|
||||
} Size;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x0, y0;
|
||||
|
@ -152,47 +101,6 @@ enum GSWindowDim
|
|||
GSDim_1280,
|
||||
};
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 texture_targs : 1;
|
||||
u32 auto_reset : 1;
|
||||
u32 interlace_2x : 1;
|
||||
u32 texa : 1; // apply texa to non textured polys
|
||||
u32 no_target_resolve : 1;
|
||||
u32 exact_color : 1;
|
||||
u32 no_color_clamp : 1;
|
||||
u32 ffx : 1;
|
||||
u32 no_alpha_fail : 1;
|
||||
u32 no_depth_update : 1;
|
||||
u32 quick_resolve_1 : 1;
|
||||
u32 no_quick_resolve : 1;
|
||||
u32 no_target_clut : 1; // full 16 bit resolution
|
||||
u32 no_stencil : 1;
|
||||
u32 vss_hack_off : 1; // vertical stripe syndrome
|
||||
u32 no_depth_resolve : 1;
|
||||
u32 full_16_bit_res : 1;
|
||||
u32 resolve_promoted : 1;
|
||||
u32 fast_update : 1;
|
||||
u32 no_alpha_test : 1;
|
||||
u32 disable_mrt_depth : 1;
|
||||
u32 args_32_bit : 1;
|
||||
u32 path3 : 1;
|
||||
u32 parallel_context : 1; // tries to parallelize both contexts so that render calls are reduced (xenosaga)
|
||||
// makes the game faster, but can be buggy
|
||||
u32 xenosaga_spec : 1; // xenosaga specularity hack (ignore any zmask=1 draws)
|
||||
u32 partial_pointers : 1; // whenver the texture or render target are small, tries to look for bigger ones to read from
|
||||
u32 partial_depth : 1; // tries to save depth targets as much as possible across height changes
|
||||
u32 reget : 1; // some sort of weirdness in ReGet() code
|
||||
u32 gust : 1; // Needed for Gustgames fast update.
|
||||
u32 no_logz : 1; // Intended for linux -- not logarithmic Z.
|
||||
u32 automatic_skip_draw :1; // allow debug of the automatic skip draw option
|
||||
u32 reserved2 :1;
|
||||
};
|
||||
u32 _u32;
|
||||
} gameHacks;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
|
@ -339,21 +247,7 @@ union name \
|
|||
|
||||
#define REG_SET_END };
|
||||
|
||||
#ifndef SAFE_DELETE
|
||||
# define SAFE_DELETE(x) if( (x) != NULL ) { delete (x); (x) = NULL; }
|
||||
#endif
|
||||
#ifndef SAFE_DELETE_ARRAY
|
||||
# define SAFE_DELETE_ARRAY(x) if( (x) != NULL ) { delete[] (x); (x) = NULL; }
|
||||
#endif
|
||||
#ifndef SAFE_RELEASE
|
||||
# define SAFE_RELEASE(x) if( (x) != NULL ) { (x)->Release(); (x) = NULL; }
|
||||
#endif
|
||||
|
||||
#define FORIT(it, v) for(it = (v).begin(); it != (v).end(); ++(it))
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
extern void LoadConfig();
|
||||
extern void SaveConfig();
|
||||
|
@ -366,12 +260,11 @@ extern char *SysLibError(); // Gets previous error loading sysbols
|
|||
extern void SysCloseLibrary(void *lib); // Closes Library
|
||||
extern void SysMessage(const char *fmt, ...);
|
||||
|
||||
#ifdef __LINUX__
|
||||
#include "Utilities/MemcpyFast.h"
|
||||
#define memcpy_amd memcpy_fast
|
||||
#else
|
||||
extern "C" void * memcpy_amd(void *dest, const void *src, size_t n);
|
||||
extern "C" u8 memcmp_mmx(const void *dest, const void *src, int n);
|
||||
#ifdef ZEROGS_DEVBUILD
|
||||
extern char* EFFECT_NAME;
|
||||
extern char* EFFECT_DIR;
|
||||
extern u32 g_nGenVars, g_nTexVars, g_nAlphaVars, g_nResolve;
|
||||
extern bool g_bSaveTrans, g_bUpdateEffect, g_bSaveTex, g_bSaveResolved;
|
||||
#endif
|
||||
|
||||
extern bool g_bDisplayFPS; // should we display FPS on screen?
|
||||
|
|
|
@ -351,7 +351,7 @@ BOOL AVI_Exit()
|
|||
static PAVIFILE pfile = NULL;
|
||||
static PAVISTREAM ps = NULL;
|
||||
static PAVISTREAM psCompressed = NULL;
|
||||
static int count = 0;
|
||||
static int avi_count = 0;
|
||||
|
||||
|
||||
// Initialization...
|
||||
|
@ -374,7 +374,7 @@ bool START_AVI(const char* file_name)
|
|||
|
||||
bool ADD_FRAME_FROM_DIB_TO_AVI(const char* _compressor, int _frameRate, int width, int height, int bits, void* pdata)
|
||||
{
|
||||
if(count == 0)
|
||||
if(avi_count == 0)
|
||||
{
|
||||
if(! AVI_CreateStream(pfile, &ps, _frameRate,
|
||||
width*height/bits,
|
||||
|
@ -401,7 +401,7 @@ bool ADD_FRAME_FROM_DIB_TO_AVI(const char* _compressor, int _frameRate, int widt
|
|||
}
|
||||
|
||||
HRESULT hr = AVIStreamWrite(psCompressed, // stream pointer
|
||||
count, // time of this frame
|
||||
avi_count, // time of this frame
|
||||
1, // number to write
|
||||
pdata,
|
||||
width*height/8, // lpbi->biSizeImage, // size of this frame
|
||||
|
@ -416,7 +416,7 @@ bool ADD_FRAME_FROM_DIB_TO_AVI(const char* _compressor, int _frameRate, int widt
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
count++;
|
||||
avi_count++;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -425,7 +425,7 @@ bool ADD_FRAME_FROM_DIB_TO_AVI(const char* _compressor, int _frameRate, int widt
|
|||
bool ADD_FRAME_FROM_DIB_TO_AVI(HANDLE dib, const char* _compressor, int _frameRate)
|
||||
{
|
||||
LPBITMAPINFOHEADER lpbi;
|
||||
if(count == 0)
|
||||
if(avi_count == 0)
|
||||
{
|
||||
lpbi = (LPBITMAPINFOHEADER)GlobalLock(dib);
|
||||
if(! AVI_CreateStream(pfile, &ps, _frameRate,
|
||||
|
@ -449,7 +449,7 @@ bool ADD_FRAME_FROM_DIB_TO_AVI(HANDLE dib, const char* _compressor, int _frameRa
|
|||
}
|
||||
|
||||
lpbi = (LPBITMAPINFOHEADER)GlobalLock(dib);
|
||||
if(! AVI_AddFrame(psCompressed, count * 1, lpbi))
|
||||
if(! AVI_AddFrame(psCompressed, avi_count * 1, lpbi))
|
||||
{
|
||||
//printf("Error - AVI_AddFrame()\n");
|
||||
GlobalUnlock(lpbi);
|
||||
|
@ -457,7 +457,7 @@ bool ADD_FRAME_FROM_DIB_TO_AVI(HANDLE dib, const char* _compressor, int _frameRa
|
|||
}
|
||||
|
||||
GlobalUnlock(lpbi);
|
||||
count++;
|
||||
avi_count++;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
<ClCompile Include="..\x86.cpp" />
|
||||
<ClCompile Include="..\zerogs.cpp" />
|
||||
<ClCompile Include="..\zpipe.cpp" />
|
||||
<ClCompile Include="..\ZZHacks.cpp" />
|
||||
<ClCompile Include="..\ZZKeyboard.cpp" />
|
||||
<ClCompile Include="..\ZZLog.cpp" />
|
||||
<ClCompile Include="..\ZZoglCreate.cpp" />
|
||||
|
@ -203,6 +204,7 @@
|
|||
<ClInclude Include="Win32.h" />
|
||||
<ClInclude Include="..\x86.h" />
|
||||
<ClInclude Include="..\ZZGl.h" />
|
||||
<ClInclude Include="..\ZZHacks.h" />
|
||||
<ClInclude Include="..\ZZLog.h" />
|
||||
<ClInclude Include="..\zerogs.h" />
|
||||
<ClInclude Include="..\zerogsmath.h" />
|
||||
|
|
|
@ -285,10 +285,6 @@
|
|||
RelativePath="..\Mem_Tables.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\memcpy_amd.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\NewRegs.cpp"
|
||||
>
|
||||
|
@ -356,10 +352,22 @@
|
|||
RelativePath="..\zpipe.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ZZClut.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ZZKeyboard.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ZZHacks.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ZZoglDrawing.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ZZLog.cpp"
|
||||
>
|
||||
|
@ -413,10 +421,18 @@
|
|||
RelativePath="..\GifTransfer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\GLWin.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\GS.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\HostMemory.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Mem.h"
|
||||
>
|
||||
|
@ -481,14 +497,34 @@
|
|||
RelativePath="..\zerogs.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\zpipe.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ZZClut.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ZZGl.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ZZHacks.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ZZoglDrawing.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ZZLog.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ZZoglCRTC.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ZZoglFlushHack.h"
|
||||
>
|
||||
|
@ -501,6 +537,14 @@
|
|||
RelativePath="..\ZZoglShaders.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ZZoglShoots.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ZZoglVB.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,30 @@
|
|||
/* ZZ Open GL graphics plugin
|
||||
* Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
|
||||
* Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef CLUT_H_INCLUDED
|
||||
#define CLUT_H_INCLUDED
|
||||
|
||||
extern void GSMem_to_ClutBuffer(tex0Info &tex0);
|
||||
template <class T> extern void ClutBuffer_to_Array(T* dst, u32 csa, u32 clutsize);
|
||||
template <class T> extern void Build_Clut_Texture(u32 psm, u32 height, T* pclut, u8* psrc, T* pdst);
|
||||
|
||||
template <class T> extern bool Cmp_ClutBuffer_GSMem(T* GSmem, u32 csa, u32 clutsize);
|
||||
template <class T> extern bool Cmp_ClutBuffer_SavedClut(T* saved_clut, u32 csa, u32 clutsize);
|
||||
|
||||
#endif // CLUT_H_INCLUDED
|
|
@ -1,135 +1,133 @@
|
|||
/* ZZ Open GL graphics plugin
|
||||
* Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
|
||||
* Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/* ZZ Open GL graphics plugin
|
||||
* Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
|
||||
* Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef ZZGL_H_INCLUDED
|
||||
#define ZZGL_H_INCLUDED
|
||||
|
||||
#include "PS2Etypes.h"
|
||||
#include "PS2Edefs.h"
|
||||
|
||||
// Need this before gl.h
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#include "glprocs.h"
|
||||
|
||||
#else
|
||||
|
||||
// adding glew support instead of glXGetProcAddress (thanks to scaught)
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
inline void* wglGetProcAddress(const char* x)
|
||||
{
|
||||
return (void*)glXGetProcAddress((const GLubyte*)x);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern u32 s_stencilfunc, s_stencilref, s_stencilmask;
|
||||
// Defines
|
||||
|
||||
#ifndef GL_DEPTH24_STENCIL8_EXT // allows FBOs to support stencils
|
||||
# define GL_DEPTH_STENCIL_EXT 0x84F9
|
||||
# define GL_UNSIGNED_INT_24_8_EXT 0x84FA
|
||||
# define GL_DEPTH24_STENCIL8_EXT 0x88F0
|
||||
# define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
|
||||
#endif
|
||||
|
||||
#define GL_STENCILFUNC(func, ref, mask) { \
|
||||
s_stencilfunc = func; \
|
||||
s_stencilref = ref; \
|
||||
s_stencilmask = mask; \
|
||||
glStencilFunc(func, ref, mask); \
|
||||
}
|
||||
|
||||
#define GL_STENCILFUNC_SET() glStencilFunc(s_stencilfunc, s_stencilref, s_stencilmask)
|
||||
|
||||
|
||||
// sets the data stream
|
||||
#define SET_STREAM() { \
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)8); \
|
||||
glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)12); \
|
||||
glTexCoordPointer(3, GL_FLOAT, sizeof(VertexGPU), (void*)16); \
|
||||
glVertexPointer(4, GL_SHORT, sizeof(VertexGPU), (void*)0); \
|
||||
}
|
||||
|
||||
|
||||
// global alpha blending settings
|
||||
extern GLenum g_internalRGBAFloat16Fmt;
|
||||
|
||||
extern const GLenum primtype[8];
|
||||
|
||||
#define SAFE_RELEASE_TEX(x) { if( (x) != 0 ) { glDeleteTextures(1, &(x)); x = 0; } }
|
||||
|
||||
// inline for an extremely often used sequence
|
||||
// This is turning off all gl functions. Safe to do updates.
|
||||
inline void DisableAllgl()
|
||||
{
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(0);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glColorMask(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
//--------------------- Dummies
|
||||
|
||||
#ifdef _WIN32
|
||||
extern void (__stdcall *zgsBlendEquationSeparateEXT)(GLenum, GLenum);
|
||||
extern void (__stdcall *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum);
|
||||
#else
|
||||
extern void (APIENTRY *zgsBlendEquationSeparateEXT)(GLenum, GLenum);
|
||||
extern void (APIENTRY *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum);
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------ Types -------------------------
|
||||
|
||||
/////////////////////
|
||||
// graphics resources
|
||||
extern GLenum s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha; // set by zgsBlendFuncSeparateEXT
|
||||
|
||||
// GL prototypes
|
||||
extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT;
|
||||
extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT;
|
||||
extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT;
|
||||
extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT;
|
||||
extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT;
|
||||
extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT;
|
||||
extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT;
|
||||
extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
|
||||
extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
|
||||
extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
|
||||
extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT;
|
||||
extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT;
|
||||
extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT;
|
||||
extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT;
|
||||
extern PFNGLDRAWBUFFERSPROC glDrawBuffers;
|
||||
#include "PS2Etypes.h"
|
||||
#include "PS2Edefs.h"
|
||||
|
||||
// Need this before gl.h
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#include "glprocs.h"
|
||||
|
||||
#else
|
||||
|
||||
// adding glew support instead of glXGetProcAddress (thanks to scaught)
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
inline void* wglGetProcAddress(const char* x)
|
||||
{
|
||||
return (void*)glXGetProcAddress((const GLubyte*)x);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern u32 s_stencilfunc, s_stencilref, s_stencilmask;
|
||||
// Defines
|
||||
|
||||
#ifndef GL_DEPTH24_STENCIL8_EXT // allows FBOs to support stencils
|
||||
# define GL_DEPTH_STENCIL_EXT 0x84F9
|
||||
# define GL_UNSIGNED_INT_24_8_EXT 0x84FA
|
||||
# define GL_DEPTH24_STENCIL8_EXT 0x88F0
|
||||
# define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
|
||||
#endif
|
||||
|
||||
#define GL_STENCILFUNC(func, ref, mask) { \
|
||||
s_stencilfunc = func; \
|
||||
s_stencilref = ref; \
|
||||
s_stencilmask = mask; \
|
||||
glStencilFunc(func, ref, mask); \
|
||||
}
|
||||
|
||||
#define GL_STENCILFUNC_SET() glStencilFunc(s_stencilfunc, s_stencilref, s_stencilmask)
|
||||
|
||||
|
||||
// sets the data stream
|
||||
#define SET_STREAM() { \
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)8); \
|
||||
glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)12); \
|
||||
glTexCoordPointer(3, GL_FLOAT, sizeof(VertexGPU), (void*)16); \
|
||||
glVertexPointer(4, GL_SHORT, sizeof(VertexGPU), (void*)0); \
|
||||
}
|
||||
|
||||
|
||||
// global alpha blending settings
|
||||
extern GLenum g_internalRGBAFloat16Fmt;
|
||||
|
||||
#define SAFE_RELEASE_TEX(x) { if( (x) != 0 ) { glDeleteTextures(1, &(x)); x = 0; } }
|
||||
|
||||
// inline for an extremely often used sequence
|
||||
// This is turning off all gl functions. Safe to do updates.
|
||||
inline void DisableAllgl()
|
||||
{
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(0);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glColorMask(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
//--------------------- Dummies
|
||||
|
||||
#ifdef _WIN32
|
||||
extern void (__stdcall *zgsBlendEquationSeparateEXT)(GLenum, GLenum);
|
||||
extern void (__stdcall *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum);
|
||||
#else
|
||||
extern void (APIENTRY *zgsBlendEquationSeparateEXT)(GLenum, GLenum);
|
||||
extern void (APIENTRY *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum);
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------ Types -------------------------
|
||||
|
||||
/////////////////////
|
||||
// graphics resources
|
||||
extern GLenum s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha; // set by zgsBlendFuncSeparateEXT
|
||||
|
||||
// GL prototypes
|
||||
extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT;
|
||||
extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT;
|
||||
extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT;
|
||||
extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT;
|
||||
extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT;
|
||||
extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT;
|
||||
extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT;
|
||||
extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
|
||||
extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
|
||||
extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
|
||||
extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT;
|
||||
extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT;
|
||||
extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT;
|
||||
extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT;
|
||||
extern PFNGLDRAWBUFFERSPROC glDrawBuffers;
|
||||
|
||||
#endif // ZZGL_H_INCLUDED
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
/* ZZ Open GL graphics plugin
|
||||
* Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
|
||||
* Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "Util.h"
|
||||
#include "ZZHacks.h"
|
||||
#include "ZZLog.h"
|
||||
|
||||
int CurrentHack = 0;
|
||||
|
||||
// A list of what bit controls each of the current hacks.
|
||||
u32 hackList[HACK_NUMBER] =
|
||||
{
|
||||
0, // No hack
|
||||
1, //GAME_TEXTURETARGS,
|
||||
2, //GAME_AUTORESET,
|
||||
3, //GAME_INTERLACE2X,
|
||||
4, //GAME_TEXAHACK,
|
||||
5, //GAME_NOTARGETRESOLVE,
|
||||
6, //GAME_EXACTCOLOR,
|
||||
//7 //GAME_NOCOLORCLAMP,
|
||||
//8 //GAME_FFXHACK,
|
||||
9, //GAME_NOALPHAFAIL,
|
||||
10, //GAME_NODEPTHUPDATE,
|
||||
11, //GAME_QUICKRESOLVE1,
|
||||
12, //GAME_NOQUICKRESOLVE,
|
||||
13, //GAME_NOTARGETCLUT,
|
||||
14, //GAME_NOSTENCIL,
|
||||
15, //GAME_NODEPTHRESOLVE,
|
||||
16, //GAME_FULL16BITRES,
|
||||
17, //GAME_RESOLVEPROMOTED,
|
||||
18, //GAME_FASTUPDATE,
|
||||
19, //GAME_NOALPHATEST,
|
||||
20, //GAME_DISABLEMRTDEPTH,
|
||||
//21 //GAME_32BITTARGS,
|
||||
//22 //GAME_PATH3HACK,
|
||||
//23 //GAME_DOPARALLELCTX,
|
||||
24, //GAME_XENOSPECHACK,
|
||||
//25 //GAME_PARTIALPOINTERS,
|
||||
26, //GAME_PARTIALDEPTH,
|
||||
27, //GAME_REGETHACK,
|
||||
28, //GAME_GUSTHACK,
|
||||
29, //GAME_NOLOGZ,
|
||||
30, //GAME_AUTOSKIPDRAW
|
||||
};
|
||||
|
||||
|
||||
char hackDesc[32][64] =
|
||||
{
|
||||
"No hack",
|
||||
"Texture targs",
|
||||
"Auto reset",
|
||||
"Interlace 2x",
|
||||
"Texa",
|
||||
"No target resolve",
|
||||
"Exact color",
|
||||
"No color clamp",
|
||||
"Final Fantasy X",
|
||||
"No alpha fail",
|
||||
"No depth update",
|
||||
"Quick resolve 1",
|
||||
"No Quick resolve",
|
||||
"No target clut",
|
||||
"No stencil",
|
||||
"VSS",
|
||||
"No depth resolve",
|
||||
"Full 16 bit resolution",
|
||||
"Resolve promoted",
|
||||
"Fast update",
|
||||
"No alpha test",
|
||||
"Disable mrt depth",
|
||||
"Args 32 bit",
|
||||
"",
|
||||
"Parallel context",
|
||||
"Xenosaga spec",
|
||||
"Partial pointers",
|
||||
"Partial depth",
|
||||
"Reget",
|
||||
"Gust",
|
||||
"No logz",
|
||||
"Automatic skip draw"
|
||||
};
|
||||
|
||||
struct hacks
|
||||
{
|
||||
bool enabled;
|
||||
char shortDesc[64];
|
||||
char longDesc[256];
|
||||
};
|
||||
|
||||
hacks hack_list[32] =
|
||||
{
|
||||
{ true, "No hack", "No hack" },
|
||||
{ true, "Texture targs", "Tex Target checking - 00000001\nLego Racers" },
|
||||
{ true, "Auto reset", "Auto reset targs - 00000002\nUse when game is slow and toggling AA fixes it. Samurai Warriors. (Automatically on for Shadow Hearts)" },
|
||||
{ true, "Interlace 2x", "Interlace 2X - 00000004\nFixes 2x bigger screen. Gradius 3." },
|
||||
{ false, "Texa", "" },
|
||||
{ true, "No target resolve", "No target resolves - 00000010\nStops all resolving of targets. Try this first for really slow games. (Automatically on for Dark Cloud 1.)" },
|
||||
{ true, "Exact color", "Exact color testing - 00000020\nFixes overbright or shadow/black artifacts. Crash 'n Burn." },
|
||||
{ false, "No color clamp", "No color clamping - 00000040\nSpeeds up games, but might be too bright or too dim." },
|
||||
{ false, "Final Fantasy X", "" },
|
||||
{ false, "No alpha fail", "Alpha Fail hack - 00000100\nRemove vertical stripes or other coloring artifacts. Breaks Persona 4 and MGS3. (Automatically on for Sonic Unleashed, Shadow the Hedgehog, & Ghost in the Shell.)" },
|
||||
{ true, "No depth update", "Disable depth updates - 00000200" },
|
||||
{ true, "Quick resolve 1", "Resolve Hack #1 - 00000400\n Speeds some games. Kingdom Hearts."},
|
||||
{ true, "No Quick resolve", "Resolve Hack #2 - 00000800\nShadow Hearts, Urbz. Destroys FFX."},
|
||||
{ true, "No target clut", "No target CLUT - 00001000\nResident Evil 4, or foggy scenes." },
|
||||
{ true, "No stencil", "Disable stencil buffer - 00002000\nUsually safe to do for simple scenes. Harvest Moon." },
|
||||
{ false, "VSS", "" },
|
||||
{ true, "No depth resolve", "No depth resolve - 00008000\nMight give z buffer artifacts." },
|
||||
{ true, "Full 16 bit resolution", "Full 16 bit resolution - 00010000\nUse when half the screen is missing." },
|
||||
{ true, "Resolve promoted", "Resolve Hack #3 - 00020000\nNeopets" },
|
||||
{ true, "Fast update", "Fast Update - 00040000\n Speeds some games. Needed for Sonic Unleashed. Okami." },
|
||||
{ true, "No alpha test", "Disable alpha testing - 00080000" },
|
||||
{ true, "Disable mrt depth", "Enable Multiple RTs - 00100000" },
|
||||
{ false, "Args 32 bit", "" },
|
||||
{ false, "Path3", "" },
|
||||
{ false, "Parallel context", "" },
|
||||
{ true, "Xenosaga spec", "Specular Highlights - 01000000\nMakes graphics faster by removing highlights. (Automatically on for Xenosaga, Okami, & Okage.)" },
|
||||
{ false, "Partial pointers", "Partial targets - 02000000" },
|
||||
{ true, "Partial depth", "Partial depth - 04000000" },
|
||||
{ false, "Reget", "" },
|
||||
{ true, "Gust", "Gust fix - 10000000. Makes gust games cleaner and faster. (Automatically on for most Gust games)" },
|
||||
{ true, "No logz", "No logarithmic Z - 20000000. Could decrease number of Z-artifacts." },
|
||||
{ true, "Automatic skip draw", "Remove blur effect on some games\nSlow games." }
|
||||
};
|
||||
|
||||
void ReportHacks(gameHacks hacks)
|
||||
{
|
||||
for(int i = 0; i < 32; i++)
|
||||
{
|
||||
if (hacks._u32 & (1 << i))
|
||||
{
|
||||
ZZLog::WriteLn("'%s' hack enabled.", hackDesc[i+1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ListHacks()
|
||||
{
|
||||
if ((!conf.disableHacks) && (conf.def_hacks._u32 != 0))
|
||||
{
|
||||
ZZLog::WriteLn("Auto-enabling these hacks:");
|
||||
ReportHacks(conf.def_hacks);
|
||||
}
|
||||
|
||||
if (conf.hacks._u32 != 0)
|
||||
{
|
||||
ZZLog::WriteLn("You've manually enabled these hacks:");
|
||||
ReportHacks(conf.hacks);
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayHack(int hack)
|
||||
{
|
||||
ZZLog::WriteToScreen2("***%d %s", hack, hackDesc[hackList[hack]]);
|
||||
}
|
||||
|
||||
void ChangeCurrentHack(int hack)
|
||||
{
|
||||
FUNCLOG
|
||||
|
||||
conf.hacks._u32 &= !(hackList[CurrentHack]);
|
||||
conf.hacks._u32 |= hackList[hack];
|
||||
|
||||
DisplayHack(hack);
|
||||
|
||||
CurrentHack = hack;
|
||||
SaveConfig();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
#ifndef ZZHACKS_H_INCLUDED
|
||||
#define ZZHACKS_H_INCLUDED
|
||||
|
||||
#include "PS2Edefs.h"
|
||||
|
||||
// This is a list of the various hacks, and what bit controls them.
|
||||
// Changing these is not advised unless you know what you are doing.
|
||||
enum GAME_HACK_OPTIONS
|
||||
{
|
||||
GAME_TEXTURETARGS = 0x00000001,
|
||||
GAME_AUTORESET = 0x00000002,
|
||||
GAME_INTERLACE2X = 0x00000004,
|
||||
GAME_TEXAHACK = 0x00000008, // apply texa to non textured polys
|
||||
GAME_NOTARGETRESOLVE = 0x00000010,
|
||||
GAME_EXACTCOLOR = 0x00000020,
|
||||
GAME_NOCOLORCLAMP = 0x00000040,
|
||||
GAME_FFXHACK = 0x00000080,
|
||||
GAME_NOALPHAFAIL = 0x00000100,
|
||||
GAME_NODEPTHUPDATE = 0x00000200,
|
||||
GAME_QUICKRESOLVE1 = 0x00000400,
|
||||
GAME_NOQUICKRESOLVE = 0x00000800,
|
||||
GAME_NOTARGETCLUT = 0x00001000, // full 16 bit resolution
|
||||
GAME_NOSTENCIL = 0x00002000,
|
||||
GAME_VSSHACKOFF = 0x00004000, // vertical stripe syndrome
|
||||
GAME_NODEPTHRESOLVE = 0x00008000,
|
||||
GAME_FULL16BITRES = 0x00010000,
|
||||
GAME_RESOLVEPROMOTED = 0x00020000,
|
||||
GAME_FASTUPDATE = 0x00040000,
|
||||
GAME_NOALPHATEST = 0x00080000,
|
||||
GAME_DISABLEMRTDEPTH = 0x00100000,
|
||||
GAME_32BITTARGS = 0x00200000,
|
||||
GAME_PATH3HACK = 0x00400000,
|
||||
GAME_DOPARALLELCTX = 0x00800000, // tries to parallelize both contexts so that render calls are reduced (xenosaga)
|
||||
// makes the game faster, but can be buggy
|
||||
GAME_XENOSPECHACK = 0x01000000, // xenosaga specularity hack (ignore any zmask=1 draws)
|
||||
GAME_PARTIALPOINTERS = 0x02000000, // whenver the texture or render target are small, tries to look for bigger ones to read from
|
||||
GAME_PARTIALDEPTH = 0x04000000, // tries to save depth targets as much as possible across height changes
|
||||
GAME_REGETHACK = 0x08000000, // some sort of weirdness in ReGet() code
|
||||
GAME_GUSTHACK = 0x10000000, // Needed for Gustgames fast update.
|
||||
GAME_NOLOGZ = 0x20000000, // Intended for linux -- not logarithmic Z.
|
||||
GAME_AUTOSKIPDRAW = 0x40000000, // Remove blur effect on some games
|
||||
GAME_RESERVED_HACK = 0x80000000
|
||||
};
|
||||
|
||||
#define USEALPHATESTING (!(conf.settings().no_alpha_test))
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 texture_targs : 1;
|
||||
u32 auto_reset : 1;
|
||||
u32 interlace_2x : 1;
|
||||
u32 texa : 1; // apply texa to non textured polys
|
||||
u32 no_target_resolve : 1;
|
||||
u32 exact_color : 1;
|
||||
u32 no_color_clamp : 1;
|
||||
u32 ffx : 1;
|
||||
u32 no_alpha_fail : 1;
|
||||
u32 no_depth_update : 1;
|
||||
u32 quick_resolve_1 : 1;
|
||||
u32 no_quick_resolve : 1;
|
||||
u32 no_target_clut : 1; // full 16 bit resolution
|
||||
u32 no_stencil : 1;
|
||||
u32 vss_hack_off : 1; // vertical stripe syndrome
|
||||
u32 no_depth_resolve : 1;
|
||||
u32 full_16_bit_res : 1;
|
||||
u32 resolve_promoted : 1;
|
||||
u32 fast_update : 1;
|
||||
u32 no_alpha_test : 1;
|
||||
u32 disable_mrt_depth : 1;
|
||||
u32 args_32_bit : 1;
|
||||
u32 path3 : 1;
|
||||
u32 parallel_context : 1; // tries to parallelize both contexts so that render calls are reduced (xenosaga)
|
||||
// makes the game faster, but can be buggy
|
||||
u32 xenosaga_spec : 1; // xenosaga specularity hack (ignore any zmask=1 draws)
|
||||
u32 partial_pointers : 1; // whenver the texture or render target are small, tries to look for bigger ones to read from
|
||||
u32 partial_depth : 1; // tries to save depth targets as much as possible across height changes
|
||||
u32 reget : 1; // some sort of weirdness in ReGet() code
|
||||
u32 gust : 1; // Needed for Gustgames fast update.
|
||||
u32 no_logz : 1; // Intended for linux -- not logarithmic Z.
|
||||
u32 automatic_skip_draw :1; // allow debug of the automatic skip draw option
|
||||
u32 reserved2 :1;
|
||||
};
|
||||
u32 _u32;
|
||||
} gameHacks;
|
||||
|
||||
#define HACK_NUMBER 25
|
||||
extern u32 hackList[HACK_NUMBER];
|
||||
extern char hackDesc[32][64];
|
||||
extern int CurrentHack;
|
||||
|
||||
extern void ReportHacks(gameHacks hacks);
|
||||
extern void ListHacks();
|
||||
|
||||
extern void DisplayHack(int hack);
|
||||
extern void ChangeCurrentHack(int hack);
|
||||
|
||||
#endif // ZZHACKS_H_INCLUDED
|
|
@ -30,12 +30,12 @@ extern char *libraryName;
|
|||
extern const unsigned char zgsversion;
|
||||
extern unsigned char zgsrevision, zgsbuild, zgsminor;
|
||||
|
||||
extern u32 THR_KeyEvent; // value for passing out key events between threads
|
||||
extern bool THR_bShift, SaveStateExists;
|
||||
extern bool SaveStateExists;
|
||||
|
||||
const char* s_aa[5] = { "AA none |", "AA 2x |", "AA 4x |", "AA 8x |", "AA 16x |" };
|
||||
const char* pbilinear[] = { "off", "normal", "forced" };
|
||||
|
||||
extern void SetAA(int mode);
|
||||
|
||||
void ProcessBilinear()
|
||||
{
|
||||
|
@ -86,7 +86,7 @@ void ProcessAASetting(bool reverse)
|
|||
conf.incAA();
|
||||
|
||||
sprintf(strtitle, "anti-aliasing - %s", s_aa[conf.aa]);
|
||||
ZeroGS::SetAA(conf.aa);
|
||||
SetAA(conf.aa);
|
||||
ZZLog::WriteToScreen(strtitle);
|
||||
|
||||
SaveConfig();
|
||||
|
@ -110,75 +110,26 @@ void ProcessWireFrame()
|
|||
ZZLog::WriteToScreen(strtitle);
|
||||
}
|
||||
|
||||
typedef struct GameHackStruct
|
||||
{
|
||||
const char HackName[40];
|
||||
u32 HackMask;
|
||||
} GameHack;
|
||||
|
||||
#define HACK_NUMBER 25
|
||||
|
||||
GameHack HackinshTable[HACK_NUMBER] =
|
||||
{
|
||||
{"*** 0 No Hack", 0},
|
||||
{"*** 1 TexTargets Check", GAME_TEXTURETARGS},
|
||||
{"*** 2 Autoreset Targets", GAME_AUTORESET},
|
||||
{"*** 3 Interlace 2x", GAME_INTERLACE2X},
|
||||
{"*** 4 TexA hack", GAME_TEXAHACK},
|
||||
{"*** 5 No Target Resolve", GAME_NOTARGETRESOLVE},
|
||||
{"*** 6 Exact color", GAME_EXACTCOLOR},
|
||||
//{"***xx No color clamp", GAME_NOCOLORCLAMP},
|
||||
//{"***xx FFX hack", GAME_FFXHACK},
|
||||
{"*** 7 No Alpha Fail", GAME_NOALPHAFAIL},
|
||||
{"*** 8 No Depth Update", GAME_NODEPTHUPDATE},
|
||||
{"*** 9 Quick Resolve 1", GAME_QUICKRESOLVE1},
|
||||
{"***10 No quick resolve", GAME_NOQUICKRESOLVE},
|
||||
{"***11 Notaget clut", GAME_NOTARGETCLUT},
|
||||
{"***12 No Stencil", GAME_NOSTENCIL},
|
||||
{"***13 No Depth resolve", GAME_NODEPTHRESOLVE},
|
||||
{"***14 Full 16 bit", GAME_FULL16BITRES},
|
||||
{"***15 Resolve promoted", GAME_RESOLVEPROMOTED},
|
||||
{"***16 Fast Update", GAME_FASTUPDATE},
|
||||
{"***17 No Alpha Test", GAME_NOALPHATEST},
|
||||
{"***18 Disable MRT depth", GAME_DISABLEMRTDEPTH},
|
||||
//{"***xx 32 bit targs", GAME_32BITTARGS},
|
||||
//{"***xx Path 3 hack", GAME_PATH3HACK},
|
||||
//{"***xx Parallel calls", GAME_DOPARALLELCTX},
|
||||
{"***19 Specular highlights", GAME_XENOSPECHACK},
|
||||
//{"***xx Partial pointers", GAME_PARTIALPOINTERS},
|
||||
{"***20 Partial depth", GAME_PARTIALDEPTH},
|
||||
{"***21 Reget hack", GAME_REGETHACK},
|
||||
|
||||
{"***22 Gust hack", GAME_GUSTHACK},
|
||||
{"***23 Log-Z", GAME_NOLOGZ},
|
||||
{"***24 Auto skipdraw", GAME_AUTOSKIPDRAW}
|
||||
};
|
||||
|
||||
int CurrentHackSetting = 0;
|
||||
|
||||
void ProcessHackSetting(bool reverse)
|
||||
{
|
||||
FUNCLOG
|
||||
|
||||
// printf ("A %d\n", HackinshTable[CurrentHackSetting].HackMask);
|
||||
conf.hacks._u32 &= !(HackinshTable[CurrentHackSetting].HackMask);
|
||||
|
||||
int hack = CurrentHack;
|
||||
|
||||
if (reverse)
|
||||
{
|
||||
CurrentHackSetting--;
|
||||
hack--;
|
||||
|
||||
if (CurrentHackSetting == -1) CurrentHackSetting = HACK_NUMBER - 1;
|
||||
if (hack < 0) hack = HACK_NUMBER - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentHackSetting++;
|
||||
hack++;
|
||||
|
||||
if (CurrentHackSetting >= HACK_NUMBER) CurrentHackSetting = 0;
|
||||
if (hack >= HACK_NUMBER) hack = 0;
|
||||
}
|
||||
|
||||
conf.hacks._u32 |= HackinshTable[CurrentHackSetting].HackMask;
|
||||
|
||||
ZZLog::WriteToScreen(HackinshTable[CurrentHackSetting].HackName);
|
||||
ChangeCurrentHack(hack);
|
||||
|
||||
SaveConfig();
|
||||
}
|
||||
|
||||
|
@ -188,7 +139,7 @@ void ProcessSaveState()
|
|||
char strtitle[256];
|
||||
sprintf(strtitle, "Saving in savestate %d", CurrentSavestate);
|
||||
SaveStateExists = true;
|
||||
ZZLog::WriteToScreen(HackinshTable[CurrentHackSetting].HackName);
|
||||
if (CurrentHack != 0) DisplayHack(CurrentHack);
|
||||
}
|
||||
|
||||
void OnFKey(int key, int shift)
|
||||
|
@ -253,99 +204,3 @@ void WriteBilinear()
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void ProcessEvents()
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
ZeroMemory(&msg, sizeof(msg));
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
||||
{
|
||||
switch (msg.message)
|
||||
{
|
||||
case WM_KEYDOWN :
|
||||
int my_KeyEvent = msg.wParam;
|
||||
bool my_bShift = !!(GetKeyState(VK_SHIFT) & 0x8000);
|
||||
|
||||
switch (msg.wParam)
|
||||
{
|
||||
case VK_F5:
|
||||
case VK_F6:
|
||||
case VK_F7:
|
||||
case VK_F9:
|
||||
OnFKey(msg.wParam - VK_F1 + 1, my_bShift);
|
||||
break;
|
||||
|
||||
case VK_ESCAPE:
|
||||
|
||||
if (conf.fullscreen())
|
||||
{
|
||||
// destroy that msg
|
||||
conf.setFullscreen(false);
|
||||
ZeroGS::ChangeDeviceSize(conf.width, conf.height);
|
||||
UpdateWindow(GShwnd);
|
||||
continue; // so that msg doesn't get sent
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessage(GShwnd, WM_DESTROY, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((GetKeyState(VK_MENU) & 0x8000) && (GetKeyState(VK_RETURN) & 0x8000))
|
||||
{
|
||||
conf.zz_options.fullscreen = !conf.zz_options.fullscreen;
|
||||
|
||||
ZeroGS::SetChangeDeviceSize(
|
||||
(conf.fullscreen()) ? 1280 : conf.width,
|
||||
(conf.fullscreen()) ? 960 : conf.height);
|
||||
}
|
||||
}
|
||||
|
||||
#else // linux
|
||||
|
||||
void ProcessEvents()
|
||||
{
|
||||
FUNCLOG
|
||||
|
||||
// check resizing
|
||||
GLWin.ResizeCheck();
|
||||
|
||||
if (THR_KeyEvent) // This value was passed from GSKeyEvents which could be in another thread
|
||||
{
|
||||
int my_KeyEvent = THR_KeyEvent;
|
||||
bool my_bShift = THR_bShift;
|
||||
THR_KeyEvent = 0;
|
||||
|
||||
switch (my_KeyEvent)
|
||||
{
|
||||
case XK_F5:
|
||||
case XK_F6:
|
||||
case XK_F7:
|
||||
case XK_F9:
|
||||
OnFKey(my_KeyEvent - XK_F1 + 1, my_bShift);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // linux
|
||||
|
|
|
@ -19,9 +19,44 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include "ZZLog.h"
|
||||
#include <list>
|
||||
#include <cstring>
|
||||
|
||||
extern GSconf conf;
|
||||
|
||||
using namespace std;
|
||||
|
||||
static list<MESSAGE> listMsgs;
|
||||
|
||||
void ProcessMessages()
|
||||
{
|
||||
FUNCLOG
|
||||
|
||||
if (listMsgs.size() > 0)
|
||||
{
|
||||
int left = 25, top = 15;
|
||||
list<MESSAGE>::iterator it = listMsgs.begin();
|
||||
|
||||
while (it != listMsgs.end())
|
||||
{
|
||||
DrawText(it->str, left + 1, top + 1, 0xff000000);
|
||||
DrawText(it->str, left, top, 0xffffff30);
|
||||
top += 15;
|
||||
|
||||
if ((int)(it->dwTimeStamp - timeGetTime()) < 0)
|
||||
it = listMsgs.erase(it);
|
||||
else ++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ZZAddMessage(const char* pstr, u32 ms)
|
||||
{
|
||||
FUNCLOG
|
||||
listMsgs.push_back(MESSAGE(pstr, timeGetTime() + ms));
|
||||
ZZLog::Log("%s\n", pstr);
|
||||
}
|
||||
|
||||
namespace ZZLog
|
||||
{
|
||||
std::string s_strLogPath("logs/");
|
||||
|
@ -68,7 +103,19 @@ void SetDir(const char* dir)
|
|||
|
||||
void WriteToScreen(const char* pstr, u32 ms)
|
||||
{
|
||||
ZeroGS::AddMessage(pstr, ms);
|
||||
ZZAddMessage(pstr, ms);
|
||||
}
|
||||
|
||||
void WriteToScreen2(const char* fmt, ...)
|
||||
{
|
||||
va_list list;
|
||||
char tmp[512];
|
||||
|
||||
va_start(list, fmt);
|
||||
vsprintf(tmp, fmt, list);
|
||||
va_end(list);
|
||||
|
||||
ZZAddMessage(tmp, 5000);
|
||||
}
|
||||
|
||||
void _Message(const char *str)
|
||||
|
@ -267,7 +314,7 @@ void Dev_Log(const char *fmt, ...)
|
|||
|
||||
void Debug_Log(const char *fmt, ...)
|
||||
{
|
||||
#if _DEBUG
|
||||
#ifdef _DEBUG
|
||||
va_list list;
|
||||
|
||||
va_start(list, fmt);
|
||||
|
|
|
@ -1,193 +1,201 @@
|
|||
/* ZZ Open GL graphics plugin
|
||||
* Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
|
||||
* Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef ZZLOG_H_INCLUDED
|
||||
#define ZZLOG_H_INCLUDED
|
||||
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
//Logging for errors that are called often should have a time counter.
|
||||
#ifdef __LINUX__
|
||||
static u32 __attribute__((unused)) lasttime = 0;
|
||||
static u32 __attribute__((unused)) BigTime = 5000;
|
||||
static bool __attribute__((unused)) SPAM_PASS;
|
||||
#else
|
||||
static u32 lasttime = 0;
|
||||
static u32 BigTime = 5000;
|
||||
static bool SPAM_PASS;
|
||||
#endif
|
||||
|
||||
#define ERROR_LOG_SPAM(text) { \
|
||||
if( timeGetTime() - lasttime > BigTime ) { \
|
||||
ZZLog::Error_Log(text); \
|
||||
lasttime = timeGetTime(); \
|
||||
} \
|
||||
}
|
||||
// The same macro with one-argument substitution.
|
||||
#define ERROR_LOG_SPAMA(fmt, value) { \
|
||||
if( timeGetTime() - lasttime > BigTime ) { \
|
||||
ZZLog::Error_Log(fmt, value); \
|
||||
lasttime = timeGetTime(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ERROR_LOG_SPAM_TEST(text) {\
|
||||
if( timeGetTime() - lasttime > BigTime ) { \
|
||||
ZZLog::Error_Log(text); \
|
||||
lasttime = timeGetTime(); \
|
||||
SPAM_PASS = true; \
|
||||
} \
|
||||
else \
|
||||
SPAM_PASS = false; \
|
||||
}
|
||||
|
||||
#if DEBUG_PROF
|
||||
#define FILE_IS_IN_CHECK ((strcmp(__FILE__, "targets.cpp") == 0) || (strcmp(__FILE__, "ZZoglFlush.cpp") == 0))
|
||||
|
||||
#define FUNCLOG {\
|
||||
static bool Was_Here = false; \
|
||||
static unsigned long int waslasttime = 0; \
|
||||
if (!Was_Here && FILE_IS_IN_CHECK) { \
|
||||
Was_Here = true;\
|
||||
ZZLog::Error_Log("%s:%d %s", __FILE__, __LINE__, __func__); \
|
||||
waslasttime = timeGetTime(); \
|
||||
} \
|
||||
if (FILE_IS_IN_CHECK && (timeGetTime() - waslasttime > BigTime )) { \
|
||||
Was_Here = false; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define FUNCLOG
|
||||
#endif
|
||||
|
||||
//#define WRITE_GREG_LOGS
|
||||
//#define WRITE_PRIM_LOGS
|
||||
#if defined(_DEBUG) && !defined(ZEROGS_DEVBUILD)
|
||||
#define ZEROGS_DEVBUILD
|
||||
#endif
|
||||
|
||||
|
||||
// sends a message to output window if assert fails
|
||||
#define BMSG(x, str) { if( !(x) ) { ZZLog::Log(str); ZZLog::Log(str); } }
|
||||
#define BMSG_RETURN(x, str) { if( !(x) ) { ZZLog::Log(str); ZZLog::Log(str); return; } }
|
||||
#define BMSG_RETURNX(x, str, rtype) { if( !(x) ) { ZZLog::Log(str); ZZLog::Log(str); return (##rtype); } }
|
||||
#define B(x) { if( !(x) ) { ZZLog::Log(_#x"\n"); ZZLog::Log(#x"\n"); } }
|
||||
#define B_RETURN(x) { if( !(x) ) { ZZLog::Error_Log("%s:%d: %s", __FILE__, (u32)__LINE__, #x); return; } }
|
||||
#define B_RETURNX(x, rtype) { if( !(x) ) { ZZLog::Error_Log("%s:%d: %s", __FILE__, (u32)__LINE__, #x); return (##rtype); } }
|
||||
#define B_G(x, action) { if( !(x) ) { ZZLog::Error_Log("%s:%d: %s", __FILE__, (u32)__LINE__, #x); action; } }
|
||||
|
||||
#define GL_REPORT_ERROR() \
|
||||
{ \
|
||||
GLenum err = glGetError(); \
|
||||
if( err != GL_NO_ERROR ) \
|
||||
{ \
|
||||
ZZLog::Error_Log("%s:%d: gl error %s(0x%x)", __FILE__, (int)__LINE__, error_name(err), err); \
|
||||
ZeroGS::HandleGLError(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
# define GL_REPORT_ERRORD() \
|
||||
{ \
|
||||
GLenum err = glGetError(); \
|
||||
if( err != GL_NO_ERROR ) \
|
||||
{ \
|
||||
ZZLog::Error_Log("%s:%d: gl error %s (0x%x)", __FILE__, (int)__LINE__, error_name(err), err); \
|
||||
ZeroGS::HandleGLError(); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
# define GL_REPORT_ERRORD()
|
||||
#endif
|
||||
|
||||
|
||||
inline const char *error_name(int err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case GL_NO_ERROR:
|
||||
return "GL_NO_ERROR";
|
||||
|
||||
case GL_INVALID_ENUM:
|
||||
return "GL_INVALID_ENUM";
|
||||
|
||||
case GL_INVALID_VALUE:
|
||||
return "GL_INVALID_VALUE";
|
||||
|
||||
case GL_INVALID_OPERATION:
|
||||
return "GL_INVALID_OPERATION";
|
||||
|
||||
case GL_STACK_OVERFLOW:
|
||||
return "GL_STACK_OVERFLOW";
|
||||
|
||||
case GL_STACK_UNDERFLOW:
|
||||
return "GL_STACK_UNDERFLOW";
|
||||
|
||||
case GL_OUT_OF_MEMORY:
|
||||
return "GL_OUT_OF_MEMORY";
|
||||
|
||||
case GL_TABLE_TOO_LARGE:
|
||||
return "GL_TABLE_TOO_LARGE";
|
||||
|
||||
case GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||
return "GL_INVALID_FRAMEBUFFER_OPERATION";
|
||||
|
||||
default:
|
||||
return "Unknown GL error";
|
||||
}
|
||||
}
|
||||
|
||||
extern void __LogToConsole(const char *fmt, ...);
|
||||
|
||||
// Subset of zerogs, to avoid that whole huge header.
|
||||
namespace ZeroGS
|
||||
{
|
||||
extern void AddMessage(const char* pstr, u32 ms);
|
||||
extern void SetAA(int mode);
|
||||
extern bool Create(int width, int height);
|
||||
extern void Destroy(bool bD3D);
|
||||
extern void StartCapture();
|
||||
extern void StopCapture();
|
||||
}
|
||||
|
||||
namespace ZZLog
|
||||
{
|
||||
extern bool IsLogging();
|
||||
void SetDir(const char* dir);
|
||||
extern void Open();
|
||||
extern void Close();
|
||||
extern void Message(const char *fmt, ...);
|
||||
extern void Log(const char *fmt, ...);
|
||||
void WriteToScreen(const char* pstr, u32 ms = 5000);
|
||||
extern void WriteToConsole(const char *fmt, ...);
|
||||
extern void Print(const char *fmt, ...);
|
||||
extern void WriteLn(const char *fmt, ...);
|
||||
|
||||
extern void Greg_Log(const char *fmt, ...);
|
||||
extern void Prim_Log(const char *fmt, ...);
|
||||
extern void GS_Log(const char *fmt, ...);
|
||||
|
||||
extern void Debug_Log(const char *fmt, ...);
|
||||
extern void Dev_Log(const char *fmt, ...);
|
||||
extern void Warn_Log(const char *fmt, ...);
|
||||
extern void Error_Log(const char *fmt, ...);
|
||||
};
|
||||
|
||||
#endif // ZZLOG_H_INCLUDED
|
||||
/* ZZ Open GL graphics plugin
|
||||
* Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
|
||||
* Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef ZZLOG_H_INCLUDED
|
||||
#define ZZLOG_H_INCLUDED
|
||||
|
||||
#include "Util.h"
|
||||
#include <cstring>
|
||||
|
||||
extern void HandleGLError();
|
||||
|
||||
//Logging for errors that are called often should have a time counter.
|
||||
#ifdef __LINUX__
|
||||
static u32 __attribute__((unused)) lasttime = 0;
|
||||
static u32 __attribute__((unused)) BigTime = 5000;
|
||||
static bool __attribute__((unused)) SPAM_PASS;
|
||||
#else
|
||||
static u32 lasttime = 0;
|
||||
static u32 BigTime = 5000;
|
||||
static bool SPAM_PASS;
|
||||
#endif
|
||||
|
||||
#define ERROR_LOG_SPAM(text) { \
|
||||
if( timeGetTime() - lasttime > BigTime ) { \
|
||||
ZZLog::Error_Log(text); \
|
||||
lasttime = timeGetTime(); \
|
||||
} \
|
||||
}
|
||||
// The same macro with one-argument substitution.
|
||||
#define ERROR_LOG_SPAMA(fmt, value) { \
|
||||
if( timeGetTime() - lasttime > BigTime ) { \
|
||||
ZZLog::Error_Log(fmt, value); \
|
||||
lasttime = timeGetTime(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ERROR_LOG_SPAM_TEST(text) {\
|
||||
if( timeGetTime() - lasttime > BigTime ) { \
|
||||
ZZLog::Error_Log(text); \
|
||||
lasttime = timeGetTime(); \
|
||||
SPAM_PASS = true; \
|
||||
} \
|
||||
else \
|
||||
SPAM_PASS = false; \
|
||||
}
|
||||
|
||||
#if DEBUG_PROF
|
||||
#define FILE_IS_IN_CHECK ((strcmp(__FILE__, "targets.cpp") == 0) || (strcmp(__FILE__, "ZZoglFlush.cpp") == 0))
|
||||
|
||||
#define FUNCLOG {\
|
||||
static bool Was_Here = false; \
|
||||
static unsigned long int waslasttime = 0; \
|
||||
if (!Was_Here && FILE_IS_IN_CHECK) { \
|
||||
Was_Here = true;\
|
||||
ZZLog::Error_Log("%s:%d %s", __FILE__, __LINE__, __func__); \
|
||||
waslasttime = timeGetTime(); \
|
||||
} \
|
||||
if (FILE_IS_IN_CHECK && (timeGetTime() - waslasttime > BigTime )) { \
|
||||
Was_Here = false; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define FUNCLOG
|
||||
#endif
|
||||
|
||||
//#define WRITE_GREG_LOGS
|
||||
//#define WRITE_PRIM_LOGS
|
||||
#if defined(_DEBUG) && !defined(ZEROGS_DEVBUILD)
|
||||
#define ZEROGS_DEVBUILD
|
||||
#endif
|
||||
|
||||
|
||||
// sends a message to output window if assert fails
|
||||
#define BMSG(x, str) { if( !(x) ) { ZZLog::Log(str); ZZLog::Log(str); } }
|
||||
#define BMSG_RETURN(x, str) { if( !(x) ) { ZZLog::Log(str); ZZLog::Log(str); return; } }
|
||||
#define BMSG_RETURNX(x, str, rtype) { if( !(x) ) { ZZLog::Log(str); ZZLog::Log(str); return (##rtype); } }
|
||||
#define B(x) { if( !(x) ) { ZZLog::Log(_#x"\n"); ZZLog::Log(#x"\n"); } }
|
||||
#define B_RETURN(x) { if( !(x) ) { ZZLog::Error_Log("%s:%d: %s", __FILE__, (u32)__LINE__, #x); return; } }
|
||||
#define B_RETURNX(x, rtype) { if( !(x) ) { ZZLog::Error_Log("%s:%d: %s", __FILE__, (u32)__LINE__, #x); return (##rtype); } }
|
||||
#define B_G(x, action) { if( !(x) ) { ZZLog::Error_Log("%s:%d: %s", __FILE__, (u32)__LINE__, #x); action; } }
|
||||
|
||||
#define GL_REPORT_ERROR() \
|
||||
{ \
|
||||
GLenum err = glGetError(); \
|
||||
if( err != GL_NO_ERROR ) \
|
||||
{ \
|
||||
ZZLog::Error_Log("%s:%d: gl error %s(0x%x)", __FILE__, (int)__LINE__, error_name(err), err); \
|
||||
HandleGLError(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
# define GL_REPORT_ERRORD() \
|
||||
{ \
|
||||
GLenum err = glGetError(); \
|
||||
if( err != GL_NO_ERROR ) \
|
||||
{ \
|
||||
ZZLog::Error_Log("%s:%d: gl error %s (0x%x)", __FILE__, (int)__LINE__, error_name(err), err); \
|
||||
/* HandleGLError();*/ \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
# define GL_REPORT_ERRORD()
|
||||
#endif
|
||||
|
||||
|
||||
inline const char *error_name(int err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case GL_NO_ERROR:
|
||||
return "GL_NO_ERROR";
|
||||
|
||||
case GL_INVALID_ENUM:
|
||||
return "GL_INVALID_ENUM";
|
||||
|
||||
case GL_INVALID_VALUE:
|
||||
return "GL_INVALID_VALUE";
|
||||
|
||||
case GL_INVALID_OPERATION:
|
||||
return "GL_INVALID_OPERATION";
|
||||
|
||||
case GL_STACK_OVERFLOW:
|
||||
return "GL_STACK_OVERFLOW";
|
||||
|
||||
case GL_STACK_UNDERFLOW:
|
||||
return "GL_STACK_UNDERFLOW";
|
||||
|
||||
case GL_OUT_OF_MEMORY:
|
||||
return "GL_OUT_OF_MEMORY";
|
||||
|
||||
case GL_TABLE_TOO_LARGE:
|
||||
return "GL_TABLE_TOO_LARGE";
|
||||
|
||||
case GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||
return "GL_INVALID_FRAMEBUFFER_OPERATION";
|
||||
|
||||
default:
|
||||
return "Unknown GL error";
|
||||
}
|
||||
}
|
||||
|
||||
struct MESSAGE
|
||||
{
|
||||
MESSAGE() {}
|
||||
|
||||
MESSAGE(const char* p, u32 dw) { strcpy(str, p); dwTimeStamp = dw; }
|
||||
|
||||
char str[255];
|
||||
u32 dwTimeStamp;
|
||||
};
|
||||
|
||||
extern void DrawText(const char* pstr, int left, int top, u32 color);
|
||||
extern void __LogToConsole(const char *fmt, ...);
|
||||
|
||||
extern void ZZAddMessage(const char* pstr, u32 ms = 5000);
|
||||
extern void StartCapture();
|
||||
extern void StopCapture();
|
||||
|
||||
|
||||
namespace ZZLog
|
||||
{
|
||||
extern bool IsLogging();
|
||||
void SetDir(const char* dir);
|
||||
extern void Open();
|
||||
extern void Close();
|
||||
extern void Message(const char *fmt, ...);
|
||||
extern void Log(const char *fmt, ...);
|
||||
void WriteToScreen(const char* pstr, u32 ms = 5000);
|
||||
void WriteToScreen2(const char* pstr, ...);
|
||||
extern void WriteToConsole(const char *fmt, ...);
|
||||
extern void Print(const char *fmt, ...);
|
||||
extern void WriteLn(const char *fmt, ...);
|
||||
|
||||
extern void Greg_Log(const char *fmt, ...);
|
||||
extern void Prim_Log(const char *fmt, ...);
|
||||
extern void GS_Log(const char *fmt, ...);
|
||||
|
||||
extern void Debug_Log(const char *fmt, ...);
|
||||
extern void Dev_Log(const char *fmt, ...);
|
||||
extern void Warn_Log(const char *fmt, ...);
|
||||
extern void Error_Log(const char *fmt, ...);
|
||||
};
|
||||
|
||||
#endif // ZZLOG_H_INCLUDED
|
||||
|
|
|
@ -21,11 +21,15 @@
|
|||
// It draw picture direct on screen, so here we have interlacing and frame skipping.
|
||||
|
||||
//------------------ Includes
|
||||
#include "Util.h"
|
||||
#include "ZZoglCRTC.h"
|
||||
#include "GLWin.h"
|
||||
#include "ZZoglShaders.h"
|
||||
|
||||
using namespace ZeroGS;
|
||||
#include "ZZoglShoots.h"
|
||||
#include "ZZoglDrawing.h"
|
||||
#include "rasterfont.h" // simple font
|
||||
#include <math.h>
|
||||
#include "ZZoglVB.h"
|
||||
|
||||
//------------------ Defines
|
||||
#if !defined(ZEROGS_DEVBUILD)
|
||||
|
@ -49,28 +53,33 @@ vector<u32> s_vecTempTextures; // temporary textures, released at the end of
|
|||
extern bool g_bMakeSnapshot;
|
||||
extern string strSnapshot;
|
||||
|
||||
extern void ExtWrite();
|
||||
extern void ZZDestroy();
|
||||
extern void ChangeDeviceSize(int nNewWidth, int nNewHeight);
|
||||
|
||||
extern GLuint vboRect;
|
||||
// Adjusts vertex shader BitBltPos vector v to preserve aspect ratio. It used to emulate 4:3 or 16:9.
|
||||
void ZeroGS::AdjustTransToAspect(float4& v)
|
||||
void AdjustTransToAspect(float4& v)
|
||||
{
|
||||
double temp;
|
||||
float f;
|
||||
const float mult = 1 / 32767.0f;
|
||||
|
||||
if (conf.width * nBackbufferHeight > conf.height * nBackbufferWidth) // limited by width
|
||||
if (conf.width * GLWin.backbuffer.h > conf.height * GLWin.backbuffer.w) // limited by width
|
||||
{
|
||||
// change in ratio
|
||||
f = ((float)nBackbufferWidth / (float)conf.width) / ((float)nBackbufferHeight / (float)conf.height);
|
||||
f = ((float)GLWin.backbuffer.w / (float)conf.width) / ((float)GLWin.backbuffer.h / (float)conf.height);
|
||||
v.y *= f;
|
||||
v.w *= f;
|
||||
|
||||
// scanlines mess up when not aligned right
|
||||
v.y += (1 - (float)modf(v.y * (float)nBackbufferHeight * 0.5f + 0.05f, &temp)) * 2.0f / (float)nBackbufferHeight;
|
||||
v.w += (1 - (float)modf(v.w * (float)nBackbufferHeight * 0.5f + 0.05f, &temp)) * 2.0f / (float)nBackbufferHeight;
|
||||
v.y += (1 - (float)modf(v.y * (float)GLWin.backbuffer.h * 0.5f + 0.05f, &temp)) * 2.0f / (float)GLWin.backbuffer.h;
|
||||
v.w += (1 - (float)modf(v.w * (float)GLWin.backbuffer.h * 0.5f + 0.05f, &temp)) * 2.0f / (float)GLWin.backbuffer.h;
|
||||
}
|
||||
else // limited by height
|
||||
{
|
||||
f = ((float)nBackbufferHeight / (float)conf.height) / ((float)nBackbufferWidth / (float)conf.width);
|
||||
f -= (float)modf(f * nBackbufferWidth, &temp) / (float)nBackbufferWidth;
|
||||
f = ((float)GLWin.backbuffer.h / (float)conf.height) / ((float)GLWin.backbuffer.w / (float)conf.width);
|
||||
f -= (float)modf(f * GLWin.backbuffer.w, &temp) / (float)GLWin.backbuffer.w;
|
||||
v.x *= f;
|
||||
v.z *= f;
|
||||
}
|
||||
|
@ -139,9 +148,6 @@ inline void FrameSavingHelper()
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// g_SaveFrameNum = 0;
|
||||
// g_bSaveFlushedFrame = 1;
|
||||
}
|
||||
|
||||
// Function populated tex0Info[2] array
|
||||
|
@ -178,20 +184,11 @@ inline void FrameObtainDispinfo(u32 bInterlace, tex0Info* dispinfo)
|
|||
}
|
||||
}
|
||||
|
||||
extern bool s_bWriteDepth;
|
||||
|
||||
// Something should be done before Renderering the picture.
|
||||
inline void RenderStartHelper(u32 bInterlace)
|
||||
{
|
||||
// Crashes Final Fantasy X at startup if uncommented. --arcum42
|
||||
//#ifdef !defined(ZEROGS_DEVBUILD)
|
||||
// if(g_nRealFrame < 80 ) {
|
||||
// RenderCustom( min(1.0f, 2.0f - (float)g_nRealFrame / 40.0f) );
|
||||
//
|
||||
// if( g_nRealFrame == 79 )
|
||||
// SAFE_RELEASE_TEX(ptexLogo);
|
||||
// return;
|
||||
// }
|
||||
//#endif
|
||||
|
||||
if (conf.mrtdepth && pvs[8] == NULL)
|
||||
{
|
||||
conf.mrtdepth = 0;
|
||||
|
@ -214,7 +211,7 @@ inline void RenderStartHelper(u32 bInterlace)
|
|||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer
|
||||
|
||||
glViewport(0, 0, nBackbufferWidth, nBackbufferHeight);
|
||||
glViewport(0, 0, GLWin.backbuffer.w, GLWin.backbuffer.h);
|
||||
|
||||
// if interlace, only clear every other vsync
|
||||
if (!bInterlace)
|
||||
|
@ -634,8 +631,23 @@ inline void RenderCheckForMemory(tex0Info& texframe, list<CRenderTarget*>& listT
|
|||
DrawTriangleArray();
|
||||
}
|
||||
|
||||
extern RasterFont* font_p;
|
||||
|
||||
void DrawText(const char* pstr, int left, int top, u32 color)
|
||||
{
|
||||
FUNCLOG
|
||||
ZZshGLDisableProfile();
|
||||
|
||||
float4 v;
|
||||
v.SetColor(color);
|
||||
glColor3f(v.z, v.y, v.x);
|
||||
|
||||
font_p->printString(pstr, left * 2.0f / (float)GLWin.backbuffer.w - 1, 1 - top * 2.0f / (float)GLWin.backbuffer.h, 0);
|
||||
ZZshGLEnableProfile();
|
||||
}
|
||||
|
||||
// Put FPS counter on screen (not in window title)
|
||||
inline void AfterRenderDisplayFPS()
|
||||
inline void DisplayFPS()
|
||||
{
|
||||
char str[64];
|
||||
int left = 10, top = 15;
|
||||
|
@ -645,16 +657,8 @@ inline void AfterRenderDisplayFPS()
|
|||
DrawText(str, left, top, 0xffc0ffff);
|
||||
}
|
||||
|
||||
// Swapping buffers, so we could use another window
|
||||
inline void AfterRenderSwapBuffers()
|
||||
{
|
||||
if (glGetError() != GL_NO_ERROR) ZZLog::Debug_Log("glError before swap!");
|
||||
|
||||
GLWin.SwapGLBuffers();
|
||||
}
|
||||
|
||||
// SnapeShoot helper
|
||||
inline void AfterRenderMadeSnapshoot()
|
||||
inline void MakeSnapshot()
|
||||
{
|
||||
|
||||
if (!g_bMakeSnapshot) return;
|
||||
|
@ -666,26 +670,40 @@ inline void AfterRenderMadeSnapshoot()
|
|||
DrawText(str, left + 1, top + 1, 0xff000000);
|
||||
DrawText(str, left, top, 0xffc0ffff);
|
||||
|
||||
if (SaveRenderTarget(strSnapshot != "" ? strSnapshot.c_str() : "temp.jpg", nBackbufferWidth, -nBackbufferHeight, 0)) //(conf.options.tga_snap)?0:1) ) {
|
||||
if (SaveRenderTarget(strSnapshot != "" ? strSnapshot.c_str() : "temp.jpg", GLWin.backbuffer.w, -GLWin.backbuffer.h, 0)) //(conf.options.tga_snap)?0:1) ) {
|
||||
{
|
||||
char str[255];
|
||||
sprintf(str, "saved %s\n", strSnapshot.c_str());
|
||||
AddMessage(str, 500);
|
||||
ZZAddMessage(str, 500);
|
||||
}
|
||||
|
||||
g_bMakeSnapshot = false;
|
||||
g_bMakeSnapshot = false;
|
||||
}
|
||||
|
||||
// If needed reset
|
||||
inline void AfterRendererResizeWindow()
|
||||
// call to destroy video resources
|
||||
void ZZReset()
|
||||
{
|
||||
Reset();
|
||||
ChangeDeviceSize(s_nNewWidth, s_nNewHeight);
|
||||
s_nNewWidth = s_nNewHeight = -1;
|
||||
FUNCLOG
|
||||
s_RTs.ResolveAll();
|
||||
s_DepthRTs.ResolveAll();
|
||||
|
||||
vb[0].nCount = 0;
|
||||
vb[1].nCount = 0;
|
||||
|
||||
memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts));
|
||||
s_nLastResolveReset = 0;
|
||||
|
||||
icurctx = -1;
|
||||
g_vsprog = g_psprog = 0;
|
||||
|
||||
ZZGSStateReset();
|
||||
ZZDestroy();
|
||||
//clear_drawfn();
|
||||
if (ZZKick != NULL) delete ZZKick;
|
||||
}
|
||||
|
||||
// Put new values on statistic variable
|
||||
inline void AfterRenderCountStatistics()
|
||||
inline void CountStatistics()
|
||||
{
|
||||
if (s_nWriteDepthCount > 0)
|
||||
{
|
||||
|
@ -708,7 +726,6 @@ inline void AfterRenderCountStatistics()
|
|||
if (g_nDepthUsed > 0) --g_nDepthUsed;
|
||||
|
||||
s_ClutResolve = 0;
|
||||
|
||||
g_nDepthUpdateCount = 0;
|
||||
}
|
||||
|
||||
|
@ -717,32 +734,33 @@ inline void AfterRendererUnimportantJob()
|
|||
{
|
||||
ProcessMessages();
|
||||
|
||||
if (g_bDisplayFPS) AfterRenderDisplayFPS();
|
||||
if (g_bDisplayFPS) DisplayFPS();
|
||||
|
||||
AfterRenderSwapBuffers();
|
||||
// Swapping buffers, so we could use another window
|
||||
GLWin.SwapGLBuffers();
|
||||
|
||||
if (conf.wireframe())
|
||||
{
|
||||
// clear all targets
|
||||
s_nWireframeCount = 1;
|
||||
}
|
||||
// clear all targets
|
||||
if (conf.wireframe()) s_nWireframeCount = 1;
|
||||
|
||||
if (g_bMakeSnapshot)
|
||||
{
|
||||
AfterRenderMadeSnapshoot();
|
||||
g_bMakeSnapshot = false;
|
||||
}
|
||||
if (g_bMakeSnapshot) MakeSnapshot();
|
||||
|
||||
CaptureFrame();
|
||||
CountStatistics();
|
||||
|
||||
AfterRenderCountStatistics();
|
||||
if (s_nNewWidth >= 0 && s_nNewHeight >= 0)
|
||||
{
|
||||
// If needed reset
|
||||
ZZReset();
|
||||
|
||||
if (s_nNewWidth >= 0 && s_nNewHeight >= 0)
|
||||
AfterRendererResizeWindow();
|
||||
ChangeDeviceSize(s_nNewWidth, s_nNewHeight);
|
||||
s_nNewWidth = s_nNewHeight = -1;
|
||||
}
|
||||
|
||||
maxmin = 608;
|
||||
}
|
||||
|
||||
extern u32 s_uFramebuffer;
|
||||
|
||||
// Swich Framebuffers
|
||||
inline void AfterRendererSwitchBackToTextures()
|
||||
{
|
||||
|
@ -780,13 +798,13 @@ inline void AfterRendererAutoresetTargets()
|
|||
if (conf.settings().auto_reset)
|
||||
{
|
||||
s_nResolveCounts[s_nCurResolveIndex] = s_nResolved;
|
||||
s_nCurResolveIndex = (s_nCurResolveIndex + 1) % ARRAY_SIZE(s_nResolveCounts);
|
||||
s_nCurResolveIndex = (s_nCurResolveIndex + 1) % ArraySize(s_nResolveCounts);
|
||||
|
||||
int total = 0;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(s_nResolveCounts); ++i) total += s_nResolveCounts[i];
|
||||
for (int i = 0; i < ArraySize(s_nResolveCounts); ++i) total += s_nResolveCounts[i];
|
||||
|
||||
if (total / ARRAY_SIZE(s_nResolveCounts) > 3)
|
||||
if (total / ArraySize(s_nResolveCounts) > 3)
|
||||
{
|
||||
if (s_nLastResolveReset > (int)(fFPS * 8))
|
||||
{
|
||||
|
@ -823,7 +841,7 @@ inline void AfterRendererAutoresetTargets()
|
|||
|
||||
int count = 0;
|
||||
// The main renderer function
|
||||
void ZeroGS::RenderCRTC(int interlace)
|
||||
void RenderCRTC(int interlace)
|
||||
{
|
||||
if (FrameSkippingHelper()) return;
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zerogs.h"
|
||||
#include "targets.h"
|
||||
|
||||
#define INTERLACE_COUNT (bInterlace && interlace == (conf.interlace))
|
||||
|
@ -36,7 +35,6 @@ extern int s_frameskipping;
|
|||
extern float fFPS;
|
||||
extern unsigned char zgsrevision, zgsbuild, zgsminor;
|
||||
|
||||
//extern u32 g_SaveFrameNum;
|
||||
extern int s_nWriteDepthCount;
|
||||
extern int s_nWireframeCount;
|
||||
extern int s_nWriteDestAlphaTest;
|
||||
|
@ -56,8 +54,6 @@ extern int g_nDepthUsed; // ffx2 pal movies
|
|||
|
||||
extern u32 s_ptexInterlace; // holds interlace fields
|
||||
|
||||
namespace ZeroGS
|
||||
{
|
||||
extern int s_nNewWidth, s_nNewHeight;
|
||||
|
||||
extern CRangeManager s_RangeMngr; // manages overwritten memory
|
||||
|
@ -65,6 +61,8 @@ extern void FlushTransferRanges(const tex0Info* ptex);
|
|||
extern void ProcessMessages();
|
||||
void AdjustTransToAspect(float4& v);
|
||||
|
||||
void ZZGSStateReset();
|
||||
|
||||
// Interlace texture is lazy 1*(height) array of 1 and 0.
|
||||
// If its height (named s_nInterlaceTexWidth here) is hanging we must redo
|
||||
// the texture.
|
||||
|
@ -95,6 +93,5 @@ inline u32 CreateInterlaceTex(int width)
|
|||
|
||||
return s_ptexInterlace;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ZZOGLCRTC_H_INCLUDED
|
||||
|
|
|
@ -22,11 +22,14 @@
|
|||
//------------------ Includes
|
||||
#include "GS.h"
|
||||
#include "Mem.h"
|
||||
#include "zerogs.h"
|
||||
#include "GLWin.h"
|
||||
|
||||
#include "ZZoglShaders.h"
|
||||
|
||||
#include "targets.h"
|
||||
#include "rasterfont.h" // simple font
|
||||
#include "ZZoglDrawing.h"
|
||||
#include "ZZoglVB.h"
|
||||
|
||||
// This include for windows resource file with Shaders
|
||||
#ifdef _WIN32
|
||||
# include "Win32.h"
|
||||
|
@ -73,14 +76,6 @@ typedef void (APIENTRYP _PFNSWAPINTERVAL)(int);
|
|||
|
||||
map<string, GLbyte> mapGLExtensions;
|
||||
|
||||
namespace ZeroGS
|
||||
{
|
||||
extern void KickPoint();
|
||||
extern void KickLine();
|
||||
extern void KickTriangle();
|
||||
extern void KickTriangleFan();
|
||||
extern void KickSprite();
|
||||
extern void KickDummy();
|
||||
extern bool LoadEffects();
|
||||
extern bool ZZshLoadExtraEffects();
|
||||
extern FRAGMENTSHADER* ZZshLoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed);
|
||||
|
@ -92,7 +87,8 @@ int g_nCurVBOIndex = 0;
|
|||
inline bool CreateImportantCheck();
|
||||
inline void CreateOtherCheck();
|
||||
inline bool CreateOpenShadersFile();
|
||||
}
|
||||
|
||||
void ZZGSStateReset();
|
||||
|
||||
//------------------ Dummies
|
||||
#ifdef _WIN32
|
||||
|
@ -129,15 +125,13 @@ void (APIENTRY *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum) = NULL;
|
|||
extern u8* s_lpShaderResources;
|
||||
|
||||
// String's for shader file in developer mode
|
||||
#ifdef DEVBUILD
|
||||
#ifdef ZEROGS_DEVBUILD
|
||||
char* EFFECT_NAME = "";
|
||||
char* EFFECT_DIR = "";
|
||||
#endif
|
||||
|
||||
/////////////////////
|
||||
// graphics resources
|
||||
FRAGMENTSHADER ppsRegular[4], ppsTexture[NUM_SHADERS];
|
||||
FRAGMENTSHADER ppsCRTC[2], ppsCRTC24[2], ppsCRTCTarg[2];
|
||||
GLenum s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha; // set by zgsBlendFuncSeparateEXT
|
||||
u32 s_stencilfunc, s_stencilref, s_stencilmask;
|
||||
GLenum s_drawbuffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };
|
||||
|
@ -164,31 +158,21 @@ u32 ptexBlocks = 0, ptexConv16to32 = 0; // holds information on block tiling
|
|||
u32 ptexBilinearBlocks = 0;
|
||||
u32 ptexConv32to16 = 0;
|
||||
int g_nDepthBias = 0;
|
||||
//u32 g_bSaveFlushedFrame = 0;
|
||||
|
||||
extern void Delete_Avi_Capture();
|
||||
extern void ZZDestroy();
|
||||
extern void SetAA(int mode);
|
||||
|
||||
//------------------ Code
|
||||
|
||||
bool ZeroGS::IsGLExt(const char* szTargetExtension)
|
||||
///< returns true if the the opengl extension is supported
|
||||
bool IsGLExt(const char* szTargetExtension)
|
||||
{
|
||||
return mapGLExtensions.find(string(szTargetExtension)) != mapGLExtensions.end();
|
||||
}
|
||||
|
||||
inline bool ZeroGS::Create_Window(int _width, int _height)
|
||||
{
|
||||
nBackbufferWidth = _width;
|
||||
nBackbufferHeight = _height;
|
||||
|
||||
if (!GLWin.DisplayWindow(_width, _height)) return false;
|
||||
|
||||
//s_nFullscreen = (conf.fullscreen()) ? 1 : 0;
|
||||
|
||||
conf.mrtdepth = 0; // for now
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Function asks about different OGL extensions, that are required to setup accordingly. Return false if checks failed
|
||||
inline bool ZeroGS::CreateImportantCheck()
|
||||
inline bool CreateImportantCheck()
|
||||
{
|
||||
bool bSuccess = true;
|
||||
#ifndef _WIN32
|
||||
|
@ -220,7 +204,7 @@ inline bool ZeroGS::CreateImportantCheck()
|
|||
}
|
||||
|
||||
// This is a check for less important open gl extensions.
|
||||
inline void ZeroGS::CreateOtherCheck()
|
||||
inline void CreateOtherCheck()
|
||||
{
|
||||
if (!IsGLExt("GL_EXT_blend_equation_separate") || glBlendEquationSeparateEXT == NULL)
|
||||
{
|
||||
|
@ -292,18 +276,21 @@ inline void ZeroGS::CreateOtherCheck()
|
|||
#endif
|
||||
}
|
||||
|
||||
// open shader file according to build target
|
||||
|
||||
inline bool ZeroGS::CreateOpenShadersFile()
|
||||
#ifdef _WIN32
|
||||
__forceinline bool LoadShadersFromRes()
|
||||
{
|
||||
#ifndef DEVBUILD
|
||||
# ifdef _WIN32
|
||||
HRSRC hShaderSrc = FindResource(hInst, MAKEINTRESOURCE(IDR_SHADERS), RT_RCDATA);
|
||||
assert(hShaderSrc != NULL);
|
||||
HGLOBAL hShaderGlob = LoadResource(hInst, hShaderSrc);
|
||||
assert(hShaderGlob != NULL);
|
||||
s_lpShaderResources = (u8*)LockResource(hShaderGlob);
|
||||
# else // not _WIN32
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
|
||||
__forceinline bool LoadShadersFromDat()
|
||||
{
|
||||
FILE* fres = fopen("ps2hw.dat", "rb");
|
||||
|
||||
if (fres == NULL)
|
||||
|
@ -324,13 +311,16 @@ inline bool ZeroGS::CreateOpenShadersFile()
|
|||
fseek(fres, 0, SEEK_SET);
|
||||
fread(s_lpShaderResources, s, 1, fres);
|
||||
s_lpShaderResources[s] = 0;
|
||||
# endif // _WIN32
|
||||
#else // defined(ZEROGS_DEVBUILD)
|
||||
# ifndef _WIN32 // NOT WINDOWS
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
__forceinline bool LoadShadersFromFX()
|
||||
{
|
||||
// test if ps2hw.fx exists
|
||||
char tempstr[255];
|
||||
char curwd[255];
|
||||
getcwd(curwd, ARRAY_SIZE(curwd));
|
||||
getcwd(curwd, ArraySize(curwd));
|
||||
|
||||
strcpy(tempstr, "/plugins/");
|
||||
sprintf(EFFECT_NAME, "%sps2hw.fx", tempstr);
|
||||
|
@ -354,58 +344,55 @@ inline bool ZeroGS::CreateOpenShadersFile()
|
|||
|
||||
sprintf(EFFECT_DIR, "%s/%s", curwd, tempstr);
|
||||
sprintf(EFFECT_NAME, "%sps2hw.fx", EFFECT_DIR);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// open shader file according to build target
|
||||
|
||||
inline bool CreateOpenShadersFile()
|
||||
{
|
||||
#ifndef DEVBUILD
|
||||
# ifdef _WIN32
|
||||
return LoadShadersFromRes();
|
||||
# else // not _WIN32
|
||||
return LoadShadersFromDat();
|
||||
# endif // _WIN32
|
||||
#else // defined(ZEROGS_DEVBUILD)
|
||||
# ifndef _WIN32 // NOT WINDOWS
|
||||
return LoadShadersFromFX();
|
||||
|
||||
// No else clause?
|
||||
#endif
|
||||
#endif // !defined(ZEROGS_DEVBUILD)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read all extensions name and fill mapGLExtensions
|
||||
inline bool CreateFillExtensionsMap()
|
||||
{
|
||||
// fill the opengl extension map
|
||||
const char* ptoken = (const char*)glGetString(GL_EXTENSIONS);
|
||||
string temp("");
|
||||
int max_ext = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &max_ext);
|
||||
|
||||
PFNGLGETSTRINGIPROC glGetStringi = 0;
|
||||
glGetStringi = (PFNGLGETSTRINGIPROC)wglGetProcAddress("glGetStringi");
|
||||
|
||||
if (ptoken == NULL) return false;
|
||||
|
||||
int prevlog = conf.log;
|
||||
|
||||
conf.log = 1;
|
||||
|
||||
ZZLog::GS_Log("Supported OpenGL Extensions:\n%s\n", ptoken); // write to the log file
|
||||
|
||||
// Probably a better way to do it, but seems to crash.
|
||||
/*int n;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &n);
|
||||
ZZLog::GS_Log("Supported OpenGL Extensions:\n");
|
||||
for (int i = 0; i < n; i++)
|
||||
for (GLint i = 0; i < max_ext; i++)
|
||||
{
|
||||
ZZLog::GS_Log("%s/n", (const char*)glGetStringi(GL_EXTENSIONS, i));
|
||||
}*/
|
||||
|
||||
conf.log = prevlog;
|
||||
|
||||
// insert all exts into mapGLExtensions
|
||||
|
||||
const char* pend = NULL;
|
||||
|
||||
while (ptoken != NULL)
|
||||
{
|
||||
pend = strchr(ptoken, ' ');
|
||||
|
||||
if (pend != NULL)
|
||||
{
|
||||
mapGLExtensions[string(ptoken, pend-ptoken)];
|
||||
}
|
||||
else
|
||||
{
|
||||
mapGLExtensions[string(ptoken)];
|
||||
break;
|
||||
}
|
||||
|
||||
ptoken = pend;
|
||||
|
||||
while (*ptoken == ' ') ++ptoken;
|
||||
string extension((const char*)glGetStringi(GL_EXTENSIONS, i));
|
||||
mapGLExtensions[extension];
|
||||
|
||||
temp = temp + extension;
|
||||
if (i != (max_ext - 1)) temp += ", ";
|
||||
}
|
||||
|
||||
// Write the extension list to the log, but only write it to the screen on a debug build.
|
||||
#ifndef _DEBUG
|
||||
ZZLog::Log("%d supported OpenGL Extensions: %s\n", max_ext, temp.c_str());
|
||||
#endif
|
||||
ZZLog::Debug_Log("%d supported OpenGL Extensions: %s\n", max_ext, temp.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -445,20 +432,22 @@ inline bool TryBlinearFormat(GLint fmt32, GLint fmt16, const GLvoid* vBilinearDa
|
|||
}
|
||||
|
||||
|
||||
bool ZeroGS::Create(int _width, int _height)
|
||||
bool ZZCreate(int _width, int _height)
|
||||
{
|
||||
GLenum err = GL_NO_ERROR;
|
||||
bool bSuccess = true;
|
||||
int i;
|
||||
|
||||
Destroy(1);
|
||||
GSStateReset();
|
||||
ZZDestroy();
|
||||
ZZGSStateReset();
|
||||
|
||||
if (!GLWin.DisplayWindow(_width, _height)) return false;
|
||||
|
||||
conf.mrtdepth = 0; // for now
|
||||
|
||||
if (!Create_Window(_width, _height)) return false;
|
||||
if (!CreateFillExtensionsMap()) return false;
|
||||
if (!CreateImportantCheck()) return false;
|
||||
|
||||
ZeroGS::CreateOtherCheck();
|
||||
CreateOtherCheck();
|
||||
|
||||
// check the max texture width and height
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &g_MaxTexWidth);
|
||||
|
@ -509,15 +498,10 @@ bool ZeroGS::Create(int _width, int _height)
|
|||
if (err != GL_NO_ERROR) bSuccess = false;
|
||||
|
||||
// init draw fns
|
||||
drawfn[0] = KickPoint;
|
||||
drawfn[1] = KickLine;
|
||||
drawfn[2] = KickLine;
|
||||
drawfn[3] = KickTriangle;
|
||||
drawfn[4] = KickTriangle;
|
||||
drawfn[5] = KickTriangleFan;
|
||||
drawfn[6] = KickSprite;
|
||||
drawfn[7] = KickDummy;
|
||||
|
||||
//init_drawfn();
|
||||
if (ZZKick != NULL) delete ZZKick;
|
||||
ZZKick = new Kick;
|
||||
|
||||
SetAA(conf.aa);
|
||||
|
||||
GSsetGameCRC(g_LastCRC, conf.settings()._u32);
|
||||
|
@ -527,7 +511,7 @@ bool ZeroGS::Create(int _width, int _height)
|
|||
//s_bWriteDepth = true;
|
||||
|
||||
GL_BLEND_ALL(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
|
||||
glViewport(0, 0, nBackbufferWidth, nBackbufferHeight); // Reset The Current Viewport
|
||||
glViewport(0, 0, GLWin.backbuffer.w, GLWin.backbuffer.h); // Reset The Current Viewport
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
@ -574,7 +558,7 @@ bool ZeroGS::Create(int _width, int _height)
|
|||
g_vboBuffers.resize(VB_NUMBUFFERS);
|
||||
glGenBuffers((GLsizei)g_vboBuffers.size(), &g_vboBuffers[0]);
|
||||
|
||||
for (i = 0; i < (int)g_vboBuffers.size(); ++i)
|
||||
for (int i = 0; i < (int)g_vboBuffers.size(); ++i)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_vboBuffers[i]);
|
||||
glBufferData(GL_ARRAY_BUFFER, 0x100*sizeof(VertexGPU), NULL, GL_STREAM_DRAW);
|
||||
|
@ -657,32 +641,16 @@ bool ZeroGS::Create(int _width, int _height)
|
|||
|
||||
VertexGPU* pvert = &verts[0];
|
||||
|
||||
pvert->x = -0x7fff;
|
||||
pvert->y = 0x7fff;
|
||||
pvert->z = 0;
|
||||
pvert->s = 0;
|
||||
pvert->t = 0;
|
||||
pvert->set_xyzst(-0x7fff, 0x7fff, 0, 0, 0);
|
||||
pvert++;
|
||||
|
||||
pvert->x = 0x7fff;
|
||||
pvert->y = 0x7fff;
|
||||
pvert->z = 0;
|
||||
pvert->s = 1;
|
||||
pvert->t = 0;
|
||||
pvert->set_xyzst(0x7fff, 0x7fff, 0, 1, 0);
|
||||
pvert++;
|
||||
|
||||
pvert->x = -0x7fff;
|
||||
pvert->y = -0x7fff;
|
||||
pvert->z = 0;
|
||||
pvert->s = 0;
|
||||
pvert->t = 1;
|
||||
pvert->set_xyzst(-0x7fff, -0x7fff, 0, 0, 1);
|
||||
pvert++;
|
||||
|
||||
pvert->x = 0x7fff;
|
||||
pvert->y = -0x7fff;
|
||||
pvert->z = 0;
|
||||
pvert->s = 1;
|
||||
pvert->t = 1;
|
||||
pvert->set_xyzst(0x7fff, -0x7fff, 0, 1, 1);
|
||||
pvert++;
|
||||
|
||||
glBufferDataARB(GL_ARRAY_BUFFER, 4*sizeof(VertexGPU), &verts[0], GL_STATIC_DRAW);
|
||||
|
@ -706,7 +674,7 @@ bool ZeroGS::Create(int _width, int _height)
|
|||
|
||||
vector<u32> conv16to32data(256*256);
|
||||
|
||||
for (i = 0; i < 256*256; ++i)
|
||||
for (int i = 0; i < 256*256; ++i)
|
||||
{
|
||||
u32 tempcol = RGBA16to32(i);
|
||||
// have to flip r and b
|
||||
|
@ -730,7 +698,7 @@ bool ZeroGS::Create(int _width, int _height)
|
|||
|
||||
u32* dst = &conv32to16data[0];
|
||||
|
||||
for (i = 0; i < 32; ++i)
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
for (int j = 0; j < 32; ++j)
|
||||
{
|
||||
|
@ -778,8 +746,6 @@ bool ZeroGS::Create(int _width, int _height)
|
|||
vb[0].Init(VB_BUFFERSIZE);
|
||||
vb[1].Init(VB_BUFFERSIZE);
|
||||
|
||||
// g_bSaveFlushedFrame = 1;
|
||||
|
||||
g_vsprog = g_psprog = 0;
|
||||
|
||||
if (glGetError() == GL_NO_ERROR)
|
||||
|
@ -793,7 +759,7 @@ bool ZeroGS::Create(int _width, int _height)
|
|||
}
|
||||
}
|
||||
|
||||
void ZeroGS::Destroy(bool bD3D)
|
||||
void ZZDestroy()
|
||||
{
|
||||
Delete_Avi_Capture();
|
||||
|
||||
|
@ -822,7 +788,7 @@ void ZeroGS::Destroy(bool bD3D)
|
|||
|
||||
if (pvs != NULL)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(pvs); ++i)
|
||||
for (int i = 0; i < ArraySize(pvs); ++i)
|
||||
{
|
||||
SAFE_RELEASE_PROG(pvs[i]);
|
||||
}
|
||||
|
@ -830,7 +796,7 @@ void ZeroGS::Destroy(bool bD3D)
|
|||
|
||||
if (ppsRegular != NULL)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(ppsRegular); ++i)
|
||||
for (int i = 0; i < ArraySize(ppsRegular); ++i)
|
||||
{
|
||||
SAFE_RELEASE_PROG(ppsRegular[i].prog);
|
||||
}
|
||||
|
@ -838,7 +804,7 @@ void ZeroGS::Destroy(bool bD3D)
|
|||
|
||||
if (ppsTexture != NULL)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(ppsTexture); ++i)
|
||||
for (int i = 0; i < ArraySize(ppsTexture); ++i)
|
||||
{
|
||||
SAFE_RELEASE_PROG(ppsTexture[i].prog);
|
||||
}
|
||||
|
@ -857,7 +823,7 @@ void ZeroGS::Destroy(bool bD3D)
|
|||
SAFE_RELEASE_PROG(ppsCRTC24[1].prog);
|
||||
SAFE_RELEASE_PROG(ppsOne.prog);
|
||||
|
||||
SAFE_DELETE(font_p);
|
||||
safe_delete(font_p);
|
||||
|
||||
GLWin.ReleaseContext();
|
||||
|
||||
|
|
|
@ -0,0 +1,254 @@
|
|||
/* ZZ Open GL graphics plugin
|
||||
* Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
|
||||
* Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "ZZoglDrawing.h"
|
||||
#include "ZZoglVB.h"
|
||||
|
||||
Kick* ZZKick;
|
||||
|
||||
const u32 g_primmult[8] = { 1, 2, 2, 3, 3, 3, 2, 0xff };
|
||||
const u32 g_primsub[8] = { 1, 2, 1, 3, 1, 1, 2, 0 };
|
||||
|
||||
const GLenum primtype[8] = { GL_POINTS, GL_LINES, GL_LINES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, 0xffffffff };
|
||||
|
||||
extern float fiTexWidth[2], fiTexHeight[2]; // current tex width and height
|
||||
|
||||
// Still thinking about the best place to put this.
|
||||
// called on a primitive switch
|
||||
void Prim()
|
||||
{
|
||||
FUNCLOG
|
||||
|
||||
VB& curvb = vb[prim->ctxt];
|
||||
|
||||
if (curvb.CheckPrim()) Flush(prim->ctxt);
|
||||
curvb.SetCurrentPrim();
|
||||
}
|
||||
|
||||
// return true if triangle SHOULD be painted.
|
||||
// Hackish and should be replaced.
|
||||
bool __forceinline NoHighlights(int i)
|
||||
{
|
||||
//Old code
|
||||
return (!(conf.settings().xenosaga_spec) || !vb[i].zbuf.zmsk || prim->iip) ;
|
||||
}
|
||||
|
||||
// Not inlining for the moment to avoid getting 'unresolved external symbol' errors in Windows.
|
||||
// This could also be resolved by moving the function into the header...
|
||||
void Kick::KickVertex(bool adc)
|
||||
{
|
||||
FUNCLOG
|
||||
if (++gs.primC >= (int)g_primmult[prim->prim])
|
||||
{
|
||||
if (!adc && NoHighlights(prim->ctxt)) DrawPrim(prim->prim);
|
||||
else DirtyValidPrevPrim();
|
||||
|
||||
gs.primC -= g_primsub[prim->prim];
|
||||
}
|
||||
gs.primIndex = gs.primNext();
|
||||
}
|
||||
|
||||
template<bool DO_Z_FOG>
|
||||
void Kick::Set_Vertex(VertexGPU *p, Vertex & gsvertex)
|
||||
{
|
||||
VB& curvb = vb[prim->ctxt];
|
||||
|
||||
p->move_x(gsvertex, curvb.offset.x);
|
||||
p->move_y(gsvertex, curvb.offset.y);
|
||||
if(DO_Z_FOG) {
|
||||
p->move_z(gsvertex, curvb.zprimmask);
|
||||
p->move_fog(gsvertex);
|
||||
}
|
||||
|
||||
p->rgba = prim->iip ? gsvertex.rgba : gs.rgba;
|
||||
|
||||
if (conf.settings().texa)
|
||||
{
|
||||
u32 B = ((p->rgba & 0xfe000000) >> 1) + (0x01000000 * vb[prim->ctxt].fba.fba);
|
||||
p->rgba = (p->rgba & 0xffffff) + B;
|
||||
}
|
||||
|
||||
if (prim->tme)
|
||||
{
|
||||
if (prim->fst)
|
||||
{
|
||||
p->s = (float)gsvertex.u * fiTexWidth[prim->ctxt];
|
||||
p->t = (float)gsvertex.v * fiTexHeight[prim->ctxt];
|
||||
p->q = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->s = gsvertex.s;
|
||||
p->t = gsvertex.t;
|
||||
p->q = gsvertex.q;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void Kick::Output_Vertex(VertexGPU vert, u32 id)
|
||||
{
|
||||
#ifdef WRITE_PRIM_LOGS
|
||||
ZZLog::Prim_Log("%c%d(%d): xyzf=(%4d,%4d,0x%x,%3d), rgba=0x%8.8x, stq = (%2.5f,%2.5f,%2.5f)",
|
||||
id == 0 ? '*' : ' ', id, prim->prim, vert.x / 8, vert.y / 8, vert.z, vert.f / 128,
|
||||
vert.rgba, Clamp(vert.s, -10, 10), Clamp(vert.t, -10, 10), Clamp(vert.q, -10, 10));
|
||||
#endif
|
||||
}
|
||||
|
||||
void Kick::DrawPrim(u32 prim_type)
|
||||
{
|
||||
VB& curvb = vb[prim->ctxt];
|
||||
|
||||
curvb.FlushTexData();
|
||||
|
||||
if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp))
|
||||
{
|
||||
assert(vb[prim->ctxt].nCount == 0);
|
||||
Flush(!prim->ctxt);
|
||||
}
|
||||
|
||||
// check enough place is left for the biggest primitive (sprite)
|
||||
// This function is unlikely to be called so do not inline it.
|
||||
if (unlikely(curvb.nCount + 6 > curvb.nNumVertices))
|
||||
curvb.IncreaseVertexBuffer();
|
||||
|
||||
VertexGPU* p = curvb.pBufferData + curvb.nCount;
|
||||
|
||||
u32 prev;
|
||||
u32 last;
|
||||
switch(prim_type) {
|
||||
case PRIM_POINT:
|
||||
Set_Vertex<true>(&p[0], gs.gsvertex[gs.primIndex]);
|
||||
curvb.nCount ++;
|
||||
break;
|
||||
|
||||
case PRIM_LINE:
|
||||
Set_Vertex<true>(&p[0], gs.gsvertex[gs.primPrev()]);
|
||||
Set_Vertex<true>(&p[1], gs.gsvertex[gs.primIndex]);
|
||||
curvb.nCount += 2;
|
||||
break;
|
||||
|
||||
case PRIM_LINE_STRIP:
|
||||
if (likely(ValidPrevPrim)) {
|
||||
assert(curvb.nCount >= 1);
|
||||
p[0] = p[-1];
|
||||
} else {
|
||||
Set_Vertex<true>(&p[0], gs.gsvertex[gs.primPrev()]);
|
||||
ValidPrevPrim = true;
|
||||
}
|
||||
|
||||
Set_Vertex<true>(&p[1], gs.gsvertex[gs.primIndex]);
|
||||
curvb.nCount += 2;
|
||||
break;
|
||||
|
||||
case PRIM_TRIANGLE:
|
||||
Set_Vertex<true>(&p[0], gs.gsvertex[gs.primPrev(2)]);
|
||||
Set_Vertex<true>(&p[1], gs.gsvertex[gs.primPrev()]);
|
||||
Set_Vertex<true>(&p[2], gs.gsvertex[gs.primIndex]);
|
||||
curvb.nCount += 3;
|
||||
break;
|
||||
|
||||
case PRIM_TRIANGLE_STRIP:
|
||||
if (likely(ValidPrevPrim)) {
|
||||
assert(curvb.nCount >= 2);
|
||||
p[0] = p[-2];
|
||||
p[1] = p[-1];
|
||||
} else {
|
||||
Set_Vertex<true>(&p[0], gs.gsvertex[gs.primPrev(2)]);
|
||||
Set_Vertex<true>(&p[1], gs.gsvertex[gs.primPrev()]);
|
||||
ValidPrevPrim = true;
|
||||
}
|
||||
|
||||
Set_Vertex<true>(&p[2], gs.gsvertex[gs.primIndex]);
|
||||
curvb.nCount += 3;
|
||||
break;
|
||||
|
||||
case PRIM_TRIANGLE_FAN:
|
||||
if (likely(ValidPrevPrim)) {
|
||||
assert(curvb.nCount >= 2);
|
||||
VertexGPU* TriFanVert = curvb.pBufferData + gs.nTriFanVert;
|
||||
p[0] = TriFanVert[0];
|
||||
p[1] = p[-1];
|
||||
} else {
|
||||
Set_Vertex<true>(&p[0], gs.gsTriFanVertex);
|
||||
Set_Vertex<true>(&p[1], gs.gsvertex[gs.primPrev(1)]);
|
||||
ValidPrevPrim = true;
|
||||
// Remenber the base for future processing
|
||||
gs.nTriFanVert = curvb.nCount;
|
||||
}
|
||||
|
||||
Set_Vertex<true>(&p[2], gs.gsvertex[gs.primIndex]);
|
||||
curvb.nCount += 3;
|
||||
break;
|
||||
|
||||
case PRIM_SPRITE:
|
||||
prev = gs.primPrev();
|
||||
last = gs.primIndex;
|
||||
|
||||
// sprite is too small and AA shows lines (tek4, Mana Khemia)
|
||||
gs.gsvertex[last].x += (4 * AA.x);
|
||||
gs.gsvertex[last].y += (4 * AA.y);
|
||||
|
||||
// might be bad sprite (KH dialog text)
|
||||
//if( gs.gsvertex[prev].x == gs.gsvertex[last].x || gs.gsvertex[prev].y == gs.gsvertex[last].y )
|
||||
//return;
|
||||
|
||||
// process sprite as 2 triangles. The common diagonal is 0,1 and 3,4
|
||||
Set_Vertex<false>(&p[0], gs.gsvertex[prev]);
|
||||
Set_Vertex<true>(&p[1], gs.gsvertex[last]);
|
||||
|
||||
// Only fog and Z of last vertex is valid
|
||||
p[0].z = p[1].z;
|
||||
p[0].f = p[1].f;
|
||||
|
||||
// Duplicate the vertex
|
||||
p[3] = p[0];
|
||||
p[2] = p[0];
|
||||
p[4] = p[1];
|
||||
p[5] = p[1];
|
||||
|
||||
// Move some vertex x coord to create the others corners of the sprite
|
||||
p[2].s = p[1].s;
|
||||
p[2].x = p[1].x;
|
||||
p[5].s = p[0].s;
|
||||
p[5].x = p[0].x;
|
||||
|
||||
curvb.nCount += 6;
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Print DEBUG info and code assertion
|
||||
switch(prim_type) {
|
||||
case PRIM_TRIANGLE:
|
||||
case PRIM_TRIANGLE_STRIP:
|
||||
case PRIM_TRIANGLE_FAN:
|
||||
assert(gs.primC >= 3);
|
||||
Output_Vertex(p[2],2);
|
||||
case PRIM_LINE:
|
||||
case PRIM_LINE_STRIP:
|
||||
case PRIM_SPRITE:
|
||||
assert(gs.primC >= 2);
|
||||
Output_Vertex(p[1],1);
|
||||
case PRIM_POINT:
|
||||
assert(gs.primC >= 1);
|
||||
Output_Vertex(p[0],0);
|
||||
default: break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/* ZZ Open GL graphics plugin
|
||||
* Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
|
||||
* Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef ZZOGLDRAWING_H_INCLUDED
|
||||
#define ZZOGLDRAWING_H_INCLUDED
|
||||
|
||||
#include "Util.h"
|
||||
#include "GS.h"
|
||||
|
||||
extern bool __forceinline NoHighlights(int i);
|
||||
|
||||
enum PRIM_TYPE {
|
||||
PRIM_POINT = 0,
|
||||
PRIM_LINE,
|
||||
PRIM_LINE_STRIP,
|
||||
PRIM_TRIANGLE,
|
||||
PRIM_TRIANGLE_STRIP,
|
||||
PRIM_TRIANGLE_FAN,
|
||||
PRIM_SPRITE,
|
||||
PRIM_DUMMY
|
||||
};
|
||||
|
||||
class Kick
|
||||
{
|
||||
private:
|
||||
// template<bool DO_Z_FOG> void Set_Vertex(VertexGPU *p, int i);
|
||||
template<bool DO_Z_FOG> void Set_Vertex(VertexGPU *p, Vertex &gsvertex);
|
||||
void Output_Vertex(VertexGPU vert, u32 id);
|
||||
bool ValidPrevPrim;
|
||||
public:
|
||||
Kick() { }
|
||||
~Kick() { }
|
||||
|
||||
void KickVertex(bool adc);
|
||||
|
||||
void DrawPrim(u32 i);
|
||||
|
||||
inline void DirtyValidPrevPrim() {
|
||||
ValidPrevPrim = 0;
|
||||
}
|
||||
};
|
||||
extern Kick* ZZKick;
|
||||
|
||||
#endif // ZZOGLDRAWING_H_INCLUDED
|
|
@ -23,12 +23,10 @@
|
|||
|
||||
#include "GS.h"
|
||||
#include "Mem.h"
|
||||
#include "zerogs.h"
|
||||
#include "targets.h"
|
||||
#include "ZZoglFlushHack.h"
|
||||
#include "ZZoglShaders.h"
|
||||
|
||||
using namespace ZeroGS;
|
||||
#include <math.h>
|
||||
|
||||
//------------------ Defines
|
||||
#ifndef ZEROGS_DEVBUILD
|
||||
|
@ -122,7 +120,6 @@ void Draw(const VB& curvb)
|
|||
extern int g_nDepthBias;
|
||||
extern float g_fBlockMult; // used for old cards, that do not support Alpha-32float textures. We store block data in u16 and use it.
|
||||
bool g_bUpdateStencil = 1;
|
||||
//u32 g_SaveFrameNum = 0; // ZZ
|
||||
|
||||
extern ZZshProgram g_psprog; // 2 -- ZZ
|
||||
|
||||
|
@ -147,6 +144,7 @@ static u32 s_ptexNextSet[2] = {0}; // ZZ
|
|||
|
||||
extern vector<u32> s_vecTempTextures; // temporary textures, released at the end of every frame
|
||||
extern bool s_bTexFlush;
|
||||
extern int g_nCurVBOIndex;
|
||||
bool s_bWriteDepth = false;
|
||||
bool s_bDestAlphaTest = false;
|
||||
int s_ClutResolve = 0; // ZZ
|
||||
|
@ -193,11 +191,9 @@ int s_nWireframeCount = 0;
|
|||
|
||||
//------------------ Namespace
|
||||
|
||||
namespace ZeroGS
|
||||
{
|
||||
|
||||
VB vb[2];
|
||||
float fiTexWidth[2], fiTexHeight[2]; // current tex width and height
|
||||
extern vector<GLuint> g_vboBuffers; // VBOs for all drawing commands
|
||||
|
||||
//u8 s_AAx = 0, s_AAy = 0; // if AAy is set, then AAx has to be set
|
||||
Point AA = {0,0};
|
||||
|
@ -211,7 +207,7 @@ void FlushTransferRanges(const tex0Info* ptex); //zz
|
|||
void SetTexVariables(int context, FRAGMENTSHADER* pfragment); // zz
|
||||
void SetTexInt(int context, FRAGMENTSHADER* pfragment, int settexint); // zz
|
||||
void SetAlphaVariables(const alphaInfo& ainfo); // zzz
|
||||
void ResetAlphaVariables();
|
||||
//void ResetAlphaVariables();
|
||||
|
||||
inline void SetAlphaTestInt(pixTest curtest);
|
||||
|
||||
|
@ -221,8 +217,11 @@ inline void ProcessStencil(const VB& curvb);
|
|||
inline void RenderFBA(const VB& curvb, ZZshParameter sOneColor);
|
||||
inline void ProcessFBA(const VB& curvb, ZZshParameter sOneColor); // zz
|
||||
|
||||
void SetContextTarget(int context);
|
||||
|
||||
}
|
||||
void SetWriteDepth();
|
||||
bool IsWriteDepth();
|
||||
void SetDestAlphaTest();
|
||||
|
||||
//------------------ Code
|
||||
|
||||
|
@ -279,6 +278,8 @@ inline void SwitchWireframeOn()
|
|||
}
|
||||
}
|
||||
|
||||
extern u32 ptexBilinearBlocks;
|
||||
|
||||
int GetTexFilter(const tex1Info& tex1)
|
||||
{
|
||||
// always force
|
||||
|
@ -299,11 +300,11 @@ int GetTexFilter(const tex1Info& tex1)
|
|||
return texfilter;
|
||||
}
|
||||
|
||||
void ZeroGS::ReloadEffects()
|
||||
void ReloadEffects()
|
||||
{
|
||||
#ifdef ZEROGS_DEVBUILD
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(ppsTexture); ++i)
|
||||
for (int i = 0; i < ArraySize(ppsTexture); ++i)
|
||||
{
|
||||
SAFE_RELEASE_PROG(ppsTexture[i].prog);
|
||||
}
|
||||
|
@ -321,7 +322,7 @@ inline void VisualBufferMessage(int context)
|
|||
{
|
||||
#if defined(WRITE_PRIM_LOGS) && defined(_DEBUG)
|
||||
BufferNumber++;
|
||||
ZeroGS::VB& curvb = vb[context];
|
||||
VB& curvb = vb[context];
|
||||
static const char* patst[8] = { "NEVER", "ALWAYS", "LESS", "LEQUAL", "EQUAL", "GEQUAL", "GREATER", "NOTEQUAL"};
|
||||
static const char* pztst[4] = { "NEVER", "ALWAYS", "GEQUAL", "GREATER" };
|
||||
static const char* pafail[4] = { "KEEP", "FB_ONLY", "ZB_ONLY", "RGB_ONLY" };
|
||||
|
@ -344,7 +345,6 @@ inline void VisualBufferMessage(int context)
|
|||
ZZLog::Error_Log("TGA name '%s'.", Name);
|
||||
free(Name);
|
||||
// }
|
||||
// ZZLog::Debug_Log("frame: %d, buffer %ld.\n", g_SaveFrameNum, BufferNumber);
|
||||
ZZLog::Debug_Log("buffer %ld.\n", BufferNumber);
|
||||
#endif
|
||||
}
|
||||
|
@ -353,12 +353,10 @@ inline void SaveRendererTarget(VB& curvb)
|
|||
{
|
||||
#ifdef _DEBUG
|
||||
|
||||
// if (g_bSaveFlushedFrame & 0x80000000)
|
||||
// {
|
||||
// Needs a # after rndr to work...
|
||||
// char str[255];
|
||||
// sprintf(str, "rndr%d.tga", g_SaveFrameNum);
|
||||
// sprintf(str, "rndr.tga");
|
||||
// SaveRenderTarget(str, curvb.prndr->fbw, curvb.prndr->fbh, 0);
|
||||
// }
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@ -466,18 +464,18 @@ inline CRenderTarget* FlushReGetTarget(int& tbw, int& tbp0, int& tpsm, VB& curvb
|
|||
if ((ptextarg == NULL) && (tpsm == PSMT8) && (conf.settings().reget))
|
||||
{
|
||||
// check for targets with half the width. Break Valkyrie Chronicles
|
||||
ptextarg = s_RTs.GetTarg(tbp0, tbw / 2, curvb);
|
||||
ptextarg = s_RTs.GetTarg(tbp0, tbw / 2);
|
||||
|
||||
if (ptextarg == NULL)
|
||||
{
|
||||
tbp0 &= ~0x7ff;
|
||||
ptextarg = s_RTs.GetTarg(tbp0, tbw / 2, curvb); // mgs3 hack
|
||||
ptextarg = s_RTs.GetTarg(tbp0, tbw / 2); // mgs3 hack
|
||||
|
||||
if (ptextarg == NULL)
|
||||
{
|
||||
// check the next level (mgs3)
|
||||
tbp0 &= ~0xfff;
|
||||
ptextarg = s_RTs.GetTarg(tbp0, tbw / 2, curvb); // mgs3 hack
|
||||
ptextarg = s_RTs.GetTarg(tbp0, tbw / 2); // mgs3 hack
|
||||
}
|
||||
|
||||
if (ptextarg != NULL && ptextarg->start > tbp0*256)
|
||||
|
@ -492,7 +490,7 @@ inline CRenderTarget* FlushReGetTarget(int& tbw, int& tbp0, int& tpsm, VB& curvb
|
|||
if (PSMT_ISZTEX(tpsm) && (ptextarg == NULL))
|
||||
{
|
||||
// try depth
|
||||
ptextarg = s_DepthRTs.GetTarg(tbp0, tbw, curvb);
|
||||
ptextarg = s_DepthRTs.GetTarg(tbp0, tbw);
|
||||
}
|
||||
|
||||
if ((ptextarg == NULL) && (conf.settings().texture_targs))
|
||||
|
@ -509,24 +507,24 @@ inline CRenderTarget* FlushReGetTarget(int& tbw, int& tbp0, int& tpsm, VB& curvb
|
|||
{
|
||||
if (ptextarg == NULL)
|
||||
{
|
||||
printf("Miss %x 0x%x %d\n", tbw, tbp0, tpsm);
|
||||
ZZLog::Debug_Log("Miss %x 0x%x %d", tbw, tbp0, tpsm);
|
||||
|
||||
typedef map<u32, CRenderTarget*> MAPTARGETS;
|
||||
|
||||
for (MAPTARGETS::iterator itnew = s_RTs.mapTargets.begin(); itnew != s_RTs.mapTargets.end(); ++itnew)
|
||||
{
|
||||
printf("\tRender %x 0x%x %x\n", itnew->second->fbw, itnew->second->fbp, itnew->second->psm);
|
||||
ZZLog::Debug_Log("\tRender %x 0x%x %x", itnew->second->fbw, itnew->second->fbp, itnew->second->psm);
|
||||
}
|
||||
|
||||
for (MAPTARGETS::iterator itnew = s_DepthRTs.mapTargets.begin(); itnew != s_DepthRTs.mapTargets.end(); ++itnew)
|
||||
{
|
||||
printf("\tDepth %x 0x%x %x\n", itnew->second->fbw, itnew->second->fbp, itnew->second->psm);
|
||||
ZZLog::Debug_Log("\tDepth %x 0x%x %x", itnew->second->fbw, itnew->second->fbp, itnew->second->psm);
|
||||
}
|
||||
|
||||
printf("\tCurvb 0x%x 0x%x 0x%x %x\n", curvb.frame.fbp, curvb.prndr->end, curvb.prndr->fbp, curvb.prndr->fbw);
|
||||
ZZLog::Debug_Log("\tCurvb 0x%x 0x%x 0x%x %x", curvb.frame.fbp, curvb.prndr->end, curvb.prndr->fbp, curvb.prndr->fbw);
|
||||
}
|
||||
else
|
||||
printf("Hit %x 0x%x %x\n", tbw, tbp0, tpsm);
|
||||
ZZLog::Debug_Log("Hit %x 0x%x %x", tbw, tbp0, tpsm);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -545,7 +543,7 @@ inline CRenderTarget* FlushGetTarget(VB& curvb)
|
|||
|
||||
if (curvb.bNeedTexCheck)
|
||||
{
|
||||
printf("How it is possible?\n");
|
||||
ZZLog::Error_Log("How it is possible?");
|
||||
// not yet initied, but still need to get correct target! (xeno3 ingame)
|
||||
tbp0 = ZZOglGet_tbp0_TexBits(curvb.uNextTex0Data[0]);
|
||||
tbw = ZZOglGet_tbw_TexBitsMult(curvb.uNextTex0Data[0]);
|
||||
|
@ -558,7 +556,7 @@ inline CRenderTarget* FlushGetTarget(VB& curvb)
|
|||
tpsm = curvb.tex0.psm;
|
||||
}
|
||||
|
||||
ptextarg = s_RTs.GetTarg(tbp0, tbw, curvb);
|
||||
ptextarg = s_RTs.GetTarg(tbp0, tbw);
|
||||
|
||||
if (ptextarg == NULL)
|
||||
ptextarg = FlushReGetTarget(tbw, tbp0, tpsm, curvb);
|
||||
|
@ -733,7 +731,7 @@ inline void FlushDecodeClut(VB& curvb, GLuint& ptexclut)
|
|||
int entries = PSMT_IS8CLUT(curvb.tex0.psm) ? 256 : 16;
|
||||
|
||||
if (curvb.tex0.csm && curvb.tex0.csa)
|
||||
printf("ERROR, csm1\n");
|
||||
ZZLog::Debug_Log("ERROR, csm1.");
|
||||
|
||||
if (PSMT_IS32BIT(curvb.tex0.cpsm)) // 32 bit
|
||||
{
|
||||
|
@ -1088,6 +1086,8 @@ inline void AlphaSetStencil(bool DoIt)
|
|||
else glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
|
||||
//inline u32 FtoDW(float f) { return (*((u32*)&f)); }
|
||||
|
||||
inline void AlphaSetDepthTest(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment)
|
||||
{
|
||||
glDepthMask(!curvb.zbuf.zmsk && curtest.zte);
|
||||
|
@ -1223,7 +1223,7 @@ inline void AlphaRenderStencil(VB& curvb, bool s_bDestAlphaTest, bool bCanRender
|
|||
|
||||
inline void AlphaTest(VB& curvb)
|
||||
{
|
||||
// printf ("%d %d %d %d %d\n", curvb.test.date, curvb.test.datm, gs.texa.aem, curvb.test.ate, curvb.test.atst );
|
||||
// ZZLog::Debug_Log("%d %d %d %d %d", curvb.test.date, curvb.test.datm, gs.texa.aem, curvb.test.ate, curvb.test.atst );
|
||||
|
||||
// return;
|
||||
// Zeydlitz changed this with a reason! It's an "Alpha more than 1 hack."
|
||||
|
@ -1236,7 +1236,7 @@ inline void AlphaTest(VB& curvb)
|
|||
else
|
||||
{
|
||||
glAlphaFunc(GL_LESS, 1.0f);
|
||||
printf("%d %d %d\n", curvb.test.date, curvb.test.datm, gs.texa.aem);
|
||||
ZZLog::Debug_Log("%d %d %d", curvb.test.date, curvb.test.datm, gs.texa.aem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1447,7 +1447,6 @@ inline void AlphaSaveTarget(VB& curvb)
|
|||
#ifdef _DEBUG
|
||||
return; // Do nothing
|
||||
|
||||
// if( g_bSaveFlushedFrame & 0xf ) {
|
||||
//#ifdef _WIN32
|
||||
// CreateDirectory("frames", NULL);
|
||||
//#else
|
||||
|
@ -1456,13 +1455,14 @@ inline void AlphaSaveTarget(VB& curvb)
|
|||
// system(strdir);
|
||||
//#endif
|
||||
// char str[255];
|
||||
// sprintf(str, "frames/frame%.4d.tga", g_SaveFrameNum++);
|
||||
|
||||
// Needs a # after frame to work properly.
|
||||
// sprintf(str, "frames/frame.tga");
|
||||
|
||||
// //glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer
|
||||
// //glFlush();
|
||||
// //SaveTexture("tex.jpg", GL_TEXTURE_RECTANGLE_NV, curvb.prndr->ptex, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh));
|
||||
// SaveRenderTarget(str, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh), 0);
|
||||
// }
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1477,7 +1477,7 @@ inline void FlushUndoFiter(u32 dwFilterOpts)
|
|||
}
|
||||
|
||||
// This is the most important function! It draws all collected info onscreen.
|
||||
void ZeroGS::Flush(int context)
|
||||
void Flush(int context)
|
||||
{
|
||||
FUNCLOG
|
||||
VB& curvb = vb[context];
|
||||
|
@ -1535,13 +1535,13 @@ void ZeroGS::Flush(int context)
|
|||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
void ZeroGS::FlushBoth()
|
||||
void FlushBoth()
|
||||
{
|
||||
Flush(0);
|
||||
Flush(1);
|
||||
}
|
||||
|
||||
inline void ZeroGS::RenderFBA(const VB& curvb, ZZshParameter sOneColor)
|
||||
inline void RenderFBA(const VB& curvb, ZZshParameter sOneColor)
|
||||
{
|
||||
// add fba to all pixels
|
||||
GL_STENCILFUNC(GL_ALWAYS, STENCIL_FBA, 0xff);
|
||||
|
@ -1585,7 +1585,7 @@ inline void ZeroGS::RenderFBA(const VB& curvb, ZZshParameter sOneColor)
|
|||
GL_ZTEST(curvb.test.zte);
|
||||
}
|
||||
|
||||
__forceinline void ZeroGS::RenderAlphaTest(const VB& curvb, ZZshParameter sOneColor)
|
||||
__forceinline void RenderAlphaTest(const VB& curvb, ZZshParameter sOneColor)
|
||||
{
|
||||
if (!g_bUpdateStencil) return;
|
||||
|
||||
|
@ -1653,7 +1653,7 @@ __forceinline void ZeroGS::RenderAlphaTest(const VB& curvb, ZZshParameter sOneCo
|
|||
}
|
||||
}
|
||||
|
||||
inline void ZeroGS::RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting)
|
||||
inline void RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting)
|
||||
{
|
||||
//NOTE: This stencil hack for dest alpha testing ONLY works when
|
||||
// the geometry in one DrawPrimitive call does not overlap
|
||||
|
@ -1670,7 +1670,7 @@ inline void ZeroGS::RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting)
|
|||
GL_STENCILFUNC_SET();
|
||||
}
|
||||
|
||||
inline void ZeroGS::ProcessStencil(const VB& curvb)
|
||||
inline void ProcessStencil(const VB& curvb)
|
||||
{
|
||||
assert(!curvb.fba.fba);
|
||||
|
||||
|
@ -1723,7 +1723,7 @@ inline void ZeroGS::ProcessStencil(const VB& curvb)
|
|||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
}
|
||||
|
||||
__forceinline void ZeroGS::ProcessFBA(const VB& curvb, ZZshParameter sOneColor)
|
||||
__forceinline void ProcessFBA(const VB& curvb, ZZshParameter sOneColor)
|
||||
{
|
||||
if ((curvb.frame.fbm&0x80000000)) return;
|
||||
|
||||
|
@ -1784,7 +1784,7 @@ __forceinline void ZeroGS::ProcessFBA(const VB& curvb, ZZshParameter sOneColor)
|
|||
GL_ZTEST(curvb.test.zte);
|
||||
}
|
||||
|
||||
void ZeroGS::SetContextTarget(int context)
|
||||
void SetContextTarget(int context)
|
||||
{
|
||||
FUNCLOG
|
||||
VB& curvb = vb[context];
|
||||
|
@ -1841,7 +1841,7 @@ void ZeroGS::SetContextTarget(int context)
|
|||
if (curvb.prndr->status & CRenderTarget::TS_NeedUpdate)
|
||||
{
|
||||
/* if(bSetTarg) {
|
||||
* printf ( " Here\n ");
|
||||
* ZZLog::Debug_Log( " Here ");
|
||||
* if(s_bWriteDepth) {
|
||||
* curvb.pdepth->SetRenderTarget(1);
|
||||
* curvb.pdepth->SetDepthStencilSurface();
|
||||
|
@ -1859,7 +1859,7 @@ void ZeroGS::SetContextTarget(int context)
|
|||
//if( bSetTarg && ((vb[0].pdepth != vb[1].pdepth && vb[!context].bVarsSetTarg) || !vb[context].bVarsSetTarg) )
|
||||
curvb.pdepth->SetDepthStencilSurface();
|
||||
|
||||
if (conf.mrtdepth && ZeroGS::IsWriteDepth()) curvb.pdepth->SetRenderTarget(1);
|
||||
if (conf.mrtdepth && IsWriteDepth()) curvb.pdepth->SetRenderTarget(1);
|
||||
if (s_ptexCurSet[0] == curvb.prndr->ptex) s_ptexCurSet[0] = 0;
|
||||
if (s_ptexCurSet[1] == curvb.prndr->ptex) s_ptexCurSet[1] = 0;
|
||||
|
||||
|
@ -1892,7 +1892,7 @@ void ZeroGS::SetContextTarget(int context)
|
|||
}
|
||||
|
||||
|
||||
void ZeroGS::SetTexInt(int context, FRAGMENTSHADER* pfragment, int settexint)
|
||||
void SetTexInt(int context, FRAGMENTSHADER* pfragment, int settexint)
|
||||
{
|
||||
FUNCLOG
|
||||
|
||||
|
@ -1929,14 +1929,14 @@ void SetTexClamping(int context, FRAGMENTSHADER* pfragment)
|
|||
{
|
||||
FUNCLOG
|
||||
SetShaderCaller("SetTexClamping");
|
||||
clampInfo* pclamp = &ZeroGS::vb[context].clamp;
|
||||
clampInfo* pclamp = &vb[context].clamp;
|
||||
float4 v, v2;
|
||||
v.x = v.y = 0;
|
||||
u32* ptex = ZeroGS::vb[context].ptexClamp;
|
||||
u32* ptex = vb[context].ptexClamp;
|
||||
ptex[0] = ptex[1] = 0;
|
||||
|
||||
float fw = ZeroGS::vb[context].tex0.tw ;
|
||||
float fh = ZeroGS::vb[context].tex0.th ;
|
||||
float fw = vb[context].tex0.tw ;
|
||||
float fh = vb[context].tex0.th ;
|
||||
|
||||
switch (pclamp->wms)
|
||||
{
|
||||
|
@ -1966,7 +1966,7 @@ void SetTexClamping(int context, FRAGMENTSHADER* pfragment)
|
|||
if (correctMinu != g_PrevBitwiseTexX)
|
||||
{
|
||||
g_PrevBitwiseTexX = correctMinu;
|
||||
ptex[0] = ZeroGS::s_BitwiseTextures.GetTex(correctMinu, 0);
|
||||
ptex[0] = s_BitwiseTextures.GetTex(correctMinu, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -2001,7 +2001,7 @@ void SetTexClamping(int context, FRAGMENTSHADER* pfragment)
|
|||
if (correctMinv != g_PrevBitwiseTexY)
|
||||
{
|
||||
g_PrevBitwiseTexY = correctMinv;
|
||||
ptex[1] = ZeroGS::s_BitwiseTextures.GetTex(correctMinv, ptex[0]);
|
||||
ptex[1] = s_BitwiseTextures.GetTex(correctMinv, ptex[0]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2015,17 +2015,8 @@ void SetTexClamping(int context, FRAGMENTSHADER* pfragment)
|
|||
|
||||
}
|
||||
|
||||
// Fixme should be in float4 lib
|
||||
inline bool equal_vectors(float4 a, float4 b)
|
||||
{
|
||||
if (abs(a.x - b.x) + abs(a.y - b.y) + abs(a.z - b.z) + abs(a.w - b.w) < 0.01)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int CheckTexArray[4][2][2][2] = {{{{0, }}}};
|
||||
void ZeroGS::SetTexVariables(int context, FRAGMENTSHADER* pfragment)
|
||||
void SetTexVariables(int context, FRAGMENTSHADER* pfragment)
|
||||
{
|
||||
FUNCLOG
|
||||
|
||||
|
@ -2169,12 +2160,12 @@ void ZeroGS::SetTexVariables(int context, FRAGMENTSHADER* pfragment)
|
|||
|
||||
if ( equal_vectors(valpha, valpha3) && equal_vectors(valpha2, valpha4) ) {
|
||||
if (CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] == 0) {
|
||||
printf ( "Good issue %d %d %d %d\n", tex0.tfx, tex0.tcc, psm, PSMT_ALPHAEXP(psm) );
|
||||
ZZLog::Debug_Log ( "Good issue %d %d %d %d", tex0.tfx, tex0.tcc, psm, PSMT_ALPHAEXP(psm) );
|
||||
CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm) ] = 1;
|
||||
}
|
||||
}
|
||||
else if (CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] == -1) {
|
||||
printf ("Bad array, %d %d %d %d\n\tolf valpha %f, %f, %f, %f : valpha2 %f %f %f %f\n\tnew valpha %f, %f, %f, %f : valpha2 %f %f %f %f\n",
|
||||
ZZLog::Debug_Log ("Bad array, %d %d %d %d\n\tolf valpha %f, %f, %f, %f : valpha2 %f %f %f %f\n\tnew valpha %f, %f, %f, %f : valpha2 %f %f %f %f",
|
||||
tex0.tfx, tex0.tcc, psm, PSMT_ALPHAEXP(psm),
|
||||
valpha3.x, valpha3.y, valpha3.z, valpha3.w, valpha4.x, valpha4.y, valpha4.z, valpha4.w,
|
||||
valpha.x, valpha.y, valpha.z, valpha.w, valpha2.x, valpha2.y, valpha2.z, valpha2.w);
|
||||
|
@ -2203,7 +2194,7 @@ void ZeroGS::SetTexVariables(int context, FRAGMENTSHADER* pfragment)
|
|||
}
|
||||
}
|
||||
|
||||
void ZeroGS::SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, bool CheckVB, FRAGMENTSHADER* pfragment, int force)
|
||||
void SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, bool CheckVB, FRAGMENTSHADER* pfragment, int force)
|
||||
{
|
||||
FUNCLOG
|
||||
float4 v;
|
||||
|
@ -2363,16 +2354,16 @@ void ZeroGS::SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0,
|
|||
//if( a.fix <= 0x80 ) { \
|
||||
// dwTemp = (a.fix*2)>255?255:(a.fix*2); \
|
||||
// dwTemp = dwTemp|(dwTemp<<8)|(dwTemp<<16)|0x80000000; \
|
||||
// printf("bfactor: %8.8x\n", dwTemp); \
|
||||
// ZZLog::Debug_Log("bfactor: %8.8x", dwTemp); \
|
||||
// glBlendColorEXT(dwTemp); \
|
||||
// } \
|
||||
// else { \
|
||||
|
||||
void ZeroGS::ResetAlphaVariables() {
|
||||
FUNCLOG
|
||||
}
|
||||
//void ResetAlphaVariables() {
|
||||
// FUNCLOG
|
||||
//}
|
||||
|
||||
inline void ZeroGS::NeedFactor(int w)
|
||||
inline void NeedFactor(int w)
|
||||
{
|
||||
if (bDestAlphaColor == 2)
|
||||
{
|
||||
|
@ -2384,7 +2375,7 @@ inline void ZeroGS::NeedFactor(int w)
|
|||
|
||||
//static int CheckArray[48][2] = {{0,}};
|
||||
|
||||
void ZeroGS::SetAlphaVariables(const alphaInfo& a)
|
||||
void SetAlphaVariables(const alphaInfo& a)
|
||||
{
|
||||
FUNCLOG
|
||||
bool alphaenable = true;
|
||||
|
@ -2849,8 +2840,8 @@ void ZeroGS::SetAlphaVariables(const alphaInfo& a)
|
|||
|
||||
if ( alphaenable && (t_rgbeq != s_rgbeq || s_srcrgb != t_srcrgb || t_dstrgb != s_dstrgb || tAlphaClamping != bAlphaClamping)) {
|
||||
if (CheckArray[code][(bDestAlphaColor==2)] != -1) {
|
||||
printf ( "A code %d, 0x%x, 0x%x, 0x%x, 0x%x %d\n", code, alpha, one_minus_alpha, one, zero, bDestAlphaColor );
|
||||
printf ( " Difference %d %d %d %d | 0x%x 0x%x | 0x%x 0x%x | 0x%x 0x%x | %d %d\n",
|
||||
ZZLog::Debug_Log( "A code %d, 0x%x, 0x%x, 0x%x, 0x%x %d", code, alpha, one_minus_alpha, one, zero, bDestAlphaColor );
|
||||
ZZLog::Debug_Log( " Difference %d %d %d %d | 0x%x 0x%x | 0x%x 0x%x | 0x%x 0x%x | %d %d",
|
||||
code, a.a, a.b, a.d,
|
||||
t_rgbeq, s_rgbeq, t_srcrgb, s_srcrgb, t_dstrgb, s_dstrgb, tAlphaClamping, bAlphaClamping);
|
||||
CheckArray[code][(bDestAlphaColor==2)] = -1;
|
||||
|
@ -2858,7 +2849,7 @@ void ZeroGS::SetAlphaVariables(const alphaInfo& a)
|
|||
}
|
||||
else
|
||||
if (CheckArray[code][(bDestAlphaColor==2)] == 0){
|
||||
printf ( "Add good code %d %d, psm %d destA %d\n", code, a.c, vb[icurctx].prndr->psm, bDestAlphaColor);
|
||||
ZZLog::Debug_Log( "Add good code %d %d, psm %d destA %d", code, a.c, vb[icurctx].prndr->psm, bDestAlphaColor);
|
||||
CheckArray[code][(bDestAlphaColor==2)] = 1;
|
||||
}*/
|
||||
|
||||
|
@ -2877,7 +2868,7 @@ void ZeroGS::SetAlphaVariables(const alphaInfo& a)
|
|||
INC_ALPHAVARS();
|
||||
}
|
||||
|
||||
void ZeroGS::SetWriteDepth()
|
||||
void SetWriteDepth()
|
||||
{
|
||||
FUNCLOG
|
||||
|
||||
|
@ -2888,26 +2879,26 @@ void ZeroGS::SetWriteDepth()
|
|||
}
|
||||
}
|
||||
|
||||
bool ZeroGS::IsWriteDepth()
|
||||
bool IsWriteDepth()
|
||||
{
|
||||
FUNCLOG
|
||||
return s_bWriteDepth;
|
||||
}
|
||||
|
||||
bool ZeroGS::IsWriteDestAlphaTest()
|
||||
bool IsWriteDestAlphaTest()
|
||||
{
|
||||
FUNCLOG
|
||||
return s_bDestAlphaTest;
|
||||
}
|
||||
|
||||
void ZeroGS::SetDestAlphaTest()
|
||||
void SetDestAlphaTest()
|
||||
{
|
||||
FUNCLOG
|
||||
s_bDestAlphaTest = true;
|
||||
s_nWriteDestAlphaTest = 4;
|
||||
}
|
||||
|
||||
void ZeroGS::SetTexFlush()
|
||||
void SetTexFlush()
|
||||
{
|
||||
FUNCLOG
|
||||
s_bTexFlush = true;
|
||||
|
|
|
@ -464,7 +464,7 @@ static const u32 MAX_FRAMES = 500;
|
|||
static GSFrameInfo FrameAppear[MAX_FRAMES];
|
||||
static u32 Rec_Numbers = 0;
|
||||
|
||||
void RecordNewFrames(ZeroGS::VB& curvb, GSFrameInfo fi) {
|
||||
void RecordNewFrames(VB& curvb, GSFrameInfo fi) {
|
||||
if (Rec_Numbers >= MAX_FRAMES)
|
||||
return;
|
||||
|
||||
|
@ -486,12 +486,12 @@ void RecordNewFrames(ZeroGS::VB& curvb, GSFrameInfo fi) {
|
|||
// Dump a nice picture of the frame
|
||||
char filename[255];
|
||||
sprintf(filename, "SkipFlushFrame_%d__%d.tga", g_SkipFlushFrame, Rec_Numbers);
|
||||
ZeroGS::SaveRenderTarget(filename, curvb.prndr->fbw, curvb.prndr->fbh, 0);
|
||||
SaveRenderTarget(filename, curvb.prndr->fbw, curvb.prndr->fbh, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
__forceinline bool IsBadFrame(ZeroGS::VB& curvb)
|
||||
__forceinline bool IsBadFrame(VB& curvb)
|
||||
{
|
||||
GSFrameInfo fi;
|
||||
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
#define ZZOGL_FLUSH_HACK_H_INCLUDED
|
||||
|
||||
#include "GS.h"
|
||||
#include "zerogs.h"
|
||||
#include "targets.h"
|
||||
#include "ZZoglVB.h"
|
||||
|
||||
extern int g_SkipFlushFrame;
|
||||
|
||||
|
@ -79,5 +80,5 @@ void GSC_StarOcean3(const GSFrameInfo& fi, int& skip);
|
|||
void GSC_ValkyrieProfile2(const GSFrameInfo& fi, int& skip);
|
||||
void GSC_RadiataStories(const GSFrameInfo& fi, int& skip);
|
||||
|
||||
extern bool IsBadFrame(ZeroGS::VB& curvb);
|
||||
extern bool IsBadFrame(VB& curvb);
|
||||
#endif
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include "Pcsx2Defs.h"
|
||||
|
||||
//#define ZZ_MMATH
|
||||
|
||||
|
@ -194,6 +195,15 @@ class Vector4
|
|||
y = ((color >> 8) & 0xff) / 255.0f;
|
||||
z = ((color >> 16) & 0xff) / 255.0f;
|
||||
}
|
||||
|
||||
bool equal_vectors(const Vector4<T>& v)
|
||||
{
|
||||
if (abs(x - v.x) + abs(y - v.y) + abs(z - v.z) + abs(w - v.w) < 0.01)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typedef Vector4<float> float4;
|
||||
|
@ -443,6 +453,14 @@ class float4
|
|||
return float4(_mm_cmple_ps(v1.m, v2.m));
|
||||
}
|
||||
|
||||
bool equal_vectors(const float4& v)
|
||||
{
|
||||
if (abs(x - v.x) + abs(y - v.y) + abs(z - v.z) + abs(w - v.w) < 0.01)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// This looked interesting, so I thought I'd include it...
|
||||
|
||||
template<int i> float4 shuffle() const
|
||||
|
|
|
@ -20,9 +20,10 @@
|
|||
// Save and Load.
|
||||
|
||||
//------------------ Includes
|
||||
#include "zerogs.h"
|
||||
#include "targets.h"
|
||||
#include "Util.h"
|
||||
#include "ZZoglVB.h"
|
||||
|
||||
extern void ZZGSStateReset();
|
||||
//----------------------- Defines
|
||||
|
||||
#define VBSAVELIMIT ((u32)((u8*)&vb[0].nNextFrameHeight-(u8*)&vb[0]))
|
||||
|
@ -44,7 +45,10 @@ char *libraryNameX = "ZeroGS Playground OpenGL ";
|
|||
extern char *libraryName;
|
||||
extern u32 s_uTex1Data[2][2], s_uClampData[2];
|
||||
|
||||
int ZeroGS::Save(s8* pbydata)
|
||||
void SetFogColor(u32 fog);
|
||||
void SetFogColor(GIFRegFOGCOL* fog);
|
||||
|
||||
int ZZSave(s8* pbydata)
|
||||
{
|
||||
if (pbydata == NULL)
|
||||
return 40 + MEMORY_END + sizeof(gs) + 2*VBSAVELIMIT + 2*sizeof(frameInfo) + 4 + 256*4;
|
||||
|
@ -85,7 +89,10 @@ int ZeroGS::Save(s8* pbydata)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool ZeroGS::Load(s8* pbydata)
|
||||
extern u32 s_uFramebuffer;
|
||||
extern int g_nCurVBOIndex;
|
||||
|
||||
bool ZZLoad(s8* pbydata)
|
||||
{
|
||||
memset(s_uTex1Data, 0, sizeof(s_uTex1Data));
|
||||
memset(s_uClampData, 0, sizeof(s_uClampData));
|
||||
|
@ -99,7 +106,7 @@ bool ZeroGS::Load(s8* pbydata)
|
|||
{
|
||||
g_MemTargs.Destroy();
|
||||
|
||||
GSStateReset();
|
||||
ZZGSStateReset();
|
||||
pbydata += 32;
|
||||
|
||||
//int context = *(int*)pbydata;
|
||||
|
|
|
@ -21,10 +21,11 @@
|
|||
// ZZogl Shader manipulation functions.
|
||||
|
||||
//------------------- Includes
|
||||
#include "zerogs.h"
|
||||
#include "Util.h"
|
||||
#include "ZZoglShaders.h"
|
||||
#include "zpipe.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <map>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include "Win32.h"
|
||||
|
@ -33,8 +34,6 @@ extern HINSTANCE hInst;
|
|||
|
||||
// ----------------- Defines
|
||||
|
||||
using namespace ZeroGS;
|
||||
|
||||
#define TEXWRAP_REPEAT 0
|
||||
#define TEXWRAP_CLAMP 1
|
||||
#define TEXWRAP_REGION_REPEAT 2
|
||||
|
@ -68,7 +67,13 @@ using namespace ZeroGS;
|
|||
|
||||
//------------------ Constants
|
||||
|
||||
// Used in a logarithmic Z-test, as (1-o(1))/log(MAX_U32).
|
||||
const float g_filog32 = 0.999f / (32.0f * logf(2.0f));
|
||||
|
||||
#ifdef _DEBUG
|
||||
const static char* g_pTexTypes[] = { "32", "tex32", "clut32", "tex32to16", "tex16to8h" };
|
||||
#endif
|
||||
const char* g_pShaders[4] = { "full", "reduced", "accurate", "accurate-reduced" };
|
||||
|
||||
// ----------------- Global Variables
|
||||
|
||||
|
@ -87,16 +92,20 @@ char* EFFECT_DIR;
|
|||
|
||||
bool g_bCRTCBilinear = true;
|
||||
|
||||
namespace ZeroGS {
|
||||
float4 g_vdepth, vlogz;
|
||||
FRAGMENTSHADER ppsBitBlt[2], ppsBitBltDepth, ppsOne;
|
||||
FRAGMENTSHADER ppsBaseTexture, ppsConvert16to32, ppsConvert32to16;
|
||||
FRAGMENTSHADER ppsRegular[4], ppsTexture[NUM_SHADERS];
|
||||
FRAGMENTSHADER ppsCRTC[2], ppsCRTC24[2], ppsCRTCTarg[2];
|
||||
VERTEXSHADER pvsBitBlt;
|
||||
|
||||
inline bool LoadEffects();
|
||||
}
|
||||
float4 g_vdepth, vlogz;
|
||||
FRAGMENTSHADER ppsBitBlt[2], ppsBitBltDepth, ppsOne;
|
||||
FRAGMENTSHADER ppsBaseTexture, ppsConvert16to32, ppsConvert32to16;
|
||||
FRAGMENTSHADER ppsRegular[4], ppsTexture[NUM_SHADERS];
|
||||
FRAGMENTSHADER ppsCRTC[2], ppsCRTC24[2], ppsCRTCTarg[2];
|
||||
VERTEXSHADER pvsBitBlt;
|
||||
|
||||
extern u32 ptexBlocks; // holds information on block tiling. It's texture number in OpenGL -- if 0 than such texture
|
||||
extern u32 ptexConv16to32; // does not exists. This textures should be created on start and released on finish.
|
||||
extern u32 ptexBilinearBlocks;
|
||||
extern u32 ptexConv32to16;
|
||||
|
||||
inline bool LoadEffects();
|
||||
extern bool s_bWriteDepth;
|
||||
|
||||
struct SHADERHEADER
|
||||
{
|
||||
|
@ -219,7 +228,7 @@ bool ZZshCreateOpenShadersFile() {
|
|||
// test if ps2hw.fx exists
|
||||
char tempstr[255];
|
||||
char curwd[255];
|
||||
getcwd(curwd, ARRAY_SIZE(curwd));
|
||||
getcwd(curwd, ArraySize(curwd));
|
||||
|
||||
strcpy(tempstr, "/plugins/");
|
||||
sprintf(EFFECT_NAME, "%sps2hw.fx", tempstr);
|
||||
|
@ -506,7 +515,7 @@ void SetupVertexProgramParameters(ZZshProgram prog, int context)
|
|||
SetupFragmentProgramParameters(&fragment, !!(Index&SH_CONTEXT1), 0); \
|
||||
} \
|
||||
|
||||
inline bool ZeroGS::LoadEffects()
|
||||
inline bool LoadEffects()
|
||||
{
|
||||
assert( s_lpShaderResources != NULL );
|
||||
|
||||
|
@ -530,7 +539,7 @@ inline bool ZeroGS::LoadEffects()
|
|||
}
|
||||
|
||||
// clear the textures
|
||||
for(u16 i = 0; i < ARRAY_SIZE(ppsTexture); ++i) {
|
||||
for(u16 i = 0; i < ArraySize(ppsTexture); ++i) {
|
||||
SAFE_RELEASE_PROG(ppsTexture[i].prog);
|
||||
ppsTexture[i].prog = NULL;
|
||||
}
|
||||
|
@ -637,7 +646,7 @@ FRAGMENTSHADER* ZZshLoadShadeEffect(int type, int texfilter, int fog, int testae
|
|||
|
||||
int index = GET_SHADER_INDEX(type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, context, 0);
|
||||
|
||||
assert( index < ARRAY_SIZE(ppsTexture) );
|
||||
assert( index < ArraySize(ppsTexture) );
|
||||
FRAGMENTSHADER* pf = ppsTexture+index;
|
||||
|
||||
if( pbFailed != NULL ) *pbFailed = false;
|
||||
|
@ -711,10 +720,10 @@ FRAGMENTSHADER* ZZshLoadShadeEffect(int type, int texfilter, int fog, int testae
|
|||
SET_PSFILENAME(fragment, name); \
|
||||
} \
|
||||
|
||||
inline bool ZeroGS::LoadEffects()
|
||||
inline bool LoadEffects()
|
||||
{
|
||||
// clear the textures
|
||||
for(int i = 0; i < ARRAY_SIZE(ppsTexture); ++i) {
|
||||
for(int i = 0; i < ArraySize(ppsTexture); ++i) {
|
||||
SAFE_RELEASE_PROG(ppsTexture[i].prog);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,9 +29,11 @@
|
|||
// Just bitmask for different type of shaders
|
||||
#define SHADER_REDUCED 1 // equivalent to ps2.0
|
||||
#define SHADER_ACCURATE 2 // for older cards with less accurate math (ps2.x+)
|
||||
// For output
|
||||
const static char* g_pShaders[] = { "full", "reduced", "accurate", "accurate-reduced" };
|
||||
|
||||
#include "ZZoglMath.h"
|
||||
#include "GS.h"
|
||||
|
||||
// For output
|
||||
#define NVIDIA_CG_API
|
||||
// --------------------------- API abstraction level --------------------------------
|
||||
|
||||
|
@ -54,7 +56,7 @@ inline bool ZZshActiveParameter(ZZshParameter param) {return (param !=NULL); }
|
|||
|
||||
#endif // end NVIDIA cg-toolkit API
|
||||
|
||||
const static char* g_pPsTexWrap[] = { "-DREPEAT", "-DCLAMP", "-DREGION_REPEAT", NULL };
|
||||
//const static char* g_pPsTexWrap[] = { "-DREPEAT", "-DCLAMP", "-DREGION_REPEAT", NULL };
|
||||
|
||||
enum ZZshShaderType {ZZ_SH_ZERO, ZZ_SH_REGULAR, ZZ_SH_REGULAR_FOG, ZZ_SH_TEXTURE, ZZ_SH_TEXTURE_FOG, ZZ_SH_CRTC};
|
||||
// We have "compatible" shaders, as RegularFogVS and RegularFogPS. if don't need to wory about incompatible shaders
|
||||
|
@ -174,7 +176,6 @@ struct VERTEXSHADER
|
|||
int ParametersStart, ParametersFinish;
|
||||
};
|
||||
|
||||
namespace ZeroGS {
|
||||
extern float4 g_vdepth;
|
||||
extern float4 vlogz;
|
||||
extern VERTEXSHADER pvsBitBlt;
|
||||
|
@ -183,7 +184,6 @@ namespace ZeroGS {
|
|||
|
||||
extern FRAGMENTSHADER ppsRegular[4], ppsTexture[NUM_SHADERS];
|
||||
extern FRAGMENTSHADER ppsCRTC[2], ppsCRTC24[2], ppsCRTCTarg[2];
|
||||
}
|
||||
|
||||
// ------------------------- Functions -------------------------------
|
||||
|
||||
|
@ -225,8 +225,7 @@ extern bool ZZshLoadExtraEffects();
|
|||
|
||||
extern FRAGMENTSHADER* ZZshLoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed);
|
||||
|
||||
namespace ZeroGS {
|
||||
// only sets a limited amount of state (for Update)
|
||||
void SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, bool CheckVB, FRAGMENTSHADER* pfragment, int force);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
// Texture and avi saving to file functions
|
||||
|
||||
//------------------ Includes
|
||||
#include "Util.h"
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
# include <aviUtil.h>
|
||||
|
@ -27,9 +28,9 @@
|
|||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zerogs.h"
|
||||
#include "targets.h"
|
||||
#include "Mem.h"
|
||||
#include "ZZoglShoots.h"
|
||||
|
||||
// AVI Capture
|
||||
int s_avicapturing = 0;
|
||||
|
@ -43,7 +44,7 @@ extern "C"
|
|||
#define HAVE_BOOLEAN
|
||||
#endif
|
||||
|
||||
#include "jpeglib.h" // This library want to be after zerogs.h
|
||||
#include "jpeglib.h"
|
||||
}
|
||||
|
||||
//------------------ Defines
|
||||
|
@ -65,14 +66,14 @@ string strSnapshot;
|
|||
//------------------ Code
|
||||
|
||||
// Set variables need to made a snapshoot when it's possible
|
||||
void ZeroGS::SaveSnapshot(const char* filename)
|
||||
void SaveSnapshot(const char* filename)
|
||||
{
|
||||
g_bMakeSnapshot = true;
|
||||
strSnapshot = filename;
|
||||
}
|
||||
|
||||
// Save curent renderer in jpeg or TGA format
|
||||
bool ZeroGS::SaveRenderTarget(const char* filename, int width, int height, int jpeg)
|
||||
bool SaveRenderTarget(const char* filename, int width, int height, int jpeg)
|
||||
{
|
||||
bool bflip = height < 0;
|
||||
height = abs(height);
|
||||
|
@ -100,7 +101,7 @@ bool ZeroGS::SaveRenderTarget(const char* filename, int width, int height, int j
|
|||
}
|
||||
|
||||
// Save selected texture as TGA
|
||||
bool ZeroGS::SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height)
|
||||
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height)
|
||||
{
|
||||
vector<u32> data(width*height);
|
||||
glBindTexture(textarget, tex);
|
||||
|
@ -112,7 +113,7 @@ bool ZeroGS::SaveTexture(const char* filename, u32 textarget, u32 tex, int width
|
|||
}
|
||||
|
||||
// save image as JPEG
|
||||
bool ZeroGS::SaveJPEG(const char* filename, int image_width, int image_height, const void* pdata, int quality)
|
||||
bool SaveJPEG(const char* filename, int image_width, int image_height, const void* pdata, int quality)
|
||||
{
|
||||
u8* image_buffer = new u8[image_width * image_height * 3];
|
||||
u8* psrc = (u8*)pdata;
|
||||
|
@ -286,7 +287,7 @@ __attribute__((packed));
|
|||
#endif
|
||||
|
||||
// Save image as TGA
|
||||
bool ZeroGS::SaveTGA(const char* filename, int width, int height, void* pdata)
|
||||
bool SaveTGA(const char* filename, int width, int height, void* pdata)
|
||||
{
|
||||
int err = 0;
|
||||
TGA_HEADER hdr;
|
||||
|
@ -314,7 +315,7 @@ bool ZeroGS::SaveTGA(const char* filename, int width, int height, void* pdata)
|
|||
|
||||
// AVI capture stuff
|
||||
// AVI start -- set needed global variables
|
||||
void ZeroGS::StartCapture()
|
||||
void StartCapture()
|
||||
{
|
||||
if (conf.captureAvi()) return;
|
||||
if (!s_aviinit)
|
||||
|
@ -338,7 +339,7 @@ void ZeroGS::StartCapture()
|
|||
}
|
||||
|
||||
// Stop.
|
||||
void ZeroGS::StopCapture()
|
||||
void StopCapture()
|
||||
{
|
||||
if (!conf.captureAvi()) return;
|
||||
s_avicapturing = 0;
|
||||
|
@ -347,25 +348,25 @@ void ZeroGS::StopCapture()
|
|||
}
|
||||
|
||||
// And capture frame does not work on linux.
|
||||
void ZeroGS::CaptureFrame()
|
||||
void CaptureFrame()
|
||||
{
|
||||
if ((!s_avicapturing) || (!s_aviinit)) return;
|
||||
|
||||
vector<u32> data(nBackbufferWidth*nBackbufferHeight);
|
||||
glReadPixels(0, 0, nBackbufferWidth, nBackbufferHeight, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
|
||||
vector<u32> data(GLWin.backbuffer.w * GLWin.backbuffer.h);
|
||||
glReadPixels(0, 0, GLWin.backbuffer.w, GLWin.backbuffer.h, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
|
||||
|
||||
if (glGetError() != GL_NO_ERROR) return;
|
||||
|
||||
#ifdef _WIN32
|
||||
int fps = SMODE1->CMOD == 3 ? 50 : 60;
|
||||
|
||||
bool bSuccess = ADD_FRAME_FROM_DIB_TO_AVI("AAAA", fps, nBackbufferWidth, nBackbufferHeight, 32, &data[0]);
|
||||
bool bSuccess = ADD_FRAME_FROM_DIB_TO_AVI("AAAA", fps, GLWin.backbuffer.w, GLWin.backbuffer.h, 32, &data[0]);
|
||||
|
||||
if (!bSuccess)
|
||||
{
|
||||
s_avicapturing = 0;
|
||||
STOP_AVI();
|
||||
ZeroGS::AddMessage("Failed to create avi");
|
||||
ZZAddMessage("Failed to create avi");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -376,7 +377,7 @@ void ZeroGS::CaptureFrame()
|
|||
|
||||
// It's nearly the same as save texture
|
||||
void
|
||||
ZeroGS::SaveTex(tex0Info* ptex, int usevid)
|
||||
SaveTex(tex0Info* ptex, int usevid)
|
||||
{
|
||||
vector<u32> data(ptex->tw*ptex->th);
|
||||
vector<u8> srcdata;
|
||||
|
@ -617,7 +618,7 @@ ZeroGS::SaveTex(tex0Info* ptex, int usevid)
|
|||
|
||||
// Do the save texture and return file name of it
|
||||
// Do not forget to call free(), other wise there would be memory leak!
|
||||
char* ZeroGS::NamedSaveTex(tex0Info* ptex, int usevid)
|
||||
char* NamedSaveTex(tex0Info* ptex, int usevid)
|
||||
{
|
||||
SaveTex(ptex, usevid);
|
||||
char* Name = (char*)malloc(TGA_FILE_NAME_MAX_LENGTH);
|
||||
|
@ -631,7 +632,7 @@ char* ZeroGS::NamedSaveTex(tex0Info* ptex, int usevid)
|
|||
}
|
||||
|
||||
// Special function, which is safe to call from any other file, without aviutils problems.
|
||||
void ZeroGS::Stop_Avi()
|
||||
void Stop_Avi()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
STOP_AVI();
|
||||
|
@ -640,7 +641,7 @@ void ZeroGS::Stop_Avi()
|
|||
#endif
|
||||
}
|
||||
|
||||
void ZeroGS::Delete_Avi_Capture()
|
||||
void Delete_Avi_Capture()
|
||||
{
|
||||
if (s_aviinit)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/* ZZ Open GL graphics plugin
|
||||
* Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
|
||||
* Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef ZZOGLSHOOTS_H_INCLUDED
|
||||
#define ZZOGLSHOOTS_H_INCLUDED
|
||||
|
||||
void SaveSnapshot(const char* filename);
|
||||
bool SaveRenderTarget(const char* filename, int width, int height, int jpeg);
|
||||
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height);
|
||||
bool SaveJPEG(const char* filename, int width, int height, const void* pdata, int quality);
|
||||
bool SaveTGA(const char* filename, int width, int height, void* pdata);
|
||||
void Stop_Avi();
|
||||
void Delete_Avi_Capture();
|
||||
|
||||
void StartCapture();
|
||||
void StopCapture();
|
||||
void CaptureFrame();
|
||||
|
||||
#endif // ZZOGLSHOOTS_H_INCLUDED
|
|
@ -21,12 +21,13 @@
|
|||
// VB stands for Visual Buffer, as I think
|
||||
|
||||
//------------------- Includes
|
||||
#include "zerogs.h"
|
||||
#include "Util.h"
|
||||
#include "targets.h"
|
||||
#include "ZZoglVB.h"
|
||||
#include "GS.h"
|
||||
#include "Mem.h"
|
||||
extern float fiTexWidth[2], fiTexHeight[2]; // current tex width and height
|
||||
|
||||
using namespace ZeroGS;
|
||||
// ----------------- Defines
|
||||
#define MINMAX_SHIFT 3
|
||||
|
||||
|
@ -37,20 +38,20 @@ int maxmin = 608;
|
|||
// ----------------- Code
|
||||
|
||||
// Constructor. Set width and height to 1
|
||||
ZeroGS::VB::VB()
|
||||
VB::VB()
|
||||
{
|
||||
memset(this, 0, sizeof(ZeroGS::VB));
|
||||
memset(this, 0, sizeof(VB));
|
||||
tex0.tw = 1;
|
||||
tex0.th = 1;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
ZeroGS::VB::~VB()
|
||||
VB::~VB()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void ZeroGS::VB::Destroy()
|
||||
void VB::Destroy()
|
||||
{
|
||||
_aligned_free(pBufferData);
|
||||
pBufferData = NULL;
|
||||
|
@ -65,7 +66,7 @@ int ConstraintReason;
|
|||
// Return number of 64-pixels block, that guaranted could be hold in memory
|
||||
// from gsfb.fbp and tbp (textrure pase), zbuf.zbp (Z-buffer), frame.fbp
|
||||
// (previous frame).
|
||||
inline int ZeroGS::VB::FindMinimalMemoryConstrain(int tbp, int maxpos)
|
||||
inline int VB::FindMinimalMemoryConstrain(int tbp, int maxpos)
|
||||
{
|
||||
int MinConstraint = maxpos;
|
||||
|
||||
|
@ -116,7 +117,7 @@ inline int ZeroGS::VB::FindMinimalMemoryConstrain(int tbp, int maxpos)
|
|||
|
||||
// Return number of 64 pizel words that could be placed in Z-Buffer
|
||||
// If no Z-buffer present return old constraint
|
||||
inline int ZeroGS::VB::FindZbufferMemoryConstrain(int tbp, int maxpos)
|
||||
inline int VB::FindZbufferMemoryConstrain(int tbp, int maxpos)
|
||||
{
|
||||
int MinConstraint = maxpos;
|
||||
|
||||
|
@ -147,7 +148,7 @@ inline int GetScissorY(int y)
|
|||
|
||||
//There is several reasons to limit a height of frame: maximum buffer size, calculated size
|
||||
//from fbw and fbh and scissoring.
|
||||
inline int ZeroGS::VB::FindMinimalHeightConstrain(int maxpos)
|
||||
inline int VB::FindMinimalHeightConstrain(int maxpos)
|
||||
{
|
||||
int MinConstraint = maxpos;
|
||||
|
||||
|
@ -176,7 +177,7 @@ inline int ZeroGS::VB::FindMinimalHeightConstrain(int maxpos)
|
|||
|
||||
// 32 bit frames have additional constraints to frame
|
||||
// maxpos was maximum length of frame at normal constraints
|
||||
inline void ZeroGS::VB::CheckFrame32bitRes(int maxpos)
|
||||
inline void VB::CheckFrame32bitRes(int maxpos)
|
||||
{
|
||||
int fbh = frame.fbh;
|
||||
|
||||
|
@ -215,7 +216,7 @@ inline void ZeroGS::VB::CheckFrame32bitRes(int maxpos)
|
|||
// 4Mb memory in 64 bit (4 bytes) words.
|
||||
// |------------------------|---------------------|----------|----------|---------------------|
|
||||
// 0 gsfb.fbp zbuff.zpb tbp frame.fbp 2^20/64
|
||||
inline int ZeroGS::VB::CheckFrameAddConstraints(int tbp)
|
||||
inline int VB::CheckFrameAddConstraints(int tbp)
|
||||
{
|
||||
if (gsfb.fbw <= 0)
|
||||
{
|
||||
|
@ -263,7 +264,7 @@ inline int ZeroGS::VB::CheckFrameAddConstraints(int tbp)
|
|||
|
||||
// Check if after resizing new depth target is needed to be used.
|
||||
// it returns 2 if a new depth target is used.
|
||||
inline int ZeroGS::VB::CheckFrameResolveDepth(int tbp)
|
||||
inline int VB::CheckFrameResolveDepth(int tbp)
|
||||
{
|
||||
int result = 0;
|
||||
CDepthTarget* pprevdepth = pdepth;
|
||||
|
@ -289,7 +290,7 @@ inline int ZeroGS::VB::CheckFrameResolveDepth(int tbp)
|
|||
|
||||
// Check if after resizing, a new render target is needed to be used. Also perform deptarget check.
|
||||
// Returns 1 if only 1 render target is changed and 3 -- if both.
|
||||
inline int ZeroGS::VB::CheckFrameResolveRender(int tbp)
|
||||
inline int VB::CheckFrameResolveRender(int tbp)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
|
@ -335,7 +336,7 @@ inline int ZeroGS::VB::CheckFrameResolveRender(int tbp)
|
|||
}
|
||||
|
||||
// After frame resetting, it is possible that 16 to 32 or 32 to 16 (color bits) conversion should be made.
|
||||
inline void ZeroGS::VB::CheckFrame16vs32Conversion()
|
||||
inline void VB::CheckFrame16vs32Conversion()
|
||||
{
|
||||
if (prndr->status & CRenderTarget::TS_NeedConvert32)
|
||||
{
|
||||
|
@ -355,9 +356,11 @@ inline void ZeroGS::VB::CheckFrame16vs32Conversion()
|
|||
}
|
||||
}
|
||||
|
||||
void SetContextTarget(int context);
|
||||
|
||||
// A lot of times, the target is too big and overwrites the texture.
|
||||
// If tbp != 0, use it to bound.
|
||||
void ZeroGS::VB::CheckFrame(int tbp)
|
||||
void VB::CheckFrame(int tbp)
|
||||
{
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
|
@ -388,7 +391,7 @@ void ZeroGS::VB::CheckFrame(int tbp)
|
|||
if ((prndr != NULL) && (prndr->psm != gsfb.psm))
|
||||
{
|
||||
// behavior for dest alpha varies
|
||||
ResetAlphaVariables();
|
||||
// ResetAlphaVariables();
|
||||
}
|
||||
|
||||
bChanged = CheckFrameResolveRender(tbp);
|
||||
|
@ -407,11 +410,11 @@ void ZeroGS::VB::CheckFrame(int tbp)
|
|||
}
|
||||
|
||||
// This is the case, most easy to perform, when nothing was changed
|
||||
inline void ZeroGS::VB::FlushTexUnchangedClutDontUpdate()
|
||||
inline void VB::FlushTexUnchangedClutDontUpdate()
|
||||
{
|
||||
if (ZZOglGet_cld_TexBits(uNextTex0Data[1]))
|
||||
{
|
||||
ZeroGS::texClutWrite(ictx);
|
||||
texClutWrite(ictx);
|
||||
// invalidate to make sure target didn't change!
|
||||
bVarsTexSync = false;
|
||||
}
|
||||
|
@ -419,9 +422,9 @@ inline void ZeroGS::VB::FlushTexUnchangedClutDontUpdate()
|
|||
|
||||
// The second of easy branch. We does not change storage model, so we don't need to
|
||||
// update anything except texture itself
|
||||
inline void ZeroGS::VB::FlushTexClutDontUpdate()
|
||||
inline void VB::FlushTexClutDontUpdate()
|
||||
{
|
||||
if (!ZZOglClutStorageUnchanged(uCurTex0Data, uNextTex0Data)) ZeroGS::Flush(ictx);
|
||||
if (!ZZOglClutStorageUnchanged(uCurTex0Data, uNextTex0Data)) Flush(ictx);
|
||||
|
||||
// clut memory isn't going to be loaded so can ignore, but at least update CSA and CPSM!
|
||||
uCurTex0Data[1] = (uCurTex0Data[1] & CPSM_CSA_NOTMASK) | (uNextTex0Data[1] & CPSM_CSA_BITMASK);
|
||||
|
@ -429,14 +432,14 @@ inline void ZeroGS::VB::FlushTexClutDontUpdate()
|
|||
tex0.csa = ZZOglGet_csa_TexBits(uNextTex0Data[1]);
|
||||
tex0.cpsm = ZZOglGet_cpsm_TexBits(uNextTex0Data[1]);
|
||||
|
||||
ZeroGS::texClutWrite(ictx);
|
||||
texClutWrite(ictx);
|
||||
|
||||
bVarsTexSync = false;
|
||||
}
|
||||
|
||||
|
||||
// Set texture variables after big change
|
||||
inline void ZeroGS::VB::FlushTexSetNewVars(u32 psm)
|
||||
inline void VB::FlushTexSetNewVars(u32 psm)
|
||||
{
|
||||
tex0.tbp0 = ZZOglGet_tbp0_TexBits(uNextTex0Data[0]);
|
||||
tex0.tbw = ZZOglGet_tbw_TexBitsMult(uNextTex0Data[0]);
|
||||
|
@ -447,13 +450,13 @@ inline void ZeroGS::VB::FlushTexSetNewVars(u32 psm)
|
|||
tex0.tcc = ZZOglGet_tcc_TexBits(uNextTex0Data[1]);
|
||||
tex0.tfx = ZZOglGet_tfx_TexBits(uNextTex0Data[1]);
|
||||
|
||||
ZeroGS::fiTexWidth[ictx] = (1 / 16.0f) / tex0.tw;
|
||||
ZeroGS::fiTexHeight[ictx] = (1 / 16.0f) / tex0.th;
|
||||
fiTexWidth[ictx] = (1 / 16.0f) / tex0.tw;
|
||||
fiTexHeight[ictx] = (1 / 16.0f) / tex0.th;
|
||||
}
|
||||
|
||||
// Flush == draw on screen
|
||||
// This function made VB state consistant before real Flush.
|
||||
void ZeroGS::VB::FlushTexData()
|
||||
void VB::FlushTexData()
|
||||
{
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
|
@ -487,7 +490,7 @@ void ZeroGS::VB::FlushTexData()
|
|||
}
|
||||
|
||||
// Made the full update
|
||||
ZeroGS::Flush(ictx);
|
||||
Flush(ictx);
|
||||
|
||||
bVarsTexSync = false;
|
||||
bTexConstsSync = false;
|
||||
|
@ -497,7 +500,7 @@ void ZeroGS::VB::FlushTexData()
|
|||
|
||||
FlushTexSetNewVars(psm);
|
||||
|
||||
if (PSMT_ISCLUT(psm)) ZeroGS::CluttingForFlushedTex(&tex0, uNextTex0Data[1], ictx) ;
|
||||
if (PSMT_ISCLUT(psm)) CluttingForFlushedTex(&tex0, uNextTex0Data[1], ictx) ;
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
/* ZZ Open GL graphics plugin
|
||||
* Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
|
||||
* Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
// Zerogs:VB implementation.
|
||||
// VB stands for Visual Buffer, as I think
|
||||
|
||||
#ifndef ZZOGLVB_H_INCLUDED
|
||||
#define ZZOGLVB_H_INCLUDED
|
||||
|
||||
#include "targets.h"
|
||||
|
||||
extern const GLenum primtype[8];
|
||||
|
||||
class VB
|
||||
{
|
||||
public:
|
||||
VB();
|
||||
~VB();
|
||||
|
||||
void Destroy();
|
||||
|
||||
inline bool CheckPrim()
|
||||
{
|
||||
static const int PRIMMASK = 0x0e; // for now ignore 0x10 (AA)
|
||||
|
||||
if ((PRIMMASK & prim->_val) != (PRIMMASK & curprim._val) || primtype[prim->prim] != primtype[curprim.prim])
|
||||
return nCount > 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetCurrentPrim()
|
||||
{
|
||||
curprim._val = prim->_val;
|
||||
curprim.prim = prim->prim;
|
||||
}
|
||||
|
||||
void CheckFrame(int tbp);
|
||||
|
||||
// context specific state
|
||||
Point offset;
|
||||
Rect2 scissor;
|
||||
tex0Info tex0;
|
||||
tex1Info tex1;
|
||||
miptbpInfo miptbp0;
|
||||
miptbpInfo miptbp1;
|
||||
alphaInfo alpha;
|
||||
fbaInfo fba;
|
||||
clampInfo clamp;
|
||||
pixTest test;
|
||||
u32 ptexClamp[2]; // textures for x and y dir region clamping
|
||||
|
||||
void FlushTexData();
|
||||
inline int CheckFrameAddConstraints(int tbp);
|
||||
inline void CheckScissors(int maxpos);
|
||||
inline void CheckFrame32bitRes(int maxpos);
|
||||
inline int FindMinimalMemoryConstrain(int tbp, int maxpos);
|
||||
inline int FindZbufferMemoryConstrain(int tbp, int maxpos);
|
||||
inline int FindMinimalHeightConstrain(int maxpos);
|
||||
|
||||
inline int CheckFrameResolveRender(int tbp);
|
||||
inline void CheckFrame16vs32Conversion();
|
||||
inline int CheckFrameResolveDepth(int tbp);
|
||||
|
||||
inline void FlushTexUnchangedClutDontUpdate() ;
|
||||
inline void FlushTexClutDontUpdate() ;
|
||||
inline void FlushTexClutting() ;
|
||||
inline void FlushTexSetNewVars(u32 psm) ;
|
||||
|
||||
// Increase the size of pbuf
|
||||
void IncreaseVertexBuffer()
|
||||
{
|
||||
assert(pBufferData != NULL);
|
||||
nNumVertices *= 2;
|
||||
VertexGPU* ptemp = (VertexGPU*)_aligned_malloc(sizeof(VertexGPU) * nNumVertices, 256);
|
||||
memcpy_amd(ptemp, pBufferData, sizeof(VertexGPU) * nCount);
|
||||
assert(nCount <= nNumVertices);
|
||||
_aligned_free(pBufferData);
|
||||
pBufferData = ptemp;
|
||||
}
|
||||
|
||||
void Init(int nVerts)
|
||||
{
|
||||
if (pBufferData == NULL && nVerts > 0)
|
||||
{
|
||||
pBufferData = (VertexGPU*)_aligned_malloc(sizeof(VertexGPU) * nVerts, 256);
|
||||
nNumVertices = nVerts;
|
||||
}
|
||||
|
||||
nCount = 0;
|
||||
}
|
||||
|
||||
u8 bNeedFrameCheck;
|
||||
u8 bNeedZCheck;
|
||||
u8 bNeedTexCheck;
|
||||
u8 dummy0;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
u8 bTexConstsSync; // only pixel shader constants that context owns
|
||||
u8 bVarsTexSync; // texture info
|
||||
u8 bVarsSetTarg;
|
||||
u8 dummy1;
|
||||
};
|
||||
|
||||
u32 bSyncVars;
|
||||
};
|
||||
|
||||
int ictx;
|
||||
VertexGPU* pBufferData; // current allocated data
|
||||
|
||||
int nNumVertices; // size of pBufferData in terms of VertexGPU objects
|
||||
int nCount;
|
||||
primInfo curprim; // the previous prim the current buffers are set to
|
||||
|
||||
zbufInfo zbuf;
|
||||
frameInfo gsfb; // the real info set by FRAME cmd
|
||||
frameInfo frame;
|
||||
int zprimmask; // zmask for incoming points
|
||||
|
||||
union
|
||||
{
|
||||
u32 uCurTex0Data[2]; // current tex0 data
|
||||
GIFRegTEX0 uCurTex0;
|
||||
};
|
||||
u32 uNextTex0Data[2]; // tex0 data that has to be applied if bNeedTexCheck is 1
|
||||
|
||||
//int nFrameHeights[8]; // frame heights for the past frame changes
|
||||
int nNextFrameHeight;
|
||||
|
||||
CMemoryTarget* pmemtarg; // the current mem target set
|
||||
CRenderTarget* prndr;
|
||||
CDepthTarget* pdepth;
|
||||
|
||||
};
|
||||
|
||||
// VB variables
|
||||
extern VB vb[2];
|
||||
|
||||
#endif // ZZOGLVB_H_INCLUDED
|
|
@ -1,480 +0,0 @@
|
|||
/******************************************************************************
|
||||
|
||||
Copyright (c) 2001 Advanced Micro Devices, Inc.
|
||||
|
||||
LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED *AS IS* WITHOUT ANY
|
||||
EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY,
|
||||
NONINFRINGEMENT OF THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY
|
||||
PARTICULAR PURPOSE. IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY
|
||||
DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS,
|
||||
BUSINESS INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR
|
||||
INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION OR LIMITATION
|
||||
OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY
|
||||
NOT APPLY TO YOU.
|
||||
|
||||
AMD does not assume any responsibility for any errors which may appear in the
|
||||
Materials nor any responsibility to support or update the Materials. AMD retains
|
||||
the right to make changes to its test specifications at any time, without notice.
|
||||
|
||||
NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
|
||||
further information, software, technical information, know-how, or show-how
|
||||
available to you.
|
||||
|
||||
So that all may benefit from your experience, please report any problems
|
||||
or suggestions about this software to 3dsdk.support@amd.com
|
||||
|
||||
AMD Developer Technologies, M/S 585
|
||||
Advanced Micro Devices, Inc.
|
||||
5900 E. Ben White Blvd.
|
||||
Austin, TX 78741
|
||||
3dsdk.support@amd.com
|
||||
******************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*****************************************************************************
|
||||
MEMCPY_AMD.CPP
|
||||
******************************************************************************/
|
||||
|
||||
// Very optimized memcpy() routine for AMD Athlon and Duron family.
|
||||
// This code uses any of FOUR different basic copy methods, depending
|
||||
// on the transfer size.
|
||||
// NOTE: Since this code uses MOVNTQ (also known as "Non-Temporal MOV" or
|
||||
// "Streaming Store"), and also uses the software prefetch instructions,
|
||||
// be sure you're running on Athlon/Duron or other recent CPU before calling!
|
||||
|
||||
#define TINY_BLOCK_COPY 64 // upper limit for movsd type copy
|
||||
// The smallest copy uses the X86 "movsd" instruction, in an optimized
|
||||
// form which is an "unrolled loop".
|
||||
|
||||
#define IN_CACHE_COPY 2 * 1024 // upper limit for movq/movq copy w/SW prefetch
|
||||
// Next is a copy that uses the MMX registers to copy 8 bytes at a time,
|
||||
// also using the "unrolled loop" optimization. This code uses
|
||||
// the software prefetch instruction to get the data into the cache.
|
||||
|
||||
#define UNCACHED_COPY 4 * 1024 // upper limit for movq/movntq w/SW prefetch
|
||||
// For larger blocks, which will spill beyond the cache, it's faster to
|
||||
// use the Streaming Store instruction MOVNTQ. This write instruction
|
||||
// bypasses the cache and writes straight to main memory. This code also
|
||||
// uses the software prefetch instruction to pre-read the data.
|
||||
// USE 64 * 1024 FOR THIS VALUE IF YOU'RE ALWAYS FILLING A "CLEAN CACHE"
|
||||
|
||||
#define BLOCK_PREFETCH_COPY infinity // no limit for movq/movntq w/block prefetch
|
||||
#define CACHEBLOCK 80h // number of 64-byte blocks (cache lines) for block prefetch
|
||||
// For the largest size blocks, a special technique called Block Prefetch
|
||||
// can be used to accelerate the read operations. Block Prefetch reads
|
||||
// one address per cache line, for a series of cache lines, in a short loop.
|
||||
// This is faster than using software prefetch. The technique is great for
|
||||
// getting maximum read bandwidth, especially in DDR memory systems.
|
||||
|
||||
//#include <stddef.h>
|
||||
|
||||
// Inline assembly syntax for use with Visual C++
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__x86_64__)
|
||||
|
||||
#include "PS2Etypes.h"
|
||||
|
||||
extern "C" {
|
||||
void * memcpy_amd(void *dest, const void *src, size_t n)
|
||||
{
|
||||
__asm {
|
||||
mov ecx, [n] ; number of bytes to copy
|
||||
mov edi, [dest] ; destination
|
||||
mov esi, [src] ; source
|
||||
mov ebx, ecx ; keep a copy of count
|
||||
|
||||
cld
|
||||
cmp ecx, TINY_BLOCK_COPY
|
||||
jb $memcpy_ic_3 ; tiny? skip mmx copy
|
||||
|
||||
cmp ecx, 32*1024 ; don't align between 32k-64k because
|
||||
jbe $memcpy_do_align ; it appears to be slower
|
||||
cmp ecx, 64*1024
|
||||
jbe $memcpy_align_done
|
||||
$memcpy_do_align:
|
||||
mov ecx, 8 ; a trick that's faster than rep movsb...
|
||||
sub ecx, edi ; align destination to qword
|
||||
and ecx, 111b ; get the low bits
|
||||
sub ebx, ecx ; update copy count
|
||||
neg ecx ; set up to jump into the array
|
||||
add ecx, offset $memcpy_align_done
|
||||
jmp ecx ; jump to array of movsb's
|
||||
|
||||
align 4
|
||||
movsb
|
||||
movsb
|
||||
movsb
|
||||
movsb
|
||||
movsb
|
||||
movsb
|
||||
movsb
|
||||
movsb
|
||||
|
||||
$memcpy_align_done: ; destination is dword aligned
|
||||
mov ecx, ebx ; number of bytes left to copy
|
||||
shr ecx, 6 ; get 64-byte block count
|
||||
jz $memcpy_ic_2 ; finish the last few bytes
|
||||
|
||||
cmp ecx, IN_CACHE_COPY/64 ; too big 4 cache? use uncached copy
|
||||
jae $memcpy_uc_test
|
||||
|
||||
// This is small block copy that uses the MMX registers to copy 8 bytes
|
||||
// at a time. It uses the "unrolled loop" optimization, and also uses
|
||||
// the software prefetch instruction to get the data into the cache.
|
||||
align 16
|
||||
$memcpy_ic_1: ; 64-byte block copies, in-cache copy
|
||||
|
||||
prefetchnta [esi + (200*64/34+192)] ; start reading ahead
|
||||
|
||||
movq mm0, [esi+0] ; read 64 bits
|
||||
movq mm1, [esi+8]
|
||||
movq [edi+0], mm0 ; write 64 bits
|
||||
movq [edi+8], mm1 ; note: the normal movq writes the
|
||||
movq mm2, [esi+16] ; data to cache; a cache line will be
|
||||
movq mm3, [esi+24] ; allocated as needed, to store the data
|
||||
movq [edi+16], mm2
|
||||
movq [edi+24], mm3
|
||||
movq mm0, [esi+32]
|
||||
movq mm1, [esi+40]
|
||||
movq [edi+32], mm0
|
||||
movq [edi+40], mm1
|
||||
movq mm2, [esi+48]
|
||||
movq mm3, [esi+56]
|
||||
movq [edi+48], mm2
|
||||
movq [edi+56], mm3
|
||||
|
||||
add esi, 64 ; update source pointer
|
||||
add edi, 64 ; update destination pointer
|
||||
dec ecx ; count down
|
||||
jnz $memcpy_ic_1 ; last 64-byte block?
|
||||
|
||||
$memcpy_ic_2:
|
||||
mov ecx, ebx ; has valid low 6 bits of the byte count
|
||||
$memcpy_ic_3:
|
||||
shr ecx, 2 ; dword count
|
||||
and ecx, 1111b ; only look at the "remainder" bits
|
||||
neg ecx ; set up to jump into the array
|
||||
add ecx, offset $memcpy_last_few
|
||||
jmp ecx ; jump to array of movsd's
|
||||
|
||||
$memcpy_uc_test:
|
||||
cmp ecx, UNCACHED_COPY/64 ; big enough? use block prefetch copy
|
||||
jae $memcpy_bp_1
|
||||
|
||||
$memcpy_64_test:
|
||||
or ecx, ecx ; tail end of block prefetch will jump here
|
||||
jz $memcpy_ic_2 ; no more 64-byte blocks left
|
||||
|
||||
// For larger blocks, which will spill beyond the cache, it's faster to
|
||||
// use the Streaming Store instruction MOVNTQ. This write instruction
|
||||
// bypasses the cache and writes straight to main memory. This code also
|
||||
// uses the software prefetch instruction to pre-read the data.
|
||||
align 16
|
||||
$memcpy_uc_1: ; 64-byte blocks, uncached copy
|
||||
|
||||
prefetchnta [esi + (200*64/34+192)] ; start reading ahead
|
||||
|
||||
movq mm0,[esi+0] ; read 64 bits
|
||||
add edi,64 ; update destination pointer
|
||||
movq mm1,[esi+8]
|
||||
add esi,64 ; update source pointer
|
||||
movq mm2,[esi-48]
|
||||
movntq [edi-64], mm0 ; write 64 bits, bypassing the cache
|
||||
movq mm0,[esi-40] ; note: movntq also prevents the CPU
|
||||
movntq [edi-56], mm1 ; from READING the destination address
|
||||
movq mm1,[esi-32] ; into the cache, only to be over-written
|
||||
movntq [edi-48], mm2 ; so that also helps performance
|
||||
movq mm2,[esi-24]
|
||||
movntq [edi-40], mm0
|
||||
movq mm0,[esi-16]
|
||||
movntq [edi-32], mm1
|
||||
movq mm1,[esi-8]
|
||||
movntq [edi-24], mm2
|
||||
movntq [edi-16], mm0
|
||||
dec ecx
|
||||
movntq [edi-8], mm1
|
||||
jnz $memcpy_uc_1 ; last 64-byte block?
|
||||
|
||||
jmp $memcpy_ic_2 ; almost done
|
||||
|
||||
// For the largest size blocks, a special technique called Block Prefetch
|
||||
// can be used to accelerate the read operations. Block Prefetch reads
|
||||
// one address per cache line, for a series of cache lines, in a short loop.
|
||||
// This is faster than using software prefetch. The technique is great for
|
||||
// getting maximum read bandwidth, especially in DDR memory systems.
|
||||
$memcpy_bp_1: ; large blocks, block prefetch copy
|
||||
|
||||
cmp ecx, CACHEBLOCK ; big enough to run another prefetch loop?
|
||||
jl $memcpy_64_test ; no, back to regular uncached copy
|
||||
|
||||
mov eax, CACHEBLOCK / 2 ; block prefetch loop, unrolled 2X
|
||||
add esi, CACHEBLOCK * 64 ; move to the top of the block
|
||||
align 16
|
||||
$memcpy_bp_2:
|
||||
mov edx, [esi-64] ; grab one address per cache line
|
||||
mov edx, [esi-128] ; grab one address per cache line
|
||||
sub esi, 128 ; go reverse order to suppress HW prefetcher
|
||||
dec eax ; count down the cache lines
|
||||
jnz $memcpy_bp_2 ; keep grabbing more lines into cache
|
||||
|
||||
mov eax, CACHEBLOCK ; now that it's in cache, do the copy
|
||||
align 16
|
||||
$memcpy_bp_3:
|
||||
movq mm0, [esi ] ; read 64 bits
|
||||
movq mm1, [esi+ 8]
|
||||
movq mm2, [esi+16]
|
||||
movq mm3, [esi+24]
|
||||
movq mm4, [esi+32]
|
||||
movq mm5, [esi+40]
|
||||
movq mm6, [esi+48]
|
||||
movq mm7, [esi+56]
|
||||
add esi, 64 ; update source pointer
|
||||
movntq [edi ], mm0 ; write 64 bits, bypassing cache
|
||||
movntq [edi+ 8], mm1 ; note: movntq also prevents the CPU
|
||||
movntq [edi+16], mm2 ; from READING the destination address
|
||||
movntq [edi+24], mm3 ; into the cache, only to be over-written,
|
||||
movntq [edi+32], mm4 ; so that also helps performance
|
||||
movntq [edi+40], mm5
|
||||
movntq [edi+48], mm6
|
||||
movntq [edi+56], mm7
|
||||
add edi, 64 ; update dest pointer
|
||||
|
||||
dec eax ; count down
|
||||
|
||||
jnz $memcpy_bp_3 ; keep copying
|
||||
sub ecx, CACHEBLOCK ; update the 64-byte block count
|
||||
jmp $memcpy_bp_1 ; keep processing chunks
|
||||
|
||||
// The smallest copy uses the X86 "movsd" instruction, in an optimized
|
||||
// form which is an "unrolled loop". Then it handles the last few bytes.
|
||||
align 4
|
||||
movsd
|
||||
movsd ; perform last 1-15 dword copies
|
||||
movsd
|
||||
movsd
|
||||
movsd
|
||||
movsd
|
||||
movsd
|
||||
movsd
|
||||
movsd
|
||||
movsd ; perform last 1-7 dword copies
|
||||
movsd
|
||||
movsd
|
||||
movsd
|
||||
movsd
|
||||
movsd
|
||||
movsd
|
||||
|
||||
$memcpy_last_few: ; dword aligned from before movsd's
|
||||
mov ecx, ebx ; has valid low 2 bits of the byte count
|
||||
and ecx, 11b ; the last few cows must come home
|
||||
jz $memcpy_final ; no more, let's leave
|
||||
rep movsb ; the last 1, 2, or 3 bytes
|
||||
|
||||
$memcpy_final:
|
||||
emms ; clean up the MMX state
|
||||
sfence ; flush the write buffer
|
||||
mov eax, [dest] ; ret value = destination pointer
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// mmx memcpy implementation, size has to be a multiple of 8
|
||||
// returns 0 is equal, nonzero value if not equal
|
||||
// ~10 times faster than standard memcmp
|
||||
// (zerofrog)
|
||||
u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize)
|
||||
{
|
||||
assert( (cmpsize&7) == 0 );
|
||||
|
||||
__asm {
|
||||
push esi
|
||||
mov ecx, cmpsize
|
||||
mov edx, src1
|
||||
mov esi, src2
|
||||
|
||||
cmp ecx, 32
|
||||
jl Done4
|
||||
|
||||
// custom test first 8 to make sure things are ok
|
||||
movq mm0, [esi]
|
||||
movq mm1, [esi+8]
|
||||
pcmpeqd mm0, [edx]
|
||||
pcmpeqd mm1, [edx+8]
|
||||
pand mm0, mm1
|
||||
movq mm2, [esi+16]
|
||||
pmovmskb eax, mm0
|
||||
movq mm3, [esi+24]
|
||||
|
||||
// check if eq
|
||||
cmp eax, 0xff
|
||||
je NextComp
|
||||
mov eax, 1
|
||||
jmp End
|
||||
|
||||
NextComp:
|
||||
pcmpeqd mm2, [edx+16]
|
||||
pcmpeqd mm3, [edx+24]
|
||||
pand mm2, mm3
|
||||
pmovmskb eax, mm2
|
||||
|
||||
sub ecx, 32
|
||||
add esi, 32
|
||||
add edx, 32
|
||||
|
||||
// check if eq
|
||||
cmp eax, 0xff
|
||||
je ContinueTest
|
||||
mov eax, 1
|
||||
jmp End
|
||||
|
||||
cmp ecx, 64
|
||||
jl Done8
|
||||
|
||||
Cmp8:
|
||||
movq mm0, [esi]
|
||||
movq mm1, [esi+8]
|
||||
movq mm2, [esi+16]
|
||||
movq mm3, [esi+24]
|
||||
movq mm4, [esi+32]
|
||||
movq mm5, [esi+40]
|
||||
movq mm6, [esi+48]
|
||||
movq mm7, [esi+56]
|
||||
pcmpeqd mm0, [edx]
|
||||
pcmpeqd mm1, [edx+8]
|
||||
pcmpeqd mm2, [edx+16]
|
||||
pcmpeqd mm3, [edx+24]
|
||||
pand mm0, mm1
|
||||
pcmpeqd mm4, [edx+32]
|
||||
pand mm0, mm2
|
||||
pcmpeqd mm5, [edx+40]
|
||||
pand mm0, mm3
|
||||
pcmpeqd mm6, [edx+48]
|
||||
pand mm0, mm4
|
||||
pcmpeqd mm7, [edx+56]
|
||||
pand mm0, mm5
|
||||
pand mm0, mm6
|
||||
pand mm0, mm7
|
||||
pmovmskb eax, mm0
|
||||
|
||||
// check if eq
|
||||
cmp eax, 0xff
|
||||
je Continue
|
||||
mov eax, 1
|
||||
jmp End
|
||||
|
||||
Continue:
|
||||
sub ecx, 64
|
||||
add esi, 64
|
||||
add edx, 64
|
||||
ContinueTest:
|
||||
cmp ecx, 64
|
||||
jge Cmp8
|
||||
|
||||
Done8:
|
||||
test ecx, 0x20
|
||||
jz Done4
|
||||
movq mm0, [esi]
|
||||
movq mm1, [esi+8]
|
||||
movq mm2, [esi+16]
|
||||
movq mm3, [esi+24]
|
||||
pcmpeqd mm0, [edx]
|
||||
pcmpeqd mm1, [edx+8]
|
||||
pcmpeqd mm2, [edx+16]
|
||||
pcmpeqd mm3, [edx+24]
|
||||
pand mm0, mm1
|
||||
pand mm0, mm2
|
||||
pand mm0, mm3
|
||||
pmovmskb eax, mm0
|
||||
sub ecx, 32
|
||||
add esi, 32
|
||||
add edx, 32
|
||||
|
||||
// check if eq
|
||||
cmp eax, 0xff
|
||||
je Done4
|
||||
mov eax, 1
|
||||
jmp End
|
||||
|
||||
Done4:
|
||||
cmp ecx, 24
|
||||
jne Done2
|
||||
movq mm0, [esi]
|
||||
movq mm1, [esi+8]
|
||||
movq mm2, [esi+16]
|
||||
pcmpeqd mm0, [edx]
|
||||
pcmpeqd mm1, [edx+8]
|
||||
pcmpeqd mm2, [edx+16]
|
||||
pand mm0, mm1
|
||||
pand mm0, mm2
|
||||
pmovmskb eax, mm0
|
||||
|
||||
// check if eq
|
||||
cmp eax, 0xff
|
||||
setne al
|
||||
jmp End
|
||||
|
||||
Done2:
|
||||
cmp ecx, 16
|
||||
jne Done1
|
||||
|
||||
movq mm0, [esi]
|
||||
movq mm1, [esi+8]
|
||||
pcmpeqd mm0, [edx]
|
||||
pcmpeqd mm1, [edx+8]
|
||||
pand mm0, mm1
|
||||
pmovmskb eax, mm0
|
||||
|
||||
// check if eq
|
||||
cmp eax, 0xff
|
||||
setne al
|
||||
jmp End
|
||||
|
||||
Done1:
|
||||
cmp ecx, 8
|
||||
jne Done
|
||||
|
||||
mov eax, [esi]
|
||||
mov esi, [esi+4]
|
||||
cmp eax, [edx]
|
||||
je Next
|
||||
mov eax, 1
|
||||
jmp End
|
||||
|
||||
Next:
|
||||
cmp esi, [edx+4]
|
||||
setne al
|
||||
jmp End
|
||||
|
||||
Done:
|
||||
xor eax, eax
|
||||
|
||||
End:
|
||||
pop esi
|
||||
emms
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#else // _MSC_VER
|
||||
// assume gcc or mingw or win x64
|
||||
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include "PS2Etypes.h"
|
||||
#include "Utilities/MemcpyFast.h"
|
||||
//void * memcpy_amd(void *dest, const void *src, size_t n)
|
||||
//{
|
||||
// //memcpy(dest, src, n);
|
||||
// memcpy_fast(dest, src, n);
|
||||
// return dest;
|
||||
//}
|
||||
#define memcpy_amd memcpy_fast
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -22,18 +22,214 @@
|
|||
|
||||
#define TARGET_VIRTUAL_KEY 0x80000000
|
||||
#include "PS2Edefs.h"
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include "GS.h"
|
||||
#include "ZZGl.h"
|
||||
//#include "ZZoglVB.h"
|
||||
|
||||
#ifndef GL_TEXTURE_RECTANGLE
|
||||
#define GL_TEXTURE_RECTANGLE GL_TEXTURE_RECTANGLE_NV
|
||||
#endif
|
||||
|
||||
namespace ZeroGS
|
||||
#define VB_BUFFERSIZE 0x4000
|
||||
|
||||
// all textures have this width
|
||||
extern int GPU_TEXWIDTH;
|
||||
extern float g_fiGPU_TEXWIDTH;
|
||||
#define MASKDIVISOR 0 // Used for decrement bitwise mask texture size if 1024 is too big
|
||||
#define GPU_TEXMASKWIDTH (1024 >> MASKDIVISOR) // bitwise mask width for region repeat mode
|
||||
|
||||
// managers render-to-texture targets
|
||||
class CRenderTarget
|
||||
{
|
||||
|
||||
inline u32 GetFrameKey(int fbp, int fbw, VB& curvb);
|
||||
public:
|
||||
CRenderTarget();
|
||||
virtual ~CRenderTarget();
|
||||
|
||||
virtual bool Create(const frameInfo& frame);
|
||||
virtual void Destroy();
|
||||
|
||||
// set the GPU_POSXY variable, scissor rect, and current render target
|
||||
void SetTarget(int fbplocal, const Rect2& scissor, int context);
|
||||
void SetViewport();
|
||||
|
||||
// copies/creates the feedback contents
|
||||
inline void CreateFeedback()
|
||||
{
|
||||
if (ptexFeedback == 0 || !(status&TS_FeedbackReady))
|
||||
_CreateFeedback();
|
||||
}
|
||||
|
||||
virtual void Resolve();
|
||||
virtual void Resolve(int startrange, int endrange); // resolves only in the allowed range
|
||||
virtual void Update(int context, CRenderTarget* pdepth);
|
||||
virtual void ConvertTo32(); // converts a psm==2 target, to a psm==0
|
||||
virtual void ConvertTo16(); // converts a psm==0 target, to a psm==2
|
||||
|
||||
virtual bool IsDepth() { return false; }
|
||||
|
||||
void SetRenderTarget(int targ);
|
||||
|
||||
void* psys; // system data used for comparison
|
||||
u32 ptex;
|
||||
|
||||
int fbp, fbw, fbh, fbhCalc; // if fbp is negative, virtual target (not mapped to any real addr)
|
||||
int start, end; // in bytes
|
||||
u32 lastused; // time stamp since last used
|
||||
float4 vposxy;
|
||||
|
||||
u32 fbm;
|
||||
u16 status;
|
||||
u8 psm;
|
||||
u8 resv0;
|
||||
Rect scissorrect;
|
||||
|
||||
u8 created; // Check for object destruction/creating for r201.
|
||||
|
||||
//int startresolve, endresolve;
|
||||
u32 nUpdateTarg; // use this target to update the texture if non 0 (one time only)
|
||||
|
||||
// this is optionally used when feedback effects are used (render target is used as a texture when rendering to itself)
|
||||
u32 ptexFeedback;
|
||||
|
||||
enum TargetStatus
|
||||
{
|
||||
TS_Resolved = 1,
|
||||
TS_NeedUpdate = 2,
|
||||
TS_Virtual = 4, // currently not mapped to memory
|
||||
TS_FeedbackReady = 8, // feedback effect is ready and doesn't need to be updated
|
||||
TS_NeedConvert32 = 16,
|
||||
TS_NeedConvert16 = 32,
|
||||
};
|
||||
inline float4 DefaultBitBltPos();
|
||||
inline float4 DefaultBitBltTex();
|
||||
|
||||
private:
|
||||
void _CreateFeedback();
|
||||
inline bool InitialiseDefaultTexture(u32 *p_ptr, int fbw, int fbh) ;
|
||||
};
|
||||
|
||||
// manages zbuffers
|
||||
|
||||
class CDepthTarget : public CRenderTarget
|
||||
{
|
||||
|
||||
public:
|
||||
CDepthTarget();
|
||||
virtual ~CDepthTarget();
|
||||
|
||||
virtual bool Create(const frameInfo& frame);
|
||||
virtual void Destroy();
|
||||
|
||||
virtual void Resolve();
|
||||
virtual void Resolve(int startrange, int endrange); // resolves only in the allowed range
|
||||
virtual void Update(int context, CRenderTarget* prndr);
|
||||
|
||||
virtual bool IsDepth() { return true; }
|
||||
|
||||
void SetDepthStencilSurface();
|
||||
|
||||
u32 pdepth; // 24 bit, will contain the stencil buffer if possible
|
||||
u32 pstencil; // if not 0, contains the stencil buffer
|
||||
int icount; // internal counter
|
||||
};
|
||||
|
||||
// manages contiguous chunks of memory (width is always 1024)
|
||||
|
||||
class CMemoryTarget
|
||||
{
|
||||
public:
|
||||
struct TEXTURE
|
||||
{
|
||||
inline TEXTURE() : tex(0), memptr(NULL), ref(0) {}
|
||||
inline ~TEXTURE() { glDeleteTextures(1, &tex); _aligned_free(memptr); }
|
||||
|
||||
u32 tex;
|
||||
u8* memptr; // GPU memory used for comparison
|
||||
int ref;
|
||||
};
|
||||
|
||||
inline CMemoryTarget() : ptex(NULL), starty(0), height(0), realy(0), realheight(0), usedstamp(0), psm(0), cpsm(0), channels(0), clearminy(0), clearmaxy(0), validatecount(0), clut(NULL), clutsize(0) {}
|
||||
|
||||
inline CMemoryTarget(const CMemoryTarget& r)
|
||||
{
|
||||
ptex = r.ptex;
|
||||
|
||||
if (ptex != NULL) ptex->ref++;
|
||||
|
||||
starty = r.starty;
|
||||
height = r.height;
|
||||
realy = r.realy;
|
||||
realheight = r.realheight;
|
||||
usedstamp = r.usedstamp;
|
||||
psm = r.psm;
|
||||
cpsm = r.cpsm;
|
||||
clut = r.clut;
|
||||
clearminy = r.clearminy;
|
||||
clearmaxy = r.clearmaxy;
|
||||
widthmult = r.widthmult;
|
||||
texH = r.texH;
|
||||
texW = r.texW;
|
||||
channels = r.channels;
|
||||
validatecount = r.validatecount;
|
||||
fmt = r.fmt;
|
||||
}
|
||||
|
||||
~CMemoryTarget() { Destroy(); }
|
||||
|
||||
inline void Destroy()
|
||||
{
|
||||
if (ptex != NULL && ptex->ref > 0)
|
||||
{
|
||||
if (--ptex->ref <= 0) delete ptex;
|
||||
}
|
||||
|
||||
ptex = NULL;
|
||||
|
||||
_aligned_free(clut);
|
||||
clut = NULL;
|
||||
clutsize = 0;
|
||||
}
|
||||
|
||||
// returns true if clut data is synced
|
||||
bool ValidateClut(const tex0Info& tex0);
|
||||
// returns true if tex data is synced
|
||||
bool ValidateTex(const tex0Info& tex0, int starttex, int endtex, bool bDeleteBadTex);
|
||||
|
||||
// realy is offset in pixels from start of valid region
|
||||
// so texture in memory is [realy,starty+height]
|
||||
// valid texture is [starty,starty+height]
|
||||
// offset in mem [starty-realy, height]
|
||||
TEXTURE* ptex; // can be 16bit
|
||||
|
||||
int starty, height; // assert(starty >= realy)
|
||||
int realy, realheight; // this is never touched once allocated
|
||||
// realy is start pointer of data in 4M data block (start) and size (end-start).
|
||||
|
||||
u32 usedstamp;
|
||||
u8 psm, cpsm; // texture and clut format. For psm, only 16bit/32bit differentiation matters
|
||||
|
||||
u32 fmt;
|
||||
|
||||
int widthmult; // Either 1 or 2.
|
||||
int channels; // The number of pixels per PSM format word. channels == PIXELS_PER_WORD(psm)
|
||||
// This is the real drawing size in pixels of the texture in renderbuffer.
|
||||
int texW; // (realheight + widthmult - 1)/widthmult == realheight or [(realheight+1)/2]
|
||||
int texH; // GPU_TEXWIDTH *widthmult * channels;
|
||||
|
||||
int clearminy, clearmaxy; // when maxy > 0, need to check for clearing
|
||||
|
||||
int validatecount; // count how many times has been validated, if too many, destroy
|
||||
|
||||
u8* clut; // Clut texture data. Null otherwise
|
||||
int clutsize; // size of the clut array. 0 otherwise
|
||||
};
|
||||
|
||||
inline u32 GetFrameKey(int fbp, int fbw);
|
||||
|
||||
// manages render targets
|
||||
|
||||
class CRenderTargetMngr
|
||||
{
|
||||
public:
|
||||
|
@ -54,22 +250,22 @@ class CRenderTargetMngr
|
|||
bool isFound(const frameInfo& frame, MAPTARGETS::iterator& it, u32 opts, u32 key, int maxposheight);
|
||||
|
||||
CRenderTarget* GetTarg(const frameInfo& frame, u32 Options, int maxposheight);
|
||||
inline CRenderTarget* GetTarg(int fbp, int fbw, VB& curvb)
|
||||
inline CRenderTarget* GetTarg(int fbp, int fbw)
|
||||
{
|
||||
MAPTARGETS::iterator it = mapTargets.find(GetFrameKey(fbp, fbw, curvb));
|
||||
MAPTARGETS::iterator it = mapTargets.find(GetFrameKey(fbp, fbw));
|
||||
|
||||
/* if (fbp == 0x3600 && fbw == 0x100 && it == mapTargets.end())
|
||||
{
|
||||
printf("%x\n", GetFrameKey(fbp, fbw, curvb)) ;
|
||||
printf("%x %x\n", fbp, fbw);
|
||||
ZZLog::Debug_Log("%x", GetFrameKey(fbp, fbw)) ;
|
||||
ZZLog::Debug_Log("%x %x", fbp, fbw);
|
||||
for(MAPTARGETS::iterator it1 = mapTargets.begin(); it1 != mapTargets.end(); ++it1)
|
||||
printf ("\t %x %x %x %x\n", it1->second->fbw, it1->second->fbh, it1->second->psm, it1->second->fbp);
|
||||
ZZLog::Debug_Log("\t %x %x %x %x", it1->second->fbw, it1->second->fbh, it1->second->psm, it1->second->fbp);
|
||||
}*/
|
||||
return it != mapTargets.end() ? it->second : NULL;
|
||||
}
|
||||
|
||||
// gets all targets with a range
|
||||
void GetTargs(int start, int end, list<ZeroGS::CRenderTarget*>& listTargets) const;
|
||||
void GetTargs(int start, int end, list<CRenderTarget*>& listTargets) const;
|
||||
|
||||
// resolves all targets within a range
|
||||
__forceinline void Resolve(int start, int end);
|
||||
|
@ -125,9 +321,9 @@ class CMemoryTargetMngr
|
|||
CMemoryTargetMngr() : curstamp(0) {}
|
||||
|
||||
CMemoryTarget* GetMemoryTarget(const tex0Info& tex0, int forcevalidate); // pcbp is pointer to start of clut
|
||||
CMemoryTarget* SearchExistTarget(int start, int end, int nClutOffset, int clutsize, const tex0Info& tex0, int forcevalidate);
|
||||
CMemoryTarget* SearchExistTarget(int start, int end, int clutsize, const tex0Info& tex0, int forcevalidate);
|
||||
CMemoryTarget* ClearedTargetsSearch(int fmt, int widthmult, int channels, int height);
|
||||
int CompareTarget(list<CMemoryTarget>::iterator& it, const tex0Info& tex0, int clutsize, int nClutOffset);
|
||||
int CompareTarget(list<CMemoryTarget>::iterator& it, const tex0Info& tex0, int clutsize);
|
||||
|
||||
void Destroy(); // destroy all targs
|
||||
|
||||
|
@ -140,7 +336,7 @@ class CMemoryTargetMngr
|
|||
|
||||
private:
|
||||
list<CMemoryTarget>::iterator DestroyTargetIter(list<CMemoryTarget>::iterator& it);
|
||||
void GetClutVariables(int& nClutOffset, int& clutsize, const tex0Info& tex0);
|
||||
void GetClutVariables(int& clutsize, const tex0Info& tex0);
|
||||
void GetMemAddress(int& start, int& end, const tex0Info& tex0);
|
||||
};
|
||||
|
||||
|
@ -202,6 +398,7 @@ class CRangeManager
|
|||
extern CRenderTargetMngr s_RTs, s_DepthRTs;
|
||||
extern CBitwiseTextureMngr s_BitwiseTextures;
|
||||
extern CMemoryTargetMngr g_MemTargs;
|
||||
extern CRangeManager s_RangeMngr; // manages overwritten memory
|
||||
|
||||
//extern u8 s_AAx, s_AAy;
|
||||
extern Point AA;
|
||||
|
@ -218,15 +415,15 @@ inline int RH(int tbh)
|
|||
return (tbh << AA.y);
|
||||
}
|
||||
|
||||
/* inline void CreateTargetsList(int start, int end, list<ZeroGS::CRenderTarget*>& listTargs) {
|
||||
/* inline void CreateTargetsList(int start, int end, list<CRenderTarget*>& listTargs) {
|
||||
s_DepthRTs.GetTargs(start, end, listTargs);
|
||||
s_RTs.GetTargs(start, end, listTargs);
|
||||
}*/
|
||||
|
||||
// This pattern of functions is called 3 times, so I add creating Targets list into one.
|
||||
inline list<ZeroGS::CRenderTarget*> CreateTargetsList(int start, int end)
|
||||
inline list<CRenderTarget*> CreateTargetsList(int start, int end)
|
||||
{
|
||||
list<ZeroGS::CRenderTarget*> listTargs;
|
||||
list<CRenderTarget*> listTargs;
|
||||
s_DepthRTs.GetTargs(start, end, listTargs);
|
||||
s_RTs.GetTargs(start, end, listTargs);
|
||||
return listTargs;
|
||||
|
@ -250,7 +447,7 @@ inline u32 GetFrameKey(CRenderTarget* frame)
|
|||
return (((frame->fbw) << 16) | (frame->fbp));
|
||||
}
|
||||
|
||||
inline u32 GetFrameKey(int fbp, int fbw, VB& curvb)
|
||||
inline u32 GetFrameKey(int fbp, int fbw)
|
||||
{
|
||||
return (((fbw) << 16) | (fbp));
|
||||
}
|
||||
|
@ -290,8 +487,6 @@ inline u32 GetFrameKeyDummy(CRenderTarget* frame)
|
|||
return GetFrameKeyDummy(frame->fbp, frame->fbw, frame->fbh, frame->psm);
|
||||
}
|
||||
|
||||
} // End of namespace
|
||||
|
||||
#include "Mem.h"
|
||||
|
||||
static __forceinline void DrawTriangleArray()
|
||||
|
@ -316,6 +511,11 @@ static __forceinline void FBTexture(int attach, int id = 0)
|
|||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
static __forceinline void ResetRenderTarget(int index)
|
||||
{
|
||||
FBTexture(index);
|
||||
}
|
||||
|
||||
static __forceinline void Texture2D(GLint iFormat, GLint width, GLint height, GLenum format, GLenum type, const GLvoid* pixels)
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, iFormat, width, height, 0, format, type, pixels);
|
||||
|
@ -388,5 +588,20 @@ static __forceinline void setRectWrap2(GLint type)
|
|||
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, type);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, type);
|
||||
}
|
||||
|
||||
|
||||
//------------------------ Inlines -------------------------
|
||||
|
||||
// Calculate maximum height for target
|
||||
inline int get_maxheight(int fbp, int fbw, int psm)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (fbw == 0) return 0;
|
||||
|
||||
ret = (((0x00100000 - 64 * fbp) / fbw) & ~0x1f);
|
||||
if (PSMT_ISHALF(psm)) ret *= 2;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -594,6 +594,7 @@ void __fastcall Frame16SwizzleBlock16ZA4_c(u16* dst, Vector_16F* src, int srcpit
|
|||
// }
|
||||
//}
|
||||
|
||||
#if 0
|
||||
extern "C" void __fastcall WriteCLUT_T32_I8_CSM1_sse2(u32* vm, u32* clut)
|
||||
{
|
||||
__m128i* src = (__m128i*)vm;
|
||||
|
@ -626,6 +627,7 @@ extern "C" void __fastcall WriteCLUT_T32_I8_CSM1_sse2(u32* vm, u32* clut)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C" void __fastcall WriteCLUT_T32_I4_CSM1_sse2(u32* vm, u32* clut)
|
||||
{
|
||||
__m128i* src = (__m128i*)vm;
|
||||
|
@ -642,13 +644,116 @@ extern "C" void __fastcall WriteCLUT_T32_I4_CSM1_sse2(u32* vm, u32* clut)
|
|||
_mm_store_si128(&dst[3], _mm_unpackhi_epi64(r2, r3));
|
||||
}
|
||||
|
||||
|
||||
static const __aligned16 int s_clut_16bits_mask[4] = { 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff };
|
||||
static const __aligned16 int s_clut16mask2[4] = { 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff };
|
||||
static const __aligned16 int s_clut16mask[8] = { 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000,
|
||||
0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff
|
||||
};
|
||||
|
||||
extern "C" void __fastcall WriteCLUT_T16_I4_CSM1_sse2(u32* vm, u32* clut)
|
||||
template<bool CSA_0_15, bool HIGH_16BITS_VM>
|
||||
void __fastcall WriteCLUT_T16_I4_CSM1_core_sse2(u32* vm, u32* clut)
|
||||
{
|
||||
__m128i vm_0;
|
||||
__m128i vm_1;
|
||||
__m128i vm_2;
|
||||
__m128i vm_3;
|
||||
__m128i clut_0;
|
||||
__m128i clut_1;
|
||||
__m128i clut_2;
|
||||
__m128i clut_3;
|
||||
|
||||
__m128i clut_mask = _mm_load_si128((__m128i*)s_clut_16bits_mask);
|
||||
|
||||
// !HIGH_16BITS_VM
|
||||
// CSA in 0-15
|
||||
// Replace lower 16 bits of clut0 with lower 16 bits of vm
|
||||
// CSA in 16-31
|
||||
// Replace higher 16 bits of clut0 with lower 16 bits of vm
|
||||
|
||||
// HIGH_16BITS_VM
|
||||
// CSA in 0-15
|
||||
// Replace lower 16 bits of clut0 with higher 16 bits of vm
|
||||
// CSA in 16-31
|
||||
// Replace higher 16 bits of clut0 with higher 16 bits of vm
|
||||
if(HIGH_16BITS_VM && CSA_0_15) {
|
||||
// move up to low
|
||||
vm_0 = _mm_load_si128((__m128i*)vm); // 9 8 1 0
|
||||
vm_1 = _mm_load_si128((__m128i*)vm+1); // 11 10 3 2
|
||||
vm_2 = _mm_load_si128((__m128i*)vm+2); // 13 12 5 4
|
||||
vm_3 = _mm_load_si128((__m128i*)vm+3); // 15 14 7 6
|
||||
vm_0 = _mm_srli_epi32(vm_0, 16);
|
||||
vm_1 = _mm_srli_epi32(vm_1, 16);
|
||||
vm_2 = _mm_srli_epi32(vm_2, 16);
|
||||
vm_3 = _mm_srli_epi32(vm_3, 16);
|
||||
} else if(HIGH_16BITS_VM && !CSA_0_15) {
|
||||
// Remove lower 16 bits
|
||||
vm_0 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)vm)); // 9 8 1 0
|
||||
vm_1 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)vm+1)); // 11 10 3 2
|
||||
vm_2 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)vm+2)); // 13 12 5 4
|
||||
vm_3 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)vm+3)); // 15 14 7 6
|
||||
} else if(!HIGH_16BITS_VM && CSA_0_15) {
|
||||
// Remove higher 16 bits
|
||||
vm_0 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)vm)); // 9 8 1 0
|
||||
vm_1 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)vm+1)); // 11 10 3 2
|
||||
vm_2 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)vm+2)); // 13 12 5 4
|
||||
vm_3 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)vm+3)); // 15 14 7 6
|
||||
} else if(!HIGH_16BITS_VM && !CSA_0_15) {
|
||||
// move low to high
|
||||
vm_0 = _mm_load_si128((__m128i*)vm); // 9 8 1 0
|
||||
vm_1 = _mm_load_si128((__m128i*)vm+1); // 11 10 3 2
|
||||
vm_2 = _mm_load_si128((__m128i*)vm+2); // 13 12 5 4
|
||||
vm_3 = _mm_load_si128((__m128i*)vm+3); // 15 14 7 6
|
||||
vm_0 = _mm_slli_epi32(vm_0, 16);
|
||||
vm_1 = _mm_slli_epi32(vm_1, 16);
|
||||
vm_2 = _mm_slli_epi32(vm_2, 16);
|
||||
vm_3 = _mm_slli_epi32(vm_3, 16);
|
||||
}
|
||||
|
||||
// Unsizzle the data
|
||||
__m128i row_0 = _mm_unpacklo_epi32(vm_0, vm_1); // 3 2 1 0
|
||||
__m128i row_1 = _mm_unpacklo_epi32(vm_2, vm_3); // 7 6 5 4
|
||||
__m128i row_2 = _mm_unpackhi_epi32(vm_0, vm_1); // 11 10 9 8
|
||||
__m128i row_3 = _mm_unpackhi_epi32(vm_2, vm_3); // 15 14 13 12
|
||||
|
||||
// load old data & remove useless part
|
||||
if(CSA_0_15) {
|
||||
// Remove lower 16 bits
|
||||
clut_0 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut));
|
||||
clut_1 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut+1));
|
||||
clut_2 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut+2));
|
||||
clut_3 = _mm_andnot_si128(clut_mask, _mm_load_si128((__m128i*)clut+3));
|
||||
} else {
|
||||
// Remove higher 16 bits
|
||||
clut_0 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut));
|
||||
clut_1 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut+1));
|
||||
clut_2 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut+2));
|
||||
clut_3 = _mm_and_si128(clut_mask, _mm_load_si128((__m128i*)clut+3));
|
||||
}
|
||||
|
||||
// Merge old & new data
|
||||
clut_0 = _mm_or_si128(clut_0, row_0);
|
||||
clut_1 = _mm_or_si128(clut_1, row_1);
|
||||
clut_2 = _mm_or_si128(clut_2, row_2);
|
||||
clut_3 = _mm_or_si128(clut_3, row_3);
|
||||
|
||||
_mm_store_si128((__m128i*)clut, clut_0);
|
||||
_mm_store_si128((__m128i*)clut+1, clut_1);
|
||||
_mm_store_si128((__m128i*)clut+2, clut_2);
|
||||
_mm_store_si128((__m128i*)clut+3, clut_3);
|
||||
}
|
||||
|
||||
extern "C" void __fastcall WriteCLUT_T16_I4_CSM1_sse2(u32* vm, u32 csa)
|
||||
{
|
||||
u32* clut = (u32*)(g_pbyGSClut + 64*(csa & 15));
|
||||
|
||||
if (csa > 15) {
|
||||
WriteCLUT_T16_I4_CSM1_core_sse2<false, false>(vm, clut);
|
||||
} else {
|
||||
WriteCLUT_T16_I4_CSM1_core_sse2<true, false>(vm, clut);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void __fastcall WriteCLUT_T16_I4_CSM1_sse2_old(u32* vm, u32* clut)
|
||||
{
|
||||
#define YET_ANOTHER_INTRINSIC
|
||||
#ifdef YET_ANOTHER_INTRINSIC
|
||||
|
@ -677,7 +782,7 @@ extern "C" void __fastcall WriteCLUT_T16_I4_CSM1_sse2(u32* vm, u32* clut)
|
|||
|
||||
// Note: MSVC complains about direct c-cast...
|
||||
// vm2 = (__m128i)_mm_shuffle_ps((__m128)vm2, (__m128)vm3, 0x88);
|
||||
__m128 vm2_f = (_mm_shuffle_ps((__m128&)vm2, (__m128&)vm3, 0x88)); // 14 12 10 8 6 4 2 0
|
||||
__m128 vm2_f = (_mm_shuffle_ps((__m128&)vm2, (__m128&)vm3, 0x88));
|
||||
vm2 = (__m128i&)vm2_f;
|
||||
vm2 = _mm_shuffle_epi32(vm2, 0xD8);
|
||||
|
||||
|
@ -997,8 +1102,47 @@ End:
|
|||
#endif
|
||||
}
|
||||
|
||||
__forceinline void WriteCLUT_T16_I8_CSM1_sse2(u32* vm, u32 csa)
|
||||
{
|
||||
// update the right clut column (csa < 16)
|
||||
u32* clut = (u32*)(g_pbyGSClut + 64*(csa & 15));
|
||||
u32 csa_right = (csa < 16) ? 16 - csa : 0;
|
||||
|
||||
for(int i = (csa_right/2); i > 0 ; --i) {
|
||||
WriteCLUT_T16_I4_CSM1_core_sse2<true,false>(vm, clut);
|
||||
clut += 16;
|
||||
WriteCLUT_T16_I4_CSM1_core_sse2<true,true>(vm, clut);
|
||||
clut += 16;
|
||||
vm += 16; // go down one column
|
||||
}
|
||||
|
||||
// update the left clut column
|
||||
u32 csa_left = (csa >= 16) ? 16 : csa;
|
||||
|
||||
// In case csa_right is odd (so csa_left is also odd), we cross the clut column
|
||||
if(csa_right & 0x1) {
|
||||
WriteCLUT_T16_I4_CSM1_core_sse2<true,false>(vm, clut);
|
||||
// go back to the base before processing left clut column
|
||||
clut = (u32*)(g_pbyGSClut);
|
||||
WriteCLUT_T16_I4_CSM1_core_sse2<false,true>(vm, clut);
|
||||
} else if(csa_right != 0) {
|
||||
// go back to the base before processing left clut column
|
||||
clut = (u32*)(g_pbyGSClut);
|
||||
}
|
||||
|
||||
for(int i = (csa_left/2); i > 0 ; --i) {
|
||||
WriteCLUT_T16_I4_CSM1_core_sse2<false,false>(vm, clut);
|
||||
clut += 16;
|
||||
WriteCLUT_T16_I4_CSM1_core_sse2<false,true>(vm, clut);
|
||||
clut += 16;
|
||||
vm += 16; // go down one column
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ZEROGS_SSE2
|
||||
|
||||
#if 0
|
||||
void __fastcall WriteCLUT_T16_I8_CSM1_c(u32* _vm, u32* _clut)
|
||||
{
|
||||
const static u32 map[] =
|
||||
|
@ -1110,6 +1254,8 @@ void __fastcall WriteCLUT_T32_I4_CSM1_c(u32* vm, u32* clut)
|
|||
dst[7] = src[7];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void SSE2_UnswizzleZ16Target(u16* dst, u16* src, int iters)
|
||||
{
|
||||
|
||||
|
|
|
@ -96,9 +96,11 @@ extern void __fastcall SwizzleColumn16_c(int y, u8* dst, u8* src, int srcpitch);
|
|||
extern void __fastcall SwizzleColumn8_c(int y, u8* dst, u8* src, int srcpitch);
|
||||
extern void __fastcall SwizzleColumn4_c(int y, u8* dst, u8* src, int srcpitch);
|
||||
|
||||
extern "C" void __fastcall WriteCLUT_T16_I8_CSM1_sse2(u32* vm, u32* clut);
|
||||
// extern "C" void __fastcall WriteCLUT_T16_I8_CSM1_sse2(u32* vm, u32* clut);
|
||||
extern "C" void __fastcall WriteCLUT_T16_I8_CSM1_sse2(u32* vm, u32 csa);
|
||||
extern "C" void __fastcall WriteCLUT_T32_I8_CSM1_sse2(u32* vm, u32* clut);
|
||||
extern "C" void __fastcall WriteCLUT_T16_I4_CSM1_sse2(u32* vm, u32* clut);
|
||||
// extern "C" void __fastcall WriteCLUT_T16_I4_CSM1_sse2(u32* vm, u32* clut);
|
||||
extern "C" void __fastcall WriteCLUT_T16_I4_CSM1_sse2(u32* vm, u32 csa);
|
||||
extern "C" void __fastcall WriteCLUT_T32_I4_CSM1_sse2(u32* vm, u32* clut);
|
||||
extern void __fastcall WriteCLUT_T16_I8_CSM1_c(u32* vm, u32* clut);
|
||||
extern void __fastcall WriteCLUT_T32_I8_CSM1_c(u32* vm, u32* clut);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -25,523 +25,62 @@
|
|||
#endif
|
||||
|
||||
// ----------------------------- Includes
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <math.h>
|
||||
|
||||
#include "ZZGl.h"
|
||||
#include "GS.h"
|
||||
#include "CRC.h"
|
||||
#include "rasterfont.h" // simple font
|
||||
|
||||
using namespace std;
|
||||
|
||||
//------------------------ Constants ----------------------
|
||||
#define VB_BUFFERSIZE 0x400
|
||||
|
||||
// Used in a logarithmic Z-test, as (1-o(1))/log(MAX_U32).
|
||||
const float g_filog32 = 0.999f / (32.0f * logf(2.0f));
|
||||
|
||||
//------------------------ Inlines -------------------------
|
||||
|
||||
// Calculate maximum height for target
|
||||
inline int get_maxheight(int fbp, int fbw, int psm)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (fbw == 0) return 0;
|
||||
|
||||
ret = (((0x00100000 - 64 * fbp) / fbw) & ~0x1f);
|
||||
if (PSMT_ISHALF(psm)) ret *= 2;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include "PS2Edefs.h"
|
||||
// ------------------------ Variables -------------------------
|
||||
|
||||
// all textures have this width
|
||||
extern int GPU_TEXWIDTH;
|
||||
extern float g_fiGPU_TEXWIDTH;
|
||||
#define MASKDIVISOR 0 // Used for decrement bitwise mask texture size if 1024 is too big
|
||||
#define GPU_TEXMASKWIDTH (1024 >> MASKDIVISOR) // bitwise mask width for region repeat mode
|
||||
|
||||
extern u32 ptexBlocks; // holds information on block tiling. It's texture number in OpenGL -- if 0 than such texture
|
||||
extern u32 ptexConv16to32; // does not exists. This textures should be created on start and released on finish.
|
||||
extern u32 ptexBilinearBlocks;
|
||||
extern u32 ptexConv32to16;
|
||||
|
||||
// this is currently *not* used as a bool, in spite of its moniker --air
|
||||
// Actually, the only thing written to it is 1 or 0, which makes the (g_bSaveFlushedFrame & 0x80000000) check rather bizzare.
|
||||
//extern u32 g_bSaveFlushedFrame;
|
||||
|
||||
//////////////////////////
|
||||
// State parameters
|
||||
|
||||
|
||||
#ifdef ZEROGS_DEVBUILD
|
||||
extern char* EFFECT_NAME;
|
||||
extern char* EFFECT_DIR;
|
||||
extern u32 g_nGenVars, g_nTexVars, g_nAlphaVars, g_nResolve;
|
||||
extern bool g_bSaveTrans, g_bUpdateEffect, g_bSaveTex, g_bSaveResolved;
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
# include "resource.h"
|
||||
#endif
|
||||
|
||||
extern u32 s_uFramebuffer;
|
||||
extern int g_nPixelShaderVer;
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "GS.h"
|
||||
#include "targets.h"
|
||||
#include "GLWin.h"
|
||||
#include "ZZoglShaders.h"
|
||||
#include "ZZClut.h"
|
||||
#include "HostMemory.h"
|
||||
|
||||
typedef void (APIENTRYP _PFNSWAPINTERVAL)(int);
|
||||
|
||||
PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT = NULL;
|
||||
PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL;
|
||||
PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL;
|
||||
PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL;
|
||||
PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL;
|
||||
PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT = NULL;
|
||||
PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT = NULL;
|
||||
PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT = NULL;
|
||||
PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT = NULL;
|
||||
PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT = NULL;
|
||||
PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT = NULL;
|
||||
PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT = NULL;
|
||||
PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT = NULL;
|
||||
PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT = NULL;
|
||||
PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
|
||||
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL;
|
||||
PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL;
|
||||
PFNGLDRAWBUFFERSPROC glDrawBuffers = NULL;
|
||||
|
||||
#ifndef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8
|
||||
#endif
|
||||
|
||||
bool ZZCreate(int width, int height);
|
||||
void ZZGSStateReset();
|
||||
|
||||
extern bool s_bWriteDepth;
|
||||
|
||||
extern u32 ptexLogo;
|
||||
extern int nLogoWidth, nLogoHeight;
|
||||
extern int nBackbufferWidth, nBackbufferHeight;
|
||||
|
||||
namespace ZeroGS
|
||||
{
|
||||
|
||||
typedef void (*DrawFn)();
|
||||
|
||||
// managers render-to-texture targets
|
||||
|
||||
class CRenderTarget
|
||||
{
|
||||
|
||||
public:
|
||||
CRenderTarget();
|
||||
virtual ~CRenderTarget();
|
||||
|
||||
virtual bool Create(const frameInfo& frame);
|
||||
virtual void Destroy();
|
||||
|
||||
// set the GPU_POSXY variable, scissor rect, and current render target
|
||||
void SetTarget(int fbplocal, const Rect2& scissor, int context);
|
||||
void SetViewport();
|
||||
|
||||
// copies/creates the feedback contents
|
||||
inline void CreateFeedback()
|
||||
{
|
||||
if (ptexFeedback == 0 || !(status&TS_FeedbackReady))
|
||||
_CreateFeedback();
|
||||
}
|
||||
|
||||
virtual void Resolve();
|
||||
virtual void Resolve(int startrange, int endrange); // resolves only in the allowed range
|
||||
virtual void Update(int context, CRenderTarget* pdepth);
|
||||
virtual void ConvertTo32(); // converts a psm==2 target, to a psm==0
|
||||
virtual void ConvertTo16(); // converts a psm==0 target, to a psm==2
|
||||
|
||||
virtual bool IsDepth() { return false; }
|
||||
|
||||
void SetRenderTarget(int targ);
|
||||
|
||||
void* psys; // system data used for comparison
|
||||
u32 ptex;
|
||||
|
||||
int fbp, fbw, fbh, fbhCalc; // if fbp is negative, virtual target (not mapped to any real addr)
|
||||
int start, end; // in bytes
|
||||
u32 lastused; // time stamp since last used
|
||||
float4 vposxy;
|
||||
|
||||
u32 fbm;
|
||||
u16 status;
|
||||
u8 psm;
|
||||
u8 resv0;
|
||||
Rect scissorrect;
|
||||
|
||||
u8 created; // Check for object destruction/creating for r201.
|
||||
|
||||
//int startresolve, endresolve;
|
||||
u32 nUpdateTarg; // use this target to update the texture if non 0 (one time only)
|
||||
|
||||
// this is optionally used when feedback effects are used (render target is used as a texture when rendering to itself)
|
||||
u32 ptexFeedback;
|
||||
|
||||
enum TargetStatus
|
||||
{
|
||||
TS_Resolved = 1,
|
||||
TS_NeedUpdate = 2,
|
||||
TS_Virtual = 4, // currently not mapped to memory
|
||||
TS_FeedbackReady = 8, // feedback effect is ready and doesn't need to be updated
|
||||
TS_NeedConvert32 = 16,
|
||||
TS_NeedConvert16 = 32,
|
||||
};
|
||||
inline float4 DefaultBitBltPos();
|
||||
inline float4 DefaultBitBltTex();
|
||||
|
||||
private:
|
||||
void _CreateFeedback();
|
||||
inline bool InitialiseDefaultTexture(u32 *p_ptr, int fbw, int fbh) ;
|
||||
};
|
||||
|
||||
// manages zbuffers
|
||||
|
||||
class CDepthTarget : public CRenderTarget
|
||||
{
|
||||
|
||||
public:
|
||||
CDepthTarget();
|
||||
virtual ~CDepthTarget();
|
||||
|
||||
virtual bool Create(const frameInfo& frame);
|
||||
virtual void Destroy();
|
||||
|
||||
virtual void Resolve();
|
||||
virtual void Resolve(int startrange, int endrange); // resolves only in the allowed range
|
||||
virtual void Update(int context, CRenderTarget* prndr);
|
||||
|
||||
virtual bool IsDepth() { return true; }
|
||||
|
||||
void SetDepthStencilSurface();
|
||||
|
||||
u32 pdepth; // 24 bit, will contain the stencil buffer if possible
|
||||
u32 pstencil; // if not 0, contains the stencil buffer
|
||||
int icount; // internal counter
|
||||
};
|
||||
|
||||
// manages contiguous chunks of memory (width is always 1024)
|
||||
|
||||
class CMemoryTarget
|
||||
{
|
||||
public:
|
||||
struct TEXTURE
|
||||
{
|
||||
inline TEXTURE() : tex(0), memptr(NULL), ref(0) {}
|
||||
inline ~TEXTURE() { glDeleteTextures(1, &tex); _aligned_free(memptr); }
|
||||
|
||||
u32 tex;
|
||||
u8* memptr; // GPU memory used for comparison
|
||||
int ref;
|
||||
};
|
||||
|
||||
inline CMemoryTarget() : ptex(NULL), starty(0), height(0), realy(0), realheight(0), usedstamp(0), psm(0), cpsm(0), channels(0), clearminy(0), clearmaxy(0), validatecount(0) {}
|
||||
|
||||
inline CMemoryTarget(const CMemoryTarget& r)
|
||||
{
|
||||
ptex = r.ptex;
|
||||
|
||||
if (ptex != NULL) ptex->ref++;
|
||||
|
||||
starty = r.starty;
|
||||
height = r.height;
|
||||
realy = r.realy;
|
||||
realheight = r.realheight;
|
||||
usedstamp = r.usedstamp;
|
||||
psm = r.psm;
|
||||
cpsm = r.cpsm;
|
||||
clut = r.clut;
|
||||
clearminy = r.clearminy;
|
||||
clearmaxy = r.clearmaxy;
|
||||
widthmult = r.widthmult;
|
||||
texH = r.texH;
|
||||
texW = r.texW;
|
||||
channels = r.channels;
|
||||
validatecount = r.validatecount;
|
||||
fmt = r.fmt;
|
||||
}
|
||||
|
||||
~CMemoryTarget() { Destroy(); }
|
||||
|
||||
inline void Destroy()
|
||||
{
|
||||
if (ptex != NULL && ptex->ref > 0)
|
||||
{
|
||||
if (--ptex->ref <= 0) delete ptex;
|
||||
}
|
||||
|
||||
ptex = NULL;
|
||||
}
|
||||
|
||||
// returns true if clut data is synced
|
||||
bool ValidateClut(const tex0Info& tex0);
|
||||
// returns true if tex data is synced
|
||||
bool ValidateTex(const tex0Info& tex0, int starttex, int endtex, bool bDeleteBadTex);
|
||||
|
||||
// realy is offset in pixels from start of valid region
|
||||
// so texture in memory is [realy,starty+height]
|
||||
// valid texture is [starty,starty+height]
|
||||
// offset in mem [starty-realy, height]
|
||||
TEXTURE* ptex; // can be 16bit
|
||||
|
||||
int starty, height; // assert(starty >= realy)
|
||||
int realy, realheight; // this is never touched once allocated
|
||||
// realy is start pointer of data in 4M data block (start) and size (end-start).
|
||||
|
||||
u32 usedstamp;
|
||||
u8 psm, cpsm; // texture and clut format. For psm, only 16bit/32bit differentiation matters
|
||||
|
||||
u32 fmt;
|
||||
|
||||
int widthmult; // Either 1 or 2.
|
||||
int channels; // The number of pixels per PSM format word. channels == PIXELS_PER_WORD(psm)
|
||||
// This is the real drawing size in pixels of the texture in renderbuffer.
|
||||
int texW; // (realheight + widthmult - 1)/widthmult == realheight or [(realheight+1)/2]
|
||||
int texH; // GPU_TEXWIDTH *widthmult * channels;
|
||||
|
||||
int clearminy, clearmaxy; // when maxy > 0, need to check for clearing
|
||||
|
||||
int validatecount; // count how many times has been validated, if too many, destroy
|
||||
|
||||
vector<u8> clut; // if nonzero, texture uses CLUT
|
||||
};
|
||||
|
||||
|
||||
struct VB
|
||||
{
|
||||
VB();
|
||||
~VB();
|
||||
|
||||
void Destroy();
|
||||
|
||||
inline bool CheckPrim()
|
||||
{
|
||||
static const int PRIMMASK = 0x0e; // for now ignore 0x10 (AA)
|
||||
|
||||
if ((PRIMMASK & prim->_val) != (PRIMMASK & curprim._val) || primtype[prim->prim] != primtype[curprim.prim])
|
||||
return nCount > 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CheckFrame(int tbp);
|
||||
|
||||
// context specific state
|
||||
Point offset;
|
||||
Rect2 scissor;
|
||||
tex0Info tex0;
|
||||
tex1Info tex1;
|
||||
miptbpInfo miptbp0;
|
||||
miptbpInfo miptbp1;
|
||||
alphaInfo alpha;
|
||||
fbaInfo fba;
|
||||
clampInfo clamp;
|
||||
pixTest test;
|
||||
u32 ptexClamp[2]; // textures for x and y dir region clamping
|
||||
|
||||
public:
|
||||
void FlushTexData();
|
||||
inline int CheckFrameAddConstraints(int tbp);
|
||||
inline void CheckScissors(int maxpos);
|
||||
inline void CheckFrame32bitRes(int maxpos);
|
||||
inline int FindMinimalMemoryConstrain(int tbp, int maxpos);
|
||||
inline int FindZbufferMemoryConstrain(int tbp, int maxpos);
|
||||
inline int FindMinimalHeightConstrain(int maxpos);
|
||||
|
||||
inline int CheckFrameResolveRender(int tbp);
|
||||
inline void CheckFrame16vs32Conversion();
|
||||
inline int CheckFrameResolveDepth(int tbp);
|
||||
|
||||
inline void FlushTexUnchangedClutDontUpdate() ;
|
||||
inline void FlushTexClutDontUpdate() ;
|
||||
inline void FlushTexClutting() ;
|
||||
inline void FlushTexSetNewVars(u32 psm) ;
|
||||
|
||||
// notify VB that nVerts need to be written to pbuf
|
||||
inline void NotifyWrite(int nVerts)
|
||||
{
|
||||
assert(pBufferData != NULL && nCount <= nNumVertices && nVerts > 0);
|
||||
|
||||
if (nCount + nVerts > nNumVertices)
|
||||
{
|
||||
// recreate except with a bigger count
|
||||
VertexGPU* ptemp = (VertexGPU*)_aligned_malloc(sizeof(VertexGPU) * nNumVertices * 2, 256);
|
||||
memcpy_amd(ptemp, pBufferData, sizeof(VertexGPU) * nCount);
|
||||
nNumVertices *= 2;
|
||||
assert(nCount + nVerts <= nNumVertices);
|
||||
_aligned_free(pBufferData);
|
||||
pBufferData = ptemp;
|
||||
}
|
||||
}
|
||||
|
||||
void Init(int nVerts)
|
||||
{
|
||||
if (pBufferData == NULL && nVerts > 0)
|
||||
{
|
||||
pBufferData = (VertexGPU*)_aligned_malloc(sizeof(VertexGPU) * nVerts, 256);
|
||||
nNumVertices = nVerts;
|
||||
}
|
||||
|
||||
nCount = 0;
|
||||
}
|
||||
|
||||
u8 bNeedFrameCheck;
|
||||
u8 bNeedZCheck;
|
||||
u8 bNeedTexCheck;
|
||||
u8 dummy0;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
u8 bTexConstsSync; // only pixel shader constants that context owns
|
||||
u8 bVarsTexSync; // texture info
|
||||
u8 bVarsSetTarg;
|
||||
u8 dummy1;
|
||||
};
|
||||
|
||||
u32 bSyncVars;
|
||||
};
|
||||
|
||||
int ictx;
|
||||
VertexGPU* pBufferData; // current allocated data
|
||||
|
||||
int nNumVertices; // size of pBufferData in terms of VertexGPU objects
|
||||
int nCount;
|
||||
primInfo curprim; // the previous prim the current buffers are set to
|
||||
|
||||
zbufInfo zbuf;
|
||||
frameInfo gsfb; // the real info set by FRAME cmd
|
||||
frameInfo frame;
|
||||
int zprimmask; // zmask for incoming points
|
||||
|
||||
union
|
||||
{
|
||||
u32 uCurTex0Data[2]; // current tex0 data
|
||||
GIFRegTEX0 uCurTex0;
|
||||
};
|
||||
u32 uNextTex0Data[2]; // tex0 data that has to be applied if bNeedTexCheck is 1
|
||||
|
||||
//int nFrameHeights[8]; // frame heights for the past frame changes
|
||||
int nNextFrameHeight;
|
||||
|
||||
CMemoryTarget* pmemtarg; // the current mem target set
|
||||
CRenderTarget* prndr;
|
||||
CDepthTarget* pdepth;
|
||||
|
||||
};
|
||||
|
||||
// visible members
|
||||
extern DrawFn drawfn[8];
|
||||
|
||||
// VB variables
|
||||
extern VB vb[2];
|
||||
extern float fiTexWidth[2], fiTexHeight[2]; // current tex width and height
|
||||
extern vector<GLuint> g_vboBuffers; // VBOs for all drawing commands
|
||||
extern GLuint vboRect;
|
||||
extern int g_nCurVBOIndex;
|
||||
|
||||
void AddMessage(const char* pstr, u32 ms = 5000);
|
||||
void DrawText(const char* pstr, int left, int top, u32 color);
|
||||
void ChangeWindowSize(int nNewWidth, int nNewHeight);
|
||||
void SetChangeDeviceSize(int nNewWidth, int nNewHeight);
|
||||
void ChangeDeviceSize(int nNewWidth, int nNewHeight);
|
||||
void SetAA(int mode);
|
||||
void SetCRC(int crc);
|
||||
|
||||
void ReloadEffects();
|
||||
|
||||
// Methods //
|
||||
bool IsGLExt(const char* szTargetExtension); ///< returns true if the the opengl extension is supported
|
||||
inline bool Create_Window(int _width, int _height);
|
||||
bool Create(int width, int height);
|
||||
void Destroy(bool bD3D);
|
||||
|
||||
void Reset(); // call to destroy video resources
|
||||
void GSStateReset();
|
||||
void GSReset();
|
||||
void GSSoftReset(u32 mask);
|
||||
|
||||
void HandleGLError();
|
||||
|
||||
// called on a primitive switch
|
||||
void Prim();
|
||||
|
||||
void SetTexFlush();
|
||||
// flush current vertices, call before setting new registers (the main render method)
|
||||
void Flush(int context);
|
||||
void FlushBoth();
|
||||
void ExtWrite();
|
||||
|
||||
void SetWriteDepth();
|
||||
bool IsWriteDepth();
|
||||
//extern u32 ptexLogo;
|
||||
//extern int nLogoWidth, nLogoHeight;
|
||||
//extern GLuint vboRect;
|
||||
//void ProcessMessages();
|
||||
//void RenderCustom(float fAlpha); // intro anim
|
||||
|
||||
void SetDestAlphaTest();
|
||||
bool IsWriteDestAlphaTest();
|
||||
|
||||
void SetFogColor(u32 fog);
|
||||
void SetFogColor(GIFRegFOGCOL* fog);
|
||||
void SaveTex(tex0Info* ptex, int usevid);
|
||||
char* NamedSaveTex(tex0Info* ptex, int usevid);
|
||||
|
||||
// called when trxdir is accessed. If host is involved, transfers memory to temp buffer byTransferBuf.
|
||||
// Otherwise performs the transfer. TODO: Perhaps divide the transfers into chunks?
|
||||
void InitTransferHostLocal();
|
||||
void TransferHostLocal(const void* pbyMem, u32 nQWordSize);
|
||||
|
||||
void InitTransferLocalHost();
|
||||
void TransferLocalHost(void* pbyMem, u32 nQWordSize);
|
||||
inline void TerminateLocalHost() {}
|
||||
|
||||
void TransferLocalLocal();
|
||||
|
||||
// switches the render target to the real target, flushes the current render targets and renders the real image
|
||||
void RenderCRTC(int interlace);
|
||||
void ResetRenderTarget(int index);
|
||||
|
||||
bool CheckChangeInClut(u32 highdword, u32 psm); // returns true if clut will change after this tex0 op
|
||||
|
||||
// call to load CLUT data (depending on CLD)
|
||||
void texClutWrite(int ctx);
|
||||
|
||||
int Save(s8* pbydata);
|
||||
bool Load(s8* pbydata);
|
||||
|
||||
void SaveSnapshot(const char* filename);
|
||||
bool SaveRenderTarget(const char* filename, int width, int height, int jpeg);
|
||||
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height);
|
||||
bool SaveJPEG(const char* filename, int width, int height, const void* pdata, int quality);
|
||||
bool SaveTGA(const char* filename, int width, int height, void* pdata);
|
||||
void Stop_Avi();
|
||||
void Delete_Avi_Capture();
|
||||
|
||||
// private methods
|
||||
void FlushSysMem(const RECT* prc);
|
||||
void _Resolve(const void* psrc, int fbp, int fbw, int fbh, int psm, u32 fbm, bool mode);
|
||||
|
||||
// returns the first and last addresses aligned to a page that cover
|
||||
void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw);
|
||||
|
||||
// inits the smallest rectangle in ptexMem that covers this region in ptexMem
|
||||
// returns the offset that needs to be added to the locked rect to get the beginning of the buffer
|
||||
//void GetMemRect(RECT& rc, int psm, int x, int y, int w, int h, int bp, int bw);
|
||||
|
||||
void SetContextTarget(int context) ;
|
||||
|
||||
void NeedFactor(int w);
|
||||
void ResetAlphaVariables();
|
||||
|
||||
void StartCapture();
|
||||
void StopCapture();
|
||||
void CaptureFrame();
|
||||
|
||||
// Perform clutting for flushed texture. Better check if it needs a prior call.
|
||||
inline void CluttingForFlushedTex(tex0Info* tex0, u32 Data, int ictx)
|
||||
{
|
||||
tex0->cbp = ZZOglGet_cbp_TexBits(Data);
|
||||
tex0->cpsm = ZZOglGet_cpsm_TexBits(Data);
|
||||
tex0->csm = ZZOglGet_csm_TexBits(Data);
|
||||
tex0->csa = ZZOglGet_csa_TexBits(Data);
|
||||
tex0->cld = ZZOglGet_cld_TexBits(Data);
|
||||
|
||||
ZeroGS::texClutWrite(ictx);
|
||||
};
|
||||
|
||||
// The size in bytes of x strings (of texture).
|
||||
inline int MemorySize(int x)
|
||||
{
|
||||
return 4 * GPU_TEXWIDTH * x;
|
||||
}
|
||||
|
||||
// Return the address in memory of data block for string x.
|
||||
inline u8* MemoryAddress(int x)
|
||||
{
|
||||
return g_pbyGSMemory + MemorySize(x);
|
||||
}
|
||||
|
||||
template <u32 mult>
|
||||
inline u8* _MemoryAddress(int x)
|
||||
{
|
||||
return g_pbyGSMemory + mult * x;
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue