Articles posted May 2006 Older >>

Help Shape MAME’s Future

This is an experiment. Below are a series of video-related questions that ask how you currently set up and use MAME. Please take the time to answer these by adding comments, even if you haven't really spent much time tweaking with all of MAME's options.

The information from this poll will help me decide which usage patterns to prioritize when optimizing the new rendering system, and will also help me figure out how to simplify the giant array of options that are currently being used.

Please adhere to the following guidelines when posting your answers:


  1. If you run MAME in multiple different settings (for example, if you run it both on your regular PC and in a cabinet), then please provide two sets of answers, one for each case.

  2. If you run MAME on a non-Windows platform, answer to the best of your ability.

  3. If you don't know the answer and just use whatever the defaults are, just say "defaults".


With those groundrules in place, here are the questions:

  1. Do you run MAME in full screen mode or in a window?

  2. Do you allow MAME to switch your screen to different resolutions or color depths?

  3. Do you use Direct3D or DirectDraw?

  4. Do you use scanlines or RGB effects? If so, which ones?

  5. Do you use artwork? If not, would you use it if it weren't so slow?

  6. Do you use tweaked video modes and try to get MAME to use those modes?

  7. Do you deliberately run games at anything other than their intended aspect ratio?

  8. Do you use the brightness or gamma parameters (either on the command line or in the INI file) to adjust the color output?

  9. Do you run games with filtering or without? Do you use the prescale option for Direct3D mode?

  10. What make/model of video card is in the computer you run MAME on?

  11. Do you ever use the debugger?


In your answers keep it simple, and just reply like this:

1. Window. 2. No. 3. DirectDraw. etc.

If you want to add comments, please do so at the end.

Multi-screen Fun

