cannonball icon indicating copy to clipboard operation
cannonball copied to clipboard

Incorrect aspect ratio in widescreen mode

Open bbfe opened this issue 2 years ago • 0 comments

It looks like Cannonball hardcodes the widescreen width to 398, but that really isn't the preserving the game's original aspect ratio.

See how, at the same screen size, the aspect ratio is different than MAME's, which is calculating it correctly. https://cdn.discordapp.com/attachments/197420215363960832/997760492623892570/unknown.png

https://cdn.discordapp.com/attachments/197420215363960832/997760669220884520/unknown.png

I added the two functions below when setting config.s16_width, which gives you the correct 16:9 resolution (426x224). If you do this, "widescreen mode" could really just become a choice between "original aspect ratio" and "native aspect ratio," because this will also give you the right number if you have an ultrawide monitor. Although for that, I think that you will have to further adjust some of the internal storage size, because an ultrawide monitor (3840x1600) will give you a native resolution of 576x224, and since that's greater than 512, I'm assuming that's going to bump heads with some internal storage sizes. I do think this would be worth doing, though, because widescreen support shouldn't just be limited to a single aspect ratio.

const double GetClosestEvenResolution(const double fractionalResolution) { const double roundedResolutionDouble = std::round(fractionalResolution); const size_t roundedResolutionInteger = static_cast<size_t>(roundedResolutionDouble);

if (roundedResolutionInteger % 2)
{
    const size_t roundedUpResolution = roundedResolutionInteger + 1;
    const size_t roundedDownResolution = roundedResolutionInteger - 1;

    const double roundDownDifference = std::fabs(fractionalResolution - static_cast<double>(roundedDownResolution));
    const double roundUpDifference = std::fabs(fractionalResolution - static_cast<double>(roundedUpResolution));

    if (roundDownDifference > roundUpDifference)
    {
        return static_cast<double>(roundedUpResolution);
    }
    else
    {
        return static_cast<double>(roundedDownResolution);
    }
}

return static_cast<double>(roundedResolutionDouble);

}

constexpr uint16_t GetInternalGameResolution(const uint16_t resolutionX, const uint16_t resolutionY) { if (resolutionX == S16_WIDTH) { return resolutionX; } else { constexpr double ORIGINAL_GAME_PIXEL_ASPECT_RATIO = static_cast(S16_WIDTH) / static_cast(S16_HEIGHT); constexpr double ORIGINAL_MONITOR_ASPECT_RATIO = 4.0 / 3.0; constexpr double VERTICAL_RESOLUTION_CORRECTION = ORIGINAL_GAME_PIXEL_ASPECT_RATIO / ORIGINAL_MONITOR_ASPECT_RATIO; constexpr double HORIZONTAL_RESOLUTION_CORRECTION_MULTIPLIER = static_cast(S16_HEIGHT) * VERTICAL_RESOLUTION_CORRECTION;

    const double currentResolutionAspectRatio = static_cast<double>(resolutionX) / static_cast<double>(resolutionY);

    const double rawResolution = currentResolutionAspectRatio * HORIZONTAL_RESOLUTION_CORRECTION_MULTIPLIER;

    return GetClosestEvenResolution(rawResolution);
}

}

Doing this, you can get ultrawide Outrun, but of course there are glitches because things need further adjustment to be truly aspect ratio independent.

https://cdn.discordapp.com/attachments/197420215363960832/997779415524196372/unknown.png

bbfe avatar Jul 16 '22 09:07 bbfe