Nvidia - How to create custom video modes

We all want our MAME games to look as original as possible.  This tutorial will tell you how to create video modes on your Nvidia Video Card to match the original Arcade game.  You must be using Windows XP and current Nvidia drivers which are 81.98 as of this writing.

The purpose of creating custom video modes is to create the same video scan lines and scaling as the original game.  This means this info only applies if you have a CRT based monitor and play the game in full screen mode.  For vertical games, I am assuming you will be rotating the monitor 90 degrees on it's side.  There is no point in making custom modes for vertical games if you do not intend to do this.  Also there is no point in creating custom video modes if you have an LCD display.  You should run your LCD at it's native resolution for best picture and tell MAME to scale the picture to fit.  If you have a plasma, what the hell are you burning games into the screen for?

Low resolution video modes will be doubled in resolution when created, but accessed at the size created.  This means a video mode of 320x240 will actually use 640x480.  You still draw to it in the native 320x240 mode, but all pixels will be doubled.  This means you will always see 2 scan lines for each pixel.  It is actually a quite pleasant look.  If only 1 scan line was used then the dark space between visible lines would be excessive on computer monitors.  This is due to their smaller dot pitch compared to old arcade monitors.  The 320x240 mode is actually one of the modes created by the default driver file.

Download the latest drivers from Nvidia. Use WinZip or your favorite extractor to extract the files to a directory.  The easiest way is to right click on the driver file and select WinZip -> Extract to xxx\. Open this directory and then open the "nv4_disp.inf" file with you favorite text editor or use notepad.

Browse down about half way through the file until you see a section that looks like this:
[nv_SoftwareDeviceSettings]
HKR,, InstalledDisplayDrivers, %REG_MULTI_SZ%, nv4_disp
HKR,, VgaCompatible, %REG_DWORD%, 0
HKR,, MultiFunctionSupported, %REG_DWORD%, 1
HKR,, RotateFlag, %REG_DWORD%, 4
HKR,, NV_R&T, %REG_MULTI_SZ%, "R&T0000=*,*,*,*,*,IBM251F.VSC2F0C.VSC3411.VSC3E19,HDLK"
HKR,, NV_R&T, %REG_SZ_APPEND%,"R&T0001=1920,1080,*,30,*,CRTX,OEM,7425,2200,48,56,562,2,5,++I"
HKR,, NV_R&T, %REG_SZ_APPEND%,"R&T0002=1920,1080,*,60,*,BNQ766A,OEM,13850,2080,48,32,1111,3,5,+-"
HKR,, NV_R&T, %REG_SZ_APPEND%,"R&T0003=1920,1200,*,60,*,BNQ766A,OEM,15399,2080,48,32,1235,3,6,+-"
HKR,, NV_R&T, %REG_SZ_APPEND%,"R&T0004=1920,1200,*,60,009D,*,OEM,15399,2080,48,32,1235,3,6,+-"
HKR,, DevSwitchSuppressMask, %REG_DWORD%, 7
HKLM,"Software\NVIDIA Corporation\Global\NvSvc\OemConfigurations",LoadLimitedSID,%REG_SZ%,"S-1-5-11"
HKR,, "DefaultSettings.XResolution",%REG_DWORD%,800
HKR,, "DefaultSettings.YResolution",%REG_DWORD%,600