After pulling on a thread that ultimately led to me rewriting how the command line and INI files are parsed (don't worry, it should all work just like before once all the bugs are sorted), I managed to get the multi-targeting drawing code working with the new renderer. This first shot is of Cyberball running two windows. Right now, cyberbal is the only driver in MAME that properly exposes multiple screens. Each window shows the contents of a single screen on my dual-monitor system. If you flip into full screen mode you'll get one screen on each monitor:






Through the UI, or on the command line, you can specify a layout view for each screen independently. By default, the game comes up with screen 0 in the first window, and screen 1 in the second window.

This second shot is just for fun. It shows me running pacman with 4 windows. Each window can have a different view, selected from all the loaded layouts. Currently there are only three different views, so screens 0 and 3 are showing the same view. I don't know any practical use for this, but if you had 4 monitors and wanted to splatter Pac-Man over all 4, you could, I guess.






I've gotten little feedback on the new system so far, but then again, there are a couple of crashes plaguing the first version. I've fixed those, and should have a new update in the next day or two. The next release should have the new renderer enabled by default, some more options implemented, plus a bunch of fixes and improvements. I'm looking more for compatibility reports than performance reports at this point. I fully expect that things will be slower for a bit until things get sorted.

More Layouts and Rendering

Continuing on from yesterday's post, let's talk about elements. Elements are really used for artwork, and allow you to combine several primitives together to form a single element, which is then referenced by an item in a view. The reason why elements are defined separately from the items in a view is because the elements may be reused multiple times, either within a single view or across multiple views.

First, let's look at a couple of elements. The first one is taken from the built-in overlay for Solar Quest:

<element name="overlay">
    <rect>
        <bounds left="0" top="0.125" right="1" bottom="0.2" />
        <color red="1.0" green="0.125" blue="0.125" />
    </rect>
    <rect>
        <bounds left="0" top="0.2" right="1" bottom="0.875" />
        <color red="0.125" green="0.125" blue="1.0" />
    </rect>
    <disk>
        <bounds left="0.47" top="0.47" right="0.53" bottom="0.53" />
        <color red="1.0" green="1.0" blue="0.125" />
    </disk>
</element>

This element, which is given the name "overlay", has three pieces to it: a solid red rectangle across the top, a blue rectangle across the bottom, and a yellow circle in the middle. Because these pieces are drawn at runtime by the rendering engine, they are automatically rendered at the proper resolution for output. You'll notice that the coordinate system here is once again arbitrary. The combined bounding box of the entire thing is (0,0.125)-(1,0.875), which happens to be a 4:3 ratio in width/height. The rendering system will examine the bounding boxes of all the pieces within an element, and scale everything within it to fit the bounds of the view item that eventually references it. See below for a full example to understand this.

Here's a second example element, taken from my conversion of the invaders.art file:

<element name="bezel">
    <image file="invadbez.png" alphafile="invadmask.png" />
</element>

This is a nice, simple example that shows a third type of piece: the image piece. Rects, disks, and images are the three types of pieces that can currently be assembled to form an element. Here you'll notice that a filename is specified, which is a source PNG file to read the data from. The PNG file can be in any of a number of formats (including palettized, RGB, and RGB with alpha). As with the old artwork system, you can also specify a separate PNG file to contain the alpha mask, if you don't have a good editor that can output a single RGB+alpha PNG. The final thing to notice about this example is that it doesn't specify any bounds. By default, if you don't specify any bounds, the bounds are assumed to be (0,0)-(1,1). Since the image is meant to define the entire element, this is fine.

And here is a third example element, taken from my conversion of the turbo.art file:

<element name="digit" defstate="10">
    <image file="digit0.png" state="0" />
    <image file="digit1.png" state="1" />
    <image file="digit2.png" state="2" />
    <image file="digit3.png" state="3" />
    <image file="digit4.png" state="4" />
    <image file="digit5.png" state="5" />
    <image file="digit6.png" state="6" />
    <image file="digit7.png" state="7" />
    <image file="digit8.png" state="8" />
    <image file="digit9.png" state="9" />
    <image file="digitX.png" state="10" />
</element>

This is a particularly interesting element. Like the previous one, it is based on images. Unlike the previous element, it supports multiple states. By default, if you don't specify any particular state, an element piece is drawn regardless of the current state of the item that contains it. In this case, we are displaying an LED digit, which can be in any of 11 different states (0-9, plus all off). You'll note the defstate attribute in the element item itself; this specifies the default state of the element, provided the item doesn't specify any particular default state. In this case, we default to the "off" state. Inside the element are 11 bitmaps, each of which is only visible in one of the 11 different states. Thus, when the view item containing this element is set to state 7, for example, only the digit7.png image will be visible; everything else will be hidden.

Okay, so now that we've examined the types of pieces that make up an element, let's look at a real life example. In this example, we will convert the existing invaders.art file over to a layout, and show how the existing overlays, bezels, and backdrops are handled in the new world. Here is the existing .art file (stripped down to its bare elements):

backdrop:
    file = invaders.png
    layer = backdrop
    priority = -2
    visible = 1
    position = 0.0,-0.14,1.29,1.15

// we use an overlay here to change the bright white color used by
// the game down to a more pleasing blue-tinted light gray
// this has the side effect of making the game graphics appear a bit
// transluscent over the backdrop
overlay:
    file = tintover.png
    alphafile = tintmask.png
    layer = overlay
    priority = -1
    visible = 1
    position = 0.0,0.0,1.0,1.0

bezel:
    file = invadbez.png
    alphafile = invadmask.png
    layer = bezel
    priority = 0
    visible = 1
    position = -0.3333,-0.8206,1.7179,1.7851
    brightness = 1.0

So, we have three pieces of art: a backdrop piece, an overlay piece, and a bezel piece. We need to first define the necessary layout elements for these pieces, and then we need to assemble them into a view.

First let's consider the overlay element, because we're not going to translate that directly. What the old overlay element did was to apply a fake overlay over the screen that reduced the brightness of the screen so that when it was added to the backdrop graphics, it had a bit of a translucent effect. The reason we used to need this is because the old .art files didn't reference the screen directly, so there was no control over how the screen graphics were drawn. This is no longer the case. As mentioned in my last article, you can specify color and alpha values for screen items in the view directly, so we'll skip the overlay for now.

The backdrop piece is simply a single PNG image with no alpha layer, so we create a new element called "backdrop" with a single image component:

<element name="backdrop">
    <image file="invaders.png" />
</element>

The bezel piece is similar, but also has an alpha layer mask specified in a separate PNG file. We'll create a second element called "bezel" with an image component that specifies both files. This is exactly the 2nd example I showed above:

<element name="bezel">
    <image file="invadbez.png" alphafile="invadmask.png" />
</element>

Now, to construct the view. This is where things get a little tricky. In the old system, the screen was hard-coded to positions (0,0)-(1,1), and the artwork pieces were all defined relative to those coordinates. There are two problems with this. First, the screen was referenced in its native, nonrotated state; invaders normally runs rotated 270 degrees, which requires swapping the X/Y coordinates and then flipping the Y coordinate. Second, the artwork aspect ratio used to stretch based on the aspect ratio of the game; this is no longer the case -- all view items are assumed to be square pixels.

So let's tackle one problem at a time. In the old coordinate system, the backdrop was positioned at (0.0,-0.14)-(1.29,1.15). The first thing we need to do is fix the orientation. As I said before, to do this we need to swap the X/Y coordinates and then flip the Y coordinates. Swapping is easy, and gives us (-0.14,0.0)-(1.15,1.29). To flip in the Y direction, we need to replace each Y coordinate value with (1.0 - Y). This gives (-0.14,1.0)-(1.15,-0.29). The only other tweak we need to make is that the left coordinate value must be less than the right coordinate; similarly, the top must be less than the bottom. After doing the Y flip, we've violated these rules, so we need to swap the Y coordinates and end up with (-0.14,-0.29)-(1.15,1.0).

With me so far?

So now we've rotated the coordinates around so that they are in the correct location with respect to the screen, except that we are still assuming the screen goes from (0,0)-(1,1). If we use these coordinates for the screen, however, the screen graphics will be stretched out to a square, and that's incorrect. The rotated monitor has a 3:4 aspect ratio, meaning that the X coordinates need to be shrunk down by a factor of 3/4 or 0.75. So, applying a 0.75 factor to the X coordinates, we get (-0.105,-0.29)-(0.8625,1.15). Whew! Putting this into a backdrop item for our view, it would look like this:

<backdrop element="backdrop">
    <bounds left="-0.105" top="-0.29" right="0.8625" bottom="1.0" />
    <orientation rotate="270" />
</backdrop>

Wait a minute! I thought we already rotated the image! Why is there an orientation tag in there? Well, if you open the PNG file that the "backdrop" element references, you'll see that the artwork is on its side. The orientation parameter rotates the graphics (not the coordinates) into the correct position.

Applying the same transform to the bezel, we get:

<bezel element="bezel">
    <bounds left="-0.61545" top="-0.7179" right="1.338825" bottom="1.3333" />
    <orientation rotate="270" />
</bezel>

Finally, the screen itself. As I mentioned before, we can ignore the old overlay technique and directly reduce the color of the screen item in the view directly:

<screen index="0">
    <bounds left="0.0" top="0.0" right="0.75" bottom="1.0" />
    <color alpha="0.75" />
</screen>

Finally, we wrap these three items up in a view, and produce the final XML:

<?xml version="1.0"?>
<mamelayout version="2">
    <element name="backdrop">
        <image file="invaders.png" />
    </element>

    <element name="bezel">
        <image file="invadbez.png" alphafile="invadmask.png" />
    </element>

    <view name="Full Artwork">
        <backdrop element="backdrop">
            <bounds left="-0.105" top="-0.29" right="0.8625" bottom="1.0" />
            <orientation rotate="270" />
        </backdrop>

        <screen index="0">
            <bounds left="0.0" top="0.0" right="0.75" bottom="1.0" />
            <color alpha="0.75" />
        </screen>
    
        <bezel element="bezel">
            <bounds left="-0.61545" top="-0.7179" right="1.338825" bottom="1.3333" />
            <orientation rotate="270" />
        </bezel>
    </view>
</mamelayout>

You can try this today with a NEW_RENDER build and see it all work. The nice thing is that with the new rendering system, all the artwork is scaled natively to whatever resolution your screen is, so you don't lose any quality. Plus, it should be a whole lot faster because your graphics card (assuming it isn't ancient) is doing all of the heavy lifting and compositing.

