Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Midtown Madness 3 - Artifacts when using screen scaling #1771

Open
kPYKx7Ddw4n1aIKZ opened this issue Sep 4, 2024 · 2 comments
Open

Midtown Madness 3 - Artifacts when using screen scaling #1771

kPYKx7Ddw4n1aIKZ opened this issue Sep 4, 2024 · 2 comments
Labels
bug Something isn't working

Comments

@kPYKx7Ddw4n1aIKZ
Copy link

kPYKx7Ddw4n1aIKZ commented Sep 4, 2024

Title

https://xemu.app/titles/4d53002a/#Midtown-Madness-3

Bug Description

I really enjoyed the first parts of Midtown Madness, so it’s disappointing that they only released Midtown Madness 3 for Xbox. The work you've done on the Xbox emulator is outstanding.

However, while using the scaling feature in Midtown Madness 3, I noticed some weird artifacts and couldn’t help but look into it further.

Have a look at this picture (screen scale x2):
xemu-2024-09-04-07-13-38

Original resolution (640x480):
xemu-2024-09-04-07-12-56

I looked around a bit with RenderDoc (great tool btw) and found a texture causing this issue which is used in some postprocessing step (I think it darkens the sky).
The following texture is used in the original screen resolution (640x480), but this texture has the resolution (1280x480) and the format GL_R16.
depth_stencil

It looks kinda weird and at first I was surprised, that it doesnt cause any artifacts in original and wondered what this texture was.
After some investigation, I found out that this is orginally the depth stencil buffer, which is downloaded from the GPU in the pgraph_download_surface_data_to_buffer() method in the pgraph.c file with the original format GL_DEPTH24_STENCIL8 and the original resolution (640x480). Even when scaling the screen, it gets scaled down to this size and is saved somewhere (ram?).

Then this memory block is interpreted again as the previously found GL_R16 texture (with the only call to generate_texture in pgraph.c).

Now follows a trick that probably the original game developers did.

Since the screen resolution has only half the width of this texture and the texture gets mapped to the screen in the postprocessing step, only every second texel column gets read resulting in this depth like texture (this is the weird, distorted looking texture, just with every second texel column):

depth_extracted

As clever as it was for the original developers, it now becomes a problem when scaling.

The texture that is downloaded from GPU and reuploaded, remains at the original resolution (1280x480) with the screen size being (1280x960) and this trick doesnt work anymore and every second row is also read causing the artifacts.

I can also confirm this, by using this hackish code around the generate_texture method call in pgraph.c:

            uint8_t * tex_theft_buf = texture_data;

            if(width == 1280 && height == 480 && color_format == NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_Y16) {
                size_t size = height*width*f.bytes_per_pixel;

                tex_theft_buf = malloc(size);
                memcpy(tex_theft_buf, texture_data, size);
                for(size_t idx = 0; idx < size; idx+=4) {
                    tex_theft_buf[idx] = tex_theft_buf[idx+2];
                    tex_theft_buf[idx+1] = tex_theft_buf[idx+3];
                }
            }

            key_out->binding = generate_texture(state, tex_theft_buf, palette_data);
            key_out->binding->data_hash = tex_data_hash;
            key_out->binding->scale = 1;

            if(width == 1280 && height == 480 && color_format == NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_Y16) {
                free(tex_theft_buf);
            }

About what this does:
It simulates exactly this behaviour of only reading every second texel column, by replacing the first texel by the content of the second one (be careful, we are talking about 16 bit texels here).
I was lucky here, that there is only one texture with the size and the NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_Y16 format so this hack-code actually worked and did no damage elsewhere.

And it worked (2x display resolution scale):
xemu-2024-09-04-07-19-15

Of course, this code isnt suitable for the emulator (or you would have to rename it MM3-emu 😊).

I basically see two possible resolutions:

  • Simulating this behaviour generic in the pixel shader when scaling and accessing such textures (like tex_coord.x = (floor(tex_coord.x/2.0)*2.0)+1.0)
  • Saving the depth stencil texture in the ram (I have no idea where the up/downloaded texture data from/to GPU is saved)

I don't know that much about the xemu emulator or the xbox in general, so i think its up to you, which one is the preferred option (or maybe another one).
In the meantime, I'll play this gem in 2x resolution 😊.

Expected Behavior

No artifacts (look at the bug description).

xemu Version

Version: 0.7.132
Branch: master
Commit: 8707d2a

System Information

OS: Windows 11 (also tested on Debian)
CPU: Intel(R) Core(TM) i5-14600
GPU: NVIDIA GeForce RTX 4060

Additional Context

No response

@kPYKx7Ddw4n1aIKZ kPYKx7Ddw4n1aIKZ added the bug Something isn't working label Sep 4, 2024
@hogfilho
Copy link

hogfilho commented Oct 2, 2024

Hello everyone,

I am sending my contribution of a patch for the Vulkan branch (feat/vulkan) based on the suggestion provided by kPYKx7Ddw4n1aIKZ. With this patch, I am now able to comfortably experience the game at 5x resolution with approximately 30 FPS.

For those interested in testing it, I have attached the patch for application to the feat/vulkan branch.

Additionally, if you wish for the hotfix to function with the OpenGL backend as well, please ensure that you apply the fix suggested by kPYKx7Ddw4n1aIKZ.

Thank you!

mm3_5x

mm3_dirtyfix_vulkan.patch.txt

@JimBebop
Copy link

Hola a todos,

Estoy enviando mi contribución de un parche para la rama Vulkan (feat/vulkan) basado en la sugerencia proporcionada por kPYKx7Ddw4n1aIKZ. Con este parche, ahora puedo experimentar cómodamente el juego con una resolución de 5x con aproximadamente 30 FPS.

Para aquellos interesados ​​en probarlo, he adjuntado el parche para su aplicación a la rama feat/vulkan.

Además, si desea que la revisión también funcione con el backend OpenGL, asegúrese de aplicar la corrección sugerida por kPYKx7Ddw4n1aIKZ.

¡Gracias!

mm3_5x

mm3_dirtyfix_vulkan.parche.txt

How can I apply the patch for Vulkan version?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants