7.3. "The New Video System" and where it lead us. Configuring MAME's current video options.
At this point, we'd recommend you to take a break and read these two articles from Aaron Giles' blog: Monkey, and very specially, The New Video Landscape. The later article was written for the new video system presentation with the release of MAME version 0.107, and has been shipped with any MAME official build since then, in the form of the newvideo.txt file.
Aaron Giles divides MAME potential users in three categories depending on their video setup. We're interested in category 3:
"Category 3: Anal video mode types. These are the guys who have generally built their own cabinets and set them up with a CRT display where they have several dozen carefully hand-tweaked video modes that approximate the original video modes the games ran at. They want MAME to pick that hand-tweaked mode and use it, drawing one pixel on the screen for each pixel in the original game. They don't give a whit about artwork or anything other than the raw pixels going to the right place. Fortunately, you can still configure MAME for this case as well."
As you may have guessed, those guys are us: all what's demanded by the above mentioned users sounds wise and reasonable to us. It's a relief the MAME team considered to continue supporting this mode, seriously.
So what's new about the new video system? First off, it is mainly focused on the Direct3D API, contrary to the old DirectDraw based video system we've been discussing. You may be wondering why Direct3D should be necessary at all, as it's well known that even 3-D hardware is emulated by software in MAME -so, at the end of the day, it's all about displaying 2-D graphics-. Of course, there was a good reason for this. Modern video cards are way faster at dealing with 2-D graphics when taking advantage of 3-D acceleration. This includes frame compositing: the use to 3-D hardware for high performance frame stretching and scaling while adding artwork overlays at the best possible resolution. Again, implementing Direct3D was quite a natural move. Microsoft had been struggling to deprecate DirectDraw for years, recommending programmers to use Direct3D instead. However, Direct3D has nothing that remotely resembles a simple frame buffer. Basically, the game's frame is going to be represented by a texture quad floating in a three-dimensional scene. There's something intrinsically bizarre in this construct that makes the 2-D programmer uneasy, although things are perfectly normal from the user's point of view.
But, is this new video system any better for us, anal video mode types? The answer is: not much, although it's not necessarily worse. Most of its new features and improvements -the bells and whistles- are for the enjoyment of Category 1: people who will stretch games over LCD screens without switching resolutions or really caring about refresh rates. That's the target user of MAME since version 0.107. This is perfectly reasonable, but it's important to remark it, as it will help us understand some of the issues that, unfortunately, came later.
As stated, the new video system still supports the old way of doing things. And, as a matter of fact, DirectDraw is still implemented and works as good as it did before. Indeed, according to the newvideo.txt document, DirectDraw is the suggested setup for Category 3 users. Even though, Direct3D can also be configured to get the exact same results that DirectDraw achieves, with just two limitations we'll discuss in a minute. We specify the video mode we want much the same as before, though now, resolution and refresh are both entered in a more convenient way:
Here is a sample of a proper configuration for MAME 0.107-0.113, both, DirectDraw and Direct3D video setups:
mame rtype -video ddraw
mame rtype -video d3d
As we said, the DirectDraw system works much the same as before. We're interested, however, in the new Direct3D system. We notice the new option -nofilter. This one is necessary as, otherwise -if -filter is enabled- the game's frame will go through bilinear filtering, producing a blurry picture, so we just disable it. Another interesting bit is that the -nohwstretch option is no longer used. With DirectDraw, we used to disable -hwstretch to prevent MAME from stretching the game's frame to the screen resolution, so to avoid the resulting artifacts. However, -hwstretch is a DirectDraw-only option. There's no equivalent for Direct3D, because this system is set to stretch the game's frame by design!
Actually, the only workaround to avoid stretching with Direct3D is to use the exact same resolution that the game frame has, and disable the -filter option. By doing this, the results are identical to DirectDraw. Even though, this has a serious drawback in practical situations: creating a separate video mode for each unique resolution required by MAME results in just too many of them, much more than what the driver supports. This is not such a big problem with DirectDraw, where we can actually reuse a container resolution for many different lower resolutions. This trick works especially well for the vertical resolution, as DirectDraw will just add black borders if necessary without affecting geometry. So for instance, take these three native video modes:
- 320 x 224 @ 60
- 320 x 232 @ 60
- 320 x 240 @ 60
Here, we'd just need to create the last one: 320 x 240, as it already contains the other two. In fact, by creating the lower ones we'd be wasting valuable space in the driver's custom mode list, because from the user's point of view they will look exactly the same!: it's a matter of the video card generating padding black lines by means of hardware blanking or MAME adding them by software into the frame. So, by using DirectDraw, a game with a native resolution of 320 x 224, will display on a 320 x 240 resolution with no visible artifacts. On the other hand, Direct3D will stretch the game vertically by a factor of 240 / 224, completely ruining the visual quality. This is the reason why the DirectDraw setting is mandatory when using the Arcade-VGA card, as this card supports a set of 240-line resolutions but no 224-line one is provided. If we still wanted to use Direct3D without any stretching, an explicit 320 x 224 resolution should be created.
There's still another limitation to Direct3D, a nearly undocumented one. Direct3D will refuse to switch to a display mode which is supposedly not supported by our monitor. DirectDraw will too, but in this case we can override this behaviour by disabling the Hide modes this monitor can't display check box in the advanced Display Properties dialog. Direct3D won't change its mind whatever we do. You may be wondering why we would want to damage our monitor by using an unsupported video mode. Well, sometimes we have created a video mode that we're positive our monitor supports, but Windows just decides to hide this mode from us. This may happen when using monitors with a valid EDID, as a regular PC monitor, so it's not a problem for arcade monitors or TV sets. Windows uses the information retrieved from the monitor's EDID to filter the list of video modes reported by the driver, resulting in some of these video modes being black-listed. Usually, a group or video modes with vertical resolutions like 256 or 512 lines will be marked as unsupported, apparently without any logical reason. As we said, the only workaround in these situations is to force Windows not to hide those modes and use DirectDraw instead of Direct3D.
An additional feature that was introduced with the new video system is a preliminary support for multithreaded execution -actually, it wasn't really available until version 0.108, but was developed during the intermediate updates from version 0.106 to 0.107-. The purpose of the multithreading approach in MAME is to improve overall performance by taking advantage of multi-core systems, moving the window and video processing to a second thread of execution. Unfortunately, the implementation of multithreaded video processing was not seen as an opportunity for adding a truly asynchronous triple buffering support.
However, due to the encapsulated design of MAME's core, there's a serious drawback to this multithreaded implementation: the emulator's core becomes unaware of what's going on in the video side, and this includes vertical retrace. Strictly speaking, the emulator's core is always blind to the vertical retrace state as this is checked in the OSD layer, but when running in a single thread, the emulator core needs to wait for the video routines to finish screen updating in order to resume execution, so both layers are forced to run synchronized. On the other hand, when multithreading is enabled, the emulator's core will be free to go on with execution without waiting for the video routines to finish, making our video synchronization options useless. That's why, starting from version 0.108, we'll make sure to add the -nomultithreading option to our MAME setup -it's the default value anyway-.
At this point, we must take a minute to mention AdvanceMAME. This was the name of a mythical derivative build of MAME, maintained by Andrea Mazzoleni, which shared the world with the official MAME build during several years. In fact, this was the preferred alternative for the exigent CRT user. AdvanceMAME kept releasing DOS and Linux builds well after the official project had moved to Windows. Thanks to this, AdvanceMAME had retained the capability to access the video hardware directly, without the interference of the operating system, thus allowing on-the-fly generation of any desired custom video mode. Although Windows builds were available too, the functionality under this operating system was way more limited and rather experimental. The last version of AdvanceMAME ever released was version 0.106. Sadly, Mazzoleni gave up updating AdvanceMAME as a consequence of the new video system being introduced. According to his words, it would have required a massive rewrite of AdvanceMAME's code. With the AdvanceMAME project halted, users who wanted to do a proper use of their CRT monitors and still keep updated with main line MAME, necessarily had to choose the Windows route combined with a 15 kHz output solution like the Arcade-VGA card or any of the incipient software methods. Apart from that, things weren't that bad in the early days of the new video system. The fundamental stuff still worked as usual.
But, unfortunately, something truly catastrophic happened in version 0.114 release. An apparently innocuous change in the source code, affecting the throttling mechanism, made the -syncrefresh option useless. By useless we mean that it doesn't block CPU throttling anymore, so MAME will still try to force the game to run at its theoretical speed, ruining video emulation smoothness, for the reasons explained above. So the situation is this:
THE SYNCREFRESH OPTION IS SERIOUSLY BROKEN SINCE MAME v0.114.
This particular issue has caused tons of pain to MAME users during these years, as can be proved by searching through the different specialized internet forums. MAME devs must be aware of this as there's a specific issue open since 2008 on the MAME Testers board. It seems to be a real flaw that becomes obvious when analyzing the source code, rather than some functionality that was dropped consciously. And in fact, there's a nice and straightforward source code fix which restores the -syncrefresh functionality without any side-effect, as we'll explain in the last chapter, but obviously it involves MAME compiling. Fortunately, MAME is so good that it's still possible to reproduce the -syncrefresh functionality in versions post-0.114, through a specific combination of options, without messing with compilation at all. The workaround consists in disabling the -throttle function manually, and then enabling some sort of vertical retrace synchronization. Now, be aware that when using the DirectDraw setting, both -syncrefresh and -waitvsync options are ignored if the -throttle option is disabled, so in this case the only option we can use for the synchronization purpose is -triplebuffer. On the other hand, if Direct3D is used, any of the three synchronization options will work fine even with throttle disabled, and they are interchangeable in practice.
For clarity and simplicity, in the previous chapter we stated that the throttling mechanism always needs to be disabled in order to achieve fluent video animation, either by enabling the good old -syncrefresh option -when functional- or just by disabling -throttle manually for newer MAME versions as explained above. However, this is only partially true. Actually, the throttling mechanism only gets in the middle if the video card's refresh is higher than the game's native refresh. There's an explanation for this paradoxical fact. Assuming we're running MAME with video synchronization enabled, there are two possible situations:
- If the video card's refresh is lower than the native refresh, MAME will notice the game is running slower than required, so the throttle routine will exit automatically, resulting in the game running smooth at the video card's refresh rate.
- If the video card's refresh is higher than the native refresh, MAME will realize the game is running too fast, and will try to compensate for this by adding some extra delay. This is the exact cause of scroll stuttering when enabling video synchronization.
So one tenth of Hz above or below the required refresh will produce completely different results in terms of smoothness, which appears as random behaviour to the user. This inconsistency has traditionally resulted in a common perception of video synchronization and MAME as something esoteric, always shrouded in uncertainty.
A possible approach is to calculate modelines so that their refresh is always a bit lower than the required one, slowing MAME down just enough to force the throttle delay to get bypassed. However, this is not a very good idea for practical situations, because the resulting refresh could turn out to be higher than calculated due to pixel clock granularity issues. In our experience, it's better to just go for the best approximation, whether it's above or below of the desired refresh, and always turn throttling off as a rule.
Putting everything together, these are the right settings for versions post-0.114 -up until this day-:
mame rtype -video ddraw
mame rtype -video d3d
-syncrefresh | -waitvsync
By using these options, you should obtain consistent results and silky smooth scrolling for any game. If you apply these settings and still experience scroll hiccups with any game, then chances are that your CPU is not powerful enough to run that specific game with video synchronization enabled. Actually, video synchronization should only be applied when a game can be fluently emulated at a rock solid 100% speed percentage with just throttling enabled. If doing this results in erratic speed, it's probably due to some of the frames taking too long to be computed, longer than it took in the original hardware. As vertical synchronization involves updating the screen at a constant pace, and we're setting our video card so that the time per frame matches the one in the emulated hardware, the time spent computing these slower frames won't fit between two vertical retraces, causing one retrace to get missed. This will force MAME to wait for nearly twice as long as it should for that frame, causing a noticeable drop in speed, often as dramatic as 50%. Therefore, in order to run MAME fluently with video synchronization enabled, our computer needs more CPU power than what's strictly needed to consider the game playable.
However, we end up feeling that we didn't achieve a fully satisfactory solution here. On the one hand, if we decide to use the DirectDraw interface, as a way to ensure proper integer scaling, we have to assume an input lag penalty, due to the compulsory use of the -triplebuffer/-nothrottle combination. But on the other hand, if we choose Direct3D to benefit from the less laggy -syncrefresh/-nothrottle combination, then we have to deal with the problem of MAME's hard coded fractional scaling, unless we have a perfect match for the game's resolution already available in the system.
Finally, let us comment on this statement from "The New Video Landscape" article:
"To avoid tearing artifacts, I recommend using the -triplebuffer option as well. Just make sure your monitor's refresh rate is higher than the game you are running."
As we've been discussing here, running MAME with -triplebuffer enabled at a refresh rate that's higher than the native one, always produces scroll hiccups. But as this is the officially recommended setting, we must conclude that scroll stuttering is assumed as normal by MAME devs, unfortunately. The above statement implies that MAME has silently renounced to smooth animation. This explains why there's no single mention to the -syncrefresh option in that article, although it's still documented by MAME as functional. And also why the -syncrefresh option stopped working short after that, and a bastard option named -refreshspeed was created instead. MAME is designed for flat panels these days and all that seems to matter is that the game's refresh is below the one of the panel.