Next I'll talk about Turbo a bit and show you how to vastly simplify the giant .art file that is currently used.

Layouts and Rendering

Today is when MAME 0.106u2 should be available. I'm sure there will be lots of questions as a result, but the one major change that needs some more detailed description is the concept of layouts and views.

As a simplistic explanation, layouts are the replacement for the artwork description files (.art) that were previously used to describe artwork to be displayed with a game. However, layouts are much more flexible and much more deeply integrated into the rendering system than the artwork files ever were. You literally can't run the new renderer without a layout loaded.

A layout consists of two parts: a list of zero or more elements, and a list of one or more views. The elements represent a sort of database of artwork pieces that can be assembled in various ways. The views represent the actual positioning of these elements relative to the game screens. The easiest way to understand this is to look at the simplest example, which is the default layout used for regular horizontal 4:3 games:

<?xml version="1.0"?>
<mamelayout version="2">
    <view name="Standard">
        <screen index="0">
            <bounds left="0" top="0" right="4" bottom="3" />
        </screen>
    </view>
</mamelayout>

This particular layout has no elements described, and only a single view. The name of the view is "Standard." This is important because there is a new menu in the UI that lets you select on the fly which view to display, and this is the name that is displayed in that menu. Within the view, there can be a number of items:

Everything in the new system is rendered back-to-front, so first all backdrop items are drawn, then all screens, then all overlays, and finally all bezels. If more than one item of a given type is present, it is rendered in the order specified in the layout XML data.

