zzogl-pg: import GSdump feature from GSdx

* Only available on debug build
* ctrl F9 -> dump a couple of frames
* ctrl shift F9 -> start/stop a stream of frames.
* Build a replayer too, called pcsx2_ZZReplayLoader

Note: dump are saved in /tmp.


git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5152 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gregory.hainaut 2012-04-07 21:23:01 +00:00
parent 6c878aa2eb
commit 49f4168974
10 changed files with 522 additions and 8 deletions

View File

@ -46,6 +46,7 @@ set(zzoglSources
GifTransfer.cpp
GLWin32.cpp
GLWinX11.cpp
GSDump.cpp
GSmain.cpp
HostMemory.cpp
Mem.cpp
@ -82,6 +83,7 @@ set(zzoglHeaders
GifTransfer.h
# glprocs.h
GS.h
GSDump.h
HostMemory.h
Mem.h
Mem_Swizzle.h
@ -141,6 +143,9 @@ add_library(${Output} SHARED
${zzoglLinuxSources}
${zzoglLinuxHeaders})
# Trick that allow to compile zzogl with GSOPEN2 and the replayer with GSOPEN
set_target_properties(${Output} PROPERTIES COMPILE_DEFINITIONS USE_GSOPEN2)
# link target with project internal libraries
target_link_libraries(${Output} Utilities)
@ -171,3 +176,45 @@ else(PACKAGE_MODE)
install(TARGETS ${Output} DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins)
install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.dat DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins)
endif(PACKAGE_MODE)
################################### Replay Loader
set(Replay pcsx2_ZZReplayLoader)
set(Static zzogl-static)
add_library(${Static} STATIC
${zzoglSources}
${zzoglHeaders}
${zzoglSSources}
${zzoglShaderSources}
${zzoglLinuxSources}
${zzoglLinuxHeaders})
target_link_libraries(${Static} Utilities)
target_link_libraries(${Static} ${CG_LIBRARIES})
target_link_libraries(${Static} ${GLEW_LIBRARY})
target_link_libraries(${Static} ${OPENGL_LIBRARIES})
target_link_libraries(${Static} ${X11_LIBRARIES})
target_link_libraries(${Static} ${JPEG_LIBRARIES})
add_executable(${Replay} linux_replay.cpp)
target_link_libraries(${Replay} ${Static})
target_link_libraries(${Replay} Utilities)
target_link_libraries(${Replay} ${CG_LIBRARIES})
target_link_libraries(${Replay} ${GLEW_LIBRARY})
target_link_libraries(${Replay} ${OPENGL_LIBRARIES})
target_link_libraries(${Replay} ${X11_LIBRARIES})
target_link_libraries(${Replay} ${JPEG_LIBRARIES})
target_link_libraries(${Replay} ${GTK2_LIBRARIES})
target_link_libraries(${Replay} ${ZLIB_LIBRARIES})
if(NOT USER_CMAKE_LD_FLAGS STREQUAL "")
target_link_libraries(${Replay} "${USER_CMAKE_LD_FLAGS}")
endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "")
if(PACKAGE_MODE)
install(TARGETS ${Replay} DESTINATION bin)
else(PACKAGE_MODE)
install(TARGETS ${Replay} DESTINATION ${CMAKE_SOURCE_DIR}/bin)
endif(PACKAGE_MODE)

View File

@ -23,7 +23,6 @@
#ifdef _WIN32
#define GL_WIN32_WINDOW
#else
#define USE_GSOPEN2
#define GL_X11_WINDOW
#endif

View File

