From 49f4168974bcf4437659c5de262498576560df54 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Sat, 7 Apr 2012 21:23:01 +0000 Subject: [PATCH] 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 --- plugins/zzogl-pg/opengl/CMakeLists.txt | 47 +++++ plugins/zzogl-pg/opengl/GLWin.h | 1 - plugins/zzogl-pg/opengl/GLWinX11.cpp | 2 +- plugins/zzogl-pg/opengl/GSDump.cpp | 96 ++++++++++ plugins/zzogl-pg/opengl/GSDump.h | 65 +++++++ plugins/zzogl-pg/opengl/GSmain.cpp | 225 ++++++++++++++++++++++- plugins/zzogl-pg/opengl/GifTransfer.cpp | 2 + plugins/zzogl-pg/opengl/Util.h | 7 + plugins/zzogl-pg/opengl/ZZKeyboard.cpp | 41 +++++ plugins/zzogl-pg/opengl/linux_replay.cpp | 44 +++++ 10 files changed, 522 insertions(+), 8 deletions(-) create mode 100644 plugins/zzogl-pg/opengl/GSDump.cpp create mode 100644 plugins/zzogl-pg/opengl/GSDump.h create mode 100644 plugins/zzogl-pg/opengl/linux_replay.cpp diff --git a/plugins/zzogl-pg/opengl/CMakeLists.txt b/plugins/zzogl-pg/opengl/CMakeLists.txt index ba0fb692ff..ed70bb2698 100644 --- a/plugins/zzogl-pg/opengl/CMakeLists.txt +++ b/plugins/zzogl-pg/opengl/CMakeLists.txt @@ -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) diff --git a/plugins/zzogl-pg/opengl/GLWin.h b/plugins/zzogl-pg/opengl/GLWin.h index ccd9353a3c..0a314b25c2 100644 --- a/plugins/zzogl-pg/opengl/GLWin.h +++ b/plugins/zzogl-pg/opengl/GLWin.h @@ -23,7 +23,6 @@ #ifdef _WIN32 #define GL_WIN32_WINDOW #else -#define USE_GSOPEN2 #define GL_X11_WINDOW #endif diff --git a/plugins/zzogl-pg/opengl/GLWinX11.cpp b/plugins/zzogl-pg/opengl/GLWinX11.cpp index 8fabfa8f74..0730acc214 100644 --- a/plugins/zzogl-pg/opengl/GLWinX11.cpp +++ b/plugins/zzogl-pg/opengl/GLWinX11.cpp @@ -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 diff --git a/plugins/zzogl-pg/opengl/GSDump.cpp b/plugins/zzogl-pg/opengl/GSDump.cpp new file mode 100644 index 0000000000..1da9a63fd1 --- /dev/null +++ b/plugins/zzogl-pg/opengl/GSDump.cpp @@ -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(); + } + } +} diff --git a/plugins/zzogl-pg/opengl/GSDump.h b/plugins/zzogl-pg/opengl/GSDump.h new file mode 100644 index 0000000000..68c2a5c19b --- /dev/null +++ b/plugins/zzogl-pg/opengl/GSDump.h @@ -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; + diff --git a/plugins/zzogl-pg/opengl/GSmain.cpp b/plugins/zzogl-pg/opengl/GSmain.cpp index 80798d9cae..af8a59173e 100644 --- a/plugins/zzogl-pg/opengl/GSmain.cpp +++ b/plugins/zzogl-pg/opengl/GSmain.cpp @@ -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 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 packets; + vector 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::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::iterator i = packets.begin(); i != packets.end(); i++) + { + delete *i; + } + + packets.clear(); + + sleep(1); + + GSclose(); + GSshutdown(); + + fclose(fp); + } +} +#endif diff --git a/plugins/zzogl-pg/opengl/GifTransfer.cpp b/plugins/zzogl-pg/opengl/GifTransfer.cpp index e05cc70253..f8be40629b 100644 --- a/plugins/zzogl-pg/opengl/GifTransfer.cpp +++ b/plugins/zzogl-pg/opengl/GifTransfer.cpp @@ -76,6 +76,8 @@ template 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) diff --git a/plugins/zzogl-pg/opengl/Util.h b/plugins/zzogl-pg/opengl/Util.h index 4bec3e82df..99c98d80a4 100644 --- a/plugins/zzogl-pg/opengl/Util.h +++ b/plugins/zzogl-pg/opengl/Util.h @@ -43,6 +43,11 @@ #include #include +#include +#include +#include +#include + #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. diff --git a/plugins/zzogl-pg/opengl/ZZKeyboard.cpp b/plugins/zzogl-pg/opengl/ZZKeyboard.cpp index 7d0ec625fb..138ed302f9 100644 --- a/plugins/zzogl-pg/opengl/ZZKeyboard.cpp +++ b/plugins/zzogl-pg/opengl/ZZKeyboard.cpp @@ -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; } diff --git a/plugins/zzogl-pg/opengl/linux_replay.cpp b/plugins/zzogl-pg/opengl/linux_replay.cpp new file mode 100644 index 0000000000..f95b19b0af --- /dev/null +++ b/plugins/zzogl-pg/opengl/linux_replay.cpp @@ -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]); +} +