Universal Deflicker/Blur Disable Code
Posted: Tue Aug 10, 2021 10:09 pm
tl;dr: The code is
It works for all games.
Most Dreamcast games ran with a deflicker filter to display a more stable image on an interlaced CRT. This works by slightly blurring the screen vertically. If you're trying to use an LCD display interlaced video, you don't really need the deflicker. This code will disable it on any game, and result in a sharper image.
It sounds like SF3 Third Strike might have had a secret option to disable it, but I'm not sure. Smash Bros Melee and Sonic Heroes had options to disable the GameCube's deflicker option.
When using VGA, most games automatically disable the deflicker, so this code won't have any effect. However, I know of three games that have deflicker on even with VGA output. Omikron, Wacky Racers, and Ready 2 Rumble (just the 1st one, not the sequel) all run with 2x horizontal supersampling, and all of these games have a vertical blur on VGA. I guess it's a mistake in the 3D driver? Using this code will remove the vertical blur while keeping 2x SSAA turned on. Fixing this was the real reason I made the code.
I actually had to disassemble Codebreaker to make this code.
The Dreamcast's 3D hardware is able to scale it's framebuffer vertically. When downscaling, there's a register that controls how to blend lines together. The deflicker works by downscaling by a single pixel (i.e. to 479), so that the filter is enabled, then having the 3D hardware vertically blur the screen when it renders. Each line is mixed with 50% of itself, 25% the line above it, and 25% the line below it. There is a hardware register that controls the percentages of the mixing.
The code sets the mixing for a line to be 99.6% itself (100% isn't possible without disabling scaling), and 0% the above and below lines. The scaling register has other functions, and changing it might have side effects on certain games. Changing the filter percentages is more likely to work with all games.
Most Codebreaker code types only allow you to modify main RAM, so it's not possible to get to the filter register. I disassembled the "in-game" part of Codebreaker to find a way to modify the register, and found two undocumented code types, not listed on the Codebreaker guide on GameFAQs. The two types of codes I found are the 03 and 08 types.
The 03 code allows writing multiple 32 bit values to anywhere, even outside of main RAM. The format looks like this:
The iiii part is how many 32-bit values to write. The aaaaaaaa line is the address of where to write the values to. The dddddddd lines are what gets written there. There should be as many lines as the value of iiii. So the deflicker disable code writes one 32-bit value (0x0000FF00) to the address 0xA05F8118
There is a similar code, type 04, but that's limited to main RAM, and preforms 8-bit writes. For the 3D hardware to work correctly, it's important that a single 32-bit write is used.
The 08 code type is used to write something indirectly using a pointer. It looks like this:
This code reads a value from the address specified by aaaaaa, adds the oooooooo value to it, then writes vvvvvvvv to the result. The bottom two bits of the aaaaaa address control the size of the value written. If it's 0, a 8-bits are written. If it's 1, 16-bits are written. And if it's 2, 32-bits are written. This code checks that the destination is in main RAM before writing to it. If it's not, it skips the code without doing anything. I guess it's an attempt to prevent crashes from writing to a bad pointer?
In C-ish code, it looks something like this (it won't compile, but should get the point across):
That's assuming I read the disassembly correctly. It should be something along those lines.
Codebreaker seems to have an inaccessible code type. All it seems to do is skip over a number of codes without processing them.
Try changing the last line of the code to 0000A080 for a trippy effect, or 00005555 for maximum blur. It won't work if the game isn't trying to use deflicker.
Code: Select all
03000001
A05F8118
0000FF00
Most Dreamcast games ran with a deflicker filter to display a more stable image on an interlaced CRT. This works by slightly blurring the screen vertically. If you're trying to use an LCD display interlaced video, you don't really need the deflicker. This code will disable it on any game, and result in a sharper image.
It sounds like SF3 Third Strike might have had a secret option to disable it, but I'm not sure. Smash Bros Melee and Sonic Heroes had options to disable the GameCube's deflicker option.
When using VGA, most games automatically disable the deflicker, so this code won't have any effect. However, I know of three games that have deflicker on even with VGA output. Omikron, Wacky Racers, and Ready 2 Rumble (just the 1st one, not the sequel) all run with 2x horizontal supersampling, and all of these games have a vertical blur on VGA. I guess it's a mistake in the 3D driver? Using this code will remove the vertical blur while keeping 2x SSAA turned on. Fixing this was the real reason I made the code.
I actually had to disassemble Codebreaker to make this code.
The Dreamcast's 3D hardware is able to scale it's framebuffer vertically. When downscaling, there's a register that controls how to blend lines together. The deflicker works by downscaling by a single pixel (i.e. to 479), so that the filter is enabled, then having the 3D hardware vertically blur the screen when it renders. Each line is mixed with 50% of itself, 25% the line above it, and 25% the line below it. There is a hardware register that controls the percentages of the mixing.
The code sets the mixing for a line to be 99.6% itself (100% isn't possible without disabling scaling), and 0% the above and below lines. The scaling register has other functions, and changing it might have side effects on certain games. Changing the filter percentages is more likely to work with all games.
Most Codebreaker code types only allow you to modify main RAM, so it's not possible to get to the filter register. I disassembled the "in-game" part of Codebreaker to find a way to modify the register, and found two undocumented code types, not listed on the Codebreaker guide on GameFAQs. The two types of codes I found are the 03 and 08 types.
The 03 code allows writing multiple 32 bit values to anywhere, even outside of main RAM. The format looks like this:
Code: Select all
0300iiii
aaaaaaaa
ddddddfd (possibly multiple lines)
There is a similar code, type 04, but that's limited to main RAM, and preforms 8-bit writes. For the 3D hardware to work correctly, it's important that a single 32-bit write is used.
The 08 code type is used to write something indirectly using a pointer. It looks like this:
Code: Select all
08aaaaaa
vvvvvvvv
oooooooo
In C-ish code, it looks something like this (it won't compile, but should get the point across):
Code: Select all
int type = aaaaaa & 0x3;
void * tmp = 0x8c000000 | (aaaaaa & 0xFFFFFC);
tmp = *(uintptr*)tmp;
tmp += oooooooo
int tmphigh = tmp >> 24;
if (tmphigh == 0x8c || tmphigh == 0xac || tmphigh == 0x0c) {
if (type == 0)
*(int8_t*)tmp = vvvvvvvv;
else if (type == 1)
*(int16_t*)tmp = vvvvvvvv;
else if (type == 2)
*(int32_t*)tmp = vvvvvvvv;
}
Codebreaker seems to have an inaccessible code type. All it seems to do is skip over a number of codes without processing them.
Try changing the last line of the code to 0000A080 for a trippy effect, or 00005555 for maximum blur. It won't work if the game isn't trying to use deflicker.