HKR,, NV_Modes, %REG_MULTI_SZ%, "{*}S 720x480 720x576=1;320x200 320x240 400x300 480x360 512x384 640x400=F;SHV 2048x1536x32=1;1920x1200x32 1920x1440x8,16=1D;640x480 800x600 1024x768 1280x768 1280x1024 1600x900 1600x1200 1920x1200x8,16=3D;1920x1440x32=9;1920x1080=C01E;2048x1536x8,16=D;{1A0}S 1920x1200x32 1920x1440x8,16 2048x1536x8,16=20;800x480=3D;{40-48,90-94,C0-C3,110-145,14F-1F0,210-334,341-34E}S 720x576=8032;{40-18B,1F0-34E}SHV 800x600=1DC2;848x480=1DFF;1920x1080x32=1F;640x480 1024x768x8,16=1FC2;"
HKR,, NV_Modes, %REG_SZ_APPEND%, "1600x1200x32 1920x1200 1920x1440 2048x1536x8,16=2;1280x768x32 1280x1024x32=2C2;1280x720x32 1280x800x32 1280x960x32 1360x768x32=2FF;1600x900x8,16=3C2;1600x1024x32 1920x1080x8,16=3F;1600x900x32 1600x1200x8,16=42;1152x864x32=6FF;1280x768x8,16 1280x1024x8,16=7C2;1600x1024x8,16=7F;1280x720x8,16 1280x800x8,16 1280x960x8,16 1360x768x8,16=7FF;960x600=DFF;1024x768x32=FC2;1152x864x8,16=FFF;{40-CE,140-165,1A0,200-242,301-34E}SHV 2048x1536x8,16=10;1920x1440x32 2048x1536x32=4;"
HKR,, NV_Modes, %REG_SZ_APPEND%, "{40-CE,140-165,200-242,258-25B,288-34E}SHV 960x600=1000;{40-CE,140-165,200-242,301-34E}SHV 1920x1440x32=10;1152x864x32 1280x720x32 1280x768x32 1280x800x32 1280x960x32 1280x1024x32 1360x768x32=100;2048x1536x32=1A;1088x612x8,16=1FFF;800x600 848x480 960x600=200;1088x612x32=FFF;{4D-4E,9D,CD-CE,14A-14E,200-203,258-25B,288-289,308-309,32A-32B,338-33F,34E}SH 960x1200=803D;{4D-4E,9D,CD-CE,14A-14E,200-203,338,33F}SHV 800x600 1024x768 1280x1024 1600x1200 1920x1154 1920x1200=8032;"
HKR,, NV_Modes, %REG_SZ_APPEND%, "{4D-4E,9D,CD-CE,14E,200-203,240,338,33F}SHV 800x600 1024x768 1280x1024 1600x1200 1920x1154 1920x1200=8032;"

[nv_WSApps_AddReg]
HKR,,"NvCplConfiguration",%REG_DWORD%,0x100000

The following section is that part that creates the video modes.  How to create custom modes is explained in the Compressed Modes User's Guide available from Nvidia.
HKR,, NV_Modes, %REG_MULTI_SZ%,  "{*}S 720x480 720x576=1;320x200 320x240 400x300 480x360 512x384 640x400=F;SHV 2048x1536x32=1;1920x1200x32 1920x1440x8,16=1D;640x480 800x600 1024x768 1280x768 1280x1024 1600x900 1600x1200 1920x1200x8,16=3D;1920x1440x32=9;1920x1080=C01E;2048x1536x8,16=D;{1A0}S 1920x1200x32 1920x1440x8,16 2048x1536x8,16=20;800x480=3D;{40-48,90-94,C0-C3,110-145,14F-1F0,210-334,341-34E}S 720x576=8032;{40-18B,1F0-34E}SHV 800x600=1DC2;848x480=1DFF;1920x1080x32=1F;640x480 1024x768x8,16=1FC2;"
HKR,, NV_Modes, %REG_SZ_APPEND%, "1600x1200x32 1920x1200 1920x1440 2048x1536x8,16=2;1280x768x32 1280x1024x32=2C2;1280x720x32 1280x800x32 1280x960x32 1360x768x32=2FF;1600x900x8,16=3C2;1600x1024x32 1920x1080x8,16=3F;1600x900x32 1600x1200x8,16=42;1152x864x32=6FF;1280x768x8,16 1280x1024x8,16=7C2;1600x1024x8,16=7F;1280x720x8,16 1280x800x8,16 1280x960x8,16 1360x768x8,16=7FF;960x600=DFF;1024x768x32=FC2;1152x864x8,16=FFF;{40-CE,140-165,1A0,200-242,301-34E}SHV 2048x1536x8,16=10;1920x1440x32 2048x1536x32=4;"
HKR,, NV_Modes, %REG_SZ_APPEND%, "{40-CE,140-165,200-242,258-25B,288-34E}SHV 960x600=1000;{40-CE,140-165,200-242,301-34E}SHV 1920x1440x32=10;1152x864x32 1280x720x32 1280x768x32 1280x800x32 1280x960x32 1280x1024x32 1360x768x32=100;2048x1536x32=1A;1088x612x8,16=1FFF;800x600 848x480 960x600=200;1088x612x32=FFF;{4D-4E,9D,CD-CE,14A-14E,200-203,258-25B,288-289,308-309,32A-32B,338-33F,34E}SH 960x1200=803D;{4D-4E,9D,CD-CE,14A-14E,200-203,338,33F}SHV 800x600 1024x768 1280x1024 1600x1200 1920x1154 1920x1200=8032;"
HKR,, NV_Modes, %REG_SZ_APPEND%, "{4D-4E,9D,CD-CE,14E,200-203,240,338,33F}SHV 800x600 1024x768 1280x1024 1600x1200 1920x1154 1920x1200=8032;"

What we want to do is append our modes onto the end.  For MAME we only need 16&32 bit colour video modes.  We do not have to worry about what our card is and what it really supports.  This is not a driver for the masses, so we are going to pretend that all video boards support all features.  Otherwise we would have to figure out the hex id number for our card, when we really don't care.  Here is the line I use.  Just paste it after the other video modes above.
HKR,, NV_Modes, %REG_SZ_APPEND%, "{*}S 240x192x16,32 240x224x16,32 240x240x16,32 240x248x16,32 248x208x16,32 248x256x16,32 256x224x16,32 256x240x16,32 256x248x16,32 288x224x16,32 292x240x16,32 304x224x16,32 320x204x16,32 320x224x16,32 320x232x16,32 320x240x16,32 384x224x16,32 384x240x16,32 384x256x16,32 400x254x16,32 512x448x16,32 512x480x16,32=1fff;"

The "HKR,, NV_Modes, %REG_SZ_APPEND%, " part tells the driver to append some more video modes.  "{*}S" tells the driver that all cards support these modes.  "240x192x16,32 ...." are the video modes we want to create.  This is the section you can change to add whatever modes you want.  The "=1fff;" at the end of the line tells the driver all refresh rates are supported.

Your card & monitor may not support all modes and refresh rates.  But at this point we don't care.  When you run a game hit "TAB" and select "Game Information".  This will tell you the resolution of the game.  For Phoenix it will say "248x208 (V)" so we create 16 & 32 bit modes by adding "248x208x16,32" as seen in the list above.  Be warned that for vertical games, MAME32's properties page will show the resolution as 208 x 248, but we need to create the mode as shown in the game information page in MAME.

Unfortunately not every mode can be created.  For modes with a vertical size less then about 400, the H&V sizes must be evenly dividable by 4.  Remember low res modes are created at 2x.  Modes greater then 400 vertical must be dividable by 8. Always make sure you round up on the number of pixels.  MAME will center itself and ignore the few extra pixels.

Once you have the modes you want added, save the file and install the driver by running the "setup.exe" file.  Once the computer has rebooted you are free to use the video modes in MAME.

The modes may not all show up in MAME32 or it's derivatives.  In that case you have to compile your own version.  You need to edit the src\ui\directdraw.h file.  On line 18 you will see this.
#define MAXMODES    256 /* Maximum number of DirectDraw Display modes. */
Change the MAXMODES to a higher number.  I use 1024.  Then recompile.  If you have recently compiled MAME32 before making the change, then you need to delete your obj\YOURMAME\ui directory, where YOURMAME is the name of your compiled MAME32.  Then recompile.  You should now be able to select all video modes and refresh rates.

To see if the modes were created, right-click on an empty spot of your desktop.  Select NVIDIA Display -> and then select your monitor.  On the left side list, select "Screen Resolutions & Refresh Rates". You should now see a window like this:

Settings

You can now slide the Screen resolution slider through the various modes.  You can also see what refresh rates your monitor supports for that mode.  If you need a refresh rate that is not listed, then you will have to read the Compressed Modes User's Guide to find out how.

Proper Display Settings

Before we go any further, you need to know the best video properties settings for your card to work with MAME.  We want the video to display as fast as possible without any tearing caused by writing video info while the screen is drawing or not blanking.  So right-click on an empty spot of your desktop.  Select NVIDIA Display -> and then select your monitor.  On the left side list, select "Performance & Quality Settings". You should now see a window like this:

Performance & Quality Settings

You want to set the "Global Driver Settings" so that "Vertical sync" is set to "Application-Controlled".  Select "Advanced settings" and turn "Triple buffering" "On".  If you don't like your global settings set this way, then I will leave it to you to create a MAME profile with those settings.

Doing this allows Triple buffering to work in MAME.  This way you can turn on Triple buffering and turn off wait for vsync in the MAME options.  This will give you your fastest game speed with no video tearing.  When you use a custom video mode that exactly matches the game resolution, you need to turn off hardware stretching and you should not use D3D.

Testing and Observations

These are the options you need when running a vertical game at it's native resolution and refresh rate while being rotated as the original would be.
mame firetrk -r 320x240 -refresh 60 -ror -tb -nowaitvsync -dd -nod3d -nohws -nowindow -noafs
This will allow Fire Truck to run full screen in it's native resolution of 320x240 and orientated vertically.  Let the game's demo run.  You will notice that the picture is crisp.  The video runs smoothly with no jitter.  If you change the refresh from it's native rate of 60 to 75, the video will not be as crisp and will no longer scroll smoothly.

If we run it at twice it's native resolution (-refresh 120) using the command below, it will scroll smoothly, but the edges of the video will have a ghosting effect.  Again let the demo run.  Look at the Fire Truck.  It will look crisp because it is not moving.  Look at the lines at the edge of the road.  The straight lines look crisp, but the diagonals are a faded gray, when they were crisp white at 60Hz refresh.  Look at the leading in trailing edges of the buildings as they scroll.  You will also see a gray ghosting effect that is not there at 60Hz.  If you pause the game, the edges will once again be clearly defined.
mame firetrk -r 320x240 -refresh 120 -ror -tb -nowaitvsync -dd -nod3d -nohws -nowindow -noafs

This is because the game is drawing the video at 60Hz and the video board is drawing it at 120Hz.  Or put another way, you are suppling the video card with 60 frames of video every second, when it wants 120.  So the video board makes up the other 60 frames using an average of 2 supplied frames.

If you tell firetruck to synchronize the game play to the 120Hz refresh rate using the command below, the video will once again be as smooth as it was using 60Hz, but the game speed will be twice as fast.
mame firetrk -r 320x240 -refresh 120 -ror -tb -nowaitvsync -dd -nod3d -nohws -nowindow -noafs -syncrefresh

If you want to try these tests out without creating the custom video modes, you can change the resolution parameter from 320x240 to 640x480.  This will allow you to at least see the ghosting I am talking about.

What is needed is a way to tell MAME to draw the video twice as fast as it is being created.  Coding video is not my thing, so if anyone knows how to make MAME draw the video at 2x the game's native refresh rate, while still running the game at it's native refresh rate, please let me know.  This would be a nice feature to allow you to use a higher refresh rate then the game original used, while keeping the video crisp.

Why allow video to run 2x game rate?

Some games use a really low resolution.  Phoenix for example.  It has a resolution of 248x208.  So when the video card creates it, it will double it to 496x416.  Phoenix used a refresh rate of 60Hz.  This would give us horizontal scanning rate of about 27kHz.  Way lower then the 31kHz cut off of most monitors, giving an out of sync range error on the monitor.  If we run the game at 2x 60Hz =120Hz, the horizontal scan rate would double to 54kHz.  This would now allow you to use the custom video mode to display the actual game resolution.  But you would have the ghosting mentioned above.  This would be noticeable on the edges of the stars as they move.

