summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/VertexLoaderManager.cpp
diff options
context:
space:
mode:
authorMarkus Wick <markus+github@selfnet.de>2015-05-31 23:26:55 +0200
committerMarkus Wick <markus+github@selfnet.de>2015-05-31 23:26:55 +0200
commitaa2576a2c7ebc589a594780726a884df1ad95d89 (patch)
tree97a97507b306cd838efa76f68fa0ee690899adea /Source/Core/VideoCommon/VertexLoaderManager.cpp
parentac1f3ef09957bc863737541b23ada77195bf41aa (diff)
parent7df69829732745d98b843d37d68a65920d1d883b (diff)
Merge pull request #2480 from phire/GamesDoWeirdShit
Fix invalid pointer errors in Burnout 2.
Diffstat (limited to 'Source/Core/VideoCommon/VertexLoaderManager.cpp')
-rw-r--r--Source/Core/VideoCommon/VertexLoaderManager.cpp42
1 files changed, 31 insertions, 11 deletions
diff --git a/Source/Core/VideoCommon/VertexLoaderManager.cpp b/Source/Core/VideoCommon/VertexLoaderManager.cpp
index 4168f7c777..dbb421991c 100644
--- a/Source/Core/VideoCommon/VertexLoaderManager.cpp
+++ b/Source/Core/VideoCommon/VertexLoaderManager.cpp
@@ -35,6 +35,8 @@ static std::mutex s_vertex_loader_map_lock;
static VertexLoaderMap s_vertex_loader_map;
// TODO - change into array of pointers. Keep a map of all seen so far.
+u8 *cached_arraybases[12];
+
void Init()
{
MarkAllDirty();
@@ -42,7 +44,6 @@ void Init()
map_entry = nullptr;
for (auto& map_entry : g_preprocess_cp_state.vertex_loaders)
map_entry = nullptr;
- RecomputeCachedArraybases();
SETSTAT(stats.numVertexLoaders, 0);
}
@@ -53,6 +54,27 @@ void Shutdown()
s_native_vertex_map.clear();
}
+void UpdateVertexArrayPointers()
+{
+ // Anything to update?
+ if (!g_main_cp_state.bases_dirty)
+ return;
+
+ // Some games such as Burnout 2 can put invalid addresses into
+ // the array base registers. (see issue 8591)
+ // But the vertex arrays with invalid addresses aren't actually enabled.
+ // Note: Only array bases 0 through 11 are used by the Vertex loaders.
+ // 12 through 15 are used for loading data into xfmem.
+ for (int i = 0; i < 12; i++)
+ {
+ // Only update the array base if the vertex description states we are going to use it.
+ if (g_main_cp_state.vtx_desc.GetVertexArrayStatus(i) >= 0x2)
+ cached_arraybases[i] = Memory::GetPointer(g_main_cp_state.array_bases[i]);
+ }
+
+ g_main_cp_state.bases_dirty = false;
+}
+
namespace
{
struct entry
@@ -136,6 +158,11 @@ static VertexLoaderBase* RefreshLoader(int vtx_attr_group, bool preprocess = fal
} else {
loader = state->vertex_loaders[vtx_attr_group];
}
+
+ // Lookup pointers for any vertex arrays.
+ if (!preprocess)
+ UpdateVertexArrayPointers();
+
return loader;
}
@@ -203,12 +230,14 @@ void LoadCPReg(u32 sub_cmd, u32 value, bool is_preprocess)
state->vtx_desc.Hex &= ~0x1FFFF; // keep the Upper bits
state->vtx_desc.Hex |= value;
state->attr_dirty = BitSet32::AllTrue(8);
+ state->bases_dirty = true;
break;
case 0x60:
state->vtx_desc.Hex &= 0x1FFFF; // keep the lower 17Bits
state->vtx_desc.Hex |= (u64)value << 17;
state->attr_dirty = BitSet32::AllTrue(8);
+ state->bases_dirty = true;
break;
case 0x70:
@@ -232,8 +261,7 @@ void LoadCPReg(u32 sub_cmd, u32 value, bool is_preprocess)
// Pointers to vertex arrays in GC RAM
case 0xA0:
state->array_bases[sub_cmd & 0xF] = value;
- if (update_global_state)
- cached_arraybases[sub_cmd & 0xF] = Memory::GetPointer(value);
+ state->bases_dirty = true;
break;
case 0xB0:
@@ -262,11 +290,3 @@ void FillCPMemoryArray(u32 *memory)
memory[0xB0 + i] = g_main_cp_state.array_strides[i];
}
}
-
-void RecomputeCachedArraybases()
-{
- for (int i = 0; i < 16; i++)
- {
- cached_arraybases[i] = Memory::GetPointer(g_main_cp_state.array_bases[i]);
- }
-}