@ -339,7 +339,7 @@ void GLWindow::Force43Ratio()
s32 new_width = (4*height)/3;
// do not bother to resize for 5 pixels. Avoid a loop
// due to round value
if ( abs(new_width - width) > 5) {
if ( ABS(new_width - width) > 5) {
width = new_width;
conf.width = new_width;
// resize the window

View File

@ -0,0 +1,96 @@
/*
* Copyright (C) 2007-2009 Gabest
* http://www.gabest.org
*
* 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, 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 GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "GSDump.h"
GSDump::GSDump()
: m_gs(NULL)
, m_frames(0)
{
}
GSDump::~GSDump()
{
Close();
}
void GSDump::Open(const string& fn, u32 crc, const freezeData& fd, u8* regs)
{
if (m_gs) return;
m_gs = fopen(fn.c_str(), "wb");
m_frames = 0;
if(m_gs)
{
fwrite(&crc, 4, 1, m_gs);
fwrite(&fd.size, 4, 1, m_gs);
fwrite(fd.data, fd.size, 1, m_gs);
fwrite(regs, 0x2000, 1, m_gs);
}
}
void GSDump::Close()
{
if(m_gs) {
fclose(m_gs);
m_gs = NULL;
fprintf(stderr, "Closing GS dump");
}
}
void GSDump::Transfer(int index, const u8* mem, size_t size)
{
if(m_gs && size > 0)
{
fputc(0, m_gs);
fputc(index, m_gs);
fwrite(&size, 4, 1, m_gs);
fwrite(mem, size, 1, m_gs);
}
}
void GSDump::ReadFIFO(u32 size)
{
if(m_gs && size > 0)
{
fputc(2, m_gs);
fwrite(&size, 4, 1, m_gs);
}
}
void GSDump::VSync(int field, bool last, u8* regs)
{
if(m_gs)
{
fputc(3, m_gs);
fwrite(regs, 0x2000, 1, m_gs);
fputc(1, m_gs);
fputc(field, m_gs);
if((++m_frames & 1) == 0 && last)
{
Close();
}
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2007-2009 Gabest
* http://www.gabest.org
*
* 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, 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 GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
#include "Util.h"
using namespace std;
/*
Dump file format:
- [crc/4] [state size/4] [state data/size] [PMODE/0x2000] [id/1] [data/?] .. [id/1] [data/?]
Transfer data (id == 0)
- [0/1] [path index/1] [size/4] [data/size]
VSync data (id == 1)
- [1/1] [field/1]
ReadFIFO2 data (id == 2)
- [2/1] [size/?]
Regs data (id == 3)
- [PMODE/0x2000]
*/
class GSDump
{
FILE* m_gs;
int m_frames;
public:
GSDump();
virtual ~GSDump();
void Open(const string& fn, u32 crc, const freezeData& fd, u8* regs);
void Close();
void ReadFIFO(u32 size);
void Transfer(int index, const u8* mem, size_t size);
void VSync(int field, bool last, u8* regs);
operator bool() {return m_gs != NULL;}
};
extern GSDump g_dump;

View File

@ -35,6 +35,7 @@ extern void SaveSnapshot(const char* filename);
GLWindow GLWin;
GSinternal gs;
GSconf conf;
GSDump g_dump;
int ppf, g_GSMultiThreaded, CurrentSavestate = 0;
int g_LastCRC = 0, g_TransferredToGPU = 0, s_frameskipping = 0;
@ -385,12 +386,11 @@ void CALLBACK GSchangeSaveState(int newstate, const char* filename)
SaveStateExists = (access(SaveStateFile, 0) == 0);
}
void CALLBACK GSmakeSnapshot(char *path)
static bool get_snapshot_filename(char *filename, char* path, const char* extension)
{
FUNCLOG
FILE *bmpfile;
char filename[256];
u32 snapshotnr = 0;
// increment snapshot value & try to get filename
@ -399,7 +399,7 @@ void CALLBACK GSmakeSnapshot(char *path)
{
snapshotnr++;
sprintf(filename, "%s/snap%03ld.%s", path, snapshotnr, (conf.zz_options.tga_snap) ? "bmp" : "jpg");
sprintf(filename, "%s/snap%03ld.%s", path, snapshotnr, extension);
bmpfile = fopen(filename, "rb");
@ -420,13 +420,21 @@ void CALLBACK GSmakeSnapshot(char *path)
mkdir(path, 0777);
#endif
if ((bmpfile = fopen(filename, "wb")) == NULL) return;
if ((bmpfile = fopen(filename, "wb")) == NULL) return false;
}
fclose(bmpfile);
// get the bits
SaveSnapshot(filename);
return true;
}
void CALLBACK GSmakeSnapshot(char *path)
{
FUNCLOG
char filename[256];
if (get_snapshot_filename(filename, path, (conf.zz_options.tga_snap) ? "bmp" : "jpg"))
SaveSnapshot(filename);
}
// I'll probably move this somewhere else later, but it's got a ton of dependencies.
@ -474,6 +482,25 @@ void CALLBACK GSvsync(int interlace)
static u32 dwTime = timeGetTime();
static int nToNextUpdate = 1;
#ifdef _DEBUG
if (conf.dump & 0x1) {
freezeData fd;
fd.size = ZZSave(NULL);
s8* payload = (s8*)malloc(fd.size);
fd.data = payload;
ZZSave(fd.data);
char filename[256];
// FIXME, there is probably a better solution than /tmp ...
// A possibility will be to save the path from GSmakeSnapshot but you still need to call
// GSmakeSnapshot first.
if (get_snapshot_filename(filename, "/tmp", "gs"))
g_dump.Open(filename, g_LastCRC, fd, g_pBasePS2Mem);
conf.dump--;
}
g_dump.VSync(interlace, (conf.dump == 0), g_pBasePS2Mem);
#endif
GL_REPORT_ERRORD();
@ -529,6 +556,7 @@ void CALLBACK GSvsync(int interlace)
#endif
GL_REPORT_ERRORD();
}
void CALLBACK GSreadFIFO(u64 *pMem)
@ -536,6 +564,9 @@ void CALLBACK GSreadFIFO(u64 *pMem)
FUNCLOG
//ZZLog::GS_Log("Calling GSreadFIFO.");
#ifdef _DEBUG
g_dump.ReadFIFO(1);
#endif
TransferLocalHost((u32*)pMem, 1);
}
@ -545,6 +576,9 @@ void CALLBACK GSreadFIFO2(u64 *pMem, int qwc)
FUNCLOG
//ZZLog::GS_Log("Calling GSreadFIFO2.");
#ifdef _DEBUG
g_dump.ReadFIFO(qwc);
#endif
TransferLocalHost((u32*)pMem, qwc);
}
@ -586,3 +620,182 @@ s32 CALLBACK GSfreeze(int mode, freezeData *data)
return 0;
}
#ifdef __LINUX__
struct Packet
{
u8 type, param;
u32 size, addr;
vector<u32> buff;
};
EXPORT_C_(void) GSReplay(char* lpszCmdLine)
{
if(FILE* fp = fopen(lpszCmdLine, "rb"))
{
GSinit();
u8 regs[0x2000];
GSsetBaseMem(regs);
//s_vsync = !!theApp.GetConfig("vsync", 0);
void* hWnd = NULL;
//_GSopen((void**)&hWnd, "", renderer);
GSopen((void**)&hWnd, "", 0);
u32 crc;
fread(&crc, 4, 1, fp);
GSsetGameCRC(crc, 0);
freezeData fd;
fread(&fd.size, 4, 1, fp);
fd.data = new s8[fd.size];
fread(fd.data, fd.size, 1, fp);
GSfreeze(FREEZE_LOAD, &fd);
delete [] fd.data;
fread(regs, 0x2000, 1, fp);
long start = ftell(fp);
GSvsync(1);
list<Packet*> packets;
vector<u8> buff;
int type;
while((type = fgetc(fp)) != EOF)
{
Packet* p = new Packet();
p->type = (u8)type;
switch(type)
{
case 0:
p->param = (u8)fgetc(fp);
fread(&p->size, 4, 1, fp);
switch(p->param)
{
case 0:
p->buff.resize(0x4000);
p->addr = 0x4000 - p->size;
fread(&p->buff[p->addr], p->size, 1, fp);
break;
case 1:
case 2:
case 3:
p->buff.resize(p->size);
fread(&p->buff[0], p->size, 1, fp);
break;
}
break;
case 1:
p->param = (u8)fgetc(fp);
break;
case 2:
fread(&p->size, 4, 1, fp);
break;
case 3:
p->buff.resize(0x2000);
fread(&p->buff[0], 0x2000, 1, fp);
break;
default: assert(0);
}
packets.push_back(p);
}
sleep(1);
//while(IsWindowVisible(hWnd))
//FIXME map?
int finished = 2;
while(finished > 0)
{
unsigned long start = timeGetTime();
unsigned long frame_number = 0;
for(list<Packet*>::iterator i = packets.begin(); i != packets.end(); i++)
{
Packet* p = *i;
switch(p->type)
{
case 0:
switch(p->param)
{
case 0: GSgifTransfer1(&p->buff[0], p->addr); break;
case 1: GSgifTransfer2(&p->buff[0], p->size / 16); break;
case 2: GSgifTransfer3(&p->buff[0], p->size / 16); break;
case 3: GSgifTransfer(&p->buff[0], p->size / 16); break;
}
break;
case 1:
GSvsync(p->param);
frame_number++;
break;
case 2:
if(buff.size() < p->size) buff.resize(p->size);
// FIXME
// GSreadFIFO2(&buff[0], p->size / 16);
break;
case 3:
memcpy(regs, &p->buff[0], 0x2000);
break;
}
}
unsigned long end = timeGetTime();
fprintf(stderr, "The %d frames of the scene was render on %dms\n", frame_number, end - start);
fprintf(stderr, "A means of %fms by frame\n", (float)(end - start)/(float)frame_number);
sleep(1);
finished--;
}
for(list<Packet*>::iterator i = packets.begin(); i != packets.end(); i++)
{
delete *i;
}
packets.clear();
sleep(1);
GSclose();
GSshutdown();
fclose(fp);
}
}
#endif