So if there was an option in MAME to update the video 2x, Phoenix and lots of other old games, would be able to be displayed on a CRT monitor in their native resolution.  They would look as close as possible to the original game display, without any scanline creation video tricks.  They would have real scanlines created by the monitor.  The game would look crisp and smooth.

So if anyone knows how to create the 2x option, please let me know on the MAME forum.
Thanks,
D.

Monitor out of Sync Range?  Where is the Picture?  Why Does it Look Weird?

Now that we have created the modes, you will find that a lot of them will not work unless you use a refresh rate of at least 70Hz.  As explained in the Phoenix example, this can not be helped.  So first try the game at it's native refresh rate.  If you monitor shuts down or displays an error, then select a higher refresh rate.  It is probably best to try a rate 2x the games native refresh rate.

Because monitor manufacturers do not really expect you to create your own video modes, your mileage may vary on how well they display.  You may not be able to fill the whole screen or get the pincushion correct.  In that case try a different refresh rate.

Setting up your game

Remember the purpose of doing all this is to run the game at the original resolution and the original refresh rate if possible.  This means no hardware stretching.  You do not need to stretch something that is already at the proper size.  You also do not need to stretch if you create modes that are exact multiples of the original resolution, eg 2x, 3x...  And do not use scanlines or any effects.  Real scanlines will be created by the monitor.  Lets dissect the test line we used previously.  This is current as of MAME 104.
mame firetrk -r 320x240 -refresh 60 -ror -tb -nowaitvsync -dd -nod3d -nohws -nowindow -noafs
mame = start mame.
firetrk = run Fire Truck ROM.
-r 320x240 = the exact resolution of the original game as specified by MAME.
-refresh 60 = the original game's refresh rate.  You may have to use a higher value to make your monitor work.  Try 2x game refresh rate.
- ror = rotate game clockwise.  Needed for vertical games .  Turn your monitor on it's side.  Do not use this if game is horizontal.
-tb = triple buffer for tear free video.
-nowaitvsync = no need to wait for vsync if triple buffering works.
-dd = always need DirectDraw
-nod3d = D3D seems to be slower.  It's my personal preference to turn D3D off when using exact modes.
-nohws = NO HARDWARE STRETCH.  Why stretch something that is already the exact size?
-nowindow = Full Screen.  The whole point was making full screen custom modes, remember.
-noafs = No auto frame skipping.  If you can not run the game full speed, why go through all the effort of making video exact?

And for the command line impaired, here are the MAME32 settings.  Look closely at all settings.  You can leave the Clean Stretch at it's default Auto setting.  It will be ignored anyways.

DisplayAdvancedDirect3D

Vertical Games.

As I have stated a few times, the modes created for vertical games require you to rotate the monitor on the side.  Which is what I do.  This also requires you to degauss your monitor after rotating.  You should be able to do this from your monitor's menu.  Read your manual for further info.

There is a way to cheat and leave your monitor horizontal, if you do not mind all your vertical games being fat and filling the whole screen.  Just swap the Horizontal and Vertical values when you create the video mode.  So for firetrk, instead of creating a 320x240 video mode.  Create a 240x320 video mode.  Now you can use that mode and not have to turn the monitor.  The game will run fat and fill the screen.  Remember, -ror is no longer needed.  For MAME32 users, set Rotation to none/default.  Turn off "Force Aspect Ratio" by using -nokeepaspect.

Another interesting way to play vertical games without rotating the monitor is to keep them at the original aspect ratio.  This requires you to use 4/3*VxV.  So for firetrk this is 4/3*320x320 = 426.667x320.  Round up so the number is /4.  Gives us 426.667/4 = 106.667.  Rounds up to 107*4.  So we create a mode  at 428x320.  Now our 240x320 fits perfectly vertically and will have the proper horizontal aspect.  MAME will center the 240 horizontal game pixels inside the full 428 by padding 94 pixels on either side.  Make sure to turn on "Force Aspect Ratio" by using -keepaspect.

Good luck.  If you have questions, post them on the MAME forum.  There are other users there that use this method.  So you may get some more help.  But be specific about what you tried and how it does not work.