The Multiple Arcade Machine Emulator (MAME) is currently the best choice for emulating arcade games. I've been looking into configuring it for my particular setup. I prefer using my 50" 1920x1080 pixel, 60 Hz refresh rate TV for the arcade games.
I prefer to represent the pixels of the original game as clearly and cleanly as possible, without any smoothing. My approach is completely subjective, and of course other people will have different goals.
For a game with a certain resolution to be shown on a higher resolution display, I prefer every line and column of the game to be mapped to an integer number of lines and columns of the display, meaning that every 1 line or column rendered in the game becomes exactly 1, 2, 3, etc. lines or column on the display. That in turn requires that every pixel in the game is displayed as 1, 4, 9, etc. pixels on the display.
As an example, the resolution of R-Type is 384x256. If we upscale that 4 times, we get the resolution 1536x1024, which fits great on my 1920x1080 display.
In the new version of MAME, there is an option to automatically use integer scaling. I configured it like this:
video auto # defaults to software renderer, works fine keepaspect 1 # retain aspect unevenstretch 0 # integer scaling
Using this configuration, the image is scaled to exactly 1536x1024, and displayed in the middle of the screen, giving us perfect square pixels.
Here is the boot screen:
In the older versions of MAME, we can use the 'prescale' option to upscale the image 4 times, but rendering using the default Direct3D output still scales the image to the full display resolution. However, the combination of keepaspect and DirectDraw rendering works as expected:
video ddraw # d3d seems to scale in non-integer ratios numscreens 1 window 0 # start in fullscreen maximize 1 # if windowed, maximize window size, not related to scaling keepaspect 1 # retain 4:3 aspect, also enables integer scaling prescale 0 # not necessary when using ddraw effect none # no crazy effects, just raw pixels
Setting up MAME for nicely synchronized video rendering without stuttering is a more complex problem than I assumed.
Let's look at a specific case, running R-Type on MAME without frame stuttering on a 60 Hz monitor. The original R-Type had a video refresh rate of 55.017606 Hz.
If we run the game without any vertical synchronization (vsync), the game will feel as close as possible to the original and the sound will work perfectly. However, we will get a vertically displacing tear in the video frames. This is because the frames rendered by MAME will be updated around 55 Hz (18.2 ms per frame), and the screen will update the display at 60 Hz (16.7 ms per frame). This means that in 0.2 s, MAME will render 11 frames, but the screen will have displayed 12 frames.
This configuration corresponds to the following MAME.ini options:
waitvsync 0 syncrefresh 0 triplebuffer 0 throttle 1 speed 1.0
To avoid the tear, we could enable vsync in MAME.ini:
Now, every frame displayed on the screen will correspond to a frame rendered by MAME and will look correct. However, this just moves the problem somewhere else. Every 0.2 s, the screen will render its 12th frame, but in this time, MAME will only have rendered 11 frames. MAME will then show the last frame rendered again, so every 12th frame will be a copy of the frame before. For scrolling games, this will look choppy and awful.
If we use triple buffering and disable throttling, the game will run at 60 Hz in fullscreen (at least, on my machine). No tearing, no frame stutters. Unfortunately, now the graphics is running 1.09 times as fast (60 / 55.017606) as the audio system, so every once in a while the audio will stutter. However, we have come pretty close to a solution here:
triplebuffer 1 throttle 0
If we speed up everything, both graphics and audio to run 1.09 times as fast, MAME will render its frames 60 times per second, audio will be synchronized, and the MAME frames will correspond to screen frames in 60 Hz.
waitvsync 1 # required in 0.183, not in 0.154 syncrefresh 0 triplebuffer 0 throttle 1 speed 1.09056 # 60 / 55.017606
To avoid tearing with minimum lag, we can enable triple buffering as well:
Of course, putting the speed modifier in MAME.ini is not practical, as this value will vary from game to game, so using a command-line option is better:
mame -speed 1.09056 rtype
Now, running the game 9% faster doesn't really help with an already insanely difficult game, but there you are.
MAME 0.183 has an option 'refreshspeed', described as:
Automatically adjusts the -speed parameter to keep the effective refresh rate below that of the lowest screen refresh rate.
I couldn't get it to work, the frame rate was uneven when using it instead of manually setting 'speed'.
Running the game at 60 / 55.017607 speed changes the key of the music.
relative_frequency = 2^( key_change / 12 )
Which means that:
key_change = log2( relative_frequency ) * 12
In this case, we have the relative frequency 60 / 55.017607:
key_change = log2( 60 / 55.017607 ) * 12 ~ 1.5
So the music is transposed 1.5 semitones up. Not too bad.