Please do not post a support request without first reading and following the advice in https://retropie.org.uk/forum/topic/3/read-this-first

Correcting scaling artifacts in lr-mame2003



  • @AndrewH I was wondering if you could take a look at this and verify if it's correct.

    # Auto-generated crt-pi.glslp .cfg
    # Game : joust , Width : 320, Height : 240, Aspect : 4:3, Widen : false, Accurate : false
    # Screen Width : 1920, Screen Height : 1080
    # Place in /opt/retropie/configs/all/retroarch/config/MAME 2003/
    video_shader_enable = "true"
    video_shader = "/opt/retropie/configs/all/retroarch/shaders/crt-pi.glslp"
    # To avoid horizontal rainbow artefacts, use integer scaling for the height
    aspect_ratio_index = "22"
    custom_viewport_width = "1440"
    custom_viewport_height = "960"
    custom_viewport_x = "240"
    custom_viewport_y = "60"
    

    Shouldn't the screen be filled vertically or is the 120 pixels in the subjective range caver was mentioning. Both regular and wide produce the same results (because it's a widescreen game?)

     else:
                        if accurate == "true":
                            viewportWidth = gameWidth * intScaleFactor
                        else:
                            viewportWidth = int(gameWidth * scaleFactor)
                            if screenWidth - viewportWidth < 10:
                                viewportWidth = screenWidth
                        
                        viewportHeight = gameHeight * intScaleFactor
    

    If accurate = false should both the y and x axis be multiplied by the intScaleFactor?

    @dankcushions Well shoot I am surprised again. I did think you would give your blessing to Andrew to use your script and give it a go on Github. I also thought I was part of the conversation. I was even included with @ in your initial post of the thread. I've defended the script when that chap said it doesn't work when he was running an old version of Python. My comments have always been taken at face value. That is until I shared a different opinion. You shared an opinion and I shared one. It was just what I thought he should do and nothing more.

    If Andrew chose to develop his own script ok or if to develop on yours that's ok too. Another community member pulled the "database" info from MAME. The folks at mamedev.org freely share all source code, drivers, everything for all to use even after putting thousands of man hours into it. Forking is a choice regardless of reasons that's why it's an option. Even if you feel it's best to focus resources in a different direction. To me nuclear would be taking 50,000 lines of code and rewriting 10,000 lines of it. Not a few dozen out of 200 making corrections.

    I always thought of public forums as public conversations for anyone to participate. I don't know how else to treat them. I guess if you would have said "no one else give your opinion or reply to this post except Andrew" that would work.

    Or if I would have said "Andrew, you should build on Dank's script and stop your development." I don't think you would have closed the thread or told me you "don't appreciate me injecting into your conversation."

    It seems I have to walk on eggshells if I can't share what I truly think. It's like asking someone to not be themselves. I'm not trolling nor being derogatory but if someone is being a contrarian or doesn't share your viewpoint you can't make it into "prohibited viewpoint discrimination" and shut them down simply because you don't like it. Let it just be that...an opinion...that you read.

    I would venture you're working up a resume for banishment simply because we have differing opinions/personalities. If you're looking for a reason expecting to find it you surly will, eventually, if you take on every differing opinion.

    I did spend a few hours last week trying to figure out this before posting a response.

    aspectRatios.reverse()
    scaleX = 98-aspectRatios.index(min(aspectRatios, key=lambda x:abs(x-aspectRatio)))
    

    I'm thinking just because you have some "wrong" calculations doesn't make it bad code but you're aware of that. I honestly find your coding very compact and well written. In fact so well written with all these functions on one line I actually had to take a piece of paper and pencil (i.e. - Notepad) and starting running numbers through it but I can't figure out what you're doing here. Nor can I figure out the tolerance parameter.

    I did make it a forgone conclusion that you would not explain exactly how your script works and it seemed you showed interest in Andrew's cold after he corrected it. You said you need a single PR for each change to understand it. That makes sense.

    I need not make assumptions about your reply but ask. If you could explain these lines with actual data so I can see it working it would help. This seems to be the "engine"? Also the tolerance and what the thought is behind it. I would try and see if I could help figure out the calculations or corrections but as it stands I don't know.

    I guess that's why I figure Andrew's code is good. As he more than explains himself with examples and his code is straight forward in understanding for me. He said he would like to make a contribution to this aspect. He pinpointed the exact games with errors and threw in a few features to boot with corrections.

    I do respect your opinion even when I don't agree and I am not trying to rub your wrong but I guess some folks just don't see eye-to-eye. In the future I will take a wide berth on any posts around you.

    I do ask myself why I react certain ways to others. Like ol' Han Solo says "I must have hit pretty close to the mark to get her riled up like that, huh, kid?" ;) I always ask myself that question when something gets me "riled" up. In the end it's more about me and how I am reacting than you and I learn something about myself.


  • Global Moderator

    @riverstorm @AndrewH is already making PRs to my repository - we are collaborating and that's awesome!

    i don't really want to add anything else. i think you should wait until we're at a stable state with the code and then retest. i will announce it in the other thread when we're ready.



  • @Riverstorm :

    Shouldn't the screen be filled vertically or is the 120 pixels in the subjective range caver was mentioning. Both regular and wide produce the same results (because it's a widescreen game?)

    For a horizontal game, with horizontal scanlines, setting the vertical scaling to an integer value should result in the 'clearest' representation. Non-integer values won't give the same problems as seen on the vertical games, but it's still less than ideal.

    If you're up for some testing, you can try manually editing the file for one game to see whether the difference is acceptable to you. One great thing about the emulationstation - retroarch setup is that you only need to exit the game and restart it for any changes to take effect i.e. there's no need to restart emulationstation, so it's really quick.
    Personally, I don't particularly notice the narrow black bars at this point.

    If accurate = false should both the y and x axis be multiplied by the intScaleFactor?

    So, the way this is intended to work is as follows;

    • The scaling factor is seldom an integer - it's likely to be 3.4 or 4.5 or whatever.
    • For horizontal games we want to constrain the vertical scaling factor to the next lower integer value, but we're not so concerned about the horizontal scaling - we can allow the original scaling factor to be used. This will result in a display that's got a wider aspect ratio than the original game (to better fill the screen), but it shouldn't be by much.
    • For vertical games, we want to constrain the horizontal scaling factor to an integer value, but we don't worry so much about vertical scaling, and again the aspect ratio may end up a bit different from the original.
    • The 'accurate' flag is intended to be used if you want to more strictly preserve the aspect ratio, and can tolerate more of a black border around the viewport.

    Using the game in your example above (Joust), the scaling factor is going to be 4.5 (1080/240 = 4.5)
    We scale the viewport height by the integer value (4) to give 240 * 4 = 960
    We only ever scale it vertically by an integer value for the reasons above.
    For the viewport width, there are now the following options;

    accurate = false
    Scale by the actual scaling factor of 4.5 --> 320 * 4.5 = 1440
    The aspect ratio will now be 4.5:3, rather than the original 4:3

    accurate=true
    Scale by the integer scaling factor of 4 --> 320 * 4 = 1280
    This preserves the original aspect ratio, but the black bars on either side will now be 320 pixels wide, rather than 240.

    As for the rest, I'm honestly not too interested in getting embroiled in any controversy. I found a problem, and I set out to troubleshoot and understand it in order to provide the (hopefully) best quality of information to get it resolved. In the process, I learned a bit, and it was great to have others take interest. I don't consider my contributions significant enough to merit a lot of ego on my part, and I want to be respectful of the work that @dankcushions has already done.

    While I have a small amount of prior 'programming' experience, it's taken a while to get to grips with Python, and then with Git, but as @dankcushions says, we're collaborating now and two things I worked on have already been incorporated into the original code (adding the helpful headers to the .cfg files, and making the display while the script runs a little nicer).

    We'll see where we go with any further contributions. I have one or two more aspects of my 'test' script that I might contribute, but would need a bit more discussion about replacing the part that's doing the calculations.


  • Global Moderator

    @andrewh said in Correcting scaling artifacts in lr-mame2003:
    accurate=true

    Scale by the integer scaling factor of 4 --> 320 * 4 = 1280
    This preserves the original aspect ratio, but the black bars on either side will now be 320 pixels wide, rather than 240.

    in this case, you don't really need the script at all - just use integer scaling. i guess the script would give you the correct vertical/horizontal variant of the shader, but it could skip all the calculation parts to and just turn on integer_scale.

    We'll see where we go with any further contributions. I have one or two more aspects of my 'test' script that I might contribute, but would need a bit more discussion about replacing the part that's doing the calculations.

    i think in the context of a PR i'd be able to understand what you're doing differently more easily and be able to accept it. seeing the diff helps a lot for me!

    the way i currently do it is really daft - looping through 99 possible scaling options every time rather than just calculating it up front. i was only interested in the cfgs so threw whatever "worked" at it ;)



  • @dankcushions said in Correcting scaling artifacts in lr-mame2003:

    but it could skip all the calculation parts to and just turn on integer_scale.

    I thought about that and wondering if it had any value. To actually have the integer scaled numbers in a config file or just remove that piece and use the built-in Retroarch integer scaling. I am not sure if you know that's an option already built-in Andrew?

    I've been doing a hybrid where I use the script configs except where @UDb23 has created an overlay then I delete that config file and add shader support to the overlay config. I also tone down the brightness/opacity on each one so the game stands out a bit brighter then the overlay.

    looping through 99 possible scaling options every time rather than just calculating it up front

    I wondered about that and if it could be a smaller loop. I thought if you're integer scale value is 99 you have a very large display and I am coming over to your place to game! Ah well...99 bottles of beer on the wall, take one down... :)

    We were up in the twin cities (Minneapolis/St. Paul) and they had a jumbo sized 8' x 6' Pac-Man & Galaga. It's was a nice bright LED screen. Very fun and impressive.

    making the display while the script runs a little nicer).

    I noticed that and I do like the dots vs. the scrolling ROM names.

    Using the game in your example above (Joust), the scaling factor is going to be 4.5 (1080/240 = 4.5)
    We scale the viewport height by the integer value (4) to give 240 * 4 = 960
    We only ever scale it vertically by an integer value for the reasons above.
    For the viewport width, there are now the following options;

    If you're up for some testing, you can try manually editing the file for one game to see whether the difference is acceptable to you.

    I might be missing it here but those are the same numbers I came up with and it all worked out correctly but I thought the goal of the script was to fill the screen vertically (Y = 0) as in how Dank is calculating which would be what you're suggesting? Still using joust as the example.

    Andrew calculations - Ratio .67
    aspect_ratio_index = "22"
    custom_viewport_width = "1440"
    custom_viewport_height = "960"
    custom_viewport_x = "240"
    custom_viewport_y = "60"

    Dank's calculations - Ratio .74
    aspect_ratio_index = "22"
    custom_viewport_width = "1460"
    custom_viewport_height = "1080"
    custom_viewport_x = "230"
    custom_viewport_y = "0"

    For a horizontal game, with horizontal scanlines,

    That's a good point. Is there horizontal games with vertical scan lines (monitor rotated) and vice versa vertical games with horizontal scanlines (monitor rotated)?

    I might be missing the whole goal here but I thought it was to fill the screen vertically and scaling the other axis? If you using int() for scaling then that's an option already built-into Retroarch.


  • Global Moderator

    @riverstorm said in Correcting scaling artifacts in lr-mame2003:

    That's a good point. Is there horizontal games with vertical scan lines (monitor rotated) and vice versa vertical games with horizontal scanlines (monitor rotated)?

    no, because by definition, if the game is vertical then the monitor is rotated :) at least, by mame's definitions.

    I might be missing the whole goal here but I thought it was to fill the screen vertically and scaling the other axis? If you using int() for scaling then that's an option already built-into Retroarch.

    i can't speak for Andrew's calculations, but for mine it (should) be always fill the screen along the Y axis...

    UNLESS they have aspect ratio larger than your screen (eg, a widescreen game on a 4:3 display), then they fill the screen along the X axis, and integer scale the Y.

    i think the latter calcs don't work properly after my last tweaks but i will review them at some point.



  • @dankcushions said in Correcting scaling artifacts in lr-mame2003:

    no, because by definition, if the game is vertical then the monitor is rotated :) at least, by mame's definitions.

    Whew, that would just require more data and calculations. I was thinking like cocktail cabinets that would have to rotate the screen (to the side). Unless they stuck with vertical games only and flipped vertically for 1 and 2 players on the ends would make sense.

    i will review them at some point.

    Alright I'll just wait and see if what you come up with. If you need any help or testing just let me know. I am setup and streamlined with Notepad++ (Unix) for making changes and running the script.


  • Global Moderator

    @riverstorm said in Correcting scaling artifacts in lr-mame2003:

    @dankcushions said in Correcting scaling artifacts in lr-mame2003:

    no, because by definition, if the game is vertical then the monitor is rotated :) at least, by mame's definitions.

    Whew, that would just require more data and calculations. I was thinking like cocktail cabinets that would have to rotate the screen (to the side). Unless they stuck with vertical games only and flipped vertically for 1 and 2 players on the ends would make sense.

    so in terms of real CRT cocktail cabinets, the games are either vertical so are displaying like so:
    alt text
    or are horizontal, like so:
    alt text

    MAME has various "cocktail mode" settings letting you run horizontal games on a traditional cocktail cab, but my understanding is that they just dupe the image like the top right image (if that even work in retropie):
    alt text

    the shader wouldn't work properly with that kind of setup anyway, so it's not something the script caters for.



  • @dankcushions said in Correcting scaling artifacts in lr-mame2003:

    the shader wouldn't work properly with that kind of setup anyway, so it's not something the script caters for.

    Ok, thanks Dank. I don't have a cocktail cabinet by no means but I was just running through different scenarios in my head. I think I prefer what your script is doing by filling the screen vertically with the AR within a tolerance. I tried integer scaling for a while but I didn't care for the black borders all the way around the game screen on some games.



  • @riverstorm said in Correcting scaling artifacts in lr-mame2003:

    I might be missing it here but those are the same numbers I came up with and it all worked out correctly but I thought the goal of the script was to fill the screen vertically (Y = 0) as in how Dank is calculating which would be what you're suggesting?

    So.. that hadn't been my goal from the outset.

    My assumption was that since we're striving for integer horizontal scaling for vertical games in order to make the scanline effect as clear as possible, it would make sense to also try to achieve the converse - namely integer vertical scaling for horizontal games.

    Maybe it doesn't make such a huge difference, though. For horizontal games, the scaling factor will be higher than for vertical games (i.e. each original game pixel is represented by a larger number of onscreen pixels), so there's more area for the shader to be applied to.

    Interestingly, though, if I remove the MAME 2003 directory entirely (i.e. remove all custom configs), and run the game as normal on my bartop (1280 x 1024 display), I get black bars at the top & bottom of horizontal format games. And that's with integer scaling turned off.

    Also interesting is that if I run Dank's current script for my setup (1280 x 1024), I do get bars at the top and bottom - here's bubble bobble's config file, for example;

    # Auto-generated crt-pi.glslp .cfg
    # Game Title : bublbobl , Width : 256, Height : 224, Aspect : 4:3
    # Screen Width : 1280, Screen Height : 1024
    # Place in /opt/retropie/configs/all/retroarch/config/MAME 2003/
    video_shader_enable = "true"
    video_shader = "/opt/retropie/configs/all/retroarch/shaders/crt-pi.glslp"
    # To avoid horizontal rainbow artefacts, use integer scaling for the height
    aspect_ratio_index = "22"
    custom_viewport_width = "1280"
    custom_viewport_height = "896"
    custom_viewport_x = "0"
    custom_viewport_y = "64"
    

    It's certainly food for further thought. One idea I'd had, but didn't get around to implementing, was to have the option to run the script only for vertical aspect ratio games, and leave the default scaling for the horizontal ones.

    In the meantime, I'm going to submit my .csv log file as a Pull Request shortly, since reviewing that is a whole lot easier than individual scrutiny of the .cfg files, even with the additional header data.



  • @andrewh said in Correcting scaling artifacts in lr-mame2003:

    was to have the option to run the script only for vertical aspect ratio games, and leave the default scaling for the horizontal ones.

    I thought of doing this like a really dirty hack of the script appending "v" to the rom name and then stripping it with a file renamer tool to get the vertical games. I suppose just processing "v" games would be more efficient and strip the "h" pieces.

    Interestingly, though, if I remove the MAME 2003 directory entirely (i.e. remove all custom configs), and run the game as normal on my bartop (1280 x 1024 display), I get black bars at the top & bottom of horizontal format games. And that's with integer scaling turned off.

    I guess a guy would need to dig into the MAME code to see how it determines scaling and if the resolution viewport numbers break down to roughly the same as Dank's formula. Hopefully this hasn't been for naught.

    That's almost confusing due to being run on a 5:4 monitor? I thought MAME would try and fill at least one axis (mainly vertical) since HD is 16:9 or 1.78:1 it fills vertically for 99% of games. When Udb creates overlays the games fit dead center while filling the screen vertically. I believe he develops them specifically for HD filling the negative space on either side perfectly.

    I have to admit I am kind of confused. The math looks good, the formulas, the screenshots show a clear difference. If it's to much to explain I'm ok with that too but I am missing the 10,000 foot overview.

    I think, maybe not, get Dank's idea. Fill the screen vertically then adjust the width resolution to target the correct AR, well as close as possible? Single axis scaling.

    But you're not doing that? You're only doing a partial on both axis. Taking Joust for example it neither starts on the x or y axis at 0 so what is the goal? If you want a perfect aspect ratio just use integer scaling that's built-in with one command and it's perfect on both axis. But it's like your trying to do a partial adjust on both axis?

    A perfect integer scale of 4x4 = 1280 x 960 but yours is 4.5 x 4 = 1440 x 960. What is corrected in those 160 extra pixels that looks better or is it just trying to use more screen to the tune of 160 pixels sacrificing the perfect AR? I am missing it I think. The key being you're not filling either axis. Which is integer scaling with partial numbers instead of whole.

    I am starting to question pixelsquareness. Does MAME already make adjustments? It seems almost every game would display incorrect on an HD monitor without factoring that in before buffering to the screen.

    Take AdvMAME for example (as an exception). I have one game that I need to use this command to get a proper display display_mode generate-double-y. I don't know if it's an extreme case game or an exception rather than rule but the game is very flat until I double the y axis.



  • @riverstorm I think Blasteroids is an example of a double-y game. If you display it in native resolution, scaled or not, it is only half as high as it should be. The game designers were expecting this to be stretched across the whole CRT.

    Since most arcade games were destined for cabinets with 4:3 or (3:4 when rotated vertical) CRTs, you can just set aside the idea of square pixels for most of them and consider that some stretching will be required in at least one dimension if you want games to look like they did in the arcades. Of course, today, we are almost always dealing with square pixels, not RGB triads on a CRT, so it becomes a struggle of how to accommodate the stretch for many games so that they display in a 4:3 AR versus how much distortion we are willing to live with to make our shaders look pretty.



  • @caver01 said in Correcting scaling artifacts in lr-mame2003:

    so it becomes a struggle of how to accommodate the stretch for many games so that they display in a 4:3 AR versus how much distortion we are willing to live with to make our shaders look pretty.

    That makes perfect sense ok maybe a 5,000 foot overview. I tweaked what I wrote above so it might help to reread it. I will throw it out there more rhetorical but if you understand that would be great.

    So what is Andrew doing with integer scaling on both axis and filling neither which is like partial integer scaling or something. Where as Dank fills one axis which makes sense to me. I am afraid it's getting more confusing for me. The Joust example is below. Neither axis starts at 0. So that being said why not just use integer scaling if you don't mind black borders or what is gained from the 160 pixels (4.5 scale on the x axis) vs. just doing a 4 x 4 integer scale. Either way you have black borders but wouldn't the perfect integer scale look more correct?

    aspect_ratio_index = "22"
    custom_viewport_width = "1440"
    custom_viewport_height = "960"
    custom_viewport_x = "240"
    custom_viewport_y = "60"
    


  • @caver01 said in Correcting scaling artifacts in lr-mame2003:

    you can just set aside the idea of square pixels for most of them and consider that some stretching will be required in at least one dimension if you want games to look like they did in the arcades

    That's my point if you displayed a game exactly with 224 x 320 pixels on a modern display I am guessing it would have improper proportions due to the pixel squareness of modern displays. Most MAME games seem to look fine hence the comment questioning is MAME accounting for and adjusting pixel squareness already and it doesn't need to be part of the calculation? A bit of rabbit hole...unless you're the guy programming it.



  • @riverstorm said in Correcting scaling artifacts in lr-mame2003:

    So what is Andrew doing with integer scaling on both axis and filling neither which is like partial integer scaling or something. Where as Dank fills one axis which makes sense to me. I am afraid it's getting more confusing for me. The Joust example is below. Neither axis starts at 0. So that being said why not just use integer scaling if you don't mind black borders or what is gained from the 160 pixels (4.5 scale on the x axis) vs. just doing a 4 x 4 integer scale. Either way you have black borders but wouldn't the perfect integer scale look more correct?

    I'm sorry if I haven't been clear enough with explanations up to this point... I'll try again;

    For the vertical games, the original goal (of Dank's script) was to have integer scaling 'across' the scanlines in order to make them look their best and avoid artefacts.

    In the work I'd done, my original idea was to extend this idea to the horizontal games - i.e. to have integer scaling 'across' the scanlines (in the vertical direction), but to leave the scaling as-was in the other direction. Following further testing, I now think that this is not necessary, and I'm hoping to shortly do a Pull Request on Dank's script to implement a new variant of the "math based scaling" in place of the existing approach of iterating through an array. At a high level, the following should give the best results (i.e. do the best job of filling the screen);

    • Calculate the squareness of the pixels in the original game to get a 'corrected' game size
    • Calculate horizontal and vertical scaling factors between the 'corrected' game and the target screen
    • Use whichever scaling factor is the lower of the two
    • For vertical games
      • Set the vertical scale to the calculated scaling factor - this will ensure the game fills the screen vertically
      • Set the horizontal scale to either the next lower or next higher integer value (using a "widen" option)
    • For horizontal games
      • Set vertical and horizontal scale to the same value - this will ensure the game fills the screen in at least one direction (depending on aspect ratio of the screen)
      • If there are narrow black bars in one direction (less than a specified tolerance value), then stretch the game to fill those.

    One thing that should be a big help in figuring all of this out is the last Pull Request I submitted, which creates a .csv log file and allows settings for all games to be reviewed in one place.


  • Global Moderator

    @riverstorm said in Correcting scaling artifacts in lr-mame2003:

    @caver01 said in Correcting scaling artifacts in lr-mame2003:

    you can just set aside the idea of square pixels for most of them and consider that some stretching will be required in at least one dimension if you want games to look like they did in the arcades

    That's my point if you displayed a game exactly with 224 x 320 pixels on a modern display I am guessing it would have improper proportions due to the pixel squareness of modern displays. Most MAME games seem to look fine hence the comment questioning is MAME accounting for and adjusting pixel squareness already and it doesn't need to be part of the calculation? A bit of rabbit hole...unless you're the guy programming it.

    yes, mame uses the exact aspect ratio every time, because it doesn't care about integer scaling. what mame does is say, "ok, this is a 4:3 game, so I will do a 4:3 image - i will simply stretch the tiny 320x240 (say) image to the biggest 4:3 image that fits on the screen"

    this is generally fine on an HD screen (it's high enough resolution for the scaling to look good, mostly)... until you come to use a scanline shader. this is the fundamental problem that i wanted to solve, and i describe it in the original post: https://retropie.org.uk/forum/topic/4046/crt-pi-shader-users-reduce-scaling-artifacts-with-these-configs-in-lr-mame2003-lr-fbalpha-lr-nestopia-and-more-to-come.


  • Global Moderator



Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.

Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.