diff options
| author | Markus Wick <markus+github@selfnet.de> | 2015-05-31 23:26:55 +0200 |
|---|---|---|
| committer | Markus Wick <markus+github@selfnet.de> | 2015-05-31 23:26:55 +0200 |
| commit | aa2576a2c7ebc589a594780726a884df1ad95d89 (patch) | |
| tree | 97a97507b306cd838efa76f68fa0ee690899adea /Source/Core/VideoCommon/VertexLoaderManager.cpp | |
| parent | ac1f3ef09957bc863737541b23ada77195bf41aa (diff) | |
| parent | 7df69829732745d98b843d37d68a65920d1d883b (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.cpp | 42 |
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]); - } -} |