View File

@ -76,6 +76,8 @@ template<int index> void _GSgifTransfer(const u32 *pMem, u32 size)
#ifdef _DEBUG
gifTransferLog(index, pMem, size);
g_dump.Transfer(index, (const u8*)pMem, size);
#endif
while (size > 0)

View File

@ -43,6 +43,11 @@
#include <GL/glx.h>
#include <gtk/gtk.h>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#endif
#define GSdefs
@ -60,6 +65,7 @@ extern "C" char* CALLBACK PS2EgetLibName(void);
#include "ZZoglMath.h"
#include "Profile.h"
#include "GSDump.h"
#include "Utilities/MemcpyFast.h"
#define memcpy_amd memcpy_fast
@ -133,6 +139,7 @@ typedef struct
u32 SkipDraw;
u32 log;
u32 disableHacks;
int dump;
void incAA() { aa++; if (aa > 4) aa = 0; }
void decAA() { aa--; if (aa > 4) aa = 4; } // u8 is unsigned, so negative value is 255.

View File

@ -37,6 +37,8 @@ const char* pbilinear[] = { "off", "normal", "forced" };
extern void SetAA(int mode);
extern bool dump_enable;
void ProcessBilinear()
{
FUNCLOG
@ -110,6 +112,37 @@ void ProcessWireFrame()
ZZLog::WriteToScreen(strtitle);
}
void ProcessFrameDump()
{
FUNCLOG
conf.dump = 1;
char strtitle[256];
sprintf(strtitle, "GS dump-frame");
ZZLog::WriteToScreen(strtitle);
SaveConfig();
}
void ProcessVideoDump()
{
FUNCLOG
char strtitle[256];
if (conf.dump != 0) {
sprintf(strtitle, "Stop GS dump-video");
conf.dump = 0;
} else {
sprintf(strtitle, "Start GS dump-video");
conf.dump = 3;
}
ZZLog::WriteToScreen(strtitle);
SaveConfig();
}
void ProcessHackSetting(bool reverse)
{
FUNCLOG
@ -168,11 +201,19 @@ void OnFKey(int key, int shift)
ProcessWireFrame();
break;
case 9:
#ifdef _DEBUG
// Fn keys are a bit overload... I don't have a better idea --Gregory
if (shift)
ProcessVideoDump();
else
ProcessFrameDump();
#else
if (shift)
ProcessHackSetting(true);
else
ProcessHackSetting(false);
break;
#endif
default:
break;
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 20011-2012 Hainaut gregory
*
* 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, 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 GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "GS.h"
EXPORT_C_(void) GSsetLogDir(const char* dir);
EXPORT_C_(void) GSsetSettingsDir(const char* dir);
EXPORT_C_(void) GSReplay(char* lpszCmdLine);
void help()
{
fprintf(stderr, "Loader gs file\n");
fprintf(stderr, "ARG1 Ini directory\n");
fprintf(stderr, "ARG2 .gs file\n");
exit(1);
}
int main ( int argc, char *argv[] )
{
if ( argc < 2 ) help();
GSsetSettingsDir(argv[1]);
GSsetLogDir("/tmp");
GSReplay(argv[2]);
}