So looking back at the example, you can see that we've specified a single item for our view, which is screen index 0 (this will be the first screen in the system). Within the item are some parameters that describe the bounds of the screen within the view. You'll notice that the width of the screen is 4 and the height is 3. What kind of coordinate system is this? Well, it's an arbitrary system, really. The layout system will read all the items described, and compute the outer bounds of all of the rectangles specified. It will then scale that to fit whatever screen you have configured. Thus, you can specify your coordinates in pixels or whatever is most convenient. The key here is that the screen as described is a standard 4:3 aspect ratio screen oriented horizontally.

Now, if you're familiar with the old artwork system, you may be scratching your head and thinking, why do we have to specify the aspect ratio of the screen? In the old system, the screen was always positioned from (0,0)-(1,1) and the aspect ratio of the screen (and the resulting artwork) was determined by flags in the game. This is true. And in retrospect, it was a mistake. Not only did it make things confusing for positioning purposes, but it meant a lot of the artwork needed to be rotated and tweaked so that it stretched correctly. In addition, in the new world, there is nothing preventing you from having one screen rotated vertically and a second screen rotated horizontally, all within the same view (and yes, there is at least one dual monitor game that is set up that way).

The next obvious question is, so are we going to need files for all these layouts, even the standard ones? The answer is no. The layout system will load a number of layouts from different sources, and offer you the option of switching between all of the views specified by all of the interesting layouts. The search order is:


  1. Explicitly specified files (on the command line)

  2. gamename.lay

  3. Game-specific built-in layouts

  4. parentname.lay

  5. Generic built-in layouts

The key are the built-in layouts. First, each game can specify a built-in layout as a parameter to the new GAMEL macro, which mimics the existing GAME macro but takes a final parameter which a pointer to an embedded XML string that holds the game-specific built-in layouts.

Second, there are a number of built-in layouts. By default, each screen in the game gets a Standard layout, which is simply a single screen displayed at its appropriate aspect ratio. Each screen in the game also gets a Native layout, which is a single screen displayed 1:1 with the height/width ratio of the pixels. This produces, for example, widescreen Capcom games for those who still believe they should be widescreen. Multi-screen games get a few additional options for displaying both screens at the same time, either on top of each other or side-by-side. And finally, just for kicks, there is a "cocktail" layout that displays two copies of screen 0, one rotated 180 degrees for a pseudo-cocktail view. How is that done? With a layout something like this:

<?xml version="1.0"?>
<mamelayout version="2">
    <view name="Cocktail">
        <screen index="0">
            <bounds left="-1.33333" top="0.0" right="0.0" bottom="1.0" />
        </screen>
        <screen index="0">
            <bounds left="0.01" top="0.0" right="1.34333" bottom="1.0" />
            <orientation rotate="180" />
        </screen>
    </view>
