GSdx: Memory Wrapping Windows port

Adds GS Memory Wrapping hack to Windows. Enabling the hack will fix cut-off cutscenes in Wallace & Gromit: The Curse of the Were-Rabbit and Thrillville.
This commit is contained in:
FlatOutPS2 2017-02-04 14:50:36 +01:00 committed by Gregory Hainaut
parent 41fb11d846
commit 2d591182c4
7 changed files with 76 additions and 11 deletions

View File

@ -84,7 +84,7 @@ GSLocalMemory::psm_t GSLocalMemory::m_psm[64];
GSLocalMemory::GSLocalMemory()
: m_clut(this)
{
if (theApp.GetConfigB("wrap_gs_mem"))
if (theApp.GetConfigB("UserHacks") && theApp.GetConfigB("wrap_gs_mem"))
m_vm8 = (uint8*)fifo_alloc(m_vmsize, 4);
else
m_vm8 = (uint8*)vmalloc(m_vmsize * 4, false);
@ -472,7 +472,7 @@ GSLocalMemory::GSLocalMemory()
GSLocalMemory::~GSLocalMemory()
{
if (theApp.GetConfigB("wrap_gs_mem"))
if (theApp.GetConfigB("UserHacks") && theApp.GetConfigB("wrap_gs_mem"))
fifo_free(m_vm8, m_vmsize, 4);
else
vmfree(m_vm8, m_vmsize * 4);

View File

@ -146,6 +146,9 @@ const char* dialog_message(int ID, bool* updateText) {
case IDC_UNSCALE_POINT_LINE:
return "Increases the width of lines at higher than native resolutions. This ensures that the lines will keep the correct proportions and prevents aliasing. "
"Avoids empty lines on the screen in games such as Ridge Racer V, and clears FMVs obscured by a grid in games like the Silent Hill series and Dirge of Cerberus.";
case IDC_MEMORY_WRAPPING:
return "Emulates GS memory wrapping accurately. This fixes issues where part of the image is cut-off by block shaped sections such as the FMVs in Wallace & Gromit: The Curse of the Were-Rabbit and Thrillville.\n"
"Note: This hack can have a small impact on performance.";
#ifdef _WIN32
// DX9 only
case IDC_FBA:

View File

@ -79,6 +79,7 @@ enum {
IDC_LINEAR_PRESENT,
IDC_AUTO_FLUSH,
IDC_UNSCALE_POINT_LINE,
IDC_MEMORY_WRAPPING,
IDC_OSD_LOG,
IDC_OSD_MONITOR,
IDC_OSD_MAX_LOG,

View File

@ -687,6 +687,7 @@ void GSHacksDlg::OnInit()
CheckDlgButton(m_hWnd, IDC_FAST_TC_INV, theApp.GetConfigB("UserHacks_DisablePartialInvalidation"));
CheckDlgButton(m_hWnd, IDC_AUTO_FLUSH, theApp.GetConfigB("UserHacks_AutoFlush"));
CheckDlgButton(m_hWnd, IDC_UNSCALE_POINT_LINE, theApp.GetConfigB("UserHacks_unscale_point_line"));
CheckDlgButton(m_hWnd, IDC_MEMORY_WRAPPING, theApp.GetConfigB("wrap_gs_mem"));
std::vector<GSSetting> hpo_combobox = theApp.m_gs_offset_hack;
if (!ogl)
{
@ -739,6 +740,7 @@ void GSHacksDlg::OnInit()
AddTooltip(IDC_FAST_TC_INV);
AddTooltip(IDC_AUTO_FLUSH);
AddTooltip(IDC_UNSCALE_POINT_LINE);
AddTooltip(IDC_MEMORY_WRAPPING);
}
void GSHacksDlg::UpdateControls()
@ -780,6 +782,7 @@ bool GSHacksDlg::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
theApp.SetConfig("UserHacks_DisablePartialInvalidation", (int)IsDlgButtonChecked(m_hWnd, IDC_FAST_TC_INV));
theApp.SetConfig("UserHacks_AutoFlush", (int)IsDlgButtonChecked(m_hWnd, IDC_AUTO_FLUSH));
theApp.SetConfig("UserHacks_unscale_point_line", (int)IsDlgButtonChecked(m_hWnd, IDC_UNSCALE_POINT_LINE));
theApp.SetConfig("wrap_gs_mem", (int)IsDlgButtonChecked(m_hWnd, IDC_MEMORY_WRAPPING));
unsigned int TCOFFSET = SendMessage(GetDlgItem(m_hWnd, IDC_TCOFFSETX), UDM_GETPOS, 0, 0) & 0xFFFF;
TCOFFSET |= (SendMessage(GetDlgItem(m_hWnd, IDC_TCOFFSETY), UDM_GETPOS, 0, 0) & 0xFFFF) << 16;

View File

@ -39,6 +39,7 @@ GSTextureCache::GSTextureCache(GSRenderer* r)
m_disable_partial_invalidation = theApp.GetConfigB("UserHacks_DisablePartialInvalidation");
m_can_convert_depth = !theApp.GetConfigB("UserHacks_DisableDepthSupport");
m_texture_inside_rt = theApp.GetConfigB("UserHacks_TextureInsideRt");
m_wrap_gs_mem = theApp.GetConfigB("wrap_gs_mem");
} else {
m_spritehack = 0;
UserHacks_HalfPixelOffset = false;
@ -46,10 +47,9 @@ GSTextureCache::GSTextureCache(GSRenderer* r)
m_disable_partial_invalidation = false;
m_can_convert_depth = true;
m_texture_inside_rt = false;
m_wrap_gs_mem = false;
}
m_wrap_gs_mem = theApp.GetConfigB("wrap_gs_mem");
m_paltex = theApp.GetConfigB("paltex");
m_can_convert_depth &= s_IS_OPENGL; // only supported by openGL so far
m_crc_hack_level = theApp.GetConfigT<CRCHackLevel>("crc_hack_level");

View File

@ -122,6 +122,7 @@
#define IDC_OSDBUTTON 2118
#define IDC_OSD_MAX_LOG 2119
#define IDC_OSD_MAX_LOG_EDIT 2120
#define IDC_MEMORY_WRAPPING 2121
#define IDR_CONVERT_FX 10000
#define IDR_TFX_FX 10001
#define IDR_MERGE_FX 10002
@ -141,7 +142,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 10013
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 2121
#define _APS_NEXT_CONTROL_VALUE 2122
#define _APS_NEXT_SYMED_VALUE 5000
#endif
#endif

View File

@ -72,16 +72,71 @@ void vmfree(void* ptr, size_t size)
VirtualFree(ptr, 0, MEM_RELEASE);
}
static HANDLE s_fh = NULL;
static uint8* s_Next[8];
void* fifo_alloc(size_t size, size_t repeat)
{
// FIXME check linux code
return vmalloc(size * repeat, false);
ASSERT(s_fh == NULL);
if (repeat >= countof(s_Next)) {
fprintf(stderr, "Memory mapping overflow (%zu >= %u)\n", repeat, countof(s_Next));
return vmalloc(size * repeat, false); // Fallback to default vmalloc
}
s_fh = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, size, nullptr);
DWORD errorID = ::GetLastError();
if (s_fh == NULL) {
fprintf(stderr, "Failed to reserve memory. WIN API ERROR:%u\n", errorID);
return vmalloc(size * repeat, false); // Fallback to default vmalloc
}
int mmap_segment_failed = 0;
void* fifo = MapViewOfFile(s_fh, FILE_MAP_ALL_ACCESS, 0, 0, size);
for (size_t i = 1; i < repeat; i++) {
void* base = (uint8*)fifo + size * i;
s_Next[i] = (uint8*)MapViewOfFileEx(s_fh, FILE_MAP_ALL_ACCESS, 0, 0, size, base);
errorID = ::GetLastError();
if (s_Next[i] != base) {
mmap_segment_failed++;
if (mmap_segment_failed > 4) {
fprintf(stderr, "Memory mapping failed after %d attempts, aborting. WIN API ERROR:%u\n", mmap_segment_failed, errorID);
fifo_free(fifo, size, repeat);
return vmalloc(size * repeat, false); // Fallback to default vmalloc
}
do {
UnmapViewOfFile(s_Next[i]);
s_Next[i] = 0;
} while (--i > 0);
fifo = MapViewOfFile(s_fh, FILE_MAP_ALL_ACCESS, 0, 0, size);
}
}
return fifo;
}
void fifo_free(void* ptr, size_t size, size_t repeat)
{
// FIXME check linux code
return vmfree(ptr, size * repeat);
ASSERT(s_fh != NULL);
if (s_fh == NULL) {
if (ptr != NULL)
vmfree(ptr, size);
return;
}
UnmapViewOfFile(ptr);
for (size_t i = 1; i < countof(s_Next); i++) {
if (s_Next[i] != 0) {
UnmapViewOfFile(s_Next[i]);
s_Next[i] = 0;
}
}
CloseHandle(s_fh);
s_fh = NULL;
}
#else
@ -125,10 +180,12 @@ void* fifo_alloc(size_t size, size_t repeat)
const char* file_name = "/GSDX.mem";
s_shm_fd = shm_open(file_name, O_RDWR | O_CREAT | O_EXCL, 0600);
if (s_shm_fd != -1)
if (s_shm_fd != -1) {
shm_unlink(file_name); // file is deleted but descriptor is still open
else
} else {
fprintf(stderr, "Failed to open %s due to %s\n", file_name, strerror(errno));
return nullptr;
}
if (ftruncate(s_shm_fd, repeat * size) < 0)
fprintf(stderr, "Failed to reserve memory due to %s\n", strerror(errno));