mirror of
https://github.com/PCSX2/gsdx-sourceforge.git
synced 2026-02-04 03:11:19 +01:00
This commit is contained in:
@@ -1,92 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual Studio 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GSdx", "gsdx\GSdx_vs2005.vcproj", "{18E42F6F-3A62-41EE-B42F-79366C4F1E95}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xpad", "xpad\xpad_vs2005.vcproj", "{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug SSE2|Win32 = Debug SSE2|Win32
|
||||
Debug SSE2|x64 = Debug SSE2|x64
|
||||
Debug SSE4|Win32 = Debug SSE4|Win32
|
||||
Debug SSE4|x64 = Debug SSE4|x64
|
||||
Debug SSSE3|Win32 = Debug SSSE3|Win32
|
||||
Debug SSSE3|x64 = Debug SSSE3|x64
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release SSE2|Win32 = Release SSE2|Win32
|
||||
Release SSE2|x64 = Release SSE2|x64
|
||||
Release SSE4|Win32 = Release SSE4|Win32
|
||||
Release SSE4|x64 = Release SSE4|x64
|
||||
Release SSSE3|Win32 = Release SSSE3|Win32
|
||||
Release SSSE3|x64 = Release SSSE3|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Debug SSE2|Win32.ActiveCfg = Debug SSE2|Win32
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Debug SSE2|Win32.Build.0 = Debug SSE2|Win32
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Debug SSE2|x64.ActiveCfg = Debug SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Debug SSE2|x64.Build.0 = Debug SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Debug SSE4|Win32.ActiveCfg = Debug SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Debug SSE4|x64.ActiveCfg = Debug SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Debug SSE4|x64.Build.0 = Debug SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Debug SSSE3|Win32.ActiveCfg = Debug SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Debug SSSE3|x64.ActiveCfg = Debug SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Debug SSSE3|x64.Build.0 = Debug SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Debug|x64.Build.0 = Debug|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Release SSE2|Win32.ActiveCfg = Release SSE2|Win32
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Release SSE2|Win32.Build.0 = Release SSE2|Win32
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Release SSE2|x64.ActiveCfg = Release SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Release SSE2|x64.Build.0 = Release SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Release SSE4|Win32.ActiveCfg = Release SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Release SSE4|x64.ActiveCfg = Release SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Release SSE4|x64.Build.0 = Release SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Release SSSE3|Win32.ActiveCfg = Release SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Release SSSE3|x64.ActiveCfg = Release SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Release SSSE3|x64.Build.0 = Release SSE2|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Release|Win32.Build.0 = Release|Win32
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Release|x64.ActiveCfg = Release|x64
|
||||
{18E42F6F-3A62-41EE-B42F-79366C4F1E95}.Release|x64.Build.0 = Release|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug SSE2|Win32.ActiveCfg = Debug SSE2|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug SSE2|Win32.Build.0 = Debug SSE2|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug SSE2|x64.ActiveCfg = Debug SSE2|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug SSE2|x64.Build.0 = Debug SSE2|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug SSE4|Win32.ActiveCfg = Debug SSE4|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug SSE4|Win32.Build.0 = Debug SSE4|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug SSE4|x64.ActiveCfg = Debug SSE4|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug SSE4|x64.Build.0 = Debug SSE4|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug SSSE3|Win32.ActiveCfg = Debug SSSE3|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug SSSE3|Win32.Build.0 = Debug SSSE3|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug SSSE3|x64.ActiveCfg = Debug SSSE3|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug SSSE3|x64.Build.0 = Debug SSSE3|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Debug|x64.Build.0 = Debug|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release SSE2|Win32.ActiveCfg = Release SSE2|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release SSE2|Win32.Build.0 = Release SSE2|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release SSE2|x64.ActiveCfg = Release SSE2|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release SSE2|x64.Build.0 = Release SSE2|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release SSE4|Win32.ActiveCfg = Release SSE4|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release SSE4|Win32.Build.0 = Release SSE4|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release SSE4|x64.ActiveCfg = Release SSE4|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release SSE4|x64.Build.0 = Release SSE4|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release SSSE3|Win32.ActiveCfg = Release SSSE3|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release SSSE3|Win32.Build.0 = Release SSSE3|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release SSSE3|x64.ActiveCfg = Release SSSE3|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release SSSE3|x64.Build.0 = Release SSSE3|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release|Win32.Build.0 = Release|Win32
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release|x64.ActiveCfg = Release|x64
|
||||
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -31,6 +31,5 @@ protected:
|
||||
LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
afx_msg void OnBrowse();
|
||||
public:
|
||||
afx_msg void OnBnClickedOk();
|
||||
};
|
||||
|
||||
272
gsdx/GPU.cpp
Normal file
272
gsdx/GPU.cpp
Normal file
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "stdafx.h"
|
||||
#include "GSUtil.h"
|
||||
#include "GPURendererSW.h"
|
||||
#include "GSDevice9.h"
|
||||
#include "GSDevice10.h"
|
||||
|
||||
#define PSE_LT_GPU 2
|
||||
|
||||
static HRESULT s_hr = E_FAIL;
|
||||
static GPURendererBase* s_gpu = NULL;
|
||||
|
||||
EXPORT_C_(UINT32) PSEgetLibType()
|
||||
{
|
||||
return PSE_LT_GPU;
|
||||
}
|
||||
|
||||
EXPORT_C_(char*) PSEgetLibName()
|
||||
{
|
||||
return GSUtil::GetLibName();
|
||||
}
|
||||
|
||||
EXPORT_C_(UINT32) PSEgetLibVersion()
|
||||
{
|
||||
static const UINT32 version = 1;
|
||||
static const UINT32 revision = 1;
|
||||
|
||||
return version << 16 | revision << 8 | PLUGIN_VERSION;
|
||||
}
|
||||
|
||||
EXPORT_C_(INT32) GPUinit()
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
// TODO
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C_(INT32) GPUshutdown()
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
// TODO
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C_(INT32) GPUclose()
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
delete s_gpu;
|
||||
|
||||
s_gpu = NULL;
|
||||
|
||||
if(SUCCEEDED(s_hr))
|
||||
{
|
||||
::CoUninitialize();
|
||||
|
||||
s_hr = E_FAIL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C_(INT32) GPUopen(HWND hWnd)
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
if(!GSUtil::CheckDirectX() || !GSUtil::CheckSSE())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
GPUclose();
|
||||
|
||||
GPURendererSettings rs;
|
||||
|
||||
rs.m_vsync = !!AfxGetApp()->GetProfileInt(_T("Settings"), _T("vsync"), FALSE);
|
||||
|
||||
s_gpu = new GPURendererSW<GSDevice10>(rs);
|
||||
|
||||
s_hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
|
||||
if(!s_gpu->Create(hWnd))
|
||||
{
|
||||
GPUclose();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C_(INT32) GPUconfigure()
|
||||
{
|
||||
// TODO
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C_(INT32) GPUtest()
|
||||
{
|
||||
// TODO
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C GPUabout()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
EXPORT_C GPUwriteDataMem(const BYTE* mem, UINT32 size)
|
||||
{
|
||||
s_gpu->WriteData(mem, size);
|
||||
}
|
||||
|
||||
EXPORT_C GPUwriteData(UINT32 data)
|
||||
{
|
||||
s_gpu->WriteData((BYTE*)&data, 1);
|
||||
}
|
||||
|
||||
EXPORT_C GPUreadDataMem(BYTE* mem, UINT32 size)
|
||||
{
|
||||
s_gpu->ReadData(mem, size);
|
||||
}
|
||||
|
||||
EXPORT_C_(UINT32) GPUreadData()
|
||||
{
|
||||
UINT32 data = 0;
|
||||
|
||||
s_gpu->ReadData((BYTE*)&data, 1);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
EXPORT_C GPUwriteStatus(UINT32 status)
|
||||
{
|
||||
s_gpu->WriteStatus(status);
|
||||
}
|
||||
|
||||
EXPORT_C_(UINT32) GPUreadStatus()
|
||||
{
|
||||
return s_gpu->ReadStatus();
|
||||
}
|
||||
|
||||
EXPORT_C_(UINT32) GPUdmaChain(const BYTE* mem, UINT32 addr)
|
||||
{
|
||||
// TODO
|
||||
|
||||
do
|
||||
{
|
||||
BYTE size = mem[addr + 3];
|
||||
|
||||
if(size > 0)
|
||||
{
|
||||
s_gpu->WriteData(&mem[addr + 4], size);
|
||||
}
|
||||
|
||||
addr = *(UINT32*)&mem[addr] & 0xffffff;
|
||||
}
|
||||
while(addr != 0xffffff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C_(UINT32) GPUgetMode()
|
||||
{
|
||||
// TODO
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C GPUsetMode(UINT32)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
EXPORT_C GPUupdateLace()
|
||||
{
|
||||
s_gpu->VSync();
|
||||
}
|
||||
|
||||
EXPORT_C GPUmakeSnapshot()
|
||||
{
|
||||
LPCTSTR path = _T("C:\\"); // TODO
|
||||
|
||||
s_gpu->MakeSnapshot(path);
|
||||
}
|
||||
|
||||
EXPORT_C GPUdisplayText(char* text)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
EXPORT_C GPUdisplayFlags(UINT32 flags)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
EXPORT_C_(INT32) GPUfreeze(UINT32 type, GPUFreezeData* data)
|
||||
{
|
||||
if(!data || data->version != 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(type == 0)
|
||||
{
|
||||
s_gpu->Defrost(data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if(type == 1)
|
||||
{
|
||||
s_gpu->Freeze(data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if(type == 2)
|
||||
{
|
||||
int slot = *(int*)data + 1;
|
||||
|
||||
if(slot < 1 || slot > 9)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C GPUgetScreenPic(BYTE* mem)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
EXPORT_C GPUshowScreenPic(BYTE* mem)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
EXPORT_C GPUcursor(int player, int x, int y)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
274
gsdx/GPU.h
Normal file
274
gsdx/GPU.h
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
#include "GS.h"
|
||||
|
||||
enum
|
||||
{
|
||||
GPU_POLYGON = 1,
|
||||
GPU_LINE = 2,
|
||||
GPU_SPRITE = 3,
|
||||
};
|
||||
|
||||
REG32_(GPUReg, STATUS)
|
||||
UINT32 TX:4;
|
||||
UINT32 TY:1;
|
||||
UINT32 ABR:2;
|
||||
UINT32 TP:2;
|
||||
UINT32 DTD:1;
|
||||
UINT32 DFE:1;
|
||||
UINT32 MD:1;
|
||||
UINT32 ME:1;
|
||||
UINT32 _PAD0:3;
|
||||
UINT32 WIDTH1:1;
|
||||
UINT32 WIDTH0:2;
|
||||
UINT32 HEIGHT:1;
|
||||
UINT32 ISPAL:1;
|
||||
UINT32 ISRGB24:1;
|
||||
UINT32 ISINTER:1;
|
||||
UINT32 DEN:1;
|
||||
UINT32 _PAD1:2;
|
||||
UINT32 IDLE:1;
|
||||
UINT32 IMG:1;
|
||||
UINT32 COM:1;
|
||||
UINT32 DMA:2;
|
||||
UINT32 LCF:1;
|
||||
/*
|
||||
UINT32 TX:4;
|
||||
UINT32 TY:1;
|
||||
UINT32 ABR:2;
|
||||
UINT32 TP:2;
|
||||
UINT32 DTD:1;
|
||||
UINT32 DFE:1;
|
||||
UINT32 PBW:1;
|
||||
UINT32 PBC:1;
|
||||
UINT32 _PAD0:3;
|
||||
UINT32 HRES2:1;
|
||||
UINT32 HRES1:2;
|
||||
UINT32 VRES:1;
|
||||
UINT32 ISPAL:1;
|
||||
UINT32 ISRGB24:1;
|
||||
UINT32 ISINTER:1;
|
||||
UINT32 ISSTOP:1;
|
||||
UINT32 _PAD1:1;
|
||||
UINT32 DMARDY:1;
|
||||
UINT32 IDIDLE:1;
|
||||
UINT32 DATARDY:1;
|
||||
UINT32 ISEMPTY:1;
|
||||
UINT32 TMODE:2;
|
||||
UINT32 ODE:1;
|
||||
*/
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, PACKET)
|
||||
UINT32 _PAD:24;
|
||||
UINT32 OPTION:5;
|
||||
UINT32 TYPE:3;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, PRIM)
|
||||
UINT32 VTX:24;
|
||||
UINT32 TGE:1;
|
||||
UINT32 ABE:1;
|
||||
UINT32 TME:1;
|
||||
UINT32 _PAD2:1;
|
||||
UINT32 IIP:1;
|
||||
UINT32 TYPE:3;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, POLYGON)
|
||||
UINT32 _PAD:24;
|
||||
UINT32 TGE:1;
|
||||
UINT32 ABE:1;
|
||||
UINT32 TME:1;
|
||||
UINT32 VTX:1;
|
||||
UINT32 IIP:1;
|
||||
UINT32 TYPE:3;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, LINE)
|
||||
UINT32 _PAD:24;
|
||||
UINT32 ZERO1:1;
|
||||
UINT32 ABE:1;
|
||||
UINT32 ZERO2:1;
|
||||
UINT32 PLL:1;
|
||||
UINT32 IIP:1;
|
||||
UINT32 TYPE:3;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, SPRITE)
|
||||
UINT32 _PAD:24;
|
||||
UINT32 ZERO:1;
|
||||
UINT32 ABE:1;
|
||||
UINT32 TME:1;
|
||||
UINT32 SIZE:2;
|
||||
UINT32 TYPE:3;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, RESET)
|
||||
UINT32 _PAD:32;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, DEN)
|
||||
UINT32 DEN:1;
|
||||
UINT32 _PAD:31;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, DMA)
|
||||
UINT32 DMA:2;
|
||||
UINT32 _PAD:30;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, DAREA)
|
||||
UINT32 X:10;
|
||||
UINT32 Y:9;
|
||||
UINT32 _PAD:13;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, DHRANGE)
|
||||
UINT32 X1:12;
|
||||
UINT32 X2:12;
|
||||
UINT32 _PAD:8;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, DVRANGE)
|
||||
UINT32 Y1:10;
|
||||
UINT32 Y2:11;
|
||||
UINT32 _PAD:11;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, DMODE)
|
||||
UINT32 WIDTH0:2;
|
||||
UINT32 HEIGHT:1;
|
||||
UINT32 ISPAL:1;
|
||||
UINT32 ISRGB24:1;
|
||||
UINT32 ISINTER:1;
|
||||
UINT32 WIDTH1:1;
|
||||
UINT32 REVERSE:1;
|
||||
UINT32 _PAD:24;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, GPUINFO)
|
||||
UINT32 PARAM:24;
|
||||
UINT32 _PAD:8;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, MODE)
|
||||
UINT32 TX:4;
|
||||
UINT32 TY:1;
|
||||
UINT32 ABR:2;
|
||||
UINT32 TP:2;
|
||||
UINT32 DTD:1;
|
||||
UINT32 DFE:1;
|
||||
UINT32 _PAD:21;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, MASK)
|
||||
UINT32 MD:1;
|
||||
UINT32 ME:1;
|
||||
UINT32 _PAD:30;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, DRAREA)
|
||||
UINT32 X:10;
|
||||
UINT32 Y:10;
|
||||
UINT32 _PAD:12;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, DROFF)
|
||||
INT32 X:11;
|
||||
INT32 Y:11;
|
||||
INT32 _PAD:10;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, RGB)
|
||||
UINT32 R:8;
|
||||
UINT32 G:8;
|
||||
UINT32 B:8;
|
||||
UINT32 _PAD:8;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, XY)
|
||||
INT32 X:16;
|
||||
INT32 Y:16;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, UV)
|
||||
UINT32 U:8;
|
||||
UINT32 V:8;
|
||||
UINT32 _PAD:16;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, TWIN)
|
||||
UINT32 TWW:5;
|
||||
UINT32 TWH:5;
|
||||
UINT32 TWX:5;
|
||||
UINT32 TWY:5;
|
||||
UINT32 _PAD:12;
|
||||
REG_END
|
||||
|
||||
REG32_(GPUReg, CLUT)
|
||||
UINT32 _PAD1:16;
|
||||
UINT32 X:6;
|
||||
UINT32 Y:9;
|
||||
UINT32 _PAD2:1;
|
||||
REG_END
|
||||
|
||||
REG32_SET(GPUReg)
|
||||
GPURegSTATUS STATUS;
|
||||
GPURegPACKET PACKET;
|
||||
GPURegPRIM PRIM;
|
||||
GPURegPOLYGON POLYGON;
|
||||
GPURegLINE LINE;
|
||||
GPURegSPRITE SPRITE;
|
||||
GPURegRESET RESET;
|
||||
GPURegDEN DEN;
|
||||
GPURegDMA DMA;
|
||||
GPURegDAREA DAREA;
|
||||
GPURegDHRANGE DHRANGE;
|
||||
GPURegDVRANGE DVRANGE;
|
||||
GPURegDMODE DMODE;
|
||||
GPURegGPUINFO GPUINFO;
|
||||
GPURegMODE MODE;
|
||||
GPURegMASK MASK;
|
||||
GPURegDRAREA DRAREA;
|
||||
GPURegDROFF DROFF;
|
||||
GPURegRGB RGB;
|
||||
GPURegXY XY;
|
||||
GPURegUV UV;
|
||||
GPURegTWIN TWIN;
|
||||
GPURegCLUT CLUT;
|
||||
REG_SET_END
|
||||
|
||||
struct GPUFreezeData
|
||||
{
|
||||
UINT32 version; // == 1
|
||||
UINT32 status;
|
||||
UINT32 control[256];
|
||||
UINT16 vram[1024 * 1024];
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
78
gsdx/GPUDrawingEnvironment.h
Normal file
78
gsdx/GPUDrawingEnvironment.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "GPU.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
__declspec(align(16)) class GPUDrawingEnvironment
|
||||
{
|
||||
public:
|
||||
GPURegSTATUS STATUS;
|
||||
GPURegPRIM PRIM;
|
||||
GPURegDAREA DAREA;
|
||||
GPURegDHRANGE DHRANGE;
|
||||
GPURegDVRANGE DVRANGE;
|
||||
GPURegDRAREA DRAREATL;
|
||||
GPURegDRAREA DRAREABR;
|
||||
GPURegDROFF DROFF;
|
||||
GPURegTWIN TWIN;
|
||||
GPURegCLUT CLUT;
|
||||
|
||||
GPUDrawingEnvironment()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
|
||||
STATUS.IDLE = 1;
|
||||
STATUS.COM = 1;
|
||||
}
|
||||
|
||||
CRect GetDisplayRect()
|
||||
{
|
||||
static int s_width[] = {256, 320, 512, 640, 384, 320, 320, 320};
|
||||
static int s_height[] = {240, 480};
|
||||
|
||||
CRect r;
|
||||
|
||||
r.left = DAREA.X & ~7;
|
||||
r.top = DAREA.Y;
|
||||
r.right = r.left + s_width[(STATUS.WIDTH1 << 2) | STATUS.WIDTH0];
|
||||
r.bottom = r.top + s_height[STATUS.HEIGHT];
|
||||
|
||||
r &= CRect(0, 0, 1024, 512);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int GetFPS()
|
||||
{
|
||||
return STATUS.ISPAL ? 50 : 60;
|
||||
}
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
246
gsdx/GPULocalMemory.cpp
Normal file
246
gsdx/GPULocalMemory.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "StdAfx.h"
|
||||
#include "GPULocalMemory.h"
|
||||
|
||||
const GSVector4i GPULocalMemory::m_xxxa(0x00008000);
|
||||
const GSVector4i GPULocalMemory::m_xxbx(0x00007c00);
|
||||
const GSVector4i GPULocalMemory::m_xgxx(0x000003e0);
|
||||
const GSVector4i GPULocalMemory::m_rxxx(0x0000001f);
|
||||
|
||||
static void CheckRect(const CRect& r)
|
||||
{
|
||||
ASSERT(r.left >= 0 && r.left <= 1024);
|
||||
ASSERT(r.right >= 0 && r.right <= 1024);
|
||||
ASSERT(r.top >= 0 && r.top <= 512);
|
||||
ASSERT(r.bottom >= 0 && r.bottom <= 512);
|
||||
ASSERT(r.left <= r.right);
|
||||
ASSERT(r.top <= r.bottom);
|
||||
}
|
||||
|
||||
GPULocalMemory::GPULocalMemory()
|
||||
{
|
||||
m_vm8 = (BYTE*)VirtualAlloc(NULL, m_vmsize * 2, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
|
||||
memset(m_vm8, 0, m_vmsize);
|
||||
}
|
||||
|
||||
GPULocalMemory::~GPULocalMemory()
|
||||
{
|
||||
VirtualFree(m_vm8, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
void GPULocalMemory::FillRect(const CRect& r, WORD c)
|
||||
{
|
||||
CheckRect(r);
|
||||
|
||||
CRect clip;
|
||||
|
||||
clip.left = (r.left + 7) & ~7;
|
||||
clip.top = r.top;
|
||||
clip.right = r.right & ~7;
|
||||
clip.bottom = r.bottom;
|
||||
|
||||
for(int y = r.top; y < clip.top; y++)
|
||||
{
|
||||
WORD* p = &m_vm16[y << 10];
|
||||
|
||||
for(int x = r.left; x < r.right; x++)
|
||||
{
|
||||
p[x] = c;
|
||||
}
|
||||
}
|
||||
|
||||
for(int y = clip.bottom; y < r.bottom; y++)
|
||||
{
|
||||
WORD* p = &m_vm16[y << 10];
|
||||
|
||||
for(int x = r.left; x < r.right; x++)
|
||||
{
|
||||
p[x] = c;
|
||||
}
|
||||
}
|
||||
|
||||
if(r.left < clip.left || clip.right < r.right)
|
||||
{
|
||||
for(int y = clip.top; y < clip.bottom; y++)
|
||||
{
|
||||
WORD* p = &m_vm16[y << 10];
|
||||
|
||||
for(int x = r.left; x < clip.left; x++)
|
||||
{
|
||||
p[x] = c;
|
||||
}
|
||||
|
||||
for(int x = clip.right; x < r.right; x++)
|
||||
{
|
||||
p[x] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GSVector4i c128((c << 16) | c);
|
||||
|
||||
for(int y = clip.top; y < clip.bottom; y++)
|
||||
{
|
||||
GSVector4i* p = (GSVector4i*)&m_vm16[(y << 10) + clip.left];
|
||||
|
||||
for(int i = 0, n = (clip.right - clip.left) >> 3; i < n; i++)
|
||||
{
|
||||
p[i] = c128;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPULocalMemory::WriteRect(const CRect& r, const WORD* c)
|
||||
{
|
||||
CheckRect(r);
|
||||
|
||||
int w = r.Width();
|
||||
|
||||
for(int y = r.top; y < r.bottom; y++)
|
||||
{
|
||||
WORD* p = &m_vm16[y << 10];
|
||||
|
||||
memcpy(&p[r.left], c, w * 2);
|
||||
|
||||
c += w;
|
||||
}
|
||||
}
|
||||
|
||||
void GPULocalMemory::ReadRect(const CRect& r, WORD* c)
|
||||
{
|
||||
CheckRect(r);
|
||||
|
||||
int w = r.Width();
|
||||
|
||||
for(int y = r.top; y < r.bottom; y++)
|
||||
{
|
||||
WORD* p = &m_vm16[y << 10];
|
||||
|
||||
memcpy(c, &p[r.left], w * 2);
|
||||
|
||||
c += w;
|
||||
}
|
||||
}
|
||||
|
||||
void GPULocalMemory::MoveRect(const CPoint& src, const CPoint& dst, int w, int h)
|
||||
{
|
||||
CheckRect(CRect(src, CSize(w, h)));
|
||||
CheckRect(CRect(dst, CSize(w, h)));
|
||||
|
||||
WORD* s = &m_vm16[(src.y << 10) + src.x];
|
||||
WORD* d = &m_vm16[(dst.y << 10) + dst.x];
|
||||
|
||||
for(int i = 0; i < h; i++, s += 1024, d += 1024)
|
||||
{
|
||||
memcpy(d, s, w * 2);
|
||||
}
|
||||
}
|
||||
|
||||
void GPULocalMemory::ReadPage4(int tx, int ty, BYTE* dst)
|
||||
{
|
||||
GSVector4i mask(0x0f0f0f0f);
|
||||
|
||||
WORD* src = &m_vm16[(ty << 18) + (tx << 6)];
|
||||
|
||||
for(int j = 0; j < 256; j++, src += 1024, dst += 256)
|
||||
{
|
||||
GSVector4i* s = (GSVector4i*)src;
|
||||
GSVector4i* d = (GSVector4i*)dst;
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
GSVector4i c = s[i];
|
||||
|
||||
GSVector4i l = c & mask;
|
||||
GSVector4i h = c.andnot(mask) >> 4;
|
||||
|
||||
d[i * 2 + 0] = l.upl8(h);
|
||||
d[i * 2 + 1] = l.uph8(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPULocalMemory::ReadPage8(int tx, int ty, BYTE* dst)
|
||||
{
|
||||
WORD* src = &m_vm16[(ty << 18) + (tx << 6)];
|
||||
|
||||
for(int j = 0; j < 256; j++, src += 1024, dst += 256)
|
||||
{
|
||||
memcpy(dst, src, 256);
|
||||
}
|
||||
}
|
||||
|
||||
void GPULocalMemory::ReadPage16(int tx, int ty, WORD* dst)
|
||||
{
|
||||
WORD* src = &m_vm16[(ty << 18) + (tx << 6)];
|
||||
|
||||
for(int j = 0; j < 256; j++, src += 1024, dst += 256)
|
||||
{
|
||||
memcpy(dst, src, 256 * sizeof(WORD));
|
||||
}
|
||||
}
|
||||
|
||||
void GPULocalMemory::ReadPalette4(int cx, int cy, WORD* dst)
|
||||
{
|
||||
memcpy(dst, &m_vm16[(cy << 10) + (cx << 4)], 16 * sizeof(WORD));
|
||||
}
|
||||
|
||||
void GPULocalMemory::ReadPalette8(int cx, int cy, WORD* dst)
|
||||
{
|
||||
memcpy(dst, &m_vm16[(cy << 10) + (cx << 4)], 256 * sizeof(WORD));
|
||||
}
|
||||
|
||||
void GPULocalMemory::Expand16(const WORD* RESTRICT src, DWORD* RESTRICT dst, int pixels)
|
||||
{
|
||||
GSVector4i rm = m_rxxx;
|
||||
GSVector4i gm = m_xgxx;
|
||||
GSVector4i bm = m_xxbx;
|
||||
GSVector4i am = m_xxxa;
|
||||
|
||||
GSVector4i* s = (GSVector4i*)src;
|
||||
GSVector4i* d = (GSVector4i*)dst;
|
||||
|
||||
for(int i = 0, j = pixels >> 3; i < j; i++)
|
||||
{
|
||||
GSVector4i c = s[i];
|
||||
|
||||
GSVector4i l = c.upl16();
|
||||
GSVector4i h = c.uph16();
|
||||
|
||||
d[i * 2 + 0] = ((l & rm) << 3) | ((l & gm) << 6) | ((l & bm) << 9) | ((l & am) << 16);
|
||||
d[i * 2 + 1] = ((h & rm) << 3) | ((h & gm) << 6) | ((h & bm) << 9) | ((h & am) << 16);
|
||||
}
|
||||
}
|
||||
|
||||
void GPULocalMemory::Expand24(const WORD* RESTRICT src, DWORD* RESTRICT dst, int pixels)
|
||||
{
|
||||
// TODO: sse
|
||||
|
||||
BYTE* s = (BYTE*)src;
|
||||
|
||||
for(int i = 0; i < pixels; i++, s += 3)
|
||||
{
|
||||
dst[i] = (s[2] << 16) | (s[1] << 8) | s[0];
|
||||
}
|
||||
}
|
||||
59
gsdx/GPULocalMemory.h
Normal file
59
gsdx/GPULocalMemory.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "GPU.h"
|
||||
#include "GSVector.h"
|
||||
|
||||
class GPULocalMemory
|
||||
{
|
||||
static const GSVector4i m_xxxa;
|
||||
static const GSVector4i m_xxbx;
|
||||
static const GSVector4i m_xgxx;
|
||||
static const GSVector4i m_rxxx;
|
||||
|
||||
public:
|
||||
static const int m_vmsize = 1024 * 1024;
|
||||
|
||||
union {BYTE* m_vm8; WORD* m_vm16; DWORD* m_vm32;};
|
||||
|
||||
public:
|
||||
GPULocalMemory();
|
||||
virtual ~GPULocalMemory();
|
||||
|
||||
void FillRect(const CRect& r, WORD c);
|
||||
void WriteRect(const CRect& r, const WORD* c);
|
||||
void ReadRect(const CRect& r, WORD* c);
|
||||
void MoveRect(const CPoint& src, const CPoint& dst, int w, int h);
|
||||
|
||||
void ReadPage4(int tx, int ty, BYTE* dst);
|
||||
void ReadPage8(int tx, int ty, BYTE* dst);
|
||||
void ReadPage16(int tx, int ty, WORD* dst);
|
||||
|
||||
void ReadPalette4(int cx, int cy, WORD* dst);
|
||||
void ReadPalette8(int cx, int cy, WORD* dst);
|
||||
|
||||
static void Expand16(const WORD* RESTRICT src, DWORD* RESTRICT dst, int pixels);
|
||||
static void Expand24(const WORD* RESTRICT src, DWORD* RESTRICT dst, int pixels);
|
||||
};
|
||||
|
||||
#pragma warning(default: 4244)
|
||||
1487
gsdx/GPURasterizer.cpp
Normal file
1487
gsdx/GPURasterizer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
125
gsdx/GPURasterizer.h
Normal file
125
gsdx/GPURasterizer.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "GPUState.h"
|
||||
#include "GPUVertexSW.h"
|
||||
#include "GPUTextureCacheSW.h"
|
||||
#include "GSAlignedClass.h"
|
||||
|
||||
class GPURasterizer : public GSAlignedClass<16>
|
||||
{
|
||||
protected:
|
||||
typedef GPUVertexSW Vertex;
|
||||
|
||||
GPUState* m_state;
|
||||
int m_id;
|
||||
int m_threads;
|
||||
|
||||
private:
|
||||
|
||||
union ScanlineSelector
|
||||
{
|
||||
struct
|
||||
{
|
||||
DWORD iip:1; // 0
|
||||
DWORD me:1; // 1
|
||||
DWORD abe:1; // 2
|
||||
DWORD abr:2; // 3
|
||||
DWORD tge:1; // 5
|
||||
DWORD tme:1; // 6
|
||||
DWORD tlu:1; // 7
|
||||
DWORD twin:1; // 8
|
||||
DWORD ltf:1; // 9
|
||||
// DWORD dtd:1; // 10
|
||||
// DWORD dte:1: // 11
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
DWORD _pad1:1; // 0
|
||||
DWORD rfb:2; // 1
|
||||
DWORD _pad2:2; // 3
|
||||
DWORD tfx:2; // 5
|
||||
};
|
||||
|
||||
DWORD dw;
|
||||
|
||||
operator DWORD() {return dw & 0x1ff;}
|
||||
};
|
||||
|
||||
__declspec(align(16)) struct ScanlineEnvironment
|
||||
{
|
||||
int steps;
|
||||
|
||||
WORD* vm;
|
||||
|
||||
const void* tex;
|
||||
const WORD* clut;
|
||||
|
||||
GSVector4i u[2];
|
||||
GSVector4i v[2];
|
||||
|
||||
GSVector4i a;
|
||||
GSVector4i md; // similar to gs fba
|
||||
|
||||
GSVector4 dp, dp8;
|
||||
GSVector4 dc, dc8;
|
||||
};
|
||||
|
||||
GSVector4i m_scissor;
|
||||
ScanlineSelector m_sel;
|
||||
ScanlineEnvironment m_slenv;
|
||||
|
||||
template<bool pos, bool col>
|
||||
__forceinline void SetupScanline(const Vertex& dv);
|
||||
|
||||
typedef void (GPURasterizer::*DrawScanlinePtr)(int top, int left, int right, const Vertex& v);
|
||||
|
||||
DrawScanlinePtr m_ds[512], m_dsf;
|
||||
|
||||
void DrawScanline(int top, int left, int right, const Vertex& v);
|
||||
|
||||
template<DWORD sel>
|
||||
void DrawScanlineEx(int top, int left, int right, const Vertex& v);
|
||||
|
||||
__forceinline void SampleTexture(int pixels, DWORD ltf, DWORD tlu, DWORD twin, GSVector4i& test, const GSVector4* s, const GSVector4* t, GSVector4i* c);
|
||||
__forceinline void ColorTFX(DWORD tfx, const GSVector4* r, const GSVector4* g, const GSVector4* b, GSVector4i* c);
|
||||
__forceinline void AlphaBlend(UINT32 abr, const GSVector4i& d, GSVector4i* c);
|
||||
__forceinline void WriteFrame(WORD* RESTRICT fb, const GSVector4i& test, const GSVector4i* c, int pixels);
|
||||
|
||||
void DrawPoint(Vertex* v);
|
||||
void DrawLine(Vertex* v);
|
||||
void DrawTriangle(Vertex* v);
|
||||
void DrawTriangleTop(Vertex* v);
|
||||
void DrawTriangleBottom(Vertex* v);
|
||||
void DrawTriangleTopBottom(Vertex* v);
|
||||
void DrawSprite(Vertex* v);
|
||||
|
||||
__forceinline void DrawTriangleSection(int top, int bottom, Vertex& l, const Vertex& dl, GSVector4& r, const GSVector4& dr, const Vertex& dscan);
|
||||
|
||||
public:
|
||||
GPURasterizer(GPUState* state, int id = 0, int threads = 0);
|
||||
virtual ~GPURasterizer();
|
||||
|
||||
int Draw(Vertex* v, int count, const void* texture);
|
||||
};
|
||||
23
gsdx/GPURenderer.cpp
Normal file
23
gsdx/GPURenderer.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "StdAfx.h"
|
||||
#include "GPURenderer.h"
|
||||
322
gsdx/GPURenderer.h
Normal file
322
gsdx/GPURenderer.h
Normal file
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "GPUState.h"
|
||||
#include "GSVertexList.h"
|
||||
|
||||
struct GPURendererSettings
|
||||
{
|
||||
bool m_vsync;
|
||||
};
|
||||
|
||||
class GPURendererBase : public GPUState, protected GPURendererSettings
|
||||
{
|
||||
protected:
|
||||
HWND m_hWnd;
|
||||
|
||||
public:
|
||||
GPURendererBase(const GPURendererSettings& rs)
|
||||
: m_hWnd(NULL)
|
||||
{
|
||||
m_vsync = rs.m_vsync;
|
||||
}
|
||||
|
||||
virtual bool Create(HWND hWnd) = 0;
|
||||
virtual void VSync() = 0;
|
||||
virtual bool MakeSnapshot(LPCTSTR path) = 0;
|
||||
};
|
||||
|
||||
template<class Device, class Vertex>
|
||||
class GPURenderer : public GPURendererBase
|
||||
{
|
||||
protected:
|
||||
typedef typename Device::Texture Texture;
|
||||
|
||||
Vertex* m_vertices;
|
||||
int m_count;
|
||||
int m_maxcount;
|
||||
GSVertexList<Vertex> m_vl;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_count = 0;
|
||||
m_vl.RemoveAll();
|
||||
|
||||
__super::Reset();
|
||||
}
|
||||
|
||||
void VertexKick()
|
||||
{
|
||||
if(m_vl.GetCount() < m_env.PRIM.VTX)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_count > m_maxcount)
|
||||
{
|
||||
m_maxcount = max(10000, m_maxcount * 3/2);
|
||||
m_vertices = (Vertex*)_aligned_realloc(m_vertices, sizeof(Vertex) * m_maxcount, 16);
|
||||
m_maxcount -= 100;
|
||||
}
|
||||
|
||||
Vertex* v = &m_vertices[m_count];
|
||||
|
||||
int count = 0;
|
||||
|
||||
switch(m_env.PRIM.TYPE)
|
||||
{
|
||||
case GPU_POLYGON:
|
||||
m_vl.GetAt(0, v[0]);
|
||||
m_vl.GetAt(1, v[1]);
|
||||
m_vl.GetAt(2, v[2]);
|
||||
m_vl.RemoveAll();
|
||||
count = 3;
|
||||
break;
|
||||
case GPU_LINE:
|
||||
m_vl.GetAt(0, v[0]);
|
||||
m_vl.GetAt(1, v[1]);
|
||||
m_vl.RemoveAll();
|
||||
count = 2;
|
||||
break;
|
||||
case GPU_SPRITE:
|
||||
m_vl.GetAt(0, v[0]);
|
||||
m_vl.GetAt(1, v[1]);
|
||||
m_vl.RemoveAll();
|
||||
count = 2;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
m_vl.RemoveAll();
|
||||
count = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
(this->*m_fpDrawingKickHandlers[m_env.PRIM.TYPE])(v, count);
|
||||
|
||||
m_count += count;
|
||||
}
|
||||
|
||||
typedef void (GPURenderer<Device, Vertex>::*DrawingKickHandler)(Vertex* v, int& count);
|
||||
|
||||
DrawingKickHandler m_fpDrawingKickHandlers[4];
|
||||
|
||||
void DrawingKickNull(Vertex* v, int& count)
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
void ResetPrim()
|
||||
{
|
||||
m_vl.RemoveAll();
|
||||
}
|
||||
|
||||
void FlushPrim()
|
||||
{
|
||||
if(m_count > 0)
|
||||
{
|
||||
Dump(_T("db"));
|
||||
|
||||
Draw();
|
||||
|
||||
m_count = 0;
|
||||
|
||||
Dump(_T("dc"), false);
|
||||
|
||||
if(m_env.PRIM.TME)
|
||||
{
|
||||
CRect r;
|
||||
|
||||
r.left = m_env.STATUS.TX << 6;
|
||||
r.top = m_env.STATUS.TY << 8;
|
||||
r.right = r.left + 256;
|
||||
r.bottom = r.top + 256;
|
||||
|
||||
CString str;
|
||||
str.Format(_T("da_%d_%d_%d_%d_%d"), m_env.STATUS.TP, r);
|
||||
Dump(str, m_env.STATUS.TP, r, false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ResetDevice() {}
|
||||
virtual void Draw() = 0;
|
||||
virtual bool GetOutput(Texture& t) = 0;
|
||||
|
||||
bool Merge()
|
||||
{
|
||||
Texture st[2];
|
||||
|
||||
if(!GetOutput(st[0]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CSize s;
|
||||
|
||||
s.cx = st[0].GetWidth();
|
||||
s.cy = st[0].GetHeight();
|
||||
|
||||
GSVector4 sr[2];
|
||||
|
||||
sr[0].x = 0;
|
||||
sr[0].y = 0;
|
||||
sr[0].z = 1.0f;
|
||||
sr[0].w = 1.0f;
|
||||
|
||||
GSVector4 dr[2];
|
||||
|
||||
dr[0].x = 0;
|
||||
dr[0].y = 0;
|
||||
dr[0].z = (float)s.cx;
|
||||
dr[0].w = (float)s.cy;
|
||||
|
||||
GSVector4 c(0, 0, 0, 1);
|
||||
|
||||
m_dev.Merge(st, sr, dr, s, 1, 1, c);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
Device m_dev;
|
||||
|
||||
public:
|
||||
GPURenderer(const GPURendererSettings& rs)
|
||||
: GPURendererBase(rs)
|
||||
, m_count(0)
|
||||
, m_maxcount(10000)
|
||||
{
|
||||
m_vertices = (Vertex*)_aligned_malloc(sizeof(Vertex) * m_maxcount, 16);
|
||||
m_maxcount -= 100;
|
||||
|
||||
for(int i = 0; i < countof(m_fpDrawingKickHandlers); i++)
|
||||
{
|
||||
m_fpDrawingKickHandlers[i] = &GPURenderer<Device, Vertex>::DrawingKickNull;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~GPURenderer()
|
||||
{
|
||||
if(m_vertices) _aligned_free(m_vertices);
|
||||
}
|
||||
|
||||
virtual bool Create(HWND hWnd)
|
||||
{
|
||||
if(!m_dev.Create(hWnd, m_vsync))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_hWnd = hWnd; // TODO
|
||||
|
||||
DWORD style = GetWindowLong(hWnd, GWL_STYLE);
|
||||
style |= WS_OVERLAPPEDWINDOW;
|
||||
SetWindowLong(hWnd, GWL_STYLE, style);
|
||||
UpdateWindow(hWnd);
|
||||
|
||||
ShowWindow(hWnd, SW_SHOWNORMAL);
|
||||
|
||||
// TODO
|
||||
|
||||
Reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void VSync()
|
||||
{
|
||||
GSPerfMonAutoTimer pmat(m_perfmon);
|
||||
|
||||
// m_env.STATUS.LCF = ~m_env.STATUS.LCF; // ?
|
||||
|
||||
if(!IsWindow(m_hWnd))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Flush();
|
||||
|
||||
m_perfmon.Put(GSPerfMon::Frame);
|
||||
|
||||
if(!Merge())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// osd
|
||||
|
||||
static UINT64 s_frame = 0;
|
||||
static CString s_stats;
|
||||
|
||||
if(m_perfmon.GetFrame() - s_frame >= 30)
|
||||
{
|
||||
m_perfmon.Update();
|
||||
|
||||
s_frame = m_perfmon.GetFrame();
|
||||
|
||||
double fps = 1000.0f / m_perfmon.Get(GSPerfMon::Frame);
|
||||
|
||||
CRect r = m_env.GetDisplayRect();
|
||||
|
||||
s_stats.Format(
|
||||
_T("%I64d | %d x %d | %.2f fps (%d%%) | %d/%d | %d%% CPU | %.2f | %.2f"),
|
||||
m_perfmon.GetFrame(), r.Width(), r.Height(), fps, (int)(100.0 * fps / m_env.GetFPS()),
|
||||
(int)m_perfmon.Get(GSPerfMon::Prim),
|
||||
(int)m_perfmon.Get(GSPerfMon::Draw),
|
||||
m_perfmon.CPU(),
|
||||
m_perfmon.Get(GSPerfMon::Swizzle) / 1024,
|
||||
m_perfmon.Get(GSPerfMon::Unswizzle) / 1024
|
||||
);
|
||||
|
||||
double fillrate = m_perfmon.Get(GSPerfMon::Fillrate);
|
||||
|
||||
if(fillrate > 0)
|
||||
{
|
||||
s_stats.Format(_T("%s | %.2f mpps"), CString(s_stats), fps * fillrate / (1024 * 1024));
|
||||
}
|
||||
|
||||
SetWindowText(m_hWnd, s_stats);
|
||||
}
|
||||
|
||||
if(m_dev.IsLost())
|
||||
{
|
||||
ResetDevice();
|
||||
}
|
||||
|
||||
CRect r;
|
||||
|
||||
GetClientRect(m_hWnd, &r);
|
||||
|
||||
m_dev.Present(r);
|
||||
}
|
||||
|
||||
virtual bool MakeSnapshot(LPCTSTR path)
|
||||
{
|
||||
CString fn;
|
||||
|
||||
fn.Format(_T("%s_%s"), path, CTime::GetCurrentTime().Format(_T("%Y%m%d%H%M%S")));
|
||||
|
||||
return m_dev.SaveCurrent(fn + _T(".bmp"));
|
||||
}
|
||||
};
|
||||
23
gsdx/GPURendererSW.cpp
Normal file
23
gsdx/GPURendererSW.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "StdAfx.h"
|
||||
#include "GPURendererSW.h"
|
||||
199
gsdx/GPURendererSW.h
Normal file
199
gsdx/GPURendererSW.h
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "GPURenderer.h"
|
||||
#include "GPUVertexSW.h"
|
||||
#include "GPURasterizer.h"
|
||||
#include "GPUTextureCacheSW.h"
|
||||
|
||||
template <class Device>
|
||||
class GPURendererSW : public GPURenderer<Device, GPUVertexSW>
|
||||
{
|
||||
typedef GPUVertexSW Vertex;
|
||||
|
||||
protected:
|
||||
long m_threads;
|
||||
GPUTextureCacheSW* m_tc;
|
||||
GPURasterizer* m_rst;
|
||||
Texture m_texture;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_tc->Invalidate(CRect(0, 0, 1024, 512));
|
||||
|
||||
__super::Reset();
|
||||
}
|
||||
|
||||
void ResetDevice()
|
||||
{
|
||||
m_texture = Texture();
|
||||
}
|
||||
|
||||
bool GetOutput(Texture& t)
|
||||
{
|
||||
CRect r = m_env.GetDisplayRect();
|
||||
|
||||
if(m_texture.GetWidth() != r.Width() || m_texture.GetHeight() != r.Height())
|
||||
{
|
||||
m_texture = Texture();
|
||||
}
|
||||
|
||||
if(!m_texture && !m_dev.CreateTexture(m_texture, r.Width(), r.Height()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO
|
||||
static DWORD* buff = (DWORD*)_aligned_malloc(1024 * 512 * 4, 16);
|
||||
static int pitch = 1024 * 4;
|
||||
|
||||
if(m_env.STATUS.ISRGB24)
|
||||
{
|
||||
for(int i = r.top; i < r.bottom; i++)
|
||||
{
|
||||
m_mem.Expand24(&m_mem.m_vm16[(i << 10) + r.left], &buff[i << 10], r.Width());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = r.top; i < r.bottom; i++)
|
||||
{
|
||||
m_mem.Expand16(&m_mem.m_vm16[(i << 10) + r.left], &buff[i << 10], r.Width());
|
||||
}
|
||||
}
|
||||
|
||||
r.OffsetRect(-r.TopLeft());
|
||||
|
||||
m_texture.Update(r, buff, pitch);
|
||||
|
||||
t = m_texture;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VertexKick()
|
||||
{
|
||||
Vertex& v = m_vl.AddTail();
|
||||
|
||||
// x/y + off.x/y should wrap around at +/-1024
|
||||
|
||||
int x = m_v.XY.X + m_env.DROFF.X;
|
||||
int y = m_v.XY.Y + m_env.DROFF.Y;
|
||||
|
||||
v.p = GSVector4(x, y, m_v.UV.X, m_v.UV.Y) + GSVector4(0.0f, 0.0f, 0.5f, 0.5f);
|
||||
v.c = GSVector4((DWORD)m_v.RGB.ai32);
|
||||
|
||||
__super::VertexKick();
|
||||
}
|
||||
|
||||
void DrawingKickTriangle(Vertex* v, int& count)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void DrawingKickLine(Vertex* v, int& count)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void DrawingKickSprite(Vertex* v, int& count)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void Draw()
|
||||
{
|
||||
const void* texture = NULL;
|
||||
|
||||
if(m_env.PRIM.TME)
|
||||
{
|
||||
texture = m_tc->Lookup(m_env.STATUS);
|
||||
|
||||
if(!texture) {ASSERT(0); return;}
|
||||
}
|
||||
|
||||
int prims = m_rst->Draw(m_vertices, m_count, texture);
|
||||
|
||||
// TODO
|
||||
{
|
||||
CRect r;
|
||||
|
||||
r.left = m_env.DRAREATL.X;
|
||||
r.top = m_env.DRAREATL.Y;
|
||||
r.right = min(m_env.DRAREABR.X + 1, 1024);
|
||||
r.bottom = min(m_env.DRAREABR.Y + 1, 512);
|
||||
|
||||
GSVector4 minv(+1e10f);
|
||||
GSVector4 maxv(-1e10f);
|
||||
|
||||
for(int i = 0, j = m_count; i < j; i++)
|
||||
{
|
||||
GSVector4 p = m_vertices[i].p;
|
||||
|
||||
minv = minv.minv(p);
|
||||
maxv = maxv.maxv(p);
|
||||
}
|
||||
|
||||
GSVector4i v(minv.xyxy(maxv));
|
||||
|
||||
r.left = max(r.left, min(r.right, v.x));
|
||||
r.top = max(r.top, min(r.bottom, v.y));
|
||||
r.right = min(r.right, max(r.left, v.z));
|
||||
r.bottom = min(r.bottom, max(r.top, v.w));
|
||||
|
||||
Invalidate(r);
|
||||
}
|
||||
|
||||
m_perfmon.Put(GSPerfMon::Prim, prims);
|
||||
m_perfmon.Put(GSPerfMon::Draw, 1);
|
||||
}
|
||||
|
||||
void Invalidate(const CRect& r)
|
||||
{
|
||||
__super::Invalidate(r);
|
||||
|
||||
m_tc->Invalidate(r);
|
||||
}
|
||||
|
||||
public:
|
||||
GPURendererSW(const GPURendererSettings& rs)
|
||||
: GPURenderer(rs)
|
||||
{
|
||||
m_threads = 1;
|
||||
|
||||
m_tc = new GPUTextureCacheSW(this);
|
||||
|
||||
m_rst = new GPURasterizer(this, 0, m_threads);
|
||||
|
||||
m_fpDrawingKickHandlers[GPU_POLYGON] = (DrawingKickHandler)&GPURendererSW::DrawingKickTriangle;
|
||||
m_fpDrawingKickHandlers[GPU_LINE] = (DrawingKickHandler)&GPURendererSW::DrawingKickLine;
|
||||
m_fpDrawingKickHandlers[GPU_SPRITE] = (DrawingKickHandler)&GPURendererSW::DrawingKickSprite;
|
||||
}
|
||||
|
||||
virtual ~GPURendererSW()
|
||||
{
|
||||
delete m_tc;
|
||||
|
||||
delete m_rst;
|
||||
}
|
||||
};
|
||||
822
gsdx/GPUState.cpp
Normal file
822
gsdx/GPUState.cpp
Normal file
@@ -0,0 +1,822 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "stdafx.h"
|
||||
#include "GPUState.h"
|
||||
|
||||
GPUState::GPUState()
|
||||
: s_n(0)
|
||||
{
|
||||
memset(m_status, 0, sizeof(m_status));
|
||||
|
||||
for(int i = 0; i < countof(m_fpGPUStatusCommandHandlers); i++)
|
||||
{
|
||||
m_fpGPUStatusCommandHandlers[i] = &GPUState::SCH_Null;
|
||||
}
|
||||
|
||||
m_fpGPUStatusCommandHandlers[0x00] = &GPUState::SCH_ResetGPU;
|
||||
m_fpGPUStatusCommandHandlers[0x01] = &GPUState::SCH_ResetCommandBuffer;
|
||||
m_fpGPUStatusCommandHandlers[0x02] = &GPUState::SCH_ResetIRQ;
|
||||
m_fpGPUStatusCommandHandlers[0x03] = &GPUState::SCH_DisplayEnable;
|
||||
m_fpGPUStatusCommandHandlers[0x04] = &GPUState::SCH_DMASetup;
|
||||
m_fpGPUStatusCommandHandlers[0x05] = &GPUState::SCH_StartOfDisplayArea;
|
||||
m_fpGPUStatusCommandHandlers[0x06] = &GPUState::SCH_HorizontalDisplayRange;
|
||||
m_fpGPUStatusCommandHandlers[0x07] = &GPUState::SCH_VerticalDisplayRange;
|
||||
m_fpGPUStatusCommandHandlers[0x08] = &GPUState::SCH_DisplayMode;
|
||||
m_fpGPUStatusCommandHandlers[0x10] = &GPUState::SCH_GPUInfo;
|
||||
|
||||
m_fpGPUPacketHandler[0] = &GPUState::PH_Command;
|
||||
m_fpGPUPacketHandler[1] = &GPUState::PH_Polygon;
|
||||
m_fpGPUPacketHandler[2] = &GPUState::PH_Line;
|
||||
m_fpGPUPacketHandler[3] = &GPUState::PH_Sprite;
|
||||
m_fpGPUPacketHandler[4] = &GPUState::PH_Move;
|
||||
m_fpGPUPacketHandler[5] = &GPUState::PH_Write;
|
||||
m_fpGPUPacketHandler[6] = &GPUState::PH_Read;
|
||||
m_fpGPUPacketHandler[7] = &GPUState::PH_Environment;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
GPUState::~GPUState()
|
||||
{
|
||||
}
|
||||
|
||||
void GPUState::Reset()
|
||||
{
|
||||
m_env.Reset();
|
||||
|
||||
memset(&m_v, 0, sizeof(m_v));
|
||||
}
|
||||
|
||||
void GPUState::Flush()
|
||||
{
|
||||
FlushPrim();
|
||||
}
|
||||
|
||||
void GPUState::SetPrim(GPUReg* r)
|
||||
{
|
||||
if(m_env.PRIM.TYPE != r->PRIM.TYPE)
|
||||
{
|
||||
ResetPrim();
|
||||
}
|
||||
|
||||
GPURegPRIM PRIM = r->PRIM;
|
||||
|
||||
PRIM.VTX = 0;
|
||||
|
||||
switch(r->PRIM.TYPE)
|
||||
{
|
||||
case GPU_POLYGON:
|
||||
PRIM.ai32 = (r->PRIM.ai32 & 0xF7000000) | 3; // TYPE IIP TME ABE TGE
|
||||
break;
|
||||
case GPU_LINE:
|
||||
PRIM.ai32 = (r->PRIM.ai32 & 0xF2000000) | 2; // TYPE IIP ABE
|
||||
PRIM.TGE = 1;
|
||||
break;
|
||||
case GPU_SPRITE:
|
||||
PRIM.ai32 = (r->PRIM.ai32 & 0xE6000000) | 2; // TYPE TME ABE
|
||||
PRIM.TGE = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_env.PRIM.ai32 != PRIM.ai32)
|
||||
{
|
||||
Flush();
|
||||
|
||||
m_env.PRIM = PRIM;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUState::SetCLUT(GPUReg* r)
|
||||
{
|
||||
UINT32 mask = 0xFFFF0000; // X Y
|
||||
|
||||
UINT32 value = (m_env.CLUT.ai32 & ~mask) | (r->ai32 & mask);
|
||||
|
||||
if(m_env.CLUT.ai32 != value)
|
||||
{
|
||||
Flush();
|
||||
|
||||
m_env.CLUT.ai32 = value;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUState::SetTPAGE(GPUReg* r)
|
||||
{
|
||||
UINT32 mask = 0x000001FF; // TP ABR TY TX
|
||||
|
||||
UINT32 value = (m_env.STATUS.ai32 & ~mask) | ((r->ai32 >> 16) & mask);
|
||||
|
||||
if(m_env.STATUS.ai32 != value)
|
||||
{
|
||||
Flush();
|
||||
|
||||
m_env.STATUS.ai32 = value;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUState::WriteData(const BYTE* mem, UINT32 size)
|
||||
{
|
||||
GSPerfMonAutoTimer pmat(m_perfmon);
|
||||
|
||||
size <<= 2;
|
||||
|
||||
m_write.Append(mem, size);
|
||||
|
||||
int i = 0;
|
||||
|
||||
while(i < m_write.bytes)
|
||||
{
|
||||
GPUReg* r = (GPUReg*)&m_write.buff[i];
|
||||
|
||||
int ret = (this->*m_fpGPUPacketHandler[r->PACKET.TYPE])(r, (m_write.bytes - i) >> 2);
|
||||
|
||||
if(ret == 0) return; // need more data
|
||||
|
||||
i += ret << 2;
|
||||
}
|
||||
|
||||
m_write.Remove(i);
|
||||
}
|
||||
|
||||
void GPUState::ReadData(BYTE* mem, UINT32 size)
|
||||
{
|
||||
GSPerfMonAutoTimer pmat(m_perfmon);
|
||||
|
||||
int remaining = m_read.bytes - m_read.cur;
|
||||
|
||||
int bytes = (int)size << 2;
|
||||
|
||||
if(bytes > remaining)
|
||||
{
|
||||
// ASSERT(0);
|
||||
|
||||
TRACE(_T("WARNING: ReadData\n"));
|
||||
|
||||
// memset(&mem[remaining], 0, bytes - remaining);
|
||||
|
||||
bytes = remaining;
|
||||
}
|
||||
|
||||
memcpy(mem, &m_read.buff[m_read.cur], bytes);
|
||||
|
||||
m_read.cur += bytes;
|
||||
|
||||
if(m_read.cur >= m_read.bytes)
|
||||
{
|
||||
m_env.STATUS.IMG = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUState::WriteStatus(UINT32 status)
|
||||
{
|
||||
GSPerfMonAutoTimer pmat(m_perfmon);
|
||||
|
||||
UINT32 b = status >> 24;
|
||||
|
||||
m_status[b] = status;
|
||||
|
||||
(this->*m_fpGPUStatusCommandHandlers[b])((GPUReg*)&status);
|
||||
}
|
||||
|
||||
UINT32 GPUState::ReadStatus()
|
||||
{
|
||||
GSPerfMonAutoTimer pmat(m_perfmon);
|
||||
|
||||
m_env.STATUS.LCF = ~m_env.STATUS.LCF; // ?
|
||||
|
||||
return m_env.STATUS.ai32;
|
||||
}
|
||||
|
||||
void GPUState::Freeze(GPUFreezeData* data)
|
||||
{
|
||||
data->status = m_env.STATUS.ai32;
|
||||
memcpy(data->control, m_status, 256 * 4);
|
||||
memcpy(data->vram, m_mem.m_vm16, 1024 * 512 * 2);
|
||||
}
|
||||
|
||||
void GPUState::Defrost(const GPUFreezeData* data)
|
||||
{
|
||||
m_env.STATUS.ai32 = data->status;
|
||||
memcpy(m_status, data->control, 256 * 4);
|
||||
memcpy(m_mem.m_vm16, data->vram, 1024 * 512 * 2);
|
||||
|
||||
for(int i = 0; i <= 8; i++)
|
||||
{
|
||||
WriteStatus(m_status[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void GPUState::SCH_Null(GPUReg* r)
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
void GPUState::SCH_ResetGPU(GPUReg* r)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void GPUState::SCH_ResetCommandBuffer(GPUReg* r)
|
||||
{
|
||||
// ?
|
||||
}
|
||||
|
||||
void GPUState::SCH_ResetIRQ(GPUReg* r)
|
||||
{
|
||||
// ?
|
||||
}
|
||||
|
||||
void GPUState::SCH_DisplayEnable(GPUReg* r)
|
||||
{
|
||||
m_env.STATUS.DEN = r->DEN.DEN;
|
||||
}
|
||||
|
||||
void GPUState::SCH_DMASetup(GPUReg* r)
|
||||
{
|
||||
m_env.STATUS.DMA = r->DMA.DMA;
|
||||
}
|
||||
|
||||
void GPUState::SCH_StartOfDisplayArea(GPUReg* r)
|
||||
{
|
||||
m_env.DAREA = r->DAREA;
|
||||
}
|
||||
|
||||
void GPUState::SCH_HorizontalDisplayRange(GPUReg* r)
|
||||
{
|
||||
m_env.DHRANGE = r->DHRANGE;
|
||||
}
|
||||
|
||||
void GPUState::SCH_VerticalDisplayRange(GPUReg* r)
|
||||
{
|
||||
m_env.DVRANGE = r->DVRANGE;
|
||||
}
|
||||
|
||||
void GPUState::SCH_DisplayMode(GPUReg* r)
|
||||
{
|
||||
m_env.STATUS.WIDTH0 = r->DMODE.WIDTH0;
|
||||
m_env.STATUS.HEIGHT = r->DMODE.HEIGHT;
|
||||
m_env.STATUS.ISPAL = r->DMODE.ISPAL;
|
||||
m_env.STATUS.ISRGB24 = r->DMODE.ISRGB24;
|
||||
m_env.STATUS.ISINTER = r->DMODE.ISINTER;
|
||||
m_env.STATUS.WIDTH1 = r->DMODE.WIDTH1;
|
||||
}
|
||||
|
||||
void GPUState::SCH_GPUInfo(GPUReg* r)
|
||||
{
|
||||
UINT32 value = 0;
|
||||
|
||||
switch(r->GPUINFO.PARAM)
|
||||
{
|
||||
case 0x2:
|
||||
value = m_env.TWIN.ai32;
|
||||
break;
|
||||
case 0x0:
|
||||
case 0x1:
|
||||
case 0x3:
|
||||
value = m_env.DRAREATL.ai32;
|
||||
break;
|
||||
case 0x4:
|
||||
value = m_env.DRAREABR.ai32;
|
||||
break;
|
||||
case 0x5:
|
||||
case 0x6:
|
||||
value = m_env.DROFF.ai32;
|
||||
break;
|
||||
case 0x7:
|
||||
value = 2;
|
||||
break;
|
||||
case 0x8:
|
||||
case 0xf:
|
||||
value = 0xBFC03720; // ?
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
m_read.RemoveAll();
|
||||
m_read.Append((BYTE*)&value, 4);
|
||||
m_read.cur = 0;
|
||||
}
|
||||
|
||||
int GPUState::PH_Command(GPUReg* r, int size)
|
||||
{
|
||||
switch(r->PACKET.OPTION)
|
||||
{
|
||||
case 0: // ???
|
||||
|
||||
return 1;
|
||||
|
||||
case 1: // clear cache
|
||||
|
||||
return 1;
|
||||
|
||||
case 2: // fillrect
|
||||
|
||||
if(size < 3) return 0;
|
||||
|
||||
Flush();
|
||||
|
||||
CRect r2;
|
||||
|
||||
r2.left = r[1].XY.X;
|
||||
r2.top = r[1].XY.Y;
|
||||
r2.right = r2.left + r[2].XY.X;
|
||||
r2.bottom = r2.top + r[2].XY.Y;
|
||||
|
||||
WORD c = (WORD)(((r[0].RGB.R >> 3) << 10) | ((r[0].RGB.R >> 3) << 5) | (r[0].RGB.R >> 3));
|
||||
|
||||
m_mem.FillRect(r2, c);
|
||||
|
||||
Invalidate(r2);
|
||||
|
||||
Dump(_T("f"));
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
ASSERT(0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GPUState::PH_Polygon(GPUReg* r, int size)
|
||||
{
|
||||
int required = 1;
|
||||
|
||||
int vertices = r[0].POLYGON.VTX ? 4 : 3;
|
||||
|
||||
required += vertices;
|
||||
|
||||
if(r[0].POLYGON.TME) required += vertices;
|
||||
|
||||
if(r[0].POLYGON.IIP) required += vertices - 1;
|
||||
|
||||
if(size < required) return 0;
|
||||
|
||||
//
|
||||
|
||||
SetPrim(r);
|
||||
|
||||
if(r[0].POLYGON.TME)
|
||||
{
|
||||
SetCLUT(&r[2]);
|
||||
|
||||
SetTPAGE(&r[r[0].POLYGON.IIP ? 5 : 4]);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
GPUVertex v[4];
|
||||
|
||||
for(int i = 0, j = 0; j < vertices; j++)
|
||||
{
|
||||
v[j].RGB = r[r[0].POLYGON.IIP ? i : 0].RGB;
|
||||
|
||||
if(j == 0 || r[0].POLYGON.IIP) i++;
|
||||
|
||||
v[j].XY = r[i++].XY;
|
||||
|
||||
if(r[0].POLYGON.TME)
|
||||
{
|
||||
v[j].UV.X = r[i].UV.U;
|
||||
v[j].UV.Y = r[i].UV.V;
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i <= vertices - 3; i++)
|
||||
{
|
||||
for(int j = 0; j < 3; j++)
|
||||
{
|
||||
m_v = v[i + j];
|
||||
|
||||
VertexKick();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
return required;
|
||||
}
|
||||
|
||||
int GPUState::PH_Line(GPUReg* r, int size)
|
||||
{
|
||||
int required = 1;
|
||||
|
||||
int vertices = 0;
|
||||
|
||||
if(r->LINE.PLL)
|
||||
{
|
||||
required++;
|
||||
|
||||
for(int i = 1; i < size; i++)
|
||||
{
|
||||
if(r[i].ai32 == 0x55555555)
|
||||
{
|
||||
vertices = i - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(vertices < 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vertices = 2;
|
||||
}
|
||||
|
||||
required += vertices;
|
||||
|
||||
if(r->LINE.IIP) required += vertices - 1;
|
||||
|
||||
//
|
||||
|
||||
SetPrim(r);
|
||||
|
||||
//
|
||||
|
||||
for(int i = 0, j = 0; j < vertices; j++)
|
||||
{
|
||||
if(j >= 2) VertexKick();
|
||||
|
||||
m_v.RGB = r[r[0].LINE.IIP ? i : 0].RGB;
|
||||
|
||||
if(j == 0 || r[0].LINE.IIP) i++;
|
||||
|
||||
m_v.XY = r[i++].XY;
|
||||
|
||||
VertexKick();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
return required;
|
||||
}
|
||||
|
||||
int GPUState::PH_Sprite(GPUReg* r, int size)
|
||||
{
|
||||
int required = 2;
|
||||
|
||||
if(r[0].SPRITE.TME) required++;
|
||||
if(r[0].SPRITE.SIZE == 0) required++;
|
||||
|
||||
if(size < required) return 0;
|
||||
|
||||
//
|
||||
|
||||
SetPrim(r);
|
||||
|
||||
if(r[0].SPRITE.TME)
|
||||
{
|
||||
SetCLUT(&r[2]);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
int i = 0;
|
||||
|
||||
m_v.RGB = r[i++].RGB;
|
||||
|
||||
m_v.XY = r[i++].XY;
|
||||
|
||||
if(r[0].SPRITE.TME)
|
||||
{
|
||||
m_v.UV.X = r[i].UV.U;
|
||||
m_v.UV.Y = r[i].UV.V;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
VertexKick();
|
||||
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
|
||||
switch(r[0].SPRITE.SIZE)
|
||||
{
|
||||
case 0: w = r[i].XY.X; h = r[i].XY.Y; i++; break;
|
||||
case 1: w = h = 1; break;
|
||||
case 2: w = h = 8; break;
|
||||
case 3: w = h = 16; break;
|
||||
default: __assume(0);
|
||||
}
|
||||
|
||||
m_v.XY.X += w;
|
||||
m_v.XY.Y += h;
|
||||
|
||||
if(r[0].SPRITE.TME)
|
||||
{
|
||||
m_v.UV.X += w;
|
||||
m_v.UV.Y += h;
|
||||
}
|
||||
|
||||
VertexKick();
|
||||
|
||||
//
|
||||
|
||||
return required;
|
||||
}
|
||||
|
||||
int GPUState::PH_Move(GPUReg* r, int size)
|
||||
{
|
||||
if(size < 4) return 0;
|
||||
|
||||
Flush();
|
||||
|
||||
CPoint src, dst;
|
||||
|
||||
src.x = r[1].XY.X;
|
||||
src.y = r[1].XY.Y;
|
||||
|
||||
dst.x = r[2].XY.X;
|
||||
dst.y = r[2].XY.Y;
|
||||
|
||||
int w = r[3].XY.X;
|
||||
int h = r[3].XY.Y;
|
||||
|
||||
m_mem.MoveRect(src, dst, w, h);
|
||||
|
||||
Invalidate(CRect(dst, CSize(w, h)));
|
||||
|
||||
Dump(_T("m"));
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
int GPUState::PH_Write(GPUReg* r, int size)
|
||||
{
|
||||
if(size < 3) return 0;
|
||||
|
||||
int w = r[2].XY.X;
|
||||
int h = r[2].XY.Y;
|
||||
|
||||
int required = 3 + ((w * h + 1) >> 1);
|
||||
|
||||
if(size < required) return 0;
|
||||
|
||||
Flush();
|
||||
|
||||
CRect r2;
|
||||
|
||||
r2.left = r[1].XY.X;
|
||||
r2.top = r[1].XY.Y;
|
||||
r2.right = r2.left + w;
|
||||
r2.bottom = r2.top + h;
|
||||
|
||||
m_mem.WriteRect(r2, (const WORD*)&r[3]);
|
||||
|
||||
Invalidate(r2);
|
||||
|
||||
Dump(_T("w"));
|
||||
|
||||
m_perfmon.Put(GSPerfMon::Swizzle, w * h * 2);
|
||||
|
||||
return required;
|
||||
}
|
||||
|
||||
int GPUState::PH_Read(GPUReg* r, int size)
|
||||
{
|
||||
if(size < 3) return 0;
|
||||
|
||||
Flush();
|
||||
|
||||
int w = r[2].XY.X;
|
||||
int h = r[2].XY.Y;
|
||||
|
||||
CRect r2;
|
||||
|
||||
r2.left = r[1].XY.X;
|
||||
r2.top = r[1].XY.Y;
|
||||
r2.right = r2.left + w;
|
||||
r2.bottom = r2.top + h;
|
||||
|
||||
m_read.bytes = ((w * h + 1) & ~1) * 2;
|
||||
m_read.cur = 0;
|
||||
m_read.Reserve(m_read.bytes);
|
||||
m_mem.ReadRect(r2, (WORD*)m_read.buff);
|
||||
|
||||
Invalidate(r2);
|
||||
|
||||
m_env.STATUS.IMG = 1;
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int GPUState::PH_Environment(GPUReg* r, int size)
|
||||
{
|
||||
Flush(); // TODO: only call when something really changes
|
||||
|
||||
switch(r->PACKET.OPTION)
|
||||
{
|
||||
case 1: // draw mode setting
|
||||
|
||||
m_env.STATUS.TX = r->MODE.TX;
|
||||
m_env.STATUS.TY = r->MODE.TY;
|
||||
m_env.STATUS.ABR = r->MODE.ABR;
|
||||
m_env.STATUS.TP = r->MODE.TP;
|
||||
m_env.STATUS.DTD = r->MODE.DTD;
|
||||
m_env.STATUS.DFE = r->MODE.DFE;
|
||||
// ?
|
||||
// m_env.STATUS.MD = r->MODE.MD;
|
||||
// m_env.STATUS.ME = r->MODE.ME;
|
||||
|
||||
// mirror bits?
|
||||
|
||||
return 1;
|
||||
|
||||
case 2: // texture window setting
|
||||
|
||||
m_env.TWIN = r->TWIN;
|
||||
|
||||
return 1;
|
||||
|
||||
case 3: // set drawing area top left
|
||||
|
||||
m_env.DRAREATL = r->DRAREA;
|
||||
|
||||
return 1;
|
||||
|
||||
case 4: // set drawing area bottom right
|
||||
|
||||
m_env.DRAREABR = r->DRAREA;
|
||||
|
||||
return 1;
|
||||
|
||||
case 5: // drawing offset
|
||||
|
||||
m_env.DROFF = r->DROFF;
|
||||
|
||||
return 1;
|
||||
|
||||
case 6: // mask setting
|
||||
|
||||
m_env.STATUS.MD = r->MASK.MD;
|
||||
m_env.STATUS.ME = r->MASK.ME;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASSERT(0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GPUState::SaveBMP(LPCTSTR path, UINT32 TP, CRect r)
|
||||
{
|
||||
r.left &= ~1;
|
||||
r.right &= ~1;
|
||||
|
||||
if(FILE* fp = _tfopen(path, _T("wb")))
|
||||
{
|
||||
BITMAPINFOHEADER bih;
|
||||
memset(&bih, 0, sizeof(bih));
|
||||
bih.biSize = sizeof(bih);
|
||||
bih.biWidth = r.Width();
|
||||
bih.biHeight = r.Height();
|
||||
bih.biPlanes = 1;
|
||||
bih.biBitCount = 32;
|
||||
bih.biCompression = BI_RGB;
|
||||
bih.biSizeImage = bih.biWidth * bih.biHeight * 4;
|
||||
|
||||
BITMAPFILEHEADER bfh;
|
||||
memset(&bfh, 0, sizeof(bfh));
|
||||
bfh.bfType = 'MB';
|
||||
bfh.bfOffBits = sizeof(bfh) + sizeof(bih);
|
||||
bfh.bfSize = bfh.bfOffBits + bih.biSizeImage;
|
||||
bfh.bfReserved1 = bfh.bfReserved2 = 0;
|
||||
|
||||
fwrite(&bfh, 1, sizeof(bfh), fp);
|
||||
fwrite(&bih, 1, sizeof(bih), fp);
|
||||
|
||||
WORD* buff = (WORD*)_aligned_malloc(sizeof(WORD) * 1024, 16);
|
||||
DWORD* buff32 = (DWORD*)_aligned_malloc(sizeof(DWORD) * 1024, 16);
|
||||
WORD* clut = GetCLUT();
|
||||
|
||||
for(int j = r.bottom - 1; j >= r.top; j--)
|
||||
{
|
||||
WORD* p = &m_mem.m_vm16[(j << 10) + r.left];
|
||||
|
||||
if(TP == 0) // 4 bpp
|
||||
{
|
||||
for(int i = 0, k = r.Width(); i < k; i++)
|
||||
{
|
||||
buff[i] = clut[(i & 1) == 0 ? (((BYTE*)p)[i] & 0xf) : (((BYTE*)p)[i] >> 4)];
|
||||
}
|
||||
}
|
||||
else if(TP == 1) // 8 bpp
|
||||
{
|
||||
for(int i = 0, k = r.Width(); i < k; i++)
|
||||
{
|
||||
buff[i] = clut[((BYTE*)p)[i]];
|
||||
}
|
||||
}
|
||||
else if(TP == 2) // 16 bpp;
|
||||
{
|
||||
for(int i = 0, k = r.Width(); i < k; i++)
|
||||
{
|
||||
buff[i] = p[i];
|
||||
}
|
||||
}
|
||||
else if(TP == 3) // 24 bpp
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
m_mem.Expand16(buff, buff32, r.Width());
|
||||
|
||||
for(int i = 0, k = r.Width(); i < k; i++)
|
||||
{
|
||||
buff32[i] = (buff32[i] & 0xff00ff00) | ((buff32[i] & 0x00ff0000) >> 16) | ((buff32[i] & 0x000000ff) << 16);
|
||||
}
|
||||
|
||||
fwrite(buff32, 1, r.Width() * 4, fp);
|
||||
}
|
||||
|
||||
_aligned_free(buff);
|
||||
_aligned_free(buff32);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
GPUState::Buffer::Buffer()
|
||||
{
|
||||
bytes = 0;
|
||||
maxbytes = 4096;
|
||||
buff = (BYTE*)_aligned_malloc(maxbytes, 16);
|
||||
cur = 0;
|
||||
}
|
||||
|
||||
GPUState::Buffer::~Buffer()
|
||||
{
|
||||
_aligned_free(buff);
|
||||
}
|
||||
|
||||
void GPUState::Buffer::Reserve(int size)
|
||||
{
|
||||
if(size > maxbytes)
|
||||
{
|
||||
maxbytes = (maxbytes + size + 1023) & ~1023;
|
||||
|
||||
buff = (BYTE*)_aligned_realloc(buff, maxbytes, 16);
|
||||
}
|
||||
}
|
||||
|
||||
void GPUState::Buffer::Append(const BYTE* src, int size)
|
||||
{
|
||||
Reserve(bytes + (int)size);
|
||||
|
||||
memcpy(&buff[bytes], src, size);
|
||||
|
||||
bytes += size;
|
||||
}
|
||||
|
||||
void GPUState::Buffer::Remove(int size)
|
||||
{
|
||||
ASSERT(size <= bytes);
|
||||
|
||||
if(size < bytes)
|
||||
{
|
||||
memmove(&buff[0], &buff[size], bytes - size);
|
||||
|
||||
bytes -= size;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
memset(&buff[bytes], 0xff, maxbytes - bytes);
|
||||
#endif
|
||||
}
|
||||
|
||||
void GPUState::Buffer::RemoveAll()
|
||||
{
|
||||
bytes = 0;
|
||||
}
|
||||
145
gsdx/GPUState.h
Normal file
145
gsdx/GPUState.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "GPU.h"
|
||||
#include "GPUDrawingEnvironment.h"
|
||||
#include "GPULocalMemory.h"
|
||||
#include "GPUVertex.h"
|
||||
#include "GSAlignedClass.h"
|
||||
#include "GSUtil.h"
|
||||
#include "GSPerfMon.h"
|
||||
|
||||
class GPUState : public GSAlignedClass<16>
|
||||
{
|
||||
typedef void (GPUState::*GPUStatusCommandHandler)(GPUReg* r);
|
||||
|
||||
GPUStatusCommandHandler m_fpGPUStatusCommandHandlers[256];
|
||||
|
||||
void SCH_Null(GPUReg* r);
|
||||
void SCH_ResetGPU(GPUReg* r);
|
||||
void SCH_ResetCommandBuffer(GPUReg* r);
|
||||
void SCH_ResetIRQ(GPUReg* r);
|
||||
void SCH_DisplayEnable(GPUReg* r);
|
||||
void SCH_DMASetup(GPUReg* r);
|
||||
void SCH_StartOfDisplayArea(GPUReg* r);
|
||||
void SCH_HorizontalDisplayRange(GPUReg* r);
|
||||
void SCH_VerticalDisplayRange(GPUReg* r);
|
||||
void SCH_DisplayMode(GPUReg* r);
|
||||
void SCH_GPUInfo(GPUReg* r);
|
||||
|
||||
typedef int (GPUState::*GPUPacketHandler)(GPUReg* r, int size);
|
||||
|
||||
GPUPacketHandler m_fpGPUPacketHandler[8];
|
||||
|
||||
int PH_Command(GPUReg* r, int size);
|
||||
int PH_Polygon(GPUReg* r, int size);
|
||||
int PH_Line(GPUReg* r, int size);
|
||||
int PH_Sprite(GPUReg* r, int size);
|
||||
int PH_Move(GPUReg* r, int size);
|
||||
int PH_Write(GPUReg* r, int size);
|
||||
int PH_Read(GPUReg* r, int size);
|
||||
int PH_Environment(GPUReg* r, int size);
|
||||
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
int bytes;
|
||||
int maxbytes;
|
||||
BYTE* buff;
|
||||
int cur;
|
||||
|
||||
public:
|
||||
Buffer();
|
||||
~Buffer();
|
||||
void Reserve(int size);
|
||||
void Append(const BYTE* src, int size);
|
||||
void Remove(int size);
|
||||
void RemoveAll();
|
||||
};
|
||||
|
||||
Buffer m_write;
|
||||
Buffer m_read;
|
||||
|
||||
void SetPrim(GPUReg* r);
|
||||
void SetCLUT(GPUReg* r);
|
||||
void SetTPAGE(GPUReg* r);
|
||||
|
||||
protected:
|
||||
|
||||
int s_n;
|
||||
|
||||
void Dump(LPCTSTR s, UINT32 TP, const CRect& r, int inc = true)
|
||||
{
|
||||
if(inc) s_n++;
|
||||
|
||||
//if(s_n < 3000 || s_n > 3100) return;
|
||||
//if(m_perfmon.GetFrame() < 1000)
|
||||
//if((m_env.TWIN.ai32 & 0xfffff) == 0)
|
||||
return;
|
||||
|
||||
int dir = 1;
|
||||
#ifdef DEBUG
|
||||
dir = 2;
|
||||
#endif
|
||||
CString str;
|
||||
str.Format(_T("c:\\temp%d\\%04d_%s.bmp"), dir, s_n, s);
|
||||
SaveBMP(str, TP, r);
|
||||
}
|
||||
|
||||
void Dump(LPCTSTR s, int inc = true)
|
||||
{
|
||||
Dump(s, 2, CRect(0, 0, 1024, 512), inc);
|
||||
}
|
||||
|
||||
void SaveBMP(LPCTSTR path, UINT32 TP, CRect r);
|
||||
|
||||
public:
|
||||
GPUDrawingEnvironment m_env;
|
||||
GPULocalMemory m_mem;
|
||||
GPUVertex m_v;
|
||||
GSPerfMon m_perfmon;
|
||||
UINT32 m_status[256];
|
||||
|
||||
public:
|
||||
GPUState();
|
||||
virtual ~GPUState();
|
||||
|
||||
virtual void Reset();
|
||||
virtual void Flush();
|
||||
virtual void FlushPrim() = 0;
|
||||
virtual void ResetPrim() = 0;
|
||||
virtual void VertexKick() = 0;
|
||||
virtual void Invalidate(const CRect& r) {}
|
||||
|
||||
WORD* GetCLUT() {return &m_mem.m_vm16[(m_env.CLUT.Y << 10) + (m_env.CLUT.X << 4)];}
|
||||
|
||||
void WriteData(const BYTE* mem, UINT32 size);
|
||||
void ReadData(BYTE* mem, UINT32 size);
|
||||
|
||||
void WriteStatus(UINT32 status);
|
||||
UINT32 ReadStatus();
|
||||
|
||||
void Freeze(GPUFreezeData* data);
|
||||
void Defrost(const GPUFreezeData* data);
|
||||
};
|
||||
|
||||
130
gsdx/GPUTextureCacheSW.cpp
Normal file
130
gsdx/GPUTextureCacheSW.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "StdAfx.h"
|
||||
#include "GPUTextureCacheSW.h"
|
||||
|
||||
GPUTextureCacheSW::GPUTextureCacheSW(GPUState* state)
|
||||
: m_state(state)
|
||||
{
|
||||
int size = 256 * 256 * (1 + 1 + 4) * 32;
|
||||
|
||||
m_buff[0] = (BYTE*)VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
m_buff[1] = m_buff[0] + 256 * 256 * 32;
|
||||
m_buff[2] = m_buff[1] + 256 * 256 * 32;
|
||||
|
||||
memset(m_buff[0], 0, size);
|
||||
|
||||
memset(m_valid, 0, sizeof(m_valid));
|
||||
|
||||
for(int y = 0, offset = 0; y < 2; y++)
|
||||
{
|
||||
for(int x = 0; x < 16; x++, offset += 256 * 256)
|
||||
{
|
||||
m_texture[0][y][x] = &((BYTE*)m_buff[0])[offset];
|
||||
m_texture[1][y][x] = &((BYTE*)m_buff[1])[offset];
|
||||
}
|
||||
}
|
||||
|
||||
for(int y = 0, offset = 0; y < 2; y++)
|
||||
{
|
||||
for(int x = 0; x < 16; x++, offset += 256 * 256)
|
||||
{
|
||||
m_texture[2][y][x] = &((DWORD*)m_buff[2])[offset];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GPUTextureCacheSW::~GPUTextureCacheSW()
|
||||
{
|
||||
VirtualFree(m_buff[0], 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
const void* GPUTextureCacheSW::Lookup(const GPURegSTATUS& TPAGE)
|
||||
{
|
||||
if(TPAGE.TP == 3)
|
||||
{
|
||||
ASSERT(0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* buff = m_texture[TPAGE.TP][TPAGE.TY][TPAGE.TX];
|
||||
|
||||
UINT32 flag = 1 << TPAGE.TX;
|
||||
|
||||
if(TPAGE.TY) flag <<= 16;
|
||||
|
||||
if((m_valid[TPAGE.TP] & flag) == 0)
|
||||
{
|
||||
int bpp = 0;
|
||||
|
||||
switch(TPAGE.TP)
|
||||
{
|
||||
case 0:
|
||||
m_state->m_mem.ReadPage4(TPAGE.TX, TPAGE.TY, (BYTE*)buff);
|
||||
bpp = 4;
|
||||
break;
|
||||
case 1:
|
||||
m_state->m_mem.ReadPage8(TPAGE.TX, TPAGE.TY, (BYTE*)buff);
|
||||
bpp = 8;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
m_state->m_mem.ReadPage16(TPAGE.TX, TPAGE.TY, (WORD*)buff);
|
||||
bpp = 16;
|
||||
default:
|
||||
// FIXME: __assume(0); // vc9 generates bogus code in release mode
|
||||
break;
|
||||
}
|
||||
|
||||
m_state->m_perfmon.Put(GSPerfMon::Unswizzle, 256 * 256 * bpp >> 3);
|
||||
|
||||
m_valid[TPAGE.TP] |= flag;
|
||||
}
|
||||
|
||||
return buff;
|
||||
}
|
||||
|
||||
void GPUTextureCacheSW::Invalidate(const CRect& r)
|
||||
{
|
||||
for(int y = 0, ye = min(r.bottom, 512), j = 0; y < ye; y += 256, j += 16)
|
||||
{
|
||||
if(r.top >= y + 256) continue;
|
||||
|
||||
for(int x = 0, xe = min(r.right, 1024), i = 0; x < xe; x += 64, i++)
|
||||
{
|
||||
DWORD flag = (1 << i) << j;
|
||||
|
||||
if(r.left >= x + 256) continue;
|
||||
|
||||
m_valid[2] &= ~flag;
|
||||
|
||||
if(r.left >= x + 128) continue;
|
||||
|
||||
m_valid[1] &= ~flag;
|
||||
|
||||
if(r.left >= x + 64) continue;
|
||||
|
||||
m_valid[0] &= ~flag;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
gsdx/GPUTextureCacheSW.h
Normal file
41
gsdx/GPUTextureCacheSW.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "GPURenderer.h"
|
||||
|
||||
class GPUTextureCacheSW
|
||||
{
|
||||
protected:
|
||||
GPUState* m_state;
|
||||
BYTE* m_buff[3];
|
||||
void* m_texture[3][2][16];
|
||||
DWORD m_valid[3];
|
||||
|
||||
public:
|
||||
GPUTextureCacheSW(GPUState* state);
|
||||
virtual ~GPUTextureCacheSW();
|
||||
|
||||
const void* Lookup(const GPURegSTATUS& TPAGE);
|
||||
|
||||
void Invalidate(const CRect& r);
|
||||
};
|
||||
51
gsdx/GPUVertex.h
Normal file
51
gsdx/GPUVertex.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "GPU.h"
|
||||
#include "GSVector.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
__declspec(align(16)) struct GPUVertex
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
GPURegRGB RGB;
|
||||
GPURegXY XY;
|
||||
GPURegXY UV;
|
||||
};
|
||||
|
||||
struct {__m128i m128i;};
|
||||
struct {__m128 m128;};
|
||||
};
|
||||
|
||||
GPUVertex() {memset(this, 0, sizeof(*this));}
|
||||
};
|
||||
|
||||
struct GPUVertexNull
|
||||
{
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
96
gsdx/GPUVertexSW.h
Normal file
96
gsdx/GPUVertexSW.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "GSVector.h"
|
||||
|
||||
__declspec(align(16)) union GPUVertexSW
|
||||
{
|
||||
typedef GSVector4 Vector;
|
||||
|
||||
struct {Vector p, c;};
|
||||
struct {Vector v[2];};
|
||||
struct {float f[8];};
|
||||
|
||||
GPUVertexSW() {}
|
||||
GPUVertexSW(const GPUVertexSW& v) {*this = v;}
|
||||
|
||||
void operator = (const GPUVertexSW& v) {c = v.c; p = v.p;}
|
||||
void operator += (const GPUVertexSW& v) {c += v.c; p += v.p;}
|
||||
|
||||
friend GPUVertexSW operator + (const GPUVertexSW& v1, const GPUVertexSW& v2);
|
||||
friend GPUVertexSW operator - (const GPUVertexSW& v1, const GPUVertexSW& v2);
|
||||
friend GPUVertexSW operator * (const GPUVertexSW& v, const Vector& vv);
|
||||
friend GPUVertexSW operator / (const GPUVertexSW& v, const Vector& vv);
|
||||
friend GPUVertexSW operator * (const GPUVertexSW& v, float f);
|
||||
friend GPUVertexSW operator / (const GPUVertexSW& v, float f);
|
||||
};
|
||||
|
||||
__forceinline GPUVertexSW operator + (const GPUVertexSW& v1, const GPUVertexSW& v2)
|
||||
{
|
||||
GPUVertexSW v0;
|
||||
v0.c = v1.c + v2.c;
|
||||
v0.p = v1.p + v2.p;
|
||||
return v0;
|
||||
}
|
||||
|
||||
__forceinline GPUVertexSW operator - (const GPUVertexSW& v1, const GPUVertexSW& v2)
|
||||
{
|
||||
GPUVertexSW v0;
|
||||
v0.c = v1.c - v2.c;
|
||||
v0.p = v1.p - v2.p;
|
||||
return v0;
|
||||
}
|
||||
|
||||
__forceinline GPUVertexSW operator * (const GPUVertexSW& v, const GPUVertexSW::Vector& vv)
|
||||
{
|
||||
GPUVertexSW v0;
|
||||
v0.c = v.c * vv;
|
||||
v0.p = v.p * vv;
|
||||
return v0;
|
||||
}
|
||||
|
||||
__forceinline GPUVertexSW operator / (const GPUVertexSW& v, const GPUVertexSW::Vector& vv)
|
||||
{
|
||||
GPUVertexSW v0;
|
||||
v0.c = v.c / vv;
|
||||
v0.p = v.p / vv;
|
||||
return v0;
|
||||
}
|
||||
|
||||
__forceinline GPUVertexSW operator * (const GPUVertexSW& v, float f)
|
||||
{
|
||||
GPUVertexSW v0;
|
||||
GPUVertexSW::Vector vf(f);
|
||||
v0.c = v.c * vf;
|
||||
v0.p = v.p * vf;
|
||||
return v0;
|
||||
}
|
||||
|
||||
__forceinline GPUVertexSW operator / (const GPUVertexSW& v, float f)
|
||||
{
|
||||
GPUVertexSW v0;
|
||||
GPUVertexSW::Vector vf(f);
|
||||
v0.c = v.c / vf;
|
||||
v0.p = v.p / vf;
|
||||
return v0;
|
||||
}
|
||||
704
gsdx/GS.cpp
Normal file
704
gsdx/GS.cpp
Normal file
@@ -0,0 +1,704 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 "stdafx.h"
|
||||
#include "GSUtil.h"
|
||||
#include "GSRendererHW9.h"
|
||||
#include "GSRendererHW10.h"
|
||||
#include "GSRendererSW.h"
|
||||
#include "GSRendererNull.h"
|
||||
#include "GSSettingsDlg.h"
|
||||
|
||||
#define PS2E_LT_GS 0x01
|
||||
#define PS2E_GS_VERSION 0x0006
|
||||
#define PS2E_X86 0x01 // 32 bit
|
||||
#define PS2E_X86_64 0x02 // 64 bit
|
||||
|
||||
static HRESULT s_hr = E_FAIL;
|
||||
static GSRendererBase* s_gs = NULL;
|
||||
static void (*s_irq)() = NULL;
|
||||
static BYTE* s_basemem = NULL;
|
||||
|
||||
EXPORT_C_(UINT32) PS2EgetLibType()
|
||||
{
|
||||
return PS2E_LT_GS;
|
||||
}
|
||||
|
||||
EXPORT_C_(char*) PS2EgetLibName()
|
||||
{
|
||||
return GSUtil::GetLibName();
|
||||
}
|
||||
|
||||
EXPORT_C_(UINT32) PS2EgetLibVersion2(UINT32 type)
|
||||
{
|
||||
const UINT32 revision = 0;
|
||||
const UINT32 build = 1;
|
||||
|
||||
return (build << 0) | (revision << 8) | (PS2E_GS_VERSION << 16) | (PLUGIN_VERSION << 24);
|
||||
}
|
||||
|
||||
EXPORT_C_(UINT32) PS2EgetCpuPlatform()
|
||||
{
|
||||
#if _M_AMD64
|
||||
return PS2E_X86_64;
|
||||
#else
|
||||
return PS2E_X86;
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPORT_C GSsetBaseMem(BYTE* mem)
|
||||
{
|
||||
s_basemem = mem - 0x12000000;
|
||||
}
|
||||
|
||||
EXPORT_C_(INT32) GSinit()
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C GSshutdown()
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
}
|
||||
|
||||
EXPORT_C GSclose()
|
||||
{
|
||||
delete s_gs;
|
||||
|
||||
s_gs = NULL;
|
||||
|
||||
if(SUCCEEDED(s_hr))
|
||||
{
|
||||
::CoUninitialize();
|
||||
|
||||
s_hr = E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 GSopen(void* dsp, char* title, int mt, int renderer)
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
if(!GSUtil::CheckDirectX() || !GSUtil::CheckSSE())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
GSclose();
|
||||
|
||||
// TODO
|
||||
|
||||
int nloophack = AfxGetApp()->GetProfileInt(_T("Settings"), _T("nloophack"), 2);
|
||||
|
||||
GSRendererSettings rs;
|
||||
|
||||
rs.m_interlace = AfxGetApp()->GetProfileInt(_T("Settings"), _T("interlace"), 0);
|
||||
rs.m_aspectratio = AfxGetApp()->GetProfileInt(_T("Settings"), _T("aspectratio"), 1);
|
||||
rs.m_filter = AfxGetApp()->GetProfileInt(_T("Settings"), _T("filter"), 1);
|
||||
rs.m_vsync = !!AfxGetApp()->GetProfileInt(_T("Settings"), _T("vsync"), FALSE);
|
||||
rs.m_nativeres = !!AfxGetApp()->GetProfileInt(_T("Settings"), _T("nativeres"), FALSE);
|
||||
|
||||
switch(renderer)
|
||||
{
|
||||
default:
|
||||
case 0: s_gs = new GSRendererHW9(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
case 1: s_gs = new GSRendererSW<GSDevice9>(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
case 2: s_gs = new GSRendererNull<GSDevice9>(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
case 3: s_gs = new GSRendererHW10(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
case 4: s_gs = new GSRendererSW<GSDevice10>(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
case 5: s_gs = new GSRendererNull<GSDevice10>(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
case 6: s_gs = new GSRendererSW<GSDeviceNull>(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
case 7: s_gs = new GSRendererNull<GSDeviceNull>(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
}
|
||||
|
||||
s_hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
|
||||
if(!s_gs->Create(CString(title)))
|
||||
{
|
||||
GSclose();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
s_gs->m_wnd.Show();
|
||||
|
||||
*(HWND*)dsp = s_gs->m_wnd;
|
||||
|
||||
// if(mt) _mm_setcsr(MXCSR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C_(INT32) GSopen(void* dsp, char* title, int mt)
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
int renderer = AfxGetApp()->GetProfileInt(_T("Settings"), _T("renderer"), 0);
|
||||
|
||||
return GSopen(dsp, title, mt, renderer);
|
||||
}
|
||||
|
||||
EXPORT_C GSreset()
|
||||
{
|
||||
s_gs->Reset();
|
||||
}
|
||||
|
||||
EXPORT_C GSgifSoftReset(int mask)
|
||||
{
|
||||
s_gs->SoftReset((BYTE)mask);
|
||||
}
|
||||
|
||||
EXPORT_C GSwriteCSR(UINT32 csr)
|
||||
{
|
||||
s_gs->WriteCSR(csr);
|
||||
}
|
||||
|
||||
EXPORT_C GSreadFIFO(BYTE* mem)
|
||||
{
|
||||
s_gs->ReadFIFO(mem, 1);
|
||||
}
|
||||
|
||||
EXPORT_C GSreadFIFO2(BYTE* mem, UINT32 size)
|
||||
{
|
||||
s_gs->ReadFIFO(mem, size);
|
||||
}
|
||||
|
||||
EXPORT_C GSgifTransfer1(BYTE* mem, UINT32 addr)
|
||||
{
|
||||
s_gs->Transfer<0>(mem + addr, (0x4000 - addr) / 16);
|
||||
}
|
||||
|
||||
EXPORT_C GSgifTransfer2(BYTE* mem, UINT32 size)
|
||||
{
|
||||
s_gs->Transfer<1>(mem, size);
|
||||
}
|
||||
|
||||
EXPORT_C GSgifTransfer3(BYTE* mem, UINT32 size)
|
||||
{
|
||||
s_gs->Transfer<2>(mem, size);
|
||||
}
|
||||
|
||||
EXPORT_C GSvsync(int field)
|
||||
{
|
||||
s_gs->VSync(field);
|
||||
}
|
||||
|
||||
EXPORT_C_(UINT32) GSmakeSnapshot(char* path)
|
||||
{
|
||||
return s_gs->MakeSnapshot(CString(path) + _T("gsdx"));
|
||||
}
|
||||
|
||||
EXPORT_C GSkeyEvent(keyEvent* ev)
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT_C_(INT32) GSfreeze(int mode, GSFreezeData* data)
|
||||
{
|
||||
if(mode == FREEZE_SAVE)
|
||||
{
|
||||
return s_gs->Freeze(data, false);
|
||||
}
|
||||
else if(mode == FREEZE_SIZE)
|
||||
{
|
||||
return s_gs->Freeze(data, true);
|
||||
}
|
||||
else if(mode == FREEZE_LOAD)
|
||||
{
|
||||
return s_gs->Defrost(data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C GSconfigure()
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
GSSettingsDlg dlg;
|
||||
|
||||
if(IDOK == dlg.DoModal())
|
||||
{
|
||||
GSshutdown();
|
||||
GSinit();
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_C_(INT32) GStest()
|
||||
{
|
||||
return 0;
|
||||
|
||||
// TODO
|
||||
|
||||
/*
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
CComPtr<ID3D10Device> dev;
|
||||
|
||||
return SUCCEEDED(D3D10CreateDevice(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION, &dev)) ? 0 : -1;
|
||||
*/
|
||||
}
|
||||
|
||||
EXPORT_C GSabout()
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT_C GSirqCallback(void (*irq)())
|
||||
{
|
||||
s_irq = irq;
|
||||
}
|
||||
|
||||
EXPORT_C GSsetGameCRC(DWORD crc, int options)
|
||||
{
|
||||
s_gs->SetGameCRC(crc, options);
|
||||
}
|
||||
|
||||
EXPORT_C GSgetLastTag(UINT32* tag)
|
||||
{
|
||||
s_gs->GetLastTag(tag);
|
||||
}
|
||||
|
||||
EXPORT_C GSsetFrameSkip(int frameskip)
|
||||
{
|
||||
s_gs->SetFrameSkip(frameskip);
|
||||
}
|
||||
|
||||
EXPORT_C GSReplay(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
||||
{
|
||||
int renderer = -1;
|
||||
|
||||
{
|
||||
char* start = lpszCmdLine;
|
||||
char* end = NULL;
|
||||
long n = strtol(lpszCmdLine, &end, 10);
|
||||
if(end > start) {renderer = n; lpszCmdLine = end;}
|
||||
}
|
||||
|
||||
while(*lpszCmdLine == ' ') lpszCmdLine++;
|
||||
|
||||
::SetPriorityClass(::GetCurrentProcess(), HIGH_PRIORITY_CLASS);
|
||||
|
||||
CAtlArray<BYTE> buff;
|
||||
|
||||
if(FILE* fp = fopen(lpszCmdLine, "rb"))
|
||||
{
|
||||
GSinit();
|
||||
|
||||
BYTE regs[0x2000];
|
||||
GSsetBaseMem(regs);
|
||||
|
||||
HWND hWnd = NULL;
|
||||
GSopen(&hWnd, _T(""), true, renderer);
|
||||
|
||||
DWORD crc;
|
||||
fread(&crc, 4, 1, fp);
|
||||
GSsetGameCRC(crc, 0);
|
||||
|
||||
GSFreezeData fd;
|
||||
fread(&fd.size, 4, 1, fp);
|
||||
fd.data = new BYTE[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);
|
||||
|
||||
unsigned int index, size, addr;
|
||||
|
||||
GSvsync(1);
|
||||
|
||||
while(1)
|
||||
{
|
||||
switch(fgetc(fp))
|
||||
{
|
||||
case EOF:
|
||||
fseek(fp, start, 0);
|
||||
if(!IsWindowVisible(hWnd)) return;
|
||||
break;
|
||||
case 0:
|
||||
index = fgetc(fp);
|
||||
fread(&size, 4, 1, fp);
|
||||
switch(index)
|
||||
{
|
||||
case 0:
|
||||
if(buff.GetCount() < 0x4000) buff.SetCount(0x4000);
|
||||
addr = 0x4000 - size;
|
||||
fread(buff.GetData() + addr, size, 1, fp);
|
||||
GSgifTransfer1(buff.GetData(), addr);
|
||||
break;
|
||||
case 1:
|
||||
if(buff.GetCount() < size) buff.SetCount(size);
|
||||
fread(buff.GetData(), size, 1, fp);
|
||||
GSgifTransfer2(buff.GetData(), size / 16);
|
||||
break;
|
||||
case 2:
|
||||
if(buff.GetCount() < size) buff.SetCount(size);
|
||||
fread(buff.GetData(), size, 1, fp);
|
||||
GSgifTransfer3(buff.GetData(), size / 16);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
GSvsync(fgetc(fp));
|
||||
if(!IsWindowVisible(hWnd)) return;
|
||||
break;
|
||||
case 2:
|
||||
fread(&size, 4, 1, fp);
|
||||
if(buff.GetCount() < size) buff.SetCount(size);
|
||||
GSreadFIFO2(buff.GetData(), size / 16);
|
||||
break;
|
||||
case 3:
|
||||
fread(regs, 0x2000, 1, fp);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GSclose();
|
||||
|
||||
GSshutdown();
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_C GSBenchmark(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
||||
{
|
||||
::SetPriorityClass(::GetCurrentProcess(), HIGH_PRIORITY_CLASS);
|
||||
|
||||
FILE* file = _tfopen(_T("c:\\log.txt"), _T("a"));
|
||||
|
||||
_ftprintf(file, _T("-------------------------\n\n"));
|
||||
|
||||
if(1)
|
||||
{
|
||||
GSLocalMemory mem;
|
||||
|
||||
static struct {int psm; LPCSTR name;} s_format[] =
|
||||
{
|
||||
{PSM_PSMCT32, "32"},
|
||||
{PSM_PSMCT24, "24"},
|
||||
{PSM_PSMCT16, "16"},
|
||||
{PSM_PSMCT16S, "16S"},
|
||||
{PSM_PSMT8, "8"},
|
||||
{PSM_PSMT4, "4"},
|
||||
{PSM_PSMT8H, "8H"},
|
||||
{PSM_PSMT4HL, "4HL"},
|
||||
{PSM_PSMT4HH, "4HH"},
|
||||
{PSM_PSMZ32, "32Z"},
|
||||
{PSM_PSMZ24, "24Z"},
|
||||
{PSM_PSMZ16, "16Z"},
|
||||
{PSM_PSMZ16S, "16ZS"},
|
||||
};
|
||||
|
||||
BYTE* ptr = (BYTE*)_aligned_malloc(1024 * 1024 * 4, 16);
|
||||
|
||||
for(int i = 0; i < 1024 * 1024 * 4; i++) ptr[i] = (BYTE)i;
|
||||
|
||||
//
|
||||
|
||||
for(int tbw = 5; tbw <= 10; tbw++)
|
||||
{
|
||||
int n = 256 << ((10 - tbw) * 2);
|
||||
|
||||
int w = 1 << tbw;
|
||||
int h = 1 << tbw;
|
||||
|
||||
_ftprintf(file, _T("%d x %d\n\n"), w, h);
|
||||
|
||||
for(int i = 0; i < countof(s_format); i++)
|
||||
{
|
||||
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[s_format[i].psm];
|
||||
|
||||
GSLocalMemory::writeImage wi = psm.wi;
|
||||
GSLocalMemory::readImage ri = psm.ri;
|
||||
GSLocalMemory::readTexture rtx = psm.rtx;
|
||||
GSLocalMemory::readTexture rtxP = psm.rtxP;
|
||||
|
||||
GIFRegBITBLTBUF BITBLTBUF;
|
||||
|
||||
BITBLTBUF.SBP = 0;
|
||||
BITBLTBUF.SBW = w / 64;
|
||||
BITBLTBUF.SPSM = s_format[i].psm;
|
||||
BITBLTBUF.DBP = 0;
|
||||
BITBLTBUF.DBW = w / 64;
|
||||
BITBLTBUF.DPSM = s_format[i].psm;
|
||||
|
||||
GIFRegTRXPOS TRXPOS;
|
||||
|
||||
TRXPOS.SSAX = 0;
|
||||
TRXPOS.SSAY = 0;
|
||||
TRXPOS.DSAX = 0;
|
||||
TRXPOS.DSAY = 0;
|
||||
|
||||
GIFRegTRXREG TRXREG;
|
||||
|
||||
TRXREG.RRW = w;
|
||||
TRXREG.RRH = h;
|
||||
|
||||
CRect r(0, 0, w, h);
|
||||
|
||||
GIFRegTEX0 TEX0;
|
||||
|
||||
TEX0.TBP0 = 0;
|
||||
TEX0.TBW = w / 64;
|
||||
|
||||
GIFRegTEXA TEXA;
|
||||
|
||||
TEXA.TA0 = 0;
|
||||
TEXA.TA1 = 0x80;
|
||||
TEXA.AEM = 0;
|
||||
|
||||
int trlen = w * h * psm.trbpp / 8;
|
||||
int len = w * h * psm.bpp / 8;
|
||||
|
||||
clock_t start, end;
|
||||
|
||||
_ftprintf(file, _T("[%4s] "), s_format[i].name);
|
||||
|
||||
start = clock();
|
||||
|
||||
for(int j = 0; j < n; j++)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
(mem.*wi)(x, y, ptr, trlen, BITBLTBUF, TRXPOS, TRXREG);
|
||||
}
|
||||
|
||||
end = clock();
|
||||
|
||||
_ftprintf(file, _T("%6d %6d | "), (int)((float)trlen * n / (end - start) / 1000), (int)((float)(w * h) * n / (end - start) / 1000));
|
||||
|
||||
start = clock();
|
||||
|
||||
for(int j = 0; j < n; j++)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
(mem.*ri)(x, y, ptr, trlen, BITBLTBUF, TRXPOS, TRXREG);
|
||||
}
|
||||
|
||||
end = clock();
|
||||
|
||||
_ftprintf(file, _T("%6d %6d | "), (int)((float)trlen * n / (end - start) / 1000), (int)((float)(w * h) * n / (end - start) / 1000));
|
||||
|
||||
start = clock();
|
||||
|
||||
for(int j = 0; j < n; j++)
|
||||
{
|
||||
(mem.*rtx)(r, ptr, w * 4, TEX0, TEXA);
|
||||
}
|
||||
|
||||
end = clock();
|
||||
|
||||
_ftprintf(file, _T("%6d %6d "), (int)((float)len * n / (end - start) / 1000), (int)((float)(w * h) * n / (end - start) / 1000));
|
||||
|
||||
if(psm.pal > 0)
|
||||
{
|
||||
start = clock();
|
||||
|
||||
for(int j = 0; j < n; j++)
|
||||
{
|
||||
(mem.*rtxP)(r, ptr, w, TEX0, TEXA);
|
||||
}
|
||||
|
||||
end = clock();
|
||||
|
||||
_ftprintf(file, _T("| %6d %6d "), (int)((float)len * n / (end - start) / 1000), (int)((float)(w * h) * n / (end - start) / 1000));
|
||||
}
|
||||
|
||||
_ftprintf(file, _T("\n"));
|
||||
|
||||
fflush(file);
|
||||
}
|
||||
|
||||
_ftprintf(file, _T("\n"));
|
||||
}
|
||||
|
||||
_aligned_free(ptr);
|
||||
}
|
||||
|
||||
if(0)
|
||||
{
|
||||
BYTE regs[0x2000];
|
||||
GSsetBaseMem(regs);
|
||||
|
||||
HWND hWnd = NULL;
|
||||
GSopen(&hWnd, _T(""), true, 6);
|
||||
|
||||
s_gs->m_env.COLCLAMP.CLAMP = 1;
|
||||
s_gs->m_env.PRIM.ABE = 0;
|
||||
s_gs->m_env.PRIM.FST = 1;
|
||||
s_gs->m_env.PRIM.TME = 1;
|
||||
s_gs->m_env.PRIM.IIP = 0;
|
||||
s_gs->m_env.TEXA.TA0 = 0;
|
||||
s_gs->m_env.TEXA.TA1 = 0x80;
|
||||
s_gs->m_env.TEXA.AEM = 0;
|
||||
s_gs->m_context->ALPHA.A = 0;
|
||||
s_gs->m_context->ALPHA.B = 1;
|
||||
s_gs->m_context->ALPHA.C = 0;
|
||||
s_gs->m_context->ALPHA.D = 1;
|
||||
s_gs->m_context->CLAMP.WMS = 1;
|
||||
s_gs->m_context->CLAMP.WMT = 1;
|
||||
s_gs->m_context->CLAMP.MINU = 0;
|
||||
s_gs->m_context->CLAMP.MINV = 0;
|
||||
s_gs->m_context->CLAMP.MAXU = 511;
|
||||
s_gs->m_context->CLAMP.MAXV = 511;
|
||||
s_gs->m_context->FRAME.FBP = 0 >> 5;
|
||||
s_gs->m_context->FRAME.FBW = 8;
|
||||
s_gs->m_context->FRAME.PSM = PSM_PSMCT16S;
|
||||
s_gs->m_context->SCISSOR.SCAX0 = 0;
|
||||
s_gs->m_context->SCISSOR.SCAY0 = 0;
|
||||
s_gs->m_context->SCISSOR.SCAX1 = 511;
|
||||
s_gs->m_context->SCISSOR.SCAY1 = 511;
|
||||
s_gs->m_context->TEST.ZTE = 0;
|
||||
s_gs->m_context->TEST.ZTST = 2;
|
||||
s_gs->m_context->TEX0.TBP0 = 0x2000;
|
||||
s_gs->m_context->TEX0.TBW = 8;
|
||||
s_gs->m_context->TEX0.PSM = PSM_PSMCT32;
|
||||
s_gs->m_context->TEX0.TFX = 1;
|
||||
s_gs->m_context->TEX0.TCC = 0;
|
||||
s_gs->m_context->TEX0.TW = 9;
|
||||
s_gs->m_context->TEX0.TH = 9;
|
||||
s_gs->m_context->TEX1.MMAG = 0;
|
||||
s_gs->m_context->TEX1.MMIN = 0;
|
||||
s_gs->m_context->ZBUF.ZBP = 0x1000 >> 5;
|
||||
s_gs->m_context->ZBUF.PSM = PSM_PSMZ24;
|
||||
|
||||
GSRasterizer* ras = ((GSRendererSW<GSDeviceNull>*)s_gs)->GetRasterizer();
|
||||
|
||||
int count = 512 * 512;
|
||||
|
||||
GSVertexSW* vertices = (GSVertexSW*)_aligned_malloc(count * sizeof(GSVertexSW), 16);
|
||||
/*
|
||||
// point
|
||||
|
||||
for(int j = 0; j < 512; j++)
|
||||
{
|
||||
for(int i = 0; i < 512; i++)
|
||||
{
|
||||
GSVertexSW& v = vertices[(j << 7) + i];
|
||||
|
||||
v.p = GSVector4(i, j, 0, 0);
|
||||
v.t = GSVector4((float)i + 0.5, (float)j + 0.5, 1.0f, 0.0f);
|
||||
v.c = GSVector4(128.0f);
|
||||
}
|
||||
}
|
||||
|
||||
s_gs->PRIM->PRIM = GS_POINTLIST;
|
||||
|
||||
ras->Draw(vertices, count);
|
||||
|
||||
vertices[0].p = GSVector4(0, 0, 0, 0);
|
||||
vertices[0].t = GSVector4(0.5, 0.5, 1.0f, 0.0f);
|
||||
vertices[0].c = GSVector4(128.0f);
|
||||
vertices[1].p = GSVector4(512, 512, 0, 0);
|
||||
vertices[1].t = GSVector4(512.5f, 512.5f, 1.0f, 0.0f);
|
||||
vertices[1].c = GSVector4(128.0f);
|
||||
|
||||
for(int i = 2; i < 512 * 512; i += 2)
|
||||
{
|
||||
memcpy(&vertices[i], &vertices[0], sizeof(vertices[0]) * 2);
|
||||
}
|
||||
|
||||
// sprite
|
||||
|
||||
s_gs->PRIM->PRIM = GS_SPRITE;
|
||||
|
||||
ras->Draw(vertices, count);
|
||||
|
||||
// triangle
|
||||
|
||||
vertices[0].p = GSVector4(0, 0, 0, 0);
|
||||
vertices[0].t = GSVector4(0.5, 0.5, 1.0f, 0.0f);
|
||||
vertices[0].c = GSVector4(128.0f);
|
||||
vertices[1].p = GSVector4(512, 0, 0, 0);
|
||||
vertices[1].t = GSVector4(512.5f, 0.5f, 1.0f, 0.0f);
|
||||
vertices[1].c = GSVector4(128.0f);
|
||||
vertices[2].p = GSVector4(512, 512, 0, 0);
|
||||
vertices[2].t = GSVector4(512.5f, 512.5f, 1.0f, 0.0f);
|
||||
vertices[2].c = GSVector4(128.0f);
|
||||
|
||||
for(int i = 3; i < 512 * 512 - 2; i += 3)
|
||||
{
|
||||
memcpy(&vertices[i], &vertices[0], sizeof(vertices[0]) * 3);
|
||||
}
|
||||
|
||||
s_gs->PRIM->PRIM = GS_TRIANGLELIST;
|
||||
|
||||
ras->Draw(vertices, 999);
|
||||
*/
|
||||
//
|
||||
|
||||
_aligned_free(vertices);
|
||||
|
||||
GSclose();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if(0)
|
||||
{
|
||||
GSLocalMemory mem;
|
||||
|
||||
BYTE* ptr = (BYTE*)_aligned_malloc(1024 * 1024 * 4, 16);
|
||||
|
||||
for(int i = 0; i < 1024 * 1024 * 4; i++) ptr[i] = (BYTE)i;
|
||||
|
||||
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[PSM_PSMCT32];
|
||||
|
||||
GSLocalMemory::writeImage wi = psm.wi;
|
||||
|
||||
GIFRegBITBLTBUF BITBLTBUF;
|
||||
|
||||
BITBLTBUF.DBP = 0;
|
||||
BITBLTBUF.DBW = 32;
|
||||
BITBLTBUF.DPSM = PSM_PSMCT32;
|
||||
|
||||
GIFRegTRXPOS TRXPOS;
|
||||
|
||||
TRXPOS.DSAX = 0;
|
||||
TRXPOS.DSAY = 1;
|
||||
|
||||
GIFRegTRXREG TRXREG;
|
||||
|
||||
TRXREG.RRW = 256;
|
||||
TRXREG.RRH = 256;
|
||||
|
||||
int trlen = 256 * 256 * psm.trbpp / 8;
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
(mem.*wi)(x, y, ptr, trlen, BITBLTBUF, TRXPOS, TRXREG);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
16
gsdx/GS.h
16
gsdx/GS.h
@@ -26,6 +26,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define PLUGIN_VERSION 10
|
||||
|
||||
#include "GSVector.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
@@ -222,6 +224,12 @@ enum GS_AFAIL
|
||||
// sps2regstructs.h
|
||||
//
|
||||
|
||||
#define REG32(name) \
|
||||
union name \
|
||||
{ \
|
||||
UINT32 ai32; \
|
||||
struct { \
|
||||
|
||||
#define REG64(name) \
|
||||
union name \
|
||||
{ \
|
||||
@@ -238,12 +246,18 @@ union name \
|
||||
UINT32 ai32[4]; \
|
||||
struct { \
|
||||
|
||||
#define REG32_(prefix, name) REG32(prefix##name)
|
||||
#define REG64_(prefix, name) REG64(prefix##name)
|
||||
#define REG128_(prefix, name) REG128(prefix##name)
|
||||
|
||||
#define REG_END }; };
|
||||
#define REG_END2 };
|
||||
|
||||
#define REG32_SET(name) \
|
||||
union name \
|
||||
{ \
|
||||
UINT32 ai32; \
|
||||
|
||||
#define REG64_SET(name) \
|
||||
union name \
|
||||
{ \
|
||||
@@ -1065,6 +1079,6 @@ enum {KEYPRESS=1, KEYRELEASE=2};
|
||||
struct keyEvent {UINT32 key, event;};
|
||||
|
||||
enum {FREEZE_LOAD=0, FREEZE_SAVE=1, FREEZE_SIZE=2};
|
||||
struct freezeData {int size; BYTE* data;};
|
||||
struct GSFreezeData {int size; BYTE* data;};
|
||||
|
||||
enum stateType {ST_WRITE, ST_TRANSFER, ST_VSYNC};
|
||||
|
||||
@@ -136,6 +136,8 @@ void GSClut::WriteCLUT32_I4_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TE
|
||||
{
|
||||
ASSERT(TEX0.CSA < 16);
|
||||
|
||||
GSVector4i dummy; // this just forces stack alignment and enables inlining the next call
|
||||
|
||||
WriteCLUT_T32_I4_CSM1(&m_mem->m_vm32[m_mem->BlockAddress32(0, 0, TEX0.CBP, 1)], m_clut + (TEX0.CSA << 4));
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ CRC::Game CRC::m_games[] =
|
||||
{0xFE961D28, DBZBT2, US, false},
|
||||
{0x0393B6BE, DBZBT2, EU, false},
|
||||
{0xE2F289ED, DBZBT2, JP, false}, // Sparking Neo!
|
||||
{0x35AA84D1, DBZBT2, Unknown, false},
|
||||
{0x428113C2, DBZBT3, US, false},
|
||||
{0xA422BB13, DBZBT3, EU, false},
|
||||
{0x983c53d2, DBZBT3, Unknown, false},
|
||||
@@ -82,14 +83,17 @@ CRC::Game CRC::m_games[] =
|
||||
{0x77E61C8A, GT4, Unknown, false},
|
||||
{0xC164550A, WildArms5, JPUNDUB, false},
|
||||
{0xC1640D2C, WildArms5, US, false},
|
||||
{0x0FCF8FE4, WildArms5, EU, false},
|
||||
{0x8B029334, Manhunt2, Unknown, false},
|
||||
{0x09F49E37, CrashBandicootWoC, Unknown, false},
|
||||
{0x013E349D, ResidentEvil4, US, false},
|
||||
{0x6BA2F6B9, ResidentEvil4, Unknown, false},
|
||||
{0x60FA8C69, ResidentEvil4, JP, false},
|
||||
{0x72E1E60E, Spartan, Unknown, false},
|
||||
{0x1B9B7563, AceCombat4, Unknown, false},
|
||||
{0xEC432B24, Drakengard2, Unknown, false},
|
||||
{0x1F88EE37, Tekken5, Unknown, false},
|
||||
{0x652050D2, Tekken5, Unknown, false},
|
||||
{0x9E98B8AE, IkkiTousen, JP, false},
|
||||
{0xD6385328, GodOfWar, US, false},
|
||||
{0xFB0E6D72, GodOfWar, EU, false},
|
||||
|
||||
@@ -35,7 +35,7 @@ GSDump::~GSDump()
|
||||
}
|
||||
}
|
||||
|
||||
void GSDump::Open(LPCTSTR fn, DWORD crc, const freezeData& fd, const void* regs)
|
||||
void GSDump::Open(LPCTSTR fn, DWORD crc, const GSFreezeData& fd, const void* regs)
|
||||
{
|
||||
m_fp = _tfopen(fn, _T("wb"));
|
||||
m_vsyncs = 0;
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
GSDump();
|
||||
virtual ~GSDump();
|
||||
|
||||
void Open(LPCTSTR fn, DWORD crc, const freezeData& fd, const void* regs);
|
||||
void Open(LPCTSTR fn, DWORD crc, const GSFreezeData& fd, const void* regs);
|
||||
void ReadFIFO(UINT32 size);
|
||||
void Transfer(int index, BYTE* mem, size_t size);
|
||||
void VSync(int field, bool last, const void* regs);
|
||||
|
||||
@@ -928,147 +928,145 @@ void GSRasterizer::DrawScanline(int top, int left, int right, const Vertex& v)
|
||||
{
|
||||
do
|
||||
{
|
||||
GSVector4i za = za_base + GSVector4i::load<true>(za_offset);
|
||||
|
||||
GSVector4i zs = (GSVector4i(z * 0.5f) << 1) | (GSVector4i(z) & GSVector4i::one(za));
|
||||
|
||||
GSVector4i za = za_base + GSVector4i::load<true>(za_offset);
|
||||
|
||||
GSVector4i zs = (GSVector4i(z * 0.5f) << 1) | (GSVector4i(z) & GSVector4i::one(za));
|
||||
GSVector4i test;
|
||||
|
||||
GSVector4i test;
|
||||
|
||||
if(!TestZ(zpsm, ztst, zs, za, test))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int pixels = GSVector4i::store(GSVector4i::load(steps).min_i16(GSVector4i::load(4)));
|
||||
|
||||
GSVector4 c[12];
|
||||
|
||||
if(m_sel.tfx != TFX_NONE)
|
||||
{
|
||||
GSVector4 u = s;
|
||||
GSVector4 v = t;
|
||||
|
||||
if(!m_sel.fst)
|
||||
if(!TestZ(zpsm, ztst, zs, za, test))
|
||||
{
|
||||
GSVector4 w = q.rcp();
|
||||
continue;
|
||||
}
|
||||
|
||||
u *= w;
|
||||
v *= w;
|
||||
int pixels = GSVector4i::store(GSVector4i::load(steps).min_i16(GSVector4i::load(4)));
|
||||
|
||||
if(m_sel.ltf)
|
||||
GSVector4 c[12];
|
||||
|
||||
if(m_sel.tfx != TFX_NONE)
|
||||
{
|
||||
GSVector4 u = s;
|
||||
GSVector4 v = t;
|
||||
|
||||
if(!m_sel.fst)
|
||||
{
|
||||
u -= 0.5f;
|
||||
v -= 0.5f;
|
||||
GSVector4 w = q.rcp();
|
||||
|
||||
u *= w;
|
||||
v *= w;
|
||||
|
||||
if(m_sel.ltf)
|
||||
{
|
||||
u -= 0.5f;
|
||||
v -= 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
SampleTexture(pixels, ztst, m_sel.ltf, m_sel.tlu, test, u, v, c);
|
||||
}
|
||||
|
||||
AlphaTFX(m_sel.tfx, m_sel.tcc, a, c[3]);
|
||||
|
||||
GSVector4i fm = m_slenv.fm;
|
||||
GSVector4i zm = m_slenv.zm;
|
||||
|
||||
if(!TestAlpha(m_sel.atst, m_sel.afail, c[3], fm, zm, test))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ColorTFX(m_sel.tfx, r, g, b, a, c[0], c[1], c[2]);
|
||||
|
||||
if(m_sel.fge)
|
||||
{
|
||||
Fog(f, c[0], c[1], c[2]);
|
||||
}
|
||||
|
||||
GSVector4i fa = fa_base + GSVector4i::load<true>(fa_offset);
|
||||
|
||||
GSVector4i d = GSVector4i::zero();
|
||||
|
||||
if(m_sel.rfb)
|
||||
{
|
||||
d = ReadFrameX(fpsm == 1 ? 0 : fpsm, fa);
|
||||
|
||||
if(fpsm != 1 && m_sel.date)
|
||||
{
|
||||
test |= (d ^ m_slenv.datm).sra32(31);
|
||||
|
||||
if(test.alltrue())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SampleTexture(ztst, test, pixels, m_sel.ltf, m_sel.tlu, u, v, c);
|
||||
}
|
||||
fm |= test;
|
||||
zm |= test;
|
||||
|
||||
AlphaTFX(m_sel.tfx, m_sel.tcc, a, c[3]);
|
||||
|
||||
GSVector4i fm = m_slenv.fm;
|
||||
GSVector4i zm = m_slenv.zm;
|
||||
|
||||
if(!TestAlpha(m_sel.atst, m_sel.afail, c[3], fm, zm, test))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ColorTFX(m_sel.tfx, r, g, b, a, c[0], c[1], c[2]);
|
||||
|
||||
if(m_sel.fge)
|
||||
{
|
||||
Fog(f, c[0], c[1], c[2]);
|
||||
}
|
||||
|
||||
GSVector4i fa = fa_base + GSVector4i::load<true>(fa_offset);
|
||||
|
||||
GSVector4i d = GSVector4i::zero();
|
||||
|
||||
if(m_sel.rfb)
|
||||
{
|
||||
d = ReadFrameX(fpsm == 1 ? 0 : fpsm, fa);
|
||||
|
||||
if(fpsm != 1 && m_sel.date)
|
||||
if(m_sel.abe != 255)
|
||||
{
|
||||
test |= (d ^ m_slenv.datm).sra32(31);
|
||||
// GSVector4::expand(d, c[4], c[5], c[6], c[7]);
|
||||
|
||||
if(test.alltrue())
|
||||
c[4] = (d << 24) >> 24;
|
||||
c[5] = (d << 16) >> 24;
|
||||
c[6] = (d << 8) >> 24;
|
||||
c[7] = (d >> 24);
|
||||
|
||||
if(fpsm == 1)
|
||||
{
|
||||
continue;
|
||||
c[7] = GSVector4(128.0f);
|
||||
}
|
||||
|
||||
c[8] = GSVector4::zero();
|
||||
c[9] = GSVector4::zero();
|
||||
c[10] = GSVector4::zero();
|
||||
c[11] = m_slenv.afix;
|
||||
|
||||
DWORD abea = m_sel.abea;
|
||||
DWORD abeb = m_sel.abeb;
|
||||
DWORD abec = m_sel.abec;
|
||||
DWORD abed = m_sel.abed;
|
||||
|
||||
GSVector4 r = (c[abea*4 + 0] - c[abeb*4 + 0]).mod2x(c[abec*4 + 3]) + c[abed*4 + 0];
|
||||
GSVector4 g = (c[abea*4 + 1] - c[abeb*4 + 1]).mod2x(c[abec*4 + 3]) + c[abed*4 + 1];
|
||||
GSVector4 b = (c[abea*4 + 2] - c[abeb*4 + 2]).mod2x(c[abec*4 + 3]) + c[abed*4 + 2];
|
||||
|
||||
if(m_sel.pabe)
|
||||
{
|
||||
GSVector4 mask = c[3] >= GSVector4(128.0f);
|
||||
|
||||
c[0] = c[0].blend8(r, mask);
|
||||
c[1] = c[1].blend8(g, mask);
|
||||
c[2] = c[2].blend8(b, mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
c[0] = r;
|
||||
c[1] = g;
|
||||
c[2] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fm |= test;
|
||||
zm |= test;
|
||||
GSVector4i rb = GSVector4i(c[0]).ps32(GSVector4i(c[2]));
|
||||
GSVector4i ga = GSVector4i(c[1]).ps32(GSVector4i(c[3]));
|
||||
|
||||
GSVector4i rg = rb.upl16(ga) & m_slenv.colclamp;
|
||||
GSVector4i ba = rb.uph16(ga) & m_slenv.colclamp;
|
||||
|
||||
GSVector4i s = rg.upl32(ba).pu16(rg.uph32(ba));
|
||||
|
||||
if(m_sel.abe != 255)
|
||||
{
|
||||
// GSVector4::expand(d, c[4], c[5], c[6], c[7]);
|
||||
|
||||
c[4] = (d << 24) >> 24;
|
||||
c[5] = (d << 16) >> 24;
|
||||
c[6] = (d << 8) >> 24;
|
||||
c[7] = (d >> 24);
|
||||
|
||||
if(fpsm == 1)
|
||||
if(fpsm != 1)
|
||||
{
|
||||
c[7] = GSVector4(128.0f);
|
||||
s |= m_slenv.fba;
|
||||
}
|
||||
|
||||
c[8] = GSVector4::zero();
|
||||
c[9] = GSVector4::zero();
|
||||
c[10] = GSVector4::zero();
|
||||
c[11] = m_slenv.afix;
|
||||
|
||||
DWORD abea = m_sel.abea;
|
||||
DWORD abeb = m_sel.abeb;
|
||||
DWORD abec = m_sel.abec;
|
||||
DWORD abed = m_sel.abed;
|
||||
|
||||
GSVector4 r = (c[abea*4 + 0] - c[abeb*4 + 0]).mod2x(c[abec*4 + 3]) + c[abed*4 + 0];
|
||||
GSVector4 g = (c[abea*4 + 1] - c[abeb*4 + 1]).mod2x(c[abec*4 + 3]) + c[abed*4 + 1];
|
||||
GSVector4 b = (c[abea*4 + 2] - c[abeb*4 + 2]).mod2x(c[abec*4 + 3]) + c[abed*4 + 2];
|
||||
|
||||
if(m_sel.pabe)
|
||||
if(m_sel.rfb)
|
||||
{
|
||||
GSVector4 mask = c[3] >= GSVector4(128.0f);
|
||||
|
||||
c[0] = c[0].blend8(r, mask);
|
||||
c[1] = c[1].blend8(g, mask);
|
||||
c[2] = c[2].blend8(b, mask);
|
||||
s = s.blend(d, fm);
|
||||
}
|
||||
else
|
||||
{
|
||||
c[0] = r;
|
||||
c[1] = g;
|
||||
c[2] = b;
|
||||
}
|
||||
}
|
||||
|
||||
GSVector4i rb = GSVector4i(c[0]).ps32(GSVector4i(c[2]));
|
||||
GSVector4i ga = GSVector4i(c[1]).ps32(GSVector4i(c[3]));
|
||||
|
||||
GSVector4i rg = rb.upl16(ga) & m_slenv.colclamp;
|
||||
GSVector4i ba = rb.uph16(ga) & m_slenv.colclamp;
|
||||
|
||||
GSVector4i s = rg.upl32(ba).pu16(rg.uph32(ba));
|
||||
|
||||
if(fpsm != 1)
|
||||
{
|
||||
s |= m_slenv.fba;
|
||||
}
|
||||
|
||||
if(m_sel.rfb)
|
||||
{
|
||||
s = s.blend(d, fm);
|
||||
}
|
||||
|
||||
WriteFrameAndZBufX(fpsm, fa, fm, s, ztst > 0 ? zpsm : 3, za, zm, zs, pixels);
|
||||
|
||||
WriteFrameAndZBufX(fpsm, fa, fm, s, ztst > 0 ? zpsm : 3, za, zm, zs, pixels);
|
||||
}
|
||||
while(0);
|
||||
|
||||
@@ -1099,7 +1097,7 @@ void GSRasterizer::DrawScanline(int top, int left, int right, const Vertex& v)
|
||||
}
|
||||
}
|
||||
|
||||
void GSRasterizer::SampleTexture(DWORD ztst, const GSVector4i& test, int pixels, DWORD ltf, DWORD tlu, const GSVector4& u, const GSVector4& v, GSVector4* c)
|
||||
void GSRasterizer::SampleTexture(int pixels, DWORD ztst, DWORD ltf, DWORD tlu, const GSVector4i& test, const GSVector4& u, const GSVector4& v, GSVector4* c)
|
||||
{
|
||||
const void* RESTRICT tex = m_slenv.tex;
|
||||
const DWORD* RESTRICT pal = m_slenv.pal;
|
||||
|
||||
@@ -43,36 +43,6 @@ private:
|
||||
DWORD hash;
|
||||
};
|
||||
|
||||
__declspec(align(16)) struct ScanlineEnvironment
|
||||
{
|
||||
int steps;
|
||||
|
||||
void* vm;
|
||||
|
||||
const void* tex;
|
||||
const DWORD* pal;
|
||||
DWORD tw;
|
||||
|
||||
GSVector4i* fbr;
|
||||
GSVector4i* zbr;
|
||||
int** fbc;
|
||||
int** zbc;
|
||||
|
||||
GSVector4i fm, zm;
|
||||
struct {GSVector4i min, max, mask;} t; // [u] x 4 [v] x 4
|
||||
GSVector4i datm;
|
||||
GSVector4i colclamp;
|
||||
GSVector4i fba;
|
||||
GSVector4i aref;
|
||||
GSVector4 afix;
|
||||
GSVector4 afix2;
|
||||
GSVector4 fc;
|
||||
|
||||
GSVector4 dp, dp4;
|
||||
GSVector4 dt, dt4;
|
||||
GSVector4 dc, dc4;
|
||||
};
|
||||
|
||||
union ScanlineSelector
|
||||
{
|
||||
struct
|
||||
@@ -111,6 +81,36 @@ private:
|
||||
operator DWORD() {return dw;}// & 0x7fffffff;}
|
||||
};
|
||||
|
||||
__declspec(align(16)) struct ScanlineEnvironment
|
||||
{
|
||||
int steps;
|
||||
|
||||
void* vm;
|
||||
|
||||
const void* tex;
|
||||
const DWORD* pal;
|
||||
DWORD tw;
|
||||
|
||||
GSVector4i* fbr;
|
||||
GSVector4i* zbr;
|
||||
int** fbc;
|
||||
int** zbc;
|
||||
|
||||
GSVector4i fm, zm;
|
||||
struct {GSVector4i min, max, mask;} t; // [u] x 4 [v] x 4
|
||||
GSVector4i datm;
|
||||
GSVector4i colclamp;
|
||||
GSVector4i fba;
|
||||
GSVector4i aref;
|
||||
GSVector4 afix;
|
||||
GSVector4 afix2;
|
||||
GSVector4 fc;
|
||||
|
||||
GSVector4 dp, dp4;
|
||||
GSVector4 dt, dt4;
|
||||
GSVector4 dc, dc4;
|
||||
};
|
||||
|
||||
GSVector4i m_scissor;
|
||||
CRBMapC<DWORD, ColumnOffset*> m_comap;
|
||||
ColumnOffset* m_fbco;
|
||||
@@ -137,7 +137,7 @@ private:
|
||||
template<DWORD sel>
|
||||
void DrawScanlineEx(int top, int left, int right, const Vertex& v);
|
||||
|
||||
__forceinline void SampleTexture(DWORD ztst, const GSVector4i& test, int pixels, DWORD ltf, DWORD pal, const GSVector4& u, const GSVector4& v, GSVector4* c);
|
||||
__forceinline void SampleTexture(int pixels, DWORD ztst, DWORD ltf, DWORD pal, const GSVector4i& test, const GSVector4& u, const GSVector4& v, GSVector4* c);
|
||||
__forceinline void ColorTFX(DWORD tfx, const GSVector4& rf, const GSVector4& gf, const GSVector4& bf, const GSVector4& af, GSVector4& rt, GSVector4& gt, GSVector4& bt);
|
||||
__forceinline void AlphaTFX(DWORD tfx, DWORD tcc, const GSVector4& af, GSVector4& at);
|
||||
__forceinline void Fog(const GSVector4& f, GSVector4& r, GSVector4& g, GSVector4& b);
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "GSRasterizer.h"
|
||||
|
||||
void GSRasterizer::InitEx()
|
||||
{
|
||||
{/*
|
||||
// ffx
|
||||
|
||||
m_dsmap.SetAt(0x2420c265, &GSRasterizer::DrawScanlineEx<0x2420c265>);
|
||||
@@ -1245,6 +1245,7 @@ void GSRasterizer::InitEx()
|
||||
m_dsmap.SetAt(0xa4802c09, &GSRasterizer::DrawScanlineEx<0xa4802c09>);
|
||||
m_dsmap.SetAt(0xa485bc29, &GSRasterizer::DrawScanlineEx<0xa485bc29>);
|
||||
m_dsmap.SetAt(0xe441bc29, &GSRasterizer::DrawScanlineEx<0xe441bc29>);
|
||||
*/
|
||||
/*
|
||||
// dmc (fixme)
|
||||
|
||||
@@ -1321,189 +1322,187 @@ void GSRasterizer::DrawScanlineEx(int top, int left, int right, const Vertex& v)
|
||||
{
|
||||
do
|
||||
{
|
||||
GSVector4i za = za_base + GSVector4i::load<true>(za_offset);
|
||||
|
||||
GSVector4i zs = (GSVector4i(z * 0.5f) << 1) | (GSVector4i(z) & GSVector4i::one(za));
|
||||
|
||||
GSVector4i za = za_base + GSVector4i::load<true>(za_offset);
|
||||
|
||||
GSVector4i zs = (GSVector4i(z * 0.5f) << 1) | (GSVector4i(z) & GSVector4i::one(za));
|
||||
GSVector4i test;
|
||||
|
||||
GSVector4i test;
|
||||
|
||||
if(!TestZ(zpsm, ztst, zs, za, test))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int pixels = GSVector4i::store(GSVector4i::load(steps).min_i16(GSVector4i::load(4)));
|
||||
|
||||
GSVector4 c[12];
|
||||
|
||||
if(tfx != TFX_NONE)
|
||||
{
|
||||
GSVector4 u = s;
|
||||
GSVector4 v = t;
|
||||
|
||||
if(!fst)
|
||||
if(!TestZ(zpsm, ztst, zs, za, test))
|
||||
{
|
||||
GSVector4 w = q.rcp();
|
||||
|
||||
u *= w;
|
||||
v *= w;
|
||||
|
||||
if(ltf)
|
||||
{
|
||||
u -= 0.5f;
|
||||
v -= 0.5f;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
SampleTexture(ztst, test, pixels, ltf, tlu, u, v, c);
|
||||
}
|
||||
int pixels = GSVector4i::store(GSVector4i::load(steps).min_i16(GSVector4i::load(4)));
|
||||
|
||||
AlphaTFX(tfx, tcc, a, c[3]);
|
||||
GSVector4 c[12];
|
||||
|
||||
GSVector4i fm = m_slenv.fm;
|
||||
GSVector4i zm = m_slenv.zm;
|
||||
|
||||
if(!TestAlpha(atst, afail, c[3], fm, zm, test))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ColorTFX(tfx, r, g, b, a, c[0], c[1], c[2]);
|
||||
|
||||
if(fge)
|
||||
{
|
||||
Fog(f, c[0], c[1], c[2]);
|
||||
}
|
||||
|
||||
GSVector4i fa = fa_base + GSVector4i::load<true>(fa_offset);
|
||||
|
||||
GSVector4i d = GSVector4i::zero();
|
||||
|
||||
if(rfb)
|
||||
{
|
||||
d = ReadFrameX(fpsm == 1 ? 0 : fpsm, fa);
|
||||
|
||||
if(fpsm != 1 && date)
|
||||
if(tfx != TFX_NONE)
|
||||
{
|
||||
test |= (d ^ m_slenv.datm).sra32(31);
|
||||
GSVector4 u = s;
|
||||
GSVector4 v = t;
|
||||
|
||||
if(test.alltrue())
|
||||
if(!fst)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
GSVector4 w = q.rcp();
|
||||
|
||||
fm |= test;
|
||||
zm |= test;
|
||||
u *= w;
|
||||
v *= w;
|
||||
|
||||
if(abe != 255)
|
||||
{
|
||||
// GSVector4::expand(d, c[4], c[5], c[6], c[7]);
|
||||
|
||||
c[4] = (d << 24) >> 24;
|
||||
c[5] = (d << 16) >> 24;
|
||||
c[6] = (d << 8) >> 24;
|
||||
c[7] = (d >> 24);
|
||||
|
||||
if(fpsm == 1)
|
||||
{
|
||||
c[7] = GSVector4(128.0f);
|
||||
}
|
||||
|
||||
c[8] = GSVector4::zero();
|
||||
c[9] = GSVector4::zero();
|
||||
c[10] = GSVector4::zero();
|
||||
c[11] = m_slenv.afix;
|
||||
|
||||
/*
|
||||
GSVector4 r = (c[abea*4 + 0] - c[abeb*4 + 0]).mod2x(c[abec*4 + 3]) + c[abed*4 + 0];
|
||||
GSVector4 g = (c[abea*4 + 1] - c[abeb*4 + 1]).mod2x(c[abec*4 + 3]) + c[abed*4 + 1];
|
||||
GSVector4 b = (c[abea*4 + 2] - c[abeb*4 + 2]).mod2x(c[abec*4 + 3]) + c[abed*4 + 2];
|
||||
*/
|
||||
|
||||
GSVector4 r, g, b;
|
||||
|
||||
if(abea != abeb)
|
||||
{
|
||||
r = c[abea*4 + 0];
|
||||
g = c[abea*4 + 1];
|
||||
b = c[abea*4 + 2];
|
||||
|
||||
if(abeb != 2)
|
||||
{
|
||||
r -= c[abeb*4 + 0];
|
||||
g -= c[abeb*4 + 1];
|
||||
b -= c[abeb*4 + 2];
|
||||
}
|
||||
|
||||
if(!(fpsm == 1 && abec == 1))
|
||||
{
|
||||
if(abec == 2)
|
||||
if(ltf)
|
||||
{
|
||||
r *= m_slenv.afix2;
|
||||
g *= m_slenv.afix2;
|
||||
b *= m_slenv.afix2;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = r.mod2x(c[abec*4 + 3]);
|
||||
g = g.mod2x(c[abec*4 + 3]);
|
||||
b = b.mod2x(c[abec*4 + 3]);
|
||||
u -= 0.5f;
|
||||
v -= 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
if(abed < 2)
|
||||
SampleTexture(ztst, test, pixels, ltf, tlu, u, v, c);
|
||||
}
|
||||
|
||||
AlphaTFX(tfx, tcc, a, c[3]);
|
||||
|
||||
GSVector4i fm = m_slenv.fm;
|
||||
GSVector4i zm = m_slenv.zm;
|
||||
|
||||
if(!TestAlpha(atst, afail, c[3], fm, zm, test))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ColorTFX(tfx, r, g, b, a, c[0], c[1], c[2]);
|
||||
|
||||
if(fge)
|
||||
{
|
||||
Fog(f, c[0], c[1], c[2]);
|
||||
}
|
||||
|
||||
GSVector4i fa = fa_base + GSVector4i::load<true>(fa_offset);
|
||||
|
||||
GSVector4i d = GSVector4i::zero();
|
||||
|
||||
if(rfb)
|
||||
{
|
||||
d = ReadFrameX(fpsm == 1 ? 0 : fpsm, fa);
|
||||
|
||||
if(fpsm != 1 && date)
|
||||
{
|
||||
r += c[abed*4 + 0];
|
||||
g += c[abed*4 + 1];
|
||||
b += c[abed*4 + 2];
|
||||
test |= (d ^ m_slenv.datm).sra32(31);
|
||||
|
||||
if(test.alltrue())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
fm |= test;
|
||||
zm |= test;
|
||||
|
||||
if(abe != 255)
|
||||
{
|
||||
r = c[abed*4 + 0];
|
||||
g = c[abed*4 + 1];
|
||||
b = c[abed*4 + 2];
|
||||
// GSVector4::expand(d, c[4], c[5], c[6], c[7]);
|
||||
|
||||
c[4] = (d << 24) >> 24;
|
||||
c[5] = (d << 16) >> 24;
|
||||
c[6] = (d << 8) >> 24;
|
||||
c[7] = (d >> 24);
|
||||
|
||||
if(fpsm == 1)
|
||||
{
|
||||
c[7] = GSVector4(128.0f);
|
||||
}
|
||||
|
||||
c[8] = GSVector4::zero();
|
||||
c[9] = GSVector4::zero();
|
||||
c[10] = GSVector4::zero();
|
||||
c[11] = m_slenv.afix;
|
||||
|
||||
/*
|
||||
GSVector4 r = (c[abea*4 + 0] - c[abeb*4 + 0]).mod2x(c[abec*4 + 3]) + c[abed*4 + 0];
|
||||
GSVector4 g = (c[abea*4 + 1] - c[abeb*4 + 1]).mod2x(c[abec*4 + 3]) + c[abed*4 + 1];
|
||||
GSVector4 b = (c[abea*4 + 2] - c[abeb*4 + 2]).mod2x(c[abec*4 + 3]) + c[abed*4 + 2];
|
||||
*/
|
||||
|
||||
GSVector4 r, g, b;
|
||||
|
||||
if(abea != abeb)
|
||||
{
|
||||
r = c[abea*4 + 0];
|
||||
g = c[abea*4 + 1];
|
||||
b = c[abea*4 + 2];
|
||||
|
||||
if(abeb != 2)
|
||||
{
|
||||
r -= c[abeb*4 + 0];
|
||||
g -= c[abeb*4 + 1];
|
||||
b -= c[abeb*4 + 2];
|
||||
}
|
||||
|
||||
if(!(fpsm == 1 && abec == 1))
|
||||
{
|
||||
if(abec == 2)
|
||||
{
|
||||
r *= m_slenv.afix2;
|
||||
g *= m_slenv.afix2;
|
||||
b *= m_slenv.afix2;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = r.mod2x(c[abec*4 + 3]);
|
||||
g = g.mod2x(c[abec*4 + 3]);
|
||||
b = b.mod2x(c[abec*4 + 3]);
|
||||
}
|
||||
}
|
||||
|
||||
if(abed < 2)
|
||||
{
|
||||
r += c[abed*4 + 0];
|
||||
g += c[abed*4 + 1];
|
||||
b += c[abed*4 + 2];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r = c[abed*4 + 0];
|
||||
g = c[abed*4 + 1];
|
||||
b = c[abed*4 + 2];
|
||||
}
|
||||
|
||||
if(pabe)
|
||||
{
|
||||
GSVector4 mask = c[3] >= GSVector4(128.0f);
|
||||
|
||||
c[0] = c[0].blend8(r, mask);
|
||||
c[1] = c[1].blend8(g, mask);
|
||||
c[2] = c[2].blend8(b, mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
c[0] = r;
|
||||
c[1] = g;
|
||||
c[2] = b;
|
||||
}
|
||||
}
|
||||
|
||||
if(pabe)
|
||||
GSVector4i rb = GSVector4i(c[0]).ps32(GSVector4i(c[2]));
|
||||
GSVector4i ga = GSVector4i(c[1]).ps32(GSVector4i(c[3]));
|
||||
|
||||
GSVector4i rg = rb.upl16(ga) & m_slenv.colclamp;
|
||||
GSVector4i ba = rb.uph16(ga) & m_slenv.colclamp;
|
||||
|
||||
GSVector4i s = rg.upl32(ba).pu16(rg.uph32(ba));
|
||||
|
||||
if(fpsm != 1)
|
||||
{
|
||||
GSVector4 mask = c[3] >= GSVector4(128.0f);
|
||||
|
||||
c[0] = c[0].blend8(r, mask);
|
||||
c[1] = c[1].blend8(g, mask);
|
||||
c[2] = c[2].blend8(b, mask);
|
||||
s |= m_slenv.fba;
|
||||
}
|
||||
else
|
||||
|
||||
if(rfb)
|
||||
{
|
||||
c[0] = r;
|
||||
c[1] = g;
|
||||
c[2] = b;
|
||||
s = s.blend(d, fm);
|
||||
}
|
||||
}
|
||||
|
||||
GSVector4i rb = GSVector4i(c[0]).ps32(GSVector4i(c[2]));
|
||||
GSVector4i ga = GSVector4i(c[1]).ps32(GSVector4i(c[3]));
|
||||
|
||||
GSVector4i rg = rb.upl16(ga) & m_slenv.colclamp;
|
||||
GSVector4i ba = rb.uph16(ga) & m_slenv.colclamp;
|
||||
|
||||
GSVector4i s = rg.upl32(ba).pu16(rg.uph32(ba));
|
||||
|
||||
if(fpsm != 1)
|
||||
{
|
||||
s |= m_slenv.fba;
|
||||
}
|
||||
|
||||
if(rfb)
|
||||
{
|
||||
s = s.blend(d, fm);
|
||||
}
|
||||
|
||||
WriteFrameAndZBufX(fpsm == 1 && rfb ? 0 : fpsm, fa, fm, s, wzb ? zpsm : 3, za, zm, zs, pixels);
|
||||
|
||||
WriteFrameAndZBufX(fpsm == 1 && rfb ? 0 : fpsm, fa, fm, s, wzb ? zpsm : 3, za, zm, zs, pixels);
|
||||
}
|
||||
while(0);
|
||||
|
||||
|
||||
@@ -89,6 +89,9 @@ protected:
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
GSWnd m_wnd;
|
||||
|
||||
public:
|
||||
GSRendererBase(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs)
|
||||
: GSState(base, mt, irq, nloophack)
|
||||
@@ -105,8 +108,6 @@ public:
|
||||
virtual bool Create(LPCTSTR title) = 0;
|
||||
virtual void VSync(int field) = 0;
|
||||
virtual bool MakeSnapshot(LPCTSTR path) = 0;
|
||||
|
||||
GSWnd m_wnd;
|
||||
};
|
||||
|
||||
template<class Device> class GSRenderer : public GSRendererBase
|
||||
@@ -445,7 +446,7 @@ public:
|
||||
|
||||
if((::GetAsyncKeyState(VK_SHIFT) & 0x8000) && !m_dump)
|
||||
{
|
||||
freezeData fd;
|
||||
GSFreezeData fd;
|
||||
fd.size = 0;
|
||||
fd.data = NULL;
|
||||
Freeze(&fd, true);
|
||||
|
||||
@@ -120,7 +120,7 @@ protected:
|
||||
|
||||
void VertexKick(bool skip)
|
||||
{
|
||||
GSVertexSW& v = m_vl.AddTail();
|
||||
Vertex& v = m_vl.AddTail();
|
||||
|
||||
int x = (int)m_v.XYZ.X - (int)m_context->XYOFFSET.OFX;
|
||||
int y = (int)m_v.XYZ.Y - (int)m_context->XYOFFSET.OFY;
|
||||
|
||||
@@ -1412,7 +1412,7 @@ template<class T> static void ReadState(T* dst, BYTE*& src, size_t len = sizeof(
|
||||
src += len;
|
||||
}
|
||||
|
||||
int GSState::Freeze(freezeData* fd, bool sizeonly)
|
||||
int GSState::Freeze(GSFreezeData* fd, bool sizeonly)
|
||||
{
|
||||
if(sizeonly)
|
||||
{
|
||||
@@ -1484,7 +1484,7 @@ int GSState::Freeze(freezeData* fd, bool sizeonly)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GSState::Defrost(const freezeData* fd)
|
||||
int GSState::Defrost(const GSFreezeData* fd)
|
||||
{
|
||||
if(!fd || !fd->data || fd->size == 0)
|
||||
{
|
||||
|
||||
@@ -147,7 +147,7 @@ public:
|
||||
GSDrawingContext* m_context;
|
||||
GSVertex m_v;
|
||||
float m_q;
|
||||
int m_vprim;
|
||||
DWORD m_vprim;
|
||||
|
||||
GSPerfMon m_perfmon;
|
||||
bool m_nloophack;
|
||||
@@ -197,8 +197,8 @@ public:
|
||||
void WriteCSR(UINT32 csr) {CSR->ai32[1] = csr;}
|
||||
void ReadFIFO(BYTE* mem, int size);
|
||||
template<int index> void Transfer(BYTE* mem, UINT32 size);
|
||||
int Freeze(freezeData* fd, bool sizeonly);
|
||||
int Defrost(const freezeData* fd);
|
||||
int Freeze(GSFreezeData* fd, bool sizeonly);
|
||||
int Defrost(const GSFreezeData* fd);
|
||||
void GetLastTag(UINT32* tag) {*tag = m_path3hack; m_path3hack = 0;}
|
||||
virtual void SetGameCRC(DWORD crc, int options);
|
||||
void SetFrameSkip(int frameskip);
|
||||
|
||||
117
gsdx/GSUtil.cpp
117
gsdx/GSUtil.cpp
@@ -22,6 +22,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "GS.h"
|
||||
#include "GSUtil.h"
|
||||
#include "svnrev.h"
|
||||
|
||||
static struct GSUtilMaps
|
||||
{
|
||||
@@ -81,15 +82,16 @@ static struct GSUtilMaps
|
||||
|
||||
} s_maps;
|
||||
|
||||
int GSUtil::GetPrimClass(DWORD prim)
|
||||
DWORD GSUtil::GetPrimClass(DWORD prim)
|
||||
{
|
||||
return s_maps.PrimClassField[prim];
|
||||
}
|
||||
|
||||
int GSUtil::GetPrimVertexCount(DWORD prim)
|
||||
DWORD GSUtil::GetPrimVertexCount(DWORD prim)
|
||||
{
|
||||
return s_maps.PrimVertexCount[prim];
|
||||
}
|
||||
|
||||
bool GSUtil::HasSharedBits(DWORD spsm, DWORD dpsm)
|
||||
{
|
||||
return s_maps.SharedBitsField[spsm][dpsm];
|
||||
@@ -124,4 +126,115 @@ bool GSUtil::IsRectInRectV(const CRect& inner, const CRect& outer)
|
||||
return outer.left <= inner.left && inner.right <= outer.right;
|
||||
}
|
||||
|
||||
bool GSUtil::CheckDirectX()
|
||||
{
|
||||
CString str;
|
||||
|
||||
str.Format(_T("d3dx9_%d.dll"), D3DX_SDK_VERSION);
|
||||
|
||||
if(HINSTANCE hDll = LoadLibrary(str))
|
||||
{
|
||||
FreeLibrary(hDll);
|
||||
}
|
||||
else
|
||||
{
|
||||
int res = AfxMessageBox(_T("Please update DirectX!\n\nWould you like to open the download page in your browser?"), MB_YESNO);
|
||||
|
||||
if(res == IDYES)
|
||||
{
|
||||
ShellExecute(NULL, _T("open"), _T("http://www.microsoft.com/downloads/details.aspx?FamilyId=2DA43D38-DB71-4C1B-BC6A-9B6652CD92A3"), NULL, NULL, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _CheckSSE()
|
||||
{
|
||||
__try
|
||||
{
|
||||
static __m128i m;
|
||||
|
||||
#if _M_SSE >= 0x402
|
||||
m.m128i_i32[0] = _mm_popcnt_u32(1234);
|
||||
#elif _M_SSE >= 0x401
|
||||
m = _mm_packus_epi32(m, m);
|
||||
#elif _M_SSE >= 0x301
|
||||
m = _mm_alignr_epi8(m, m, 1);
|
||||
#elif _M_SSE >= 0x200
|
||||
m = _mm_packs_epi32(m, m);
|
||||
#endif
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSUtil::CheckSSE()
|
||||
{
|
||||
if(!_CheckSSE())
|
||||
{
|
||||
CString str;
|
||||
str.Format(_T("This CPU does not support SSE %d.%02d"), _M_SSE >> 8, _M_SSE & 0xff);
|
||||
AfxMessageBox(str, MB_OK);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char* GSUtil::GetLibName()
|
||||
{
|
||||
CString str;
|
||||
|
||||
str.Format(_T("GSdx %d"), SVN_REV);
|
||||
|
||||
if(SVN_MODS) str += _T("m");
|
||||
|
||||
#if _M_AMD64
|
||||
str += _T(" 64-bit");
|
||||
#endif
|
||||
|
||||
CAtlList<CString> sl;
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
CString s;
|
||||
s.Format(_T("Intel C++ %d.%02d"), __INTEL_COMPILER/100, __INTEL_COMPILER%100);
|
||||
sl.AddTail(s);
|
||||
#elif _MSC_VER
|
||||
CString s;
|
||||
s.Format(_T("MSVC %d.%02d"), _MSC_VER/100, _MSC_VER%100);
|
||||
sl.AddTail(s);
|
||||
#endif
|
||||
|
||||
#if _M_SSE >= 0x402
|
||||
sl.AddTail(_T("SSE42"));
|
||||
#elif _M_SSE >= 0x401
|
||||
sl.AddTail(_T("SSE41"));
|
||||
#elif _M_SSE >= 0x301
|
||||
sl.AddTail(_T("SSSE3"));
|
||||
#elif _M_SSE >= 0x200
|
||||
sl.AddTail(_T("SSE2"));
|
||||
#elif _M_SSE >= 0x100
|
||||
sl.AddTail(_T("SSE"));
|
||||
#endif
|
||||
|
||||
POSITION pos = sl.GetHeadPosition();
|
||||
|
||||
while(pos)
|
||||
{
|
||||
if(pos == sl.GetHeadPosition()) str += _T(" (");
|
||||
str += sl.GetNext(pos);
|
||||
str += pos ? _T(", ") : _T(")");
|
||||
}
|
||||
|
||||
static char buff[256];
|
||||
strncpy(buff, CStringA(str), min(countof(buff)-1, str.GetLength()));
|
||||
return buff;
|
||||
}
|
||||
@@ -21,44 +21,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GS.h"
|
||||
|
||||
class GSUtil
|
||||
{
|
||||
public:
|
||||
static int GetPrimClass(DWORD prim);
|
||||
static int GetPrimVertexCount(DWORD prim);
|
||||
/*
|
||||
static int GetPrimClass(DWORD prim)
|
||||
{
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST: return 0;
|
||||
case GS_LINELIST: return 1;
|
||||
case GS_LINESTRIP: return 1;
|
||||
case GS_TRIANGLELIST: return 2;
|
||||
case GS_TRIANGLESTRIP: return 2;
|
||||
case GS_TRIANGLEFAN: return 2;
|
||||
case GS_SPRITE: return 3;
|
||||
case GS_INVALID: return -1;
|
||||
default: __assume(0);
|
||||
}
|
||||
}
|
||||
static DWORD GetPrimClass(DWORD prim);
|
||||
static DWORD GetPrimVertexCount(DWORD prim);
|
||||
|
||||
static int GetPrimVertexCount(DWORD prim)
|
||||
{
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST: return 1;
|
||||
case GS_LINELIST: return 2;
|
||||
case GS_LINESTRIP: return 2;
|
||||
case GS_TRIANGLELIST: return 3;
|
||||
case GS_TRIANGLESTRIP: return 3;
|
||||
case GS_TRIANGLEFAN: return 3;
|
||||
case GS_SPRITE: return 2;
|
||||
case GS_INVALID: return 1;
|
||||
default: __assume(0);
|
||||
}
|
||||
}
|
||||
*/
|
||||
static bool HasSharedBits(DWORD spsm, DWORD dpsm);
|
||||
static bool HasSharedBits(DWORD sbp, DWORD spsm, DWORD dbp, DWORD dpsm);
|
||||
static bool HasCompatibleBits(DWORD spsm, DWORD dpsm);
|
||||
@@ -86,5 +56,10 @@ public:
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
static bool CheckDirectX();
|
||||
static bool CheckSSE();
|
||||
|
||||
static char* GetLibName();
|
||||
};
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "GSVector.h"
|
||||
|
||||
const GSVector4 GSVector4::m_ps0123(0.0f, 1.0f, 2.0f, 3.0f);
|
||||
const GSVector4 GSVector4::m_ps4567(4.0f, 5.0f, 6.0f, 7.0f);
|
||||
|
||||
void GSVector4::operator = (const GSVector4i& v)
|
||||
{
|
||||
@@ -34,3 +35,12 @@ void GSVector4i::operator = (const GSVector4& v)
|
||||
m = _mm_cvttps_epi32(v);
|
||||
}
|
||||
|
||||
GSVector4i GSVector4i::cast(const GSVector4& v)
|
||||
{
|
||||
return GSVector4i(_mm_castps_si128(v.m));
|
||||
}
|
||||
|
||||
GSVector4 GSVector4::cast(const GSVector4i& v)
|
||||
{
|
||||
return GSVector4(_mm_castsi128_ps(v.m));
|
||||
}
|
||||
|
||||
@@ -174,6 +174,8 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
static GSVector4i cast(const GSVector4& v);
|
||||
|
||||
#if _M_SSE >= 0x401
|
||||
|
||||
GSVector4i sat_i8(const GSVector4i& a, const GSVector4i& b) const
|
||||
@@ -605,6 +607,51 @@ public:
|
||||
|
||||
#endif
|
||||
|
||||
GSVector4i eq8(const GSVector4i& v) const
|
||||
{
|
||||
return GSVector4i(_mm_cmpeq_epi8(m, v.m));
|
||||
}
|
||||
|
||||
GSVector4i eq16(const GSVector4i& v) const
|
||||
{
|
||||
return GSVector4i(_mm_cmpeq_epi16(m, v.m));
|
||||
}
|
||||
|
||||
GSVector4i eq32(const GSVector4i& v) const
|
||||
{
|
||||
return GSVector4i(_mm_cmpeq_epi32(m, v.m));
|
||||
}
|
||||
|
||||
GSVector4i gt8(const GSVector4i& v) const
|
||||
{
|
||||
return GSVector4i(_mm_cmpgt_epi8(m, v.m));
|
||||
}
|
||||
|
||||
GSVector4i gt16(const GSVector4i& v) const
|
||||
{
|
||||
return GSVector4i(_mm_cmpgt_epi16(m, v.m));
|
||||
}
|
||||
|
||||
GSVector4i gt32(const GSVector4i& v) const
|
||||
{
|
||||
return GSVector4i(_mm_cmpgt_epi32(m, v.m));
|
||||
}
|
||||
|
||||
GSVector4i lt8(const GSVector4i& v) const
|
||||
{
|
||||
return GSVector4i(_mm_cmplt_epi8(m, v.m));
|
||||
}
|
||||
|
||||
GSVector4i lt16(const GSVector4i& v) const
|
||||
{
|
||||
return GSVector4i(_mm_cmplt_epi16(m, v.m));
|
||||
}
|
||||
|
||||
GSVector4i lt32(const GSVector4i& v) const
|
||||
{
|
||||
return GSVector4i(_mm_cmplt_epi32(m, v.m));
|
||||
}
|
||||
|
||||
GSVector4i andnot(const GSVector4i& v) const
|
||||
{
|
||||
return GSVector4i(_mm_andnot_si128(v.m, m));
|
||||
@@ -1105,6 +1152,11 @@ public:
|
||||
return invzero().srl16(15);
|
||||
}
|
||||
|
||||
static GSVector4i x00ff()
|
||||
{
|
||||
return invzero().srl16(8);
|
||||
}
|
||||
|
||||
static GSVector4i x000000ff()
|
||||
{
|
||||
return invzero().srl32(24);
|
||||
@@ -1130,6 +1182,11 @@ public:
|
||||
return invzero().srl32(18);
|
||||
}
|
||||
|
||||
static GSVector4i x00007fff()
|
||||
{
|
||||
return invzero().srl32(17);
|
||||
}
|
||||
|
||||
static GSVector4i invzero(const GSVector4i& v)
|
||||
{
|
||||
// - vc can't generate a simple pxor xmm0, xmm0 / pcmpeqd xmm0, xmm0
|
||||
@@ -1148,6 +1205,11 @@ public:
|
||||
return invzero(v).srl16(15);
|
||||
}
|
||||
|
||||
static GSVector4i x00ff(const GSVector4i& v)
|
||||
{
|
||||
return invzero(v).srl16(8);
|
||||
}
|
||||
|
||||
static GSVector4i x000000ff(const GSVector4i& v)
|
||||
{
|
||||
return invzero(v).srl32(24);
|
||||
@@ -1173,6 +1235,11 @@ public:
|
||||
return invzero(v).srl32(18);
|
||||
}
|
||||
|
||||
static GSVector4i x00007fff(const GSVector4i& v)
|
||||
{
|
||||
return invzero(v).srl32(17);
|
||||
}
|
||||
|
||||
#if _M_SSE >= 0x401
|
||||
|
||||
static GSVector4i loadnt(const void* p)
|
||||
@@ -1596,6 +1663,7 @@ public:
|
||||
};
|
||||
|
||||
static const GSVector4 m_ps0123;
|
||||
static const GSVector4 m_ps4567;
|
||||
|
||||
GSVector4()
|
||||
{
|
||||
@@ -1688,6 +1756,8 @@ public:
|
||||
return GSVector4i(*this).rgba64();
|
||||
}
|
||||
|
||||
static GSVector4 cast(const GSVector4i& v);
|
||||
|
||||
GSVector4 abs() const
|
||||
{
|
||||
return GSVector4(_mm_abs_ps(m));
|
||||
@@ -1874,6 +1944,11 @@ public:
|
||||
return GSVector4(m_ps0123);
|
||||
}
|
||||
|
||||
static GSVector4 ps4567()
|
||||
{
|
||||
return GSVector4(m_ps4567);
|
||||
}
|
||||
|
||||
static GSVector4 loadl(const void* p)
|
||||
{
|
||||
return GSVector4(_mm_castpd_ps(_mm_load_sd((double*)p)));
|
||||
|
||||
@@ -25,7 +25,7 @@ template <class Vertex> class GSVertexList
|
||||
{
|
||||
void* m_base;
|
||||
Vertex* m_v[3];
|
||||
int m_count;
|
||||
DWORD m_count;
|
||||
|
||||
public:
|
||||
GSVertexList()
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
v = *m_v[i];
|
||||
}
|
||||
|
||||
int GetCount()
|
||||
DWORD GetCount()
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
787
gsdx/GSdx.cpp
787
gsdx/GSdx.cpp
@@ -21,12 +21,8 @@
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "GSdx.h"
|
||||
#include "GSRendererHW9.h"
|
||||
#include "GSRendererHW10.h"
|
||||
#include "GSRendererSW.h"
|
||||
#include "GSRendererNull.h"
|
||||
#include "GSSettingsDlg.h"
|
||||
#include "svnrev.h"
|
||||
|
||||
#define PLUGIN_VERSION 10
|
||||
|
||||
//
|
||||
// Note!
|
||||
@@ -100,781 +96,4 @@ BOOL GSdxApp::InitInstance()
|
||||
m_pszProfileName = _tcsdup((LPCTSTR)path);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool CheckSSE()
|
||||
{
|
||||
__try
|
||||
{
|
||||
static __m128i m;
|
||||
|
||||
#if _M_SSE >= 0x402
|
||||
m.m128i_i32[0] = _mm_popcnt_u32(1234);
|
||||
#elif _M_SSE >= 0x401
|
||||
m = _mm_packus_epi32(m, m);
|
||||
#elif _M_SSE >= 0x301
|
||||
m = _mm_alignr_epi8(m, m, 1);
|
||||
#elif _M_SSE >= 0x200
|
||||
m = _mm_packs_epi32(m, m);
|
||||
#endif
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
#define PS2E_LT_GS 0x01
|
||||
#define PS2E_GS_VERSION 0x0006
|
||||
#define PS2E_X86 0x01 // 32 bit
|
||||
#define PS2E_X86_64 0x02 // 64 bit
|
||||
|
||||
EXPORT_C_(UINT32) PS2EgetLibType()
|
||||
{
|
||||
return PS2E_LT_GS;
|
||||
}
|
||||
|
||||
EXPORT_C_(char*) PS2EgetLibName()
|
||||
{
|
||||
CString str;
|
||||
|
||||
str.Format(_T("GSdx %d"), SVN_REV);
|
||||
|
||||
if(SVN_MODS) str += _T("m");
|
||||
|
||||
#if _M_AMD64
|
||||
str += _T(" 64-bit");
|
||||
#endif
|
||||
|
||||
CAtlList<CString> sl;
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
CString s;
|
||||
s.Format(_T("Intel C++ %d.%02d"), __INTEL_COMPILER/100, __INTEL_COMPILER%100);
|
||||
sl.AddTail(s);
|
||||
#elif _MSC_VER
|
||||
CString s;
|
||||
s.Format(_T("MSVC %d.%02d"), _MSC_VER/100, _MSC_VER%100);
|
||||
sl.AddTail(s);
|
||||
#endif
|
||||
|
||||
#if _M_SSE >= 0x402
|
||||
sl.AddTail(_T("SSE42"));
|
||||
#elif _M_SSE >= 0x401
|
||||
sl.AddTail(_T("SSE41"));
|
||||
#elif _M_SSE >= 0x301
|
||||
sl.AddTail(_T("SSSE3"));
|
||||
#elif _M_SSE >= 0x200
|
||||
sl.AddTail(_T("SSE2"));
|
||||
#elif _M_SSE >= 0x100
|
||||
sl.AddTail(_T("SSE"));
|
||||
#endif
|
||||
|
||||
POSITION pos = sl.GetHeadPosition();
|
||||
|
||||
while(pos)
|
||||
{
|
||||
if(pos == sl.GetHeadPosition()) str += _T(" (");
|
||||
str += sl.GetNext(pos);
|
||||
str += pos ? _T(", ") : _T(")");
|
||||
}
|
||||
|
||||
static char buff[256];
|
||||
strncpy(buff, CStringA(str), min(countof(buff)-1, str.GetLength()));
|
||||
return buff;
|
||||
}
|
||||
|
||||
EXPORT_C_(UINT32) PS2EgetLibVersion2(UINT32 type)
|
||||
{
|
||||
const UINT32 revision = 0;
|
||||
const UINT32 build = 1;
|
||||
const UINT32 minor = 10;
|
||||
|
||||
return (build << 0) | (revision << 8) | (PS2E_GS_VERSION << 16) | (minor << 24);
|
||||
}
|
||||
|
||||
EXPORT_C_(UINT32) PS2EgetCpuPlatform()
|
||||
{
|
||||
#if _M_AMD64
|
||||
return PS2E_X86_64;
|
||||
#else
|
||||
return PS2E_X86;
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////
|
||||
|
||||
static HRESULT s_hr = E_FAIL;
|
||||
static GSRendererBase* s_gs;
|
||||
static void (*s_irq)() = NULL;
|
||||
static BYTE* s_basemem = NULL;
|
||||
|
||||
EXPORT_C GSsetBaseMem(BYTE* mem)
|
||||
{
|
||||
s_basemem = mem - 0x12000000;
|
||||
}
|
||||
|
||||
EXPORT_C_(INT32) GSinit()
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C GSshutdown()
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
}
|
||||
|
||||
EXPORT_C GSclose()
|
||||
{
|
||||
delete s_gs;
|
||||
|
||||
s_gs = NULL;
|
||||
|
||||
if(SUCCEEDED(s_hr))
|
||||
{
|
||||
::CoUninitialize();
|
||||
|
||||
s_hr = E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 GSopen(void* dsp, char* title, int mt, int renderer)
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
//
|
||||
|
||||
CString str;
|
||||
|
||||
str.Format(_T("d3dx9_%d.dll"), D3DX_SDK_VERSION);
|
||||
|
||||
if(HINSTANCE hDll = LoadLibrary(str))
|
||||
{
|
||||
FreeLibrary(hDll);
|
||||
}
|
||||
else
|
||||
{
|
||||
int res = AfxMessageBox(_T("Please update DirectX!\n\nWould you like to open the download page in your browser?"), MB_YESNO);
|
||||
|
||||
if(res == IDYES)
|
||||
{
|
||||
ShellExecute(NULL, _T("open"), _T("http://www.microsoft.com/downloads/details.aspx?FamilyId=2DA43D38-DB71-4C1B-BC6A-9B6652CD92A3"), NULL, NULL, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if(!CheckSSE())
|
||||
{
|
||||
CString str;
|
||||
str.Format(_T("This CPU does not support SSE %d.%02d"), _M_SSE >> 8, _M_SSE & 0xff);
|
||||
AfxMessageBox(str, MB_OK);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
GSclose();
|
||||
|
||||
// TODO
|
||||
|
||||
int nloophack = AfxGetApp()->GetProfileInt(_T("Settings"), _T("nloophack"), 2);
|
||||
|
||||
GSRendererSettings rs;
|
||||
|
||||
rs.m_interlace = AfxGetApp()->GetProfileInt(_T("Settings"), _T("interlace"), 0);
|
||||
rs.m_aspectratio = AfxGetApp()->GetProfileInt(_T("Settings"), _T("aspectratio"), 1);
|
||||
rs.m_filter = AfxGetApp()->GetProfileInt(_T("Settings"), _T("filter"), 1);
|
||||
rs.m_vsync = !!AfxGetApp()->GetProfileInt(_T("Settings"), _T("vsync"), FALSE);
|
||||
rs.m_nativeres = !!AfxGetApp()->GetProfileInt(_T("Settings"), _T("nativeres"), FALSE);
|
||||
|
||||
switch(renderer)
|
||||
{
|
||||
default:
|
||||
case 0: s_gs = new GSRendererHW9(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
case 1: s_gs = new GSRendererSW<GSDevice9>(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
case 2: s_gs = new GSRendererNull<GSDevice9>(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
case 3: s_gs = new GSRendererHW10(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
case 4: s_gs = new GSRendererSW<GSDevice10>(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
case 5: s_gs = new GSRendererNull<GSDevice10>(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
case 6: s_gs = new GSRendererSW<GSDeviceNull>(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
case 7: s_gs = new GSRendererNull<GSDeviceNull>(s_basemem, !!mt, s_irq, nloophack, rs); break;
|
||||
}
|
||||
|
||||
s_hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
|
||||
if(!s_gs->Create(CString(title)))
|
||||
{
|
||||
GSclose();
|
||||
return -1;
|
||||
}
|
||||
|
||||
s_gs->m_wnd.Show();
|
||||
|
||||
*(HWND*)dsp = s_gs->m_wnd;
|
||||
|
||||
// if(mt) _mm_setcsr(MXCSR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C_(INT32) GSopen(void* dsp, char* title, int mt)
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
int renderer = AfxGetApp()->GetProfileInt(_T("Settings"), _T("renderer"), 0);
|
||||
|
||||
return GSopen(dsp, title, mt, renderer);
|
||||
}
|
||||
|
||||
EXPORT_C GSreset()
|
||||
{
|
||||
s_gs->Reset();
|
||||
}
|
||||
|
||||
EXPORT_C GSgifSoftReset(int mask)
|
||||
{
|
||||
s_gs->SoftReset((BYTE)mask);
|
||||
}
|
||||
|
||||
EXPORT_C GSwriteCSR(UINT32 csr)
|
||||
{
|
||||
s_gs->WriteCSR(csr);
|
||||
}
|
||||
|
||||
EXPORT_C GSreadFIFO(BYTE* mem)
|
||||
{
|
||||
s_gs->ReadFIFO(mem, 1);
|
||||
}
|
||||
|
||||
EXPORT_C GSreadFIFO2(BYTE* mem, UINT32 size)
|
||||
{
|
||||
s_gs->ReadFIFO(mem, size);
|
||||
}
|
||||
|
||||
EXPORT_C GSgifTransfer1(BYTE* mem, UINT32 addr)
|
||||
{
|
||||
s_gs->Transfer<0>(mem + addr, (0x4000 - addr) / 16);
|
||||
}
|
||||
|
||||
EXPORT_C GSgifTransfer2(BYTE* mem, UINT32 size)
|
||||
{
|
||||
s_gs->Transfer<1>(mem, size);
|
||||
}
|
||||
|
||||
EXPORT_C GSgifTransfer3(BYTE* mem, UINT32 size)
|
||||
{
|
||||
s_gs->Transfer<2>(mem, size);
|
||||
}
|
||||
|
||||
EXPORT_C GSvsync(int field)
|
||||
{
|
||||
s_gs->VSync(field);
|
||||
}
|
||||
|
||||
EXPORT_C_(UINT32) GSmakeSnapshot(char* path)
|
||||
{
|
||||
return s_gs->MakeSnapshot(CString(path) + _T("gsdx"));
|
||||
}
|
||||
|
||||
EXPORT_C GSkeyEvent(keyEvent* ev)
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT_C_(INT32) GSfreeze(int mode, freezeData* data)
|
||||
{
|
||||
if(mode == FREEZE_SAVE)
|
||||
{
|
||||
return s_gs->Freeze(data, false);
|
||||
}
|
||||
else if(mode == FREEZE_SIZE)
|
||||
{
|
||||
return s_gs->Freeze(data, true);
|
||||
}
|
||||
else if(mode == FREEZE_LOAD)
|
||||
{
|
||||
return s_gs->Defrost(data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_C GSconfigure()
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
GSSettingsDlg dlg;
|
||||
|
||||
if(IDOK == dlg.DoModal())
|
||||
{
|
||||
GSshutdown();
|
||||
GSinit();
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_C_(INT32) GStest()
|
||||
{
|
||||
return 0;
|
||||
|
||||
// TODO
|
||||
|
||||
/*
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
CComPtr<ID3D10Device> dev;
|
||||
|
||||
return SUCCEEDED(D3D10CreateDevice(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION, &dev)) ? 0 : -1;
|
||||
*/
|
||||
}
|
||||
|
||||
EXPORT_C GSabout()
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT_C GSirqCallback(void (*irq)())
|
||||
{
|
||||
s_irq = irq;
|
||||
}
|
||||
|
||||
EXPORT_C GSsetGameCRC(DWORD crc, int options)
|
||||
{
|
||||
s_gs->SetGameCRC(crc, options);
|
||||
}
|
||||
|
||||
EXPORT_C GSgetLastTag(UINT32* tag)
|
||||
{
|
||||
s_gs->GetLastTag(tag);
|
||||
}
|
||||
|
||||
EXPORT_C GSsetFrameSkip(int frameskip)
|
||||
{
|
||||
s_gs->SetFrameSkip(frameskip);
|
||||
}
|
||||
|
||||
EXPORT_C GSReplay(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
||||
{
|
||||
int renderer = -1;
|
||||
|
||||
{
|
||||
char* start = lpszCmdLine;
|
||||
char* end = NULL;
|
||||
long n = strtol(lpszCmdLine, &end, 10);
|
||||
if(end > start) {renderer = n; lpszCmdLine = end;}
|
||||
}
|
||||
|
||||
while(*lpszCmdLine == ' ') lpszCmdLine++;
|
||||
|
||||
::SetPriorityClass(::GetCurrentProcess(), HIGH_PRIORITY_CLASS);
|
||||
|
||||
CAtlArray<BYTE> buff;
|
||||
|
||||
if(FILE* fp = fopen(lpszCmdLine, "rb"))
|
||||
{
|
||||
GSinit();
|
||||
|
||||
BYTE regs[0x2000];
|
||||
GSsetBaseMem(regs);
|
||||
|
||||
HWND hWnd = NULL;
|
||||
GSopen(&hWnd, _T(""), true, renderer);
|
||||
|
||||
DWORD crc;
|
||||
fread(&crc, 4, 1, fp);
|
||||
GSsetGameCRC(crc, 0);
|
||||
|
||||
freezeData fd;
|
||||
fread(&fd.size, 4, 1, fp);
|
||||
fd.data = new BYTE[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);
|
||||
|
||||
unsigned int index, size, addr;
|
||||
|
||||
GSvsync(1);
|
||||
|
||||
while(1)
|
||||
{
|
||||
switch(fgetc(fp))
|
||||
{
|
||||
case EOF:
|
||||
fseek(fp, start, 0);
|
||||
if(!IsWindowVisible(hWnd)) return;
|
||||
break;
|
||||
case 0:
|
||||
index = fgetc(fp);
|
||||
fread(&size, 4, 1, fp);
|
||||
switch(index)
|
||||
{
|
||||
case 0:
|
||||
if(buff.GetCount() < 0x4000) buff.SetCount(0x4000);
|
||||
addr = 0x4000 - size;
|
||||
fread(buff.GetData() + addr, size, 1, fp);
|
||||
GSgifTransfer1(buff.GetData(), addr);
|
||||
break;
|
||||
case 1:
|
||||
if(buff.GetCount() < size) buff.SetCount(size);
|
||||
fread(buff.GetData(), size, 1, fp);
|
||||
GSgifTransfer2(buff.GetData(), size / 16);
|
||||
break;
|
||||
case 2:
|
||||
if(buff.GetCount() < size) buff.SetCount(size);
|
||||
fread(buff.GetData(), size, 1, fp);
|
||||
GSgifTransfer3(buff.GetData(), size / 16);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
GSvsync(fgetc(fp));
|
||||
if(!IsWindowVisible(hWnd)) return;
|
||||
break;
|
||||
case 2:
|
||||
fread(&size, 4, 1, fp);
|
||||
if(buff.GetCount() < size) buff.SetCount(size);
|
||||
GSreadFIFO2(buff.GetData(), size / 16);
|
||||
break;
|
||||
case 3:
|
||||
fread(regs, 0x2000, 1, fp);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GSclose();
|
||||
|
||||
GSshutdown();
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_C GSBenchmark(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
||||
{
|
||||
::SetPriorityClass(::GetCurrentProcess(), HIGH_PRIORITY_CLASS);
|
||||
|
||||
FILE* file = _tfopen(_T("c:\\log.txt"), _T("a"));
|
||||
|
||||
_ftprintf(file, _T("-------------------------\n\n"));
|
||||
|
||||
if(1)
|
||||
{
|
||||
GSLocalMemory mem;
|
||||
|
||||
static struct {int psm; LPCSTR name;} s_format[] =
|
||||
{
|
||||
{PSM_PSMCT32, "32"},
|
||||
{PSM_PSMCT24, "24"},
|
||||
{PSM_PSMCT16, "16"},
|
||||
{PSM_PSMCT16S, "16S"},
|
||||
{PSM_PSMT8, "8"},
|
||||
{PSM_PSMT4, "4"},
|
||||
{PSM_PSMT8H, "8H"},
|
||||
{PSM_PSMT4HL, "4HL"},
|
||||
{PSM_PSMT4HH, "4HH"},
|
||||
{PSM_PSMZ32, "32Z"},
|
||||
{PSM_PSMZ24, "24Z"},
|
||||
{PSM_PSMZ16, "16Z"},
|
||||
{PSM_PSMZ16S, "16ZS"},
|
||||
};
|
||||
|
||||
BYTE* ptr = (BYTE*)_aligned_malloc(1024 * 1024 * 4, 16);
|
||||
|
||||
for(int i = 0; i < 1024 * 1024 * 4; i++) ptr[i] = (BYTE)i;
|
||||
|
||||
//
|
||||
|
||||
for(int tbw = 5; tbw <= 10; tbw++)
|
||||
{
|
||||
int n = 256 << ((10 - tbw) * 2);
|
||||
|
||||
int w = 1 << tbw;
|
||||
int h = 1 << tbw;
|
||||
|
||||
_ftprintf(file, _T("%d x %d\n\n"), w, h);
|
||||
|
||||
for(int i = 0; i < countof(s_format); i++)
|
||||
{
|
||||
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[s_format[i].psm];
|
||||
|
||||
GSLocalMemory::writeImage wi = psm.wi;
|
||||
GSLocalMemory::readImage ri = psm.ri;
|
||||
GSLocalMemory::readTexture rtx = psm.rtx;
|
||||
GSLocalMemory::readTexture rtxP = psm.rtxP;
|
||||
|
||||
GIFRegBITBLTBUF BITBLTBUF;
|
||||
|
||||
BITBLTBUF.SBP = 0;
|
||||
BITBLTBUF.SBW = w / 64;
|
||||
BITBLTBUF.SPSM = s_format[i].psm;
|
||||
BITBLTBUF.DBP = 0;
|
||||
BITBLTBUF.DBW = w / 64;
|
||||
BITBLTBUF.DPSM = s_format[i].psm;
|
||||
|
||||
GIFRegTRXPOS TRXPOS;
|
||||
|
||||
TRXPOS.SSAX = 0;
|
||||
TRXPOS.SSAY = 0;
|
||||
TRXPOS.DSAX = 0;
|
||||
TRXPOS.DSAY = 0;
|
||||
|
||||
GIFRegTRXREG TRXREG;
|
||||
|
||||
TRXREG.RRW = w;
|
||||
TRXREG.RRH = h;
|
||||
|
||||
CRect r(0, 0, w, h);
|
||||
|
||||
GIFRegTEX0 TEX0;
|
||||
|
||||
TEX0.TBP0 = 0;
|
||||
TEX0.TBW = w / 64;
|
||||
|
||||
GIFRegTEXA TEXA;
|
||||
|
||||
TEXA.TA0 = 0;
|
||||
TEXA.TA1 = 0x80;
|
||||
TEXA.AEM = 0;
|
||||
|
||||
int trlen = w * h * psm.trbpp / 8;
|
||||
int len = w * h * psm.bpp / 8;
|
||||
|
||||
clock_t start, end;
|
||||
|
||||
_ftprintf(file, _T("[%4s] "), s_format[i].name);
|
||||
|
||||
start = clock();
|
||||
|
||||
for(int j = 0; j < n; j++)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
(mem.*wi)(x, y, ptr, trlen, BITBLTBUF, TRXPOS, TRXREG);
|
||||
}
|
||||
|
||||
end = clock();
|
||||
|
||||
_ftprintf(file, _T("%6d %6d | "), (int)((float)trlen * n / (end - start) / 1000), (int)((float)(w * h) * n / (end - start) / 1000));
|
||||
|
||||
start = clock();
|
||||
|
||||
for(int j = 0; j < n; j++)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
(mem.*ri)(x, y, ptr, trlen, BITBLTBUF, TRXPOS, TRXREG);
|
||||
}
|
||||
|
||||
end = clock();
|
||||
|
||||
_ftprintf(file, _T("%6d %6d | "), (int)((float)trlen * n / (end - start) / 1000), (int)((float)(w * h) * n / (end - start) / 1000));
|
||||
|
||||
start = clock();
|
||||
|
||||
for(int j = 0; j < n; j++)
|
||||
{
|
||||
(mem.*rtx)(r, ptr, w * 4, TEX0, TEXA);
|
||||
}
|
||||
|
||||
end = clock();
|
||||
|
||||
_ftprintf(file, _T("%6d %6d "), (int)((float)len * n / (end - start) / 1000), (int)((float)(w * h) * n / (end - start) / 1000));
|
||||
|
||||
if(psm.pal > 0)
|
||||
{
|
||||
start = clock();
|
||||
|
||||
for(int j = 0; j < n; j++)
|
||||
{
|
||||
(mem.*rtxP)(r, ptr, w, TEX0, TEXA);
|
||||
}
|
||||
|
||||
end = clock();
|
||||
|
||||
_ftprintf(file, _T("| %6d %6d "), (int)((float)len * n / (end - start) / 1000), (int)((float)(w * h) * n / (end - start) / 1000));
|
||||
}
|
||||
|
||||
_ftprintf(file, _T("\n"));
|
||||
|
||||
fflush(file);
|
||||
}
|
||||
|
||||
_ftprintf(file, _T("\n"));
|
||||
}
|
||||
|
||||
_aligned_free(ptr);
|
||||
}
|
||||
|
||||
if(0)
|
||||
{
|
||||
BYTE regs[0x2000];
|
||||
GSsetBaseMem(regs);
|
||||
|
||||
HWND hWnd = NULL;
|
||||
GSopen(&hWnd, _T(""), true, 6);
|
||||
|
||||
s_gs->m_env.COLCLAMP.CLAMP = 1;
|
||||
s_gs->m_env.PRIM.ABE = 0;
|
||||
s_gs->m_env.PRIM.FST = 1;
|
||||
s_gs->m_env.PRIM.TME = 1;
|
||||
s_gs->m_env.PRIM.IIP = 0;
|
||||
s_gs->m_env.TEXA.TA0 = 0;
|
||||
s_gs->m_env.TEXA.TA1 = 0x80;
|
||||
s_gs->m_env.TEXA.AEM = 0;
|
||||
s_gs->m_context->ALPHA.A = 0;
|
||||
s_gs->m_context->ALPHA.B = 1;
|
||||
s_gs->m_context->ALPHA.C = 0;
|
||||
s_gs->m_context->ALPHA.D = 1;
|
||||
s_gs->m_context->CLAMP.WMS = 1;
|
||||
s_gs->m_context->CLAMP.WMT = 1;
|
||||
s_gs->m_context->CLAMP.MINU = 0;
|
||||
s_gs->m_context->CLAMP.MINV = 0;
|
||||
s_gs->m_context->CLAMP.MAXU = 511;
|
||||
s_gs->m_context->CLAMP.MAXV = 511;
|
||||
s_gs->m_context->FRAME.FBP = 0 >> 5;
|
||||
s_gs->m_context->FRAME.FBW = 8;
|
||||
s_gs->m_context->FRAME.PSM = PSM_PSMCT16S;
|
||||
s_gs->m_context->SCISSOR.SCAX0 = 0;
|
||||
s_gs->m_context->SCISSOR.SCAY0 = 0;
|
||||
s_gs->m_context->SCISSOR.SCAX1 = 511;
|
||||
s_gs->m_context->SCISSOR.SCAY1 = 511;
|
||||
s_gs->m_context->TEST.ZTE = 0;
|
||||
s_gs->m_context->TEST.ZTST = 2;
|
||||
s_gs->m_context->TEX0.TBP0 = 0x2000;
|
||||
s_gs->m_context->TEX0.TBW = 8;
|
||||
s_gs->m_context->TEX0.PSM = PSM_PSMCT32;
|
||||
s_gs->m_context->TEX0.TFX = 1;
|
||||
s_gs->m_context->TEX0.TCC = 0;
|
||||
s_gs->m_context->TEX0.TW = 9;
|
||||
s_gs->m_context->TEX0.TH = 9;
|
||||
s_gs->m_context->TEX1.MMAG = 0;
|
||||
s_gs->m_context->TEX1.MMIN = 0;
|
||||
s_gs->m_context->ZBUF.ZBP = 0x1000 >> 5;
|
||||
s_gs->m_context->ZBUF.PSM = PSM_PSMZ24;
|
||||
|
||||
GSRasterizer* ras = ((GSRendererSW<GSDeviceNull>*)s_gs)->GetRasterizer();
|
||||
|
||||
int count = 512 * 512;
|
||||
|
||||
GSVertexSW* vertices = (GSVertexSW*)_aligned_malloc(count * sizeof(GSVertexSW), 16);
|
||||
/*
|
||||
// point
|
||||
|
||||
for(int j = 0; j < 512; j++)
|
||||
{
|
||||
for(int i = 0; i < 512; i++)
|
||||
{
|
||||
GSVertexSW& v = vertices[(j << 7) + i];
|
||||
|
||||
v.p = GSVector4(i, j, 0, 0);
|
||||
v.t = GSVector4((float)i + 0.5, (float)j + 0.5, 1.0f, 0.0f);
|
||||
v.c = GSVector4(128.0f);
|
||||
}
|
||||
}
|
||||
|
||||
s_gs->PRIM->PRIM = GS_POINTLIST;
|
||||
|
||||
ras->Draw(vertices, count);
|
||||
|
||||
vertices[0].p = GSVector4(0, 0, 0, 0);
|
||||
vertices[0].t = GSVector4(0.5, 0.5, 1.0f, 0.0f);
|
||||
vertices[0].c = GSVector4(128.0f);
|
||||
vertices[1].p = GSVector4(512, 512, 0, 0);
|
||||
vertices[1].t = GSVector4(512.5f, 512.5f, 1.0f, 0.0f);
|
||||
vertices[1].c = GSVector4(128.0f);
|
||||
|
||||
for(int i = 2; i < 512 * 512; i += 2)
|
||||
{
|
||||
memcpy(&vertices[i], &vertices[0], sizeof(vertices[0]) * 2);
|
||||
}
|
||||
|
||||
// sprite
|
||||
|
||||
s_gs->PRIM->PRIM = GS_SPRITE;
|
||||
|
||||
ras->Draw(vertices, count);
|
||||
|
||||
// triangle
|
||||
|
||||
vertices[0].p = GSVector4(0, 0, 0, 0);
|
||||
vertices[0].t = GSVector4(0.5, 0.5, 1.0f, 0.0f);
|
||||
vertices[0].c = GSVector4(128.0f);
|
||||
vertices[1].p = GSVector4(512, 0, 0, 0);
|
||||
vertices[1].t = GSVector4(512.5f, 0.5f, 1.0f, 0.0f);
|
||||
vertices[1].c = GSVector4(128.0f);
|
||||
vertices[2].p = GSVector4(512, 512, 0, 0);
|
||||
vertices[2].t = GSVector4(512.5f, 512.5f, 1.0f, 0.0f);
|
||||
vertices[2].c = GSVector4(128.0f);
|
||||
|
||||
for(int i = 3; i < 512 * 512 - 2; i += 3)
|
||||
{
|
||||
memcpy(&vertices[i], &vertices[0], sizeof(vertices[0]) * 3);
|
||||
}
|
||||
|
||||
s_gs->PRIM->PRIM = GS_TRIANGLELIST;
|
||||
|
||||
ras->Draw(vertices, 999);
|
||||
*/
|
||||
//
|
||||
|
||||
_aligned_free(vertices);
|
||||
|
||||
GSclose();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if(0)
|
||||
{
|
||||
GSLocalMemory mem;
|
||||
|
||||
BYTE* ptr = (BYTE*)_aligned_malloc(1024 * 1024 * 4, 16);
|
||||
|
||||
for(int i = 0; i < 1024 * 1024 * 4; i++) ptr[i] = (BYTE)i;
|
||||
|
||||
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[PSM_PSMCT32];
|
||||
|
||||
GSLocalMemory::writeImage wi = psm.wi;
|
||||
|
||||
GIFRegBITBLTBUF BITBLTBUF;
|
||||
|
||||
BITBLTBUF.DBP = 0;
|
||||
BITBLTBUF.DBW = 32;
|
||||
BITBLTBUF.DPSM = PSM_PSMCT32;
|
||||
|
||||
GIFRegTRXPOS TRXPOS;
|
||||
|
||||
TRXPOS.DSAX = 0;
|
||||
TRXPOS.DSAY = 1;
|
||||
|
||||
GIFRegTRXREG TRXREG;
|
||||
|
||||
TRXREG.RRW = 256;
|
||||
TRXREG.RRH = 256;
|
||||
|
||||
int trlen = 256 * 256 * psm.trbpp / 8;
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
(mem.*wi)(x, y, ptr, trlen, BITBLTBUF, TRXPOS, TRXREG);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
@@ -33,4 +33,31 @@ EXPORTS
|
||||
GSsetFrameSkip
|
||||
GSgetLastTag
|
||||
GSReplay
|
||||
GSBenchmark
|
||||
GSBenchmark
|
||||
PSEgetLibType
|
||||
PSEgetLibName
|
||||
PSEgetLibVersion
|
||||
GPUinit
|
||||
GPUshutdown
|
||||
GPUopen
|
||||
GPUclose
|
||||
GPUconfigure
|
||||
GPUabout
|
||||
GPUtest
|
||||
GPUwriteData
|
||||
GPUwriteStatus
|
||||
GPUreadData
|
||||
GPUreadStatus
|
||||
GPUdmaChain
|
||||
GPUgetMode
|
||||
GPUsetMode
|
||||
GPUupdateLace
|
||||
GPUmakeSnapshot
|
||||
GPUwriteDataMem
|
||||
GPUreadDataMem
|
||||
GPUdisplayText
|
||||
GPUdisplayFlags
|
||||
GPUfreeze
|
||||
GPUshowScreenPic
|
||||
GPUgetScreenPic
|
||||
GPUcursor
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1051,6 +1051,54 @@
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\GPU.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GPULocalMemory.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release SSE4|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AssemblerOutput="4"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GPURasterizer.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release SSE4|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AssemblerOutput="4"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GPURenderer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GPURendererSW.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GPUState.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GPUTextureCacheSW.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GS.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GSAlignedClass.cpp"
|
||||
>
|
||||
@@ -1597,6 +1645,46 @@
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\GPU.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GPUDrawingEnvironment.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GPULocalMemory.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GPURasterizer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GPURenderer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GPURendererSW.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GPUState.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GPUTextureCacheSW.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GPUVertex.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GPUVertexSW.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GS.h"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user