forked from Ports/perfect_dark
Introduce support for gcc
This commit is contained in:
1 parent
4b7e93de8a
commit
17583575e4
266 files changed
+2277
-1640
No files matched your search
@@ -6,9 +6,9 @@ Thanks to the decompilation project we can easily see all the differences betwee
|
||||
|
||||
## The Root Cause
|
||||
|
||||
The root cause is in a function that the decomp project has named bgInit which can be found in [src/game/bg.c](src/game/bg.c). This function is somewhat complex so we'll just cover the important parts here.
|
||||
The root cause is in a function that the decomp project has named bgReset which can be found in [src/game/bg.c](src/game/bg.c). This function is somewhat complex so we'll just cover the important parts here.
|
||||
|
||||
bgInit is called while the screen is black after accepting the challenge. It's responsible for loading the background (BG) file for a stage. BG files contain the stage polygon data, room information, a texture list and lighting information among other things. The exact format of the file is not important here, but you just need to know that it contains several sections and some of those sections are compressed, similar to a zip file.
|
||||
bgReset is called while the screen is black after accepting the challenge. It's responsible for loading the background (BG) file for a stage. BG files contain the stage polygon data, room information, a texture list and lighting information among other things. The exact format of the file is not important here, but you just need to know that it contains several sections and some of those sections are compressed, similar to a zip file.
|
||||
|
||||
The problem starts when loading the section 2 data, approximately half way into the function. Section 2 is a section of the BG file that is very simple; it's just a compressed list of texture IDs. Let's start by looking at the fix the developers made:
|
||||
|
||||
@@ -102,7 +102,7 @@ A better fix would be to change the allocation size so it's just the aligned inf
|
||||
|
||||
The one line tl;dr: When loading the background data for a stage, if the background file contained a specific section that decompressed to a smaller size than the compressed data itself, an overflow would occur due to a miscalculated buffer size. For the overflow to cause any problems the allocation had to be made from the first memory bank and be the exact same size as the remaining space in that bank. If this criteria was met, the overflow would overwrite a pointer in texture data which would cause a crash. The fix that was made increases the allocation to point where it can never be made out of the first bank, therefore avoiding the issue.
|
||||
|
||||
But what about the requirement of having 3 players? Why does it not happen with 4? Because each additional player causes an additional player structure to be allocated, and these are made prior to bgInit being called which means they affect the amount of free space in the first bank when bgInit is run. With 1 or 2 players there's going to be more memory available so the issue does not occur. And when playing with 4 players the expansion pak bank starts to be used sooner so the issue does not occur there either. Using 3 players on this particular stage made it total to the exact value that was needed for the onboard bank to be full at this point. In contrast, changing other settings like the number of bots or the weapon loadout would have no effect on this because those are allocated after bgInit is called.
|
||||
But what about the requirement of having 3 players? Why does it not happen with 4? Because each additional player causes an additional player structure to be allocated, and these are made prior to bgReset being called which means they affect the amount of free space in the first bank when bgReset is run. With 1 or 2 players there's going to be more memory available so the issue does not occur. And when playing with 4 players the expansion pak bank starts to be used sooner so the issue does not occur there either. Using 3 players on this particular stage made it total to the exact value that was needed for the onboard bank to be full at this point. In contrast, changing other settings like the number of bots or the weapon loadout would have no effect on this because those are allocated after bgReset is called.
|
||||
|
||||
Just to be clear, this situation was incredibly unlucky. Adding or deleting a couple of lines of code anywhere else in the game would have made this a non-issue because it would change the heap size (the heap is sized based on what's left over after code and data). And even if the memory system is in the danger territory, there's a 1 in 455 chance that any number of player structure allocations would line it up in a way that can trigger the bug (each player structure is 7280 bytes and there's a 16 byte window where the bug can occur).
|
||||
|
||||
|
||||
Reference in new issue
Block a user