</mamelayout>

You'll notice a couple of interesting things here. First is, you can repeat the same screen multiple times in a view if you'd like. For fun, I've even created a "quad" view that displays the screen 4 times rotated all four directions. Second is that you can specify an orientation for screens and actually for any item. This allows rotation and flipping of items, and even works with vector games or other special cases. Finally, you see how the coordinate system really is arbitrary. Here I'm using 1.333 as the width of each screen and 1.0 as the height. This is the same as 4:3. Really. :)

For completeness sake, here are all the attributes you can specify for items:

<bounds left="0" top="0" right="4" bottom="3" />
<bounds x="0" y="0" width="4" height="3" />
<color red="1.0" green="1.0" blue="1.0" alpha="0.5" />
<orientation rotate="90" swapxy="yes" flipx="yes" flipy="no" />

You can control the bounds either by specifying left/top/right/bottom coordinates, or by specifying x/y/width/height coordinates. But only one or the other. The color tag lets you affect the overall color and alpha blending factors of the item. Each color value ranges from 0-1. And you can control orientation of the item via both a rotate parameter as well as through more primitive flipping and swapping controls.

Well, that seems like enough for a single article. I'll talk about elements and artwork and how they work in the next article.

Monkey

What you may have deduced from the whatsnew in MAME 0.106u1 (assuming you read it) is that some work on the video system was under way. I've been claiming "video system rewrite!" for so long that I can barely remember when I first started discussing it. It was at least a year ago, if not longer.

Ever since I first mentioned it, it has been a monkey on my back -- a giant "everything's gonna break" rewrite that I've been both itching to do and dreading at the same time. It's been clear for years that MAME has needed far more fleixibility in handling things like multiple screens. It's also been clear that my original attempt at a system to incorporate artwork was only partly successful. And there has been way too much interference with game-drawn graphics by external entities like the user interface, which has created a lot of grossness about the way video is handled.

All this was to be fixed with the video rewrite. And if you know me, you know that fixing all those problems is something that I really, really wanted to do. But at the same time, I was dreading it. Why? Well, the biggest reason is probably the fact that it would mean delving back into DirectX programming once again, which is always fraught with pain. Ever since the original port to Windows a number of years back, I haven't had to deal with the DirectX side of things much.

Plus, it's a hard problem, and not the sort of problem that I can easily solve in one-hour sessions over the course of a number of weeks. It's really the sort of problem that requires me to sit down with several days' worth of completely dedicated time ahead of me so I can get "over the hump" of the initial programming work and then spend the more normal one-hour sessions debugging/fixing the remaining problems.

Well, this past weekend, I'm happy to say, it finally happened. Bye bye, monkey. :)

A number of factors came together to get most of the work done, but the most important one (and the one that I have been planning around) is that the missus was out of town from Thursday noon to Sunday evening. Couple that with some vacation time, a bunch of junk food, some musical inspiration, limited sleep, and you end up with a solid 78 hours of geekdom. I think I ended up programming for 55-60 of those. It's all a blur now anyway.

The practical upshot of this is that the core work for the new video system is now written. I had the software-only version up and running by the wee hours of Friday morning, and the Direct3D-based version running about the same time Saturday morning. Artwork of all forms -- bezels, overlays, backdrops -- is working, including more flexible state-based control over the pieces. Vector games use the hardware to render the vectors. Multiple screen support works in the core, and most of the code is written to allow it to actually render to multiple screens/windows on the Windows-specific side, though I'm still at a loss for how to expose the new gamut of options in the limited form of the command line.

In subsequent days, I hope to provide more information about the rewrite, including details on the new layout file format and some of the internals of the new system. For now, I'm just going to list out a few interesting tidbits/side effects that you should be aware of. Keep in mind that although the basic system works, there are still a lot of things left to do.

That's it for now. I'll post some screenshots later, and discuss more details over the next week or two. Again, remember this is all still very much a WIP, but the remaining issues can all be tackled one at a time. The big deal was getting the core work done, and thankfully, that's finished!