Main Restorations Software Audio/Jukebox/MP3 Everything Else Buy/Sell/Trade
Project Announcements Monitor/Video GroovyMAME Merit/JVL Touchscreen Meet Up Retail Vendors
Driving & Racing Woodworking Software Support Forums Consoles Project Arcade Reviews
Automated Projects Artwork Frontend Support Forums Pinball Forum Discussion Old Boards
Raspberry Pi & Dev Board controls.dat Linux Miscellaneous Arcade Wiki Discussion Old Archives
Lightguns Arcade1Up Try the site in https mode Site News

Unread posts | New Replies | Recent posts | Rules | Chatroom | Wiki | File Repository | RSS | Submit news

  

Author Topic: Switchres: modeline generator engine  (Read 344253 times)

0 Members and 1 Guest are viewing this topic.

Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .14)
« Reply #120 on: November 03, 2010, 06:30:12 pm »
I've posted this on the Spanish forum, hopefully VeS can try this stuff with a distribution, if you think it's a good idea.

Modifying the frame buffer modes sounds interesting. It's unlikely that 640x480@31i mode will work with many fixed frequency arcade monitors, because vesa porchs and sync pulses are shorter, and probably the mode will be out of sync, however it's a matter of testing. This applies only to the console, doesn't it?



Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .14)
« Reply #121 on: November 03, 2010, 08:37:38 pm »
I've posted this on the Spanish forum, hopefully VeS can try this stuff with a distribution, if you think it's a good idea.

Modifying the frame buffer modes sounds interesting. It's unlikely that 640x480@31i mode will work with many fixed frequency arcade monitors, because vesa porchs and sync pulses are shorter, and probably the mode will be out of sync, however it's a matter of testing. This applies only to the console, doesn't it?




Yeah it's just the console, I think it's not too hard to adapt to arcade monitor support by just putting in some default modelines that work well with arcade monitors and forcing them through a kernel command line option. 

Definitely would be good to base a distribution off the xserver patch that I posted, only avoiding the default modes when there's modelines defined, and the newest X  Windows build and Linux kernel with the drm patches I have (plus xrandr patch, although I'm trying to obsolete that, I think it may not be needed, testing that right now). 

I'll post an updated genres here in the next day or so that should hopefully remove the need for the xrandr patch, include the right xserver patch (simpler one), and linux kernel patch with possible fixed freq arcade monitor support.  For now he should become familiar with the newest Linux kernel, I think 2.6.37-rc1 is fine, and the method of using the modular build.sh script to download the newest X build.  I'd be curious about any feedback on using that script, and if any issues come up.  It seems pretty solid and they are actively working on it so it's pretty smooth working on downloading/compiling/installing everything.   I've found I have to set 'export USE_XCB=NO' because xcb won't build with the python version before 3.0 which then isn't stable and breaks other X packages.  That's the main caveat I've found with the build.sh script so far, otherwise it's nice and can combine it with the newest Linux kernel to get a pretty nice setup.  The module options are important, in the radeon.conf file, and must build with radeon drm with KMS built in for the Linux kernel to use the newer radeon kernel code.   

I think I can get most things worked out to be minimal in patching the xserver only, linux kernel drm stuff, hopefully including a console that is arcade monitor friendly.  Will see how that goes, not sure how much work the console framebuffer will be.
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .14)
« Reply #122 on: November 04, 2010, 05:54:22 pm »
I've posted this on the Spanish forum, hopefully VeS can try this stuff with a distribution, if you think it's a good idea.

Modifying the frame buffer modes sounds interesting. It's unlikely that 640x480@31i mode will work with many fixed frequency arcade monitors, because vesa porchs and sync pulses are shorter, and probably the mode will be out of sync, however it's a matter of testing. This applies only to the console, doesn't it?





I have been able to add the arcade frame buffer support/modes to the Linux kernel, and at the same time can avoid needing to patch the X server or X programs at all.  You will need the newest versions of X Windows still of course, but may be able to use ones that are from code after this last May (when they added an option called "DefaultModes" to the Monitor sections).  With that option we can turn off the default modes, so makes my patch obsolete.  Now I basically can give the Linux kernel an option like "video=DVI-I-0:640x480c" which the 'c' at the end tells it to kick into CGA mode, I have a 640x240, 320x240, 384x288 in there that can also be chosen but still need to test those, the 640x480 is interlaced and generated with lrmc using the -cga command line.  It's only for the frame buffer, but it's important to do this because of how X Windows and the DRM stuff in the framebuffer code work together now to do mode switching.  There are more default modes that can be pushed into the X server from the kernel framebuffer now, but my patch will allow the CGA mode to avoid using those plus also optimize modeline setup for an arcade monitor.  It will avoid trying to get an EDID over and over from the arcade monitor, and from adding any extra modes besides the one you pick on the kernel command line.

So basically with this one patch to the kernel, using Linux 2.6.37-rc1, and a newer X Windows from GIT or any that support the DefaultModes option, you should be able to use the radeon cards and my switchres program utilizing xrandr and we can do everything we want to with an arcade monitor through Linux.  The xorg.conf config of course needs that DefaultModes options set to False and possibly a few other tweaks too, although that might be it actually.  The console framebuffer mode you choose, will also be your default X modeline that it starts up with if you don't add more modelines in the xorg.conf. 

It's looking pretty promising, I'm thinking of repackaging the whole GenRes zip file to just include what is necessary now that we no longer require much extra stuff.  Mainly just lrmc, switchres, linux patch, mame patch (optional), and general info on getting/patching the kernel and getting the X org modular package and running build.sh to download/compile/install a fresh version of X Windows.  This is so far also running really stable on my arcade cabinet, the radeon driver is good.  I can say though the nouveau driver is quite unstable, I'm running it on my workstation and can lockup randomly.  All this also kinda abstracts the need for only Radeon cards in the future.  The blocks to that are doing some more min-pixclock changing for the other drivers in the DRM part of the kernel, hoping the other DRM cards become fully xrandr compliant and support the vsync stuff from OpenGL correctly.  Most of the focus though is in the kernel now, so it's just a custom kernel that should be necessary to get things working for any card in the future.

Also if you have any good all-around default modelines I should use in the kernel for these modes chosen on the commandline, I'm using the lrmc ones and thinking about instead using the Soft15Khz ones possibly since I am guessing they are probably better.  I'm going to write a script to convert them quickly into the structure format in C used for storing them in the kernel code, so I can make most any arcade mode possible for the console.  This also should make a system easy to reboot into any frame buffer mode specific to a game and use DirectFB with mame and avoid the X Windows if one wanted a dedicated console for one resolution.  Dynamically changing it may be a pain for now, not fully sure. 

So I'll have a new GenRes with a linux kernel patch and a bit more organized up later tonight or sometime tomorrow.
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

elvis

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 1154
  • Last login:April 13, 2023, 05:31:03 pm
  • penguin poker
    • StickFreaks
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .14)
« Reply #123 on: November 07, 2010, 07:42:11 am »
You will need the newest versions of X Windows still of course, but may be able to use ones that are from code after this last May (when they added an option called "DefaultModes" to the Monitor sections).
For anyone wondering, Ubuntu 10.10 "Maverick" supports "DefaultModes" with it's provided version of xorg-server.  I'll try to test with the latest version of switchres+kernel-patches next weekend.

Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #124 on: November 07, 2010, 10:05:49 am »
I am thinking of building all this stuff myself as I'm definitely getting interested in Linux and I want to test it directly. I've seen the readme is focused on Gentoo, is it a good way to start? Any advices on distributions or packages to start with?
Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #125 on: November 07, 2010, 12:49:26 pm »
I am thinking of building all this stuff myself as I'm definitely getting interested in Linux and I want to test it directly. I've seen the readme is focused on Gentoo, is it a good way to start? Any advices on distributions or packages to start with?


Sounds like Ubuntu might just be  a good way to start, creating a dpkg of the ubuntu kernel with the patch applied already would make it a super simple way to do this since in Gentoo it's in a  sense like building your own Linux distribution but with everything ready to be put onto the partition. 

I'll look into building a patched ubuntu kernel package. 

Also I'm currently experimenting with a command line option I added to lrmc which directly feeds the variables it uses to calculate a display structure for the modeline generation.  It's giving me a quick way to fiddle around with the settings of active/total lines and front/back porch size etc.  At least on the d9800 I'm finding some logic to being able to customize these with some algorithm on each games HxW@R values  and getting some even more exact refresh rates and display sizes.  If anything it's helping me get closer to moving some of the logic of lrmc into the perl script and having control and understanding it.

Basically right now a command line like these w/modelines, some are somewhat shifted to the right slightly but defender most of these examples, just started but guessing you might get some insight into these values and modelines (basically input for the -custom command are for HFPORCH, HACTIVE, HSYNC, HTOTAL, VFPORCH, VACTIVE, VSYNC, VTOTAL)
Code: [Select]
# suprmrio  256x240x32@60.000000 - lrmc 256 240 60.000000  -v -n -custom 15250 40000 40 85 3000000 90000000 8 320 32 384 4 240 3 256 -sl -i
"256x240"  4.669440 256 264 288 304 240 244 247 256 -HSync -VSync
# mario  256x224x32@59.185606 - lrmc 256 224 59.185606  -v -n -custom 15250 40000 40 85 3000000 90000000 8 320 32 384 4 224 3 240 -sl -i
"280x240"  5.124000 280 288 320 336 240 244 247 257 -HSync -VSync
# puckman  384x288x32@60.606061 - lrmc 384 288 60.606061  -v -n -custom 15250 40000 40 85 3000000 90000000 8 384 32 512 4 288 3 312 -sl -i
"384x288"  9.681455 384 392 424 512 288 292 295 312 -HSync -VSync
# defender  296x240x32@60.096154 - lrmc 296 240 60.096154  -v -n -custom 15250 40000 40 85 3000000 90000000 8 296 32 384 4 240 3 256 -sl -i
"296x240"  5.907693 296 304 336 384 240 244 247 256 -HSync -VSync
# dkong  344x256x32@60.606061 - lrmc 344 256 60.606061  -v -n -custom 15250 40000 40 85 3000000 90000000 8 344 32 448 4 256 3 280 -sl -i
"344x256"  7.602425 344 352 384 448 256 260 263 280 -HSync -VSync
# dbz  384x256x32@55.000000 - lrmc 384 256 55.000000  -v -n -custom 15250 40000 40 85 3000000 90000000 8 384 32 512 4 256 3 288 -sl -i
"384x256"  8.110080 384 392 424 512 256 260 263 288 -HSync -VSync

I started doing this after trying as reference modelines in lrmc.conf the ones from Soft15Khz, which I admit when using those I got better values for the blanking stuff and only issue was that on some modelines the screen has side boarders and not filling it fully horizontally.  So from there , since it's sort of the opposite of what lrmc does with the d9800 values it uses by default, figured this could hopefully help find the logic in between the two.  So far at least I've been able to work all vertical values logically and seem good, the horizontal is slowly getting to work correctly on more and more modelines horzontal resolution sizes.  Seems those are more up in the air which on the vertical side I just had a somewhat simple way of calculating and there's a lot more varying horizontal sizes to adjust for.
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #126 on: November 07, 2010, 12:52:22 pm »
I am thinking of building all this stuff myself as I'm definitely getting interested in Linux and I want to test it directly. I've seen the readme is focused on Gentoo, is it a good way to start? Any advices on distributions or packages to start with?


Sounds great, If you know about building ubuntu packages would be interesting to get a kernel build package with the patch.  I'll look into this, I'm using the newest Ubuntu now on my desktop system as of the last few days and should help me be able to do things like that too.  I'm guessing it'll be a good combination using the newest Ubuntu and some modified packages to support arcade monitors, which is quite exciting since it sounds like a lot easier than my previous thoughts on how to make this work for people with the least amount of knowing details of compiling things and rebuilding parts of the system.
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #127 on: November 07, 2010, 05:33:00 pm »
Sounds like Ubuntu might just be  a good way to start, creating a dpkg of the ubuntu kernel with the patch applied already would make it a super simple way to do this since in Gentoo it's in a  sense like building your own Linux distribution but with everything ready to be put onto the partition.  

I'll look into building a patched ubuntu kernel package.

I'll have a look at Ubuntu, I've been tempted to try it before and now I have a good reason.

Also I'm currently experimenting with a command line option I added to lrmc which directly feeds the variables it uses to calculate a display structure for the modeline generation.  It's giving me a quick way to fiddle around with the settings of active/total lines and front/back porch size etc.  At least on the d9800 I'm finding some logic to being able to customize these with some algorithm on each games HxW@R values  and getting some even more exact refresh rates and display sizes.  If anything it's helping me get closer to moving some of the logic of lrmc into the perl script and having control and understanding it.

Basically right now a command line like these w/modelines, some are somewhat shifted to the right slightly but defender most of these examples, just started but guessing you might get some insight into these values and modelines (basically input for the -custom command are for HFPORCH, HACTIVE, HSYNC, HTOTAL, VFPORCH, VACTIVE, VSYNC, VTOTAL)

I started doing this after trying as reference modelines in lrmc.conf the ones from Soft15Khz, which I admit when using those I got better values for the blanking stuff and only issue was that on some modelines the screen has side boarders and not filling it fully horizontally.  So from there , since it's sort of the opposite of what lrmc does with the d9800 values it uses by default, figured this could hopefully help find the logic in between the two.  So far at least I've been able to work all vertical values logically and seem good, the horizontal is slowly getting to work correctly on more and more modelines horzontal resolution sizes.  Seems those are more up in the air which on the vertical side I just had a somewhat simple way of calculating and there's a lot more varying horizontal sizes to adjust for.

As you have seen vertical and horizontal values can be worked out separately and be tied up later by the dotclock value. Horizontal values are a bit more tricky to calculate than vertical ones. All approaches I've seen (included AdvanceMame and lrmc I believe) use reference modelines or simply proportions among hactive/htotal/porches. This is a botch, that can work more ore less ok in many situations, but you don't have full control of the results and sometimes it may fail to produce a good modeline. Using that method, you need ad hoc reference modelines for each hfreq, which is not good at all.

In order to get rid of reference modelines, we need to know the right values of our monitor's front and back porches and sync pulse. These values are given in µs. If we are able to get modelines that produce these values, then we'll solve all our horizontal sizing and centering for any resolution. These are the ones I use with my monitor (Hantarex 9110) that could be good for any lowres monitor or TV:

   FrontPorch = 2.0
   SyncPulse = 4.7
   BackPorch = 8.0

These values are very similar to the ones used with standard NTSC/PAL signals, except for the porches that are a little bit bigger. The reason is that TVs were designed to work with a significant overscan, and if we used the same values we would have a chopped picture on the sides.

Second, we must know that horizontal timings are programmed using 'characters', not pixels. Characters are a group of 8 horizontal pixels. That's why all horizontal values must use 8-multiples. But this introduces a serious limitation in precision for horizontal calculations, as the picture can only be shifted right or left by 8 pixel jumps. So with really low resolutions, it may be difficult to center the picture properly, as normally it may be either too shifted to the right or to the left. The only way to solve this is to increase horizontal total and recenter the picture with bigger margins. Another issue with this is that if calculations are considered 'continuous', then when translating them to these 'discrete' character elements, the rounding to 8 can produce porch values that are too low, or even worse, sync pulses that are too short. So we need to check the output values against some minimums in order to accept them, mine are:

   FrontPorchMin = 1.8
   SyncPulseMin = 4.5
   BackPorchMin = 7.8

Let's have a look at one of your modelines and calculate the values directly:

"384x256"  8.110080 384 392 424 512 256 260 263 288 -HSync -VSync

hs = ( 392 - 384 ) / 8 = 1 (front porch in chars)
he = ( 424 - 392 ) / 8 = 4 (sync pulse in chars)
ht = ( 512 - 424 ) / 8 = 11 (back porch in chars)

LineTime = 1 / ( 8110080 / 512 ) * 1000000 = 63.1313 µs (this is the length of a single line)
CharTime = 63.1313 / ( 512 / 8 ) = 0.9864 µs (this is the length of a single character)

FrontPorch = hs * 0.9864 = 0.9864 ( < FrontPorchMin !)
SyncPulse = he * 0.9864 = 3.9457 ( < SyncPulseMin ! )
BackPorch = ht * 0.9864 = 10.8507 ( way bigger than needed BackPorch ! )

I haven't tested this modeline, but it's clear it would be shifted to the right on my monitor. Sync pulse is short, and though my monitor would synchronize with no problem, it's likely some monitors would not, as it's below the standard. We should change the horizontal values like this:

"384x256"  8.110080 384 400 440 512 256 260 263 288 -HSync -VSync

... to get 1.97, 4.93, 8.88 respectively.

We tend to use modelines with bigger back porches as its closer to NTSC/PAL standards, however arcade monitors are very flexible. All we need is to keep our values as constant as possible from one modeline to another, and they will all be centered. This method allows as to shift all resolutions to the right/left at the same time by re-calculating them using new porches.

This is the easy part. Now we need the opposite: to get the modeline values from the porch/sync ones. These calculations need to be iterated as CharTime changes each time we change HTotal. I'll show the algorithm I use. This is used once you have calculated the vertical part and know your Hfreq (note that only input values required are Hfreq and xres, the rest are output values):

Code: [Select]
SUB ModelineGetLineParams ( hfreq AS SINGLE, xres AS LONG, hhh AS LONG, hhi AS LONG, hhf AS LONG, hht AS LONG )

  LOCAL hh, hs, he, ht AS LONG
  LOCAL LineTime, CharTime, NewCharTime AS SINGLE

  LineTime = 1 / hfreq * 1000000

  hh = ROUND ( xres / 8, 0 )
  hs = 1
  he = 1
  ht = 1

  DO
    CharTime = LineTime / ( hh + hs + he + ht )
    IF hs * CharTime < FrontPorchMin OR ABS ( ( hs + 1 ) * CharTime - FrontPorch ) < ABS ( hs * CharTime - FrontPorch ) THEN INCR hs
    IF he * CharTime < SyncPulseMin OR ABS ( ( he + 1 ) * CharTime - SyncPulse ) < ABS ( he * CharTime - SyncPulse ) THEN INCR he
    IF ht * CharTime < BackPorchMin OR ABS ( ( ht + 1 ) * CharTime - BackPorch ) < ABS ( ht * CharTime - BackPorch ) THEN INCR ht
    NewCharTime = LineTime / ( hh + hs + he + ht )
  LOOP UNTIL NewCharTime = CharTime

  hhh = hh * 8
  hhi = ( hh + hs ) * 8
  hhf = ( hh + hs + he ) * 8
  hht = ( hh + hs + he + ht ) * 8

END SUB

What you need to know is if your monitor is either truly continuous in the whole hfreq range (then you shoud find out the right porches for the highest and the lowest frequency and then interpolate) or it works by intervals where fixed porches and pulses need to be used. Mine uses fixed values in the whole range (15.625-16.700) so I predefine FrontPorch/SyncPulse/BackPorch as globals right from a ini file, but you may need to calculate them depending of mode's hfreq or have a table (similar of what you've been doing with those intervals). I hope this can be of help.

« Last Edit: November 07, 2010, 05:45:20 pm by Calamity »
Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #128 on: November 07, 2010, 08:44:57 pm »
Sounds like Ubuntu might just be  a good way to start, creating a dpkg of the ubuntu kernel with the patch applied already would make it a super simple way to do this since in Gentoo it's in a  sense like building your own Linux distribution but with everything ready to be put onto the partition.  

I'll look into building a patched ubuntu kernel package.

I'll have a look at Ubuntu, I've been tempted to try it before and now I have a good reason.

Also I'm currently experimenting with a command line option I added to lrmc which directly feeds the variables it uses to calculate a display structure for the modeline generation.  It's giving me a quick way to fiddle around with the settings of active/total lines and front/back porch size etc.  At least on the d9800 I'm finding some logic to being able to customize these with some algorithm on each games HxW@R values  and getting some even more exact refresh rates and display sizes.  If anything it's helping me get closer to moving some of the logic of lrmc into the perl script and having control and understanding it.

Basically right now a command line like these w/modelines, some are somewhat shifted to the right slightly but defender most of these examples, just started but guessing you might get some insight into these values and modelines (basically input for the -custom command are for HFPORCH, HACTIVE, HSYNC, HTOTAL, VFPORCH, VACTIVE, VSYNC, VTOTAL)

I started doing this after trying as reference modelines in lrmc.conf the ones from Soft15Khz, which I admit when using those I got better values for the blanking stuff and only issue was that on some modelines the screen has side boarders and not filling it fully horizontally.  So from there , since it's sort of the opposite of what lrmc does with the d9800 values it uses by default, figured this could hopefully help find the logic in between the two.  So far at least I've been able to work all vertical values logically and seem good, the horizontal is slowly getting to work correctly on more and more modelines horzontal resolution sizes.  Seems those are more up in the air which on the vertical side I just had a somewhat simple way of calculating and there's a lot more varying horizontal sizes to adjust for.

As you have seen vertical and horizontal values can be worked out separately and be tied up later by the dotclock value. Horizontal values are a bit more tricky to calculate than vertical ones. All approaches I've seen (included AdvanceMame and lrmc I believe) use reference modelines or simply proportions among hactive/htotal/porches. This is a botch, that can work more ore less ok in many situations, but you don't have full control of the results and sometimes it may fail to produce a good modeline. Using that method, you need ad hoc reference modelines for each hfreq, which is not good at all.

In order to get rid of reference modelines, we need to know the right values of our monitor's front and back porches and sync pulse. These values are given in µs. If we are able to get modelines that produce these values, then we'll solve all our horizontal sizing and centering for any resolution. These are the ones I use with my monitor (Hantarex 9110) that could be good for any lowres monitor or TV:

   FrontPorch = 2.0
   SyncPulse = 4.7
   BackPorch = 8.0

These values are very similar to the ones used with standard NTSC/PAL signals, except for the porches that are a little bit bigger. The reason is that TVs were designed to work with a significant overscan, and if we used the same values we would have a chopped picture on the sides.

Second, we must know that horizontal timings are programmed using 'characters', not pixels. Characters are a group of 8 horizontal pixels. That's why all horizontal values must use 8-multiples. But this introduces a serious limitation in precision for horizontal calculations, as the picture can only be shifted right or left by 8 pixel jumps. So with really low resolutions, it may be difficult to center the picture properly, as normally it may be either too shifted to the right or to the left. The only way to solve this is to increase horizontal total and recenter the picture with bigger margins. Another issue with this is that if calculations are considered 'continuous', then when translating them to these 'discrete' character elements, the rounding to 8 can produce porch values that are too low, or even worse, sync pulses that are too short. So we need to check the output values against some minimums in order to accept them, mine are:

   FrontPorchMin = 1.8
   SyncPulseMin = 4.5
   BackPorchMin = 7.8

Let's have a look at one of your modelines and calculate the values directly:

"384x256"  8.110080 384 392 424 512 256 260 263 288 -HSync -VSync

hs = ( 392 - 384 ) / 8 = 1 (front porch in chars)
he = ( 424 - 392 ) / 8 = 4 (sync pulse in chars)
ht = ( 512 - 424 ) / 8 = 11 (back porch in chars)

LineTime = 1 / ( 8110080 / 512 ) * 1000000 = 63.1313 µs (this is the length of a single line)
CharTime = 63.1313 / ( 512 / 8 ) = 0.9864 µs (this is the length of a single character)

FrontPorch = hs * 0.9864 = 0.9864 ( < FrontPorchMin !)
SyncPulse = he * 0.9864 = 3.9457 ( < SyncPulseMin ! )
BackPorch = ht * 0.9864 = 10.8507 ( way bigger than needed BackPorch ! )

I haven't tested this modeline, but it's clear it would be shifted to the right on my monitor. Sync pulse is short, and though my monitor would synchronize with no problem, it's likely some monitors would not, as it's below the standard. We should change the horizontal values like this:

"384x256"  8.110080 384 400 440 512 256 260 263 288 -HSync -VSync

... to get 1.97, 4.93, 8.88 respectively.

We tend to use modelines with bigger back porches as its closer to NTSC/PAL standards, however arcade monitors are very flexible. All we need is to keep our values as constant as possible from one modeline to another, and they will all be centered. This method allows as to shift all resolutions to the right/left at the same time by re-calculating them using new porches.

This is the easy part. Now we need the opposite: to get the modeline values from the porch/sync ones. These calculations need to be iterated as CharTime changes each time we change HTotal. I'll show the algorithm I use. This is used once you have calculated the vertical part and know your Hfreq (note that only input values required are Hfreq and xres, the rest are output values):

Code: [Select]
SUB ModelineGetLineParams ( hfreq AS SINGLE, xres AS LONG, hhh AS LONG, hhi AS LONG, hhf AS LONG, hht AS LONG )

  LOCAL hh, hs, he, ht AS LONG
  LOCAL LineTime, CharTime, NewCharTime AS SINGLE

  LineTime = 1 / hfreq * 1000000

  hh = ROUND ( xres / 8, 0 )
  hs = 1
  he = 1
  ht = 1

  DO
    CharTime = LineTime / ( hh + hs + he + ht )
    IF hs * CharTime < FrontPorchMin OR ABS ( ( hs + 1 ) * CharTime - FrontPorch ) < ABS ( hs * CharTime - FrontPorch ) THEN INCR hs
    IF he * CharTime < SyncPulseMin OR ABS ( ( he + 1 ) * CharTime - SyncPulse ) < ABS ( he * CharTime - SyncPulse ) THEN INCR he
    IF ht * CharTime < BackPorchMin OR ABS ( ( ht + 1 ) * CharTime - BackPorch ) < ABS ( ht * CharTime - BackPorch ) THEN INCR ht
    NewCharTime = LineTime / ( hh + hs + he + ht )
  LOOP UNTIL NewCharTime = CharTime

  hhh = hh * 8
  hhi = ( hh + hs ) * 8
  hhf = ( hh + hs + he ) * 8
  hht = ( hh + hs + he + ht ) * 8

END SUB

What you need to know is if your monitor is either truly continuous in the whole hfreq range (then you shoud find out the right porches for the highest and the lowest frequency and then interpolate) or it works by intervals where fixed porches and pulses need to be used. Mine uses fixed values in the whole range (15.625-16.700) so I predefine FrontPorch/SyncPulse/BackPorch as globals right from a ini file, but you may need to calculate them depending of mode's hfreq or have a table (similar of what you've been doing with those intervals). I hope this can be of help.



Cool, this is great, I can see what your saying about the horizontal issue and makes total sense from what I am having to deal with.  I do have the timing values of the WG D9800/D9400 Monitors, they have 5 standard factory pre-set timing modes.  They can be set to any values between 15.75-40Khz hor and 40-100Hz ver, at the factory they have the 15.725, 24.395, 31.469 another 31.469 and a 37.879 modes.  From what the engineer said, any values for H/V freq can be used in those bigger ranges, but I'm guessing the values you mention are the key in using within each range.  The CGA mode ranges are close to yours somewhat, 2.187, 4.688, 6.719, EGA mode ranges are 2.910, 3.000, 4.440, VGA .636, 3.813, 1.906, second VGA mode the same which I guess it's extended and a 720x400 size for it compared to 640x480 on the first VGA mode, and SVGA 1.000, 3.200, 2.200.   So I'm not totally sure how to choose which values besides just the closest Hfreq to one of the preset modes, like when in the 17-19Khz Horz range for the 288 line pacman resolution at 60.61Hz.  That one looks good already though, so seem to be doing mostly right with what I've done but then it's mostly a few vertical games and a fewer odd ones like the one you pointed out (dbz) that it's shifted to one side or the other of the screen (although compared to what I was doing it's much better than before).  I'm just surprised with the one single display setting line I input now, I can mostly get games all looking decent, compared to the way lrmc usually works with the d9200 and d9800 having multiple display settings, since I guess I'm calculating the display setting more dynamically and vertical looks good on all games so it's now just the horizontal.

I converted your code/function for the horizontal calculation into perl, made a little program I ran and tested values with and looks good.  I was thinking about running things through lrmc twice, once I got the the basic resolution, but this makes more sense and probably what I was thinking would have never worked right.  I am guessing that after running through lrmc to calculate the basic resolution, this would be used to fixup the horizontal settings. 

The only thing odd is my perl script gives the last value as 504 instead of 512 for the total, basically  "384 400 440 504" for horizontal, maybe a rounding issue in perl?  Here's the perl program created from your function:
Code: [Select]
#!/usr/bin/perl
#
#
use POSIX;
use Getopt::Long;

my $FrontPorch = 2.187;
my $SyncPulse  = 4.688;
my $BackPorch  = 6.719;

my $HFreq = "15840";
my $HRes  = "384";

my $help    = 0;
my $debug   = 0;

my $result = GetOptions (
                "help|h" => \$help,
                "debug|d" => \$debug,
                "hfreq|hf=s" => \$HFreq,
                "hres|hr=s" => \$HRes,
                "fp=s" => \$FrontPorch,
                "sp=s" => \$SyncPulse,
                "bp=s" => \$BackPorch,
);

if ($help) {
        print "Usage:\n";
        print "  -hf    Horizontal Frequency\n";
        print "  -hr    Horizontal Resolution\n";
        print "  -fp    FrontPorch\n";
        print "  -sp    SyncPulse\n";
        print "  -bp    BackPorch\n";
        exit 0;
}

my $FrontPorchMin = sprintf("%.2f", ($FrontPorch - .20));
my $SyncPulseMin  = sprintf("%.2f", ($SyncPulse - .20));
my $BackPorchMin  = sprintf("%.2f", ($BackPorch - .20));

my $output = ModelineGetLineParams($HFreq, $HRes);

print "$output\n";

exit 0;


sub ModelineGetLineParams() {
  my $hfreq = shift(@_); # SINGLE
  my $xres  = shift(@_); #LONG 
  my $hhh = 0; # LONG
  my $hhi = 0;
  my $hhf = 0;
  my $hht = 0;

  my $hh, $hs, $he, $ht; # LONG
  my $LineTime, $CharTime, $NewCharTime; #  SINGLE

  $LineTime = 1 / $hfreq * 1000000;
  $LineTime = sprintf("%.4f", $LineTime);

  $hh = ceil( ($xres / 8) );
  $hs = 1;
  $he = 1;
  $ht = 1;

  if ($debug) {
        print "Input hfreq: $hfreq xres: $xres LineTime: $LineTime hh: $hh\n";
  }

  do {
    $CharTime = $LineTime / ( $hh + $hs + $he + $ht );
    if ((($hs * $CharTime) < $FrontPorchMin) ||
        (abs(( $hs + 1 ) * $CharTime - $FrontPorch ) < abs( $hs * $CharTime - $FrontPorch ))) {
                $hs++;
    }
    if ((($he * $CharTime) < $SyncPulseMin) ||
        (abs(( $he + 1 ) * $CharTime - $SyncPulse ) < abs( $he * $CharTime - $SyncPulse ))) {
                $he++;
    }
    if ((($ht * $CharTime) < $BackPorchMin) ||
        (abs(( $ht + 1 ) * $CharTime - $BackPorch ) < abs( $ht * $CharTime - $BackPorch ))) {
                $ht++;
    }
    $NewCharTime = $LineTime / ( $hh + $hs + $he + $ht );
    if ($debug) {
      print "CharTime: $CharTime NewCharTime: $NewCharTime LineTime: $LineTime hh: $hh hs: $hs he: $he ht: $ht\n";
    }
  } while ($NewCharTime != $CharTime);
  # LOOP UNTIL NewCharTime = CharTime

  $hhh = $hh * 8;
  $hhi = ( $hh + $hs ) * 8;
  $hhf = ( $hh + $hs + $he ) * 8;
  $hht = ( $hh + $hs + $he + $ht ) * 8;

  return "$hhh $hhi $hhf $hht";
}

It's great though to now have an entry point into your code from this, and start figuring out how to make the same calculations your talking about instead of trusting lrmc which definitely sounds like it causes they issues your talking about and I'm seeing because of use of reference modelines. 

I've attached the full set of specs for the D9400/9800 monitors, for the first time I see how the values are directly able to calculate the modlines, thanks for tying this together into that.  I've been wanting to be able to use those values somehow and didn't realize how they translated to the actual ones but now see that the character conversion makes them make sense.
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

elvis

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 1154
  • Last login:April 13, 2023, 05:31:03 pm
  • penguin poker
    • StickFreaks
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #129 on: November 08, 2010, 07:12:17 am »
I'll look into building a patched ubuntu kernel package.  
Install a package called "kernel-package" and then read the man file on "kpkg".  It makes building custom kernel packages a piece of cake.

I'm sure there's an equivalent in RPM-based distros, but kpkg is the way to go in Debian, Ubuntu and the various derivatives.

Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #130 on: November 08, 2010, 07:46:30 am »
The only thing odd is my perl script gives the last value as 504 instead of 512 for the total, basically  "384 400 440 504" for horizontal, maybe a rounding issue in perl?  Here's the perl program created from your function:

Your script is working fine. It gives 504 instead of 512 because your entering 6.719 for the back porch, smaller than 8.88 of the modeline we used as sample and I modified by hand. I'm happy you could translate it into perl!

I've attached the full set of specs for the D9400/9800 monitors, for the first time I see how the values are directly able to calculate the modlines, thanks for tying this together into that.  I've been wanting to be able to use those values somehow and didn't realize how they translated to the actual ones but now see that the character conversion makes them make sense.

Precious information. If you look at VGA_m3 and VGA_m2 they are much the same, horizontal values are equal so you may use just one interval for both modes. Only difference is vertical porches. I'm gessing your monitor has a sort of auto-adjust mechanism, and it's separating 400 and 480 vertical resolutions to properly adjust vertical amplitude, so both of them fill the screen.

Appart from that, your decision of which interval to use should be hfreq-driven, the closest to the reference one for the interval may be a good first approach, but there must be a jump somewhere in between 15.725 and 24.394, (etc.) where the respective values of each interval should apply (unless they are continuous and interpolated that would be very strange). Without more info, the only way to establish that point is by experimenting.
Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #131 on: November 08, 2010, 07:47:33 am »
I'll look into building a patched ubuntu kernel package.  
Install a package called "kernel-package" and then read the man file on "kpkg".  It makes building custom kernel packages a piece of cake.

I'm sure there's an equivalent in RPM-based distros, but kpkg is the way to go in Debian, Ubuntu and the various derivatives.

Thanks! I'll have a look at this!
Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #132 on: November 08, 2010, 09:36:30 am »
I'll look into building a patched ubuntu kernel package.  
Install a package called "kernel-package" and then read the man file on "kpkg".  It makes building custom kernel packages a piece of cake.

I'm sure there's an equivalent in RPM-based distros, but kpkg is the way to go in Debian, Ubuntu and the various derivatives.

Thanks! I'll have a look at this!


I've actually just built a ubuntu kernel package last night, it's for amd64 though and I'm now trying to figure out how to cross compile one for 32 bit processors.  I haven't given it a test though, guessing it should work but of course will need to add the video=640x480c option into grub.cfg manually (not sure yet how to build that into the install, seems they are vague about that part).  I'm looking at testing it, and cleaning up the build of it and uploading it my sourceforge page.  So looks like this should make it pretty easy on ubuntu to get things working on an arcade monitor, hopefully the X Windows version and the 2.6.37-rc1 play together well.

I sort of plugged in that function to replace the horizontal values in the modeline after the vertical ones are created with lrmc.  It does align things back up horizontally but I now see that partly the original modeline values for the custom one I'm doing have the too small across the screen issue.  I will look more at your code and try to get the vertical calculation stuff figured out to go along with it, so possibly can fully escape the need for lrmc.  I'm right now just dividing up the range of horizontal freq seeing that there's about 8 between like 15 - 23 and between 23 - 31 and 31 - 37, roughly at least, and so having a 8 Khz range centered on each of those 15-19,20-27,28-35,36-40 values for now seems to work from what I can tell.

Also when I calculate, it gives a new total horizontal lines, and I'm finding that if I recalculate the dotclock and use that it still matches the vertical refresh I was aiming at.  Is that normal, and expected, or will it probably only match correctly if I start doing the vertical calculations with the horizontal ones (or is that another part of your code, shifting around the dotclock to adjust that vertical refresh rate).  Looks exciting though, glad to start seeing some of the calculating able to happen outside lrmc, even though lrmc is doing pretty good this has much more potential actually using the monitors values and building a database of different monitor values would be interesting.     
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #133 on: November 08, 2010, 10:39:17 am »
Also when I calculate, it gives a new total horizontal lines, and I'm finding that if I recalculate the dotclock and use that it still matches the vertical refresh I was aiming at.  Is that normal, and expected, or will it probably only match correctly if I start doing the vertical calculations with the horizontal ones (or is that another part of your code, shifting around the dotclock to adjust that vertical refresh rate).  Looks exciting though, glad to start seeing some of the calculating able to happen outside lrmc, even though lrmc is doing pretty good this has much more potential actually using the monitors values and building a database of different monitor values would be interesting.     

It's a must to recalculate the dotclock to match the vfreq you was aiming at the beginning, otherwise the hfreq premise used by the above function wouldn't be right (as vfreq and hfreq are related). Vertical porches and pulses are not affected by this.

The logic I use is this:

Calculate vertical values from required Vfreq -> total number of lines (Hfreq) -> horizontal values (Htotal) -> dotclock

Actual calculations for the whole modeline are more straight-forward than the ones I do in my modeline function, that is a bit twisted to account for an issue with actual dotclocks that cannot adopt any value we imagine, but only some discrete ones, that I keep in a table, however you may ignore this by now and build the modeline function without that, as it is only there to improve accuracy. Later today I'll paste the function with some comments to explain it.

Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #134 on: November 08, 2010, 05:17:14 pm »
This is the function I use, I've added some comments:

Code: [Select]
FUNCTION ModelineCreate ( BYVAL xres AS LONG, BYVAL yres AS LONG, BYVAL vfreq AS SINGLE, BYVAL rotation AS LONG, index AS LONG ) AS LONG

  LOCAL i, j, result, interlace, margen, DotClockIdx AS LONG
  LOCAL hhh, hhi, hhf, hht, newHhh, newHhi, newHhf, newHht, vvv, vvi, vvf, vvt, vIncr, vfreqLabel AS LONG
  LOCAL hfreq, Dotclock, DotclockReq, vvtIni, VBlankLines, diff, newDiff, newVfreq, hfreqReal, vfreqReal AS SINGLE

' We set default 'interlace' to 1 (no interlace). When set to 2 it means interlace is on. I use these values as they are
' useful for calculations, instead of 0, 1.

  INCR interlace

' This part is just to filter max and min resolutions, hfreq and vfreq values to keep them inside our monitor limits.
' It also handles vertical games (rotated resolutions). But its focused on lowres monitors with some hardcoded conditionals,
' so you may want to modify things to adapt it to multifrequency monitors. However, this should better be kept outside
' this function.

  IF xres < XresMin THEN xres = XresMin : result = result OR %SimilarRes
  IF yres < YresMin THEN yres = YResMin : result = result OR %SimilarRes

  IF rotation = 1 THEN VerticalToHorizontal ( xres, yres )

  IF vfreq < VfreqMin THEN
    IF vfreq * 2 <= VfreqMax THEN
      vfreq = vfreq * 2
      result = result OR %DoubleVfreq
    ELSE
      vfreq = VfreqMin
    END IF
  ELSEIF vfreq > VfreqMax THEN
     vfreq = VfreqMax
  END IF

  IF yres > ActiveLinesLimit AND Rotation = 0 THEN
    interlace = 2
    result = result OR %InterlacedRes
    IF yres < VirtualLinesLimit THEN ResVirtualize ( xres, yres, vfreq, hfreq ) : result = result OR %VirtualizedRes
  END IF

' here we start calculating an estimation of hfreq required for the mode, and check if it exceeds our monitor's limits.

  hfreq = vfreq * yres / ( interlace * ( 1 - vfreq * VerticalBlank ) )

  IF hfreq < HfreqMin THEN
    hfreq = HfreqMin
  ELSEIF hfreq > HfreqMax THEN
    IF yres > ActiveLinesLimit THEN
      ResVirtualize ( xres, yres, vfreq, hfreq )
      interlace = 2
      result = result OR %VirtualizedRes
    ELSE
      hfreq = HfreqMax
      VBlankLines = ROUND ( hfreq * VerticalBlank, 0 )
      vfreq = hfreq / ( yres / interlace + VBlankLines )
      result = result OR %BadVfreq
    END IF
  END IF

' Now, we need to know the minimum integer number of total lines needed to produce a mode that matches vfreq within
' our hfreq limits (vvtIni)

  vvtIni = ROUND ( hfreq / vfreq, 0 ) + IIF ( interlace = 2, 0.5, 0 )
  WHILE vfreq * vvtIni < HfreqMin - HfreqTolerance
    INCR vvtIni
  WEND

' Next block is used to get horizontal values and dotclock. This version uses an iterated loop and a dotclock table for
' accuracy, but it's not necessary and can be simplified like this (not tested):
'
'   hfreq = vfreq * vvtIni
'   ModelineGetLineParams ( hfreq, xres, Hhh, Hhi, Hhf, Hht )
'   DotClockReq = hfreq * Hht
'
' (notice hfreq is recalculated here from our integer vvtIni)

  FOR i = 0 TO Iterations
    hfreq = vfreq * ( vvtIni + i )
    IF hfreq <= HfreqMax + HfreqTolerance THEN
      ModelineGetLineParams ( hfreq, xres, newHhh, newHhi, newHhf, newHht )
      DotClockReq = hfreq * newHht
      ARRAY SCAN DotClockTable(), >= DotClockReq, TO j
      IF ABS ( DotClockTable( j - 1 ) - DotClockReq ) < ABS ( DotclockTable( j ) - DotClockReq ) THEN DECR j
      newVfreq = DotClockTable ( j ) / ( ( vvtIni + i ) * newHht )
      newDiff = ABS ( newVfreq - vfreq )
      IF newDiff < Diff OR Diff = 0 THEN
        hhh = newHhh : hhi = newHhi : hhf = NewHhf : hht = NewHht
        Diff = newDiff
        vIncr = i
        DotClockIdx = j
      END IF
    END IF
  NEXT

' Now we calculate the number of lines needed for vertical blanking. VerticalBlank is the time in µs our monitor needs
' to complete it's vertical retrace (front and back porches + sync pulses). I use 1280 µs for TVs and lowres monitors.
' Notice the 0.5 increment in case of interlace: this is used to make sure that vvt will be an uneven value if the mode
' is interlaced, otherwise our timings would be wrong as all interlaced modes have an uneven number of lines despite
' we set vvt as an even number.

  VBlankLines = INT ( hfreq * VerticalBlank ) + IIF ( interlace = 2, 0.5, 0 )

' Now we work out the vertical part of the modeline (forget about vIncr). We start with vvt and substract vvv and Vblanklines
' The rest is considered as fill in margins needed to achive the required vfreq, and we divide then by 2 (up and down margins
' are equal.
' For the sync pulse, 3 and 5 lines long pulses are hardcoded (progressive or interlaced) according to PAL standard, however
' this should be checked for higher frequencies
' Notice all calculations have beed done as 'progressive', and here we use the 'interlace' multiplier to get the right
' values in case of interlace

  vvv = yres
  vvt = ( vvtIni + vIncr ) * interlace
  margen = vvt - vvv - VBlankLines * interlace
  vvi = vvv + ROUND ( margen / 2, 0 ) + 1 * interlace
  vvf = vvi + IIF ( interlace = 2, 5, 3 )

' That's all, the rest is for storing values, etc.

  DotClock = DotClockIdx * 10
  hfreqReal = DotClockTable ( DotClockIdx ) / hht
  vfreqReal = hfreqReal / vvt * interlace
  vfreqLabel = ROUND ( vfreqReal, 0 )

  Mode(index).x = hhh
  Mode(index).y = vvv
  Mode(index).vfreq = vfreqReal

  Mode(index).Xlabel = hhh
  Mode(index).Ylabel = vvv
  Mode(index).Vlabel = vfreqLabel

  Mdln(index).dotclockReal = DotClockTable ( DotClockIdx )
  Mdln(index).dotclock = DotClock
  Mdln(index).hhh = hhh
  Mdln(index).hhi = hhi
  Mdln(index).hhf = hhf
  Mdln(index).hht = hht
  Mdln(index).vvv = vvv
  Mdln(index).vvi = vvi
  Mdln(index).vvf = vvf
  Mdln(index).vvt = vvt
  Mdln(index).interlace = interlace

  FUNCTION = result

END FUNCTION
Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #135 on: November 08, 2010, 05:43:25 pm »
This is the function I use, I've added some comments:

Code: [Select]
FUNCTION ModelineCreate ( BYVAL xres AS LONG, BYVAL yres AS LONG, BYVAL vfreq AS SINGLE, BYVAL rotation AS LONG, index AS LONG ) AS LONG

  LOCAL i, j, result, interlace, margen, DotClockIdx AS LONG
  LOCAL hhh, hhi, hhf, hht, newHhh, newHhi, newHhf, newHht, vvv, vvi, vvf, vvt, vIncr, vfreqLabel AS LONG
  LOCAL hfreq, Dotclock, DotclockReq, vvtIni, VBlankLines, diff, newDiff, newVfreq, hfreqReal, vfreqReal AS SINGLE

' We set default 'interlace' to 1 (no interlace). When set to 2 it means interlace is on. I use these values as they are
' useful for calculations, instead of 0, 1.

  INCR interlace

' This part is just to filter max and min resolutions, hfreq and vfreq values to keep them inside our monitor limits.
' It also handles vertical games (rotated resolutions). But its focused on lowres monitors with some hardcoded conditionals,
' so you may want to modify things to adapt it to multifrequency monitors. However, this should better be kept outside
' this function.

  IF xres < XresMin THEN xres = XresMin : result = result OR %SimilarRes
  IF yres < YresMin THEN yres = YResMin : result = result OR %SimilarRes

  IF rotation = 1 THEN VerticalToHorizontal ( xres, yres )

  IF vfreq < VfreqMin THEN
    IF vfreq * 2 <= VfreqMax THEN
      vfreq = vfreq * 2
      result = result OR %DoubleVfreq
    ELSE
      vfreq = VfreqMin
    END IF
  ELSEIF vfreq > VfreqMax THEN
     vfreq = VfreqMax
  END IF

  IF yres > ActiveLinesLimit AND Rotation = 0 THEN
    interlace = 2
    result = result OR %InterlacedRes
    IF yres < VirtualLinesLimit THEN ResVirtualize ( xres, yres, vfreq, hfreq ) : result = result OR %VirtualizedRes
  END IF

' here we start calculating an estimation of hfreq required for the mode, and check if it exceeds our monitor's limits.

  hfreq = vfreq * yres / ( interlace * ( 1 - vfreq * VerticalBlank ) )

  IF hfreq < HfreqMin THEN
    hfreq = HfreqMin
  ELSEIF hfreq > HfreqMax THEN
    IF yres > ActiveLinesLimit THEN
      ResVirtualize ( xres, yres, vfreq, hfreq )
      interlace = 2
      result = result OR %VirtualizedRes
    ELSE
      hfreq = HfreqMax
      VBlankLines = ROUND ( hfreq * VerticalBlank, 0 )
      vfreq = hfreq / ( yres / interlace + VBlankLines )
      result = result OR %BadVfreq
    END IF
  END IF

' Now, we need to know the minimum integer number of total lines needed to produce a mode that matches vfreq within
' our hfreq limits (vvtIni)

  vvtIni = ROUND ( hfreq / vfreq, 0 ) + IIF ( interlace = 2, 0.5, 0 )
  WHILE vfreq * vvtIni < HfreqMin - HfreqTolerance
    INCR vvtIni
  WEND

' Next block is used to get horizontal values and dotclock. This version uses an iterated loop and a dotclock table for
' accuracy, but it's not necessary and can be simplified like this (not tested):
'
'   hfreq = vfreq * vvtIni
'   ModelineGetLineParams ( hfreq, xres, Hhh, Hhi, Hhf, Hht )
'   DotClockReq = hfreq * Hht
'
' (notice hfreq is recalculated here from our integer vvtIni)

  FOR i = 0 TO Iterations
    hfreq = vfreq * ( vvtIni + i )
    IF hfreq <= HfreqMax + HfreqTolerance THEN
      ModelineGetLineParams ( hfreq, xres, newHhh, newHhi, newHhf, newHht )
      DotClockReq = hfreq * newHht
      ARRAY SCAN DotClockTable(), >= DotClockReq, TO j
      IF ABS ( DotClockTable( j - 1 ) - DotClockReq ) < ABS ( DotclockTable( j ) - DotClockReq ) THEN DECR j
      newVfreq = DotClockTable ( j ) / ( ( vvtIni + i ) * newHht )
      newDiff = ABS ( newVfreq - vfreq )
      IF newDiff < Diff OR Diff = 0 THEN
        hhh = newHhh : hhi = newHhi : hhf = NewHhf : hht = NewHht
        Diff = newDiff
        vIncr = i
        DotClockIdx = j
      END IF
    END IF
  NEXT

' Now we calculate the number of lines needed for vertical blanking. VerticalBlank is the time in µs our monitor needs
' to complete it's vertical retrace (front and back porches + sync pulses). I use 1280 µs for TVs and lowres monitors.
' Notice the 0.5 increment in case of interlace: this is used to make sure that vvt will be an uneven value if the mode
' is interlaced, otherwise our timings would be wrong as all interlaced modes have an uneven number of lines despite
' we set vvt as an even number.

  VBlankLines = INT ( hfreq * VerticalBlank ) + IIF ( interlace = 2, 0.5, 0 )

' Now we work out the vertical part of the modeline (forget about vIncr). We start with vvt and substract vvv and Vblanklines
' The rest is considered as fill in margins needed to achive the required vfreq, and we divide then by 2 (up and down margins
' are equal.
' For the sync pulse, 3 and 5 lines long pulses are hardcoded (progressive or interlaced) according to PAL standard, however
' this should be checked for higher frequencies
' Notice all calculations have beed done as 'progressive', and here we use the 'interlace' multiplier to get the right
' values in case of interlace

  vvv = yres
  vvt = ( vvtIni + vIncr ) * interlace
  margen = vvt - vvv - VBlankLines * interlace
  vvi = vvv + ROUND ( margen / 2, 0 ) + 1 * interlace
  vvf = vvi + IIF ( interlace = 2, 5, 3 )

' That's all, the rest is for storing values, etc.

  DotClock = DotClockIdx * 10
  hfreqReal = DotClockTable ( DotClockIdx ) / hht
  vfreqReal = hfreqReal / vvt * interlace
  vfreqLabel = ROUND ( vfreqReal, 0 )

  Mode(index).x = hhh
  Mode(index).y = vvv
  Mode(index).vfreq = vfreqReal

  Mode(index).Xlabel = hhh
  Mode(index).Ylabel = vvv
  Mode(index).Vlabel = vfreqLabel

  Mdln(index).dotclockReal = DotClockTable ( DotClockIdx )
  Mdln(index).dotclock = DotClock
  Mdln(index).hhh = hhh
  Mdln(index).hhi = hhi
  Mdln(index).hhf = hhf
  Mdln(index).hht = hht
  Mdln(index).vvv = vvv
  Mdln(index).vvi = vvi
  Mdln(index).vvf = vvf
  Mdln(index).vvt = vvt
  Mdln(index).interlace = interlace

  FUNCTION = result

END FUNCTION

This is great, I've been actually digging through that code today and so this is perfect and on time to help me figure out the deeper details of the interlacing and limits issues when out of bounds.  I've gotten the basic calculating working when the v/h freq's are in range and interlacing isn't required, screen sizes are in range, and it definitely is really looking amazing compared with lrmc.  I can actually calculate the resolution for mario brothers to exact original everything and it fills the screen and is perfect, never could do that with lrmc.

One question I have, have you any ideas how to also put in doublescan support, I can figure things out probably from looking at lrmc and seeing the difference between it and interlace.  From what I can tell you haven't got doublescan support in there, so I may try to add it for the games with 192 vertical resolutions.  Also I am figuring when things go into VGA/SVGA areas then there may be some issues there, but I am guessing the -Vsync and -Hsync are changed to be positive possibly when encountering a certain threshhold.

I so far have a pretty good perl hash and config format it reads to have one or more lines of the monitor parameters, ranges so with the d9800 I can have 4 ranges and have a basic way of going through and figuring out which range to use and starting to tie that into your checks to adapt to a d9800 monitor or other multi range ones.  I take it that the vertical front porch/sync/back porch values are really not necessary, so can throw those out or is there some use for them down the road to be extra accurate?  Sounds like your defaults then would work for most arcade monitors and then for ones with special needs or the d9800 that's where these config lines added with multiple ranges can be used.

Thanks again for all this information, hopefully have something in a few days at most, also hopefully have these ubuntu kernel packages built in a day or so.  They take forever to build, lots of modules.  I think I got it so it'll default to arcade mode when a monitor has no EDID so should make it easier to install and the grub.cfg editing for the video=640x480c line won't hopefully be as important or possibly not needed.  There will be a necessary module options config file though to turn off polling of the monitor, since that just makes the system slow from the arcade monitor lacking an EDID and it constantly harrassing it for one.
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #136 on: November 09, 2010, 02:03:44 am »
I have ubuntu kernel builds for 64 bit and 32 bit on the sourceforge project site now.  These are needing testing, I'm not sure how well they'll work but you'll definitely need to use the radeon.conf modprobe settings in the switchres.zip archive.  That file needs to be put into /etc/modprobe.d/, to stop polling.  Then I think by default it'll use 640x480 interlaced in arcade monitor compatible resolution, but if not it needs the /boot/grub/grub.cfg file to use the "video=640x480c" arg on the command line for the kernel.  When installing these, they will make themselves the default choice in the grub boot menu, but can choose the old kernel and uninstall them if they don't work.  Let me know how they work, hopefully they work right for the 32bit one and there's no other necessary config options that ubuntu uses (used the default config so would guess it's the same as their kernel, but sometimes distros get sort of customized builds unfortunately).

I have just about gotten the basic modeline generation being done in perl too, Thanks to Calamity for giving me the information/code for that to be possible.  It's definitely looking amazing, compared to what lrmc was doing, seems to be generating almost perfect modelines.  I've got it able to take the monitor parameters in the switchres.conf config but defaults to basic arcade monitor settings.  Would only need to set those I think if you have a d9800 or something, which I've got a default switchres.conf example file showing what is necessary.

So next release of switchres will definitely be a bit 'beta' testing, can still use lrmc with a command line option, but by default it now uses it's own perl logic to do the modeline stuff and will no longer need to worry about lrmc at all.  Hopefully I get that up here in a bit, I think it's ready but need to edit the readme files a little probably.
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .18)
« Reply #137 on: November 09, 2010, 02:34:23 am »
Version 0.18 - Dropped need for lrmc and Ubuntu kernel packages available
* Thanks to Calamity switchres no longer needs lrmc and generates modelines itself, which are way better than lrmc ever did.
* Now can output modelines just with switchres on the command line, like "switchres -calc 320 240 60.00" or for a specific game in mame "switchres -calcgame galaga".
* With new modeline creation, if you have anything more than an ordinary arcade monitor you'll need to put the specific parameters into the ~/switchres.conf file.  There's an example file included in the extras directory.
* Generally seems to produce a lot better results than before, can get exact resolutions now instead of rather odd ones that lrmc would produce.  With a d9800 monitor I can almost perfectly get every games resolution and refresh rate to exact specs.  I never could do that with lrmc.
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

elvis

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 1154
  • Last login:April 13, 2023, 05:31:03 pm
  • penguin poker
    • StickFreaks
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #138 on: November 09, 2010, 04:50:41 am »
I'll look into building a patched ubuntu kernel package.  
Install a package called "kernel-package" and then read the man file on "kpkg".  It makes building custom kernel packages a piece of cake.

I'm sure there's an equivalent in RPM-based distros, but kpkg is the way to go in Debian, Ubuntu and the various derivatives.

Thanks! I'll have a look at this!


I've actually just built a ubuntu kernel package last night, it's for amd64 though and I'm now trying to figure out how to cross compile one for 32 bit processors. 

I made a mistake above.  You want to run "man make-kpkg".

In there you'll find a flag called "--cross-compile" which will do exactly what you want.

Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #139 on: November 09, 2010, 06:22:42 am »
It's great you managed to get this working on a multrifrequency monitor! It's such a nice feeling when you know you're directly driving the electron beam ;)

I take it that the vertical front porch/sync/back porch values are really not necessary, so can throw those out or is there some use for them down the road to be extra accurate?  Sounds like your defaults then would work for most arcade monitors and then for ones with special needs or the d9800 that's where these config lines added with multiple ranges can be used.

Vertical porch/sync values you have are good to avoid hardcoding that 1280 µs value I use, which I took from this book (highly recommended):

http://books.google.es/books?id=u-3oFBzrQ0sC&pg=PA49&lpg=PA49&dq=fly-back+time+ms++tv+sync&source=bl&ots=PKl_u_8HKn&sig=l7S_AYEtoenKFEU0TnUzlNNOvhg&hl=es&ei=pd9lSsvyOYeenQOe9rXaDQ&sa=X&oi=book_result&ct=result&resnum=1#v=onepage&q&f=false

For instance, let us work out the values for your monitor's Mode 1. The ones we're interested in are B (sync pulse), C (back porch) and E (front porch). We'll convert the timings into lines:

B = 191 µs = 3 * 63.594 (length of a line) -> 3 lines
C = 190 µs = 3 * 63.594 (length of a line) -> 3 lines
E = 1018 µs = 16 * 63.594 (length of a line) -> 16 lines

VerticalBlank = 191 + 190 + 1018 = 1399 µs -> 22 lines

The same can be done for the rest of modes.
(it seems to me C and E values are swaped in that table but it does not matter now)*

In many modes, you may want to add extra lines to delay the video and get a lower vertical refresh that matches the one you want, those extra lines are the one I add like margins to C and E.

You may have notice that this is an ideal case, and as we move from that reference mode the length of the lines (in time) will vary slightly. As we can only use integers for the number of lines, we must check that the above values are respected, to do things right. However, I used hardcoded number of lines for vertical sync pulses as they are constant in the practical situations I've been working with, but in order to make this extensive for more monitors this should be done properly.

I unfortunately dropped doublescan support in my code because I never got it working with Catalyst drivers. However, I believe the only thing that needs to be done is to double the required dotclock for a single scan mode, and do all calculations as progressive (the modeline will be the same as if it was single scan, we just need to do DotClock * 2, and bear this in mind when we compute Vfreq, otherwise we would get Vfreq * 2 too).

By the way, did you check if those positive polarities in some modes are really needed or just recommended?

* Normally, vertical front porch, the one before sync pulse and right after visible video, is as short as one line, as we just need a small delay before we send the sync pulse to make the beam return to the top of the screen. On the other hand, back porch needs to be longer, because once the beam reaches the top it needs some time to stabilize itself before we can start drawing again.
« Last Edit: November 09, 2010, 06:43:24 am by Calamity »
Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Genres modeline generator and switchres dynamic modeline switcher (ver .17)
« Reply #140 on: November 10, 2010, 12:38:39 pm »
It's great you managed to get this working on a multrifrequency monitor! It's such a nice feeling when you know you're directly driving the electron beam ;)

I take it that the vertical front porch/sync/back porch values are really not necessary, so can throw those out or is there some use for them down the road to be extra accurate?  Sounds like your defaults then would work for most arcade monitors and then for ones with special needs or the d9800 that's where these config lines added with multiple ranges can be used.

Vertical porch/sync values you have are good to avoid hardcoding that 1280 µs value I use, which I took from this book (highly recommended):

http://books.google.es/books?id=u-3oFBzrQ0sC&pg=PA49&lpg=PA49&dq=fly-back+time+ms++tv+sync&source=bl&ots=PKl_u_8HKn&sig=l7S_AYEtoenKFEU0TnUzlNNOvhg&hl=es&ei=pd9lSsvyOYeenQOe9rXaDQ&sa=X&oi=book_result&ct=result&resnum=1#v=onepage&q&f=false

For instance, let us work out the values for your monitor's Mode 1. The ones we're interested in are B (sync pulse), C (back porch) and E (front porch). We'll convert the timings into lines:

B = 191 µs = 3 * 63.594 (length of a line) -> 3 lines
C = 190 µs = 3 * 63.594 (length of a line) -> 3 lines
E = 1018 µs = 16 * 63.594 (length of a line) -> 16 lines

VerticalBlank = 191 + 190 + 1018 = 1399 µs -> 22 lines

The same can be done for the rest of modes.
(it seems to me C and E values are swaped in that table but it does not matter now)*

In many modes, you may want to add extra lines to delay the video and get a lower vertical refresh that matches the one you want, those extra lines are the one I add like margins to C and E.

You may have notice that this is an ideal case, and as we move from that reference mode the length of the lines (in time) will vary slightly. As we can only use integers for the number of lines, we must check that the above values are respected, to do things right. However, I used hardcoded number of lines for vertical sync pulses as they are constant in the practical situations I've been working with, but in order to make this extensive for more monitors this should be done properly.

I unfortunately dropped doublescan support in my code because I never got it working with Catalyst drivers. However, I believe the only thing that needs to be done is to double the required dotclock for a single scan mode, and do all calculations as progressive (the modeline will be the same as if it was single scan, we just need to do DotClock * 2, and bear this in mind when we compute Vfreq, otherwise we would get Vfreq * 2 too).

By the way, did you check if those positive polarities in some modes are really needed or just recommended?

* Normally, vertical front porch, the one before sync pulse and right after visible video, is as short as one line, as we just need a small delay before we send the sync pulse to make the beam return to the top of the screen. On the other hand, back porch needs to be longer, because once the beam reaches the top it needs some time to stabilize itself before we can start drawing again.


I don't think the polarity values matter, at least up through VGA modes, in SVGA mode I think they might not matter but it might be a slightly better display with them positive.

I am trying to plug in those vertical values and it's odd, because basically when I use those I get the margen value less than 0, like -2 or more and it causes the whole calculation to get off and output is wider than it should be.  It's odd because it's a difference of .00128 vs .001399 or something and that seems to totally throw it off.  I'm still checking that, seeing why it's happening and if I'm missing something.  Also it's kind of tricky in the multi frequency case to use those, because the first calculation doesn't know which range it'll use, although in the cases I'm testing it's always the first CGA range anyways.  You values seem to be pretty much perfect that you used/hardcoded, always work great besides possibly a few lines too low in the 288 line high pacman case although all other games are perfect.

I'm wondering if there's  a bit more I'm missing needed to calculate the vertical values, than just changing that main verticalblank value.

Also doublescan support doesn't seem as important as I had thought, although still interested in it.  I now can get the native 192 high line resolutions which before lrmc wouldn't even do without using doublescan.  Although I think in other monitor types and possibly to get things a bit better in a few resolutions doublescan support would be good.  I'm still wanting to look into that, did a little, will have to start doing some tests and see if I can find how to put it into the logic of the calculations.

I'm making it so the -mon argument works again and can avoid having to put monitor details into the config unless it's not known already by the program, so will be more user friendly at least if it's a known monitor type.
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .18)
« Reply #141 on: November 10, 2010, 04:38:19 pm »
I think I somewhat figured out how to use the vertical timing values, required a bit more work but now actually improved the way things are calculated when having multiple ranges to check against.  I had to do some tricky moving of the checking of stuff, so that those values can be used to jumpstart the first calculations and think I figured out how to use them to calculate out the rest of the vertical modeline values.  It seems to be working, and centering the vertical picture now as well as it is centering the horizontal.  Do you know the timings of the vertical for other arcade monitors I could plug in and test with, I'm going to look around for some other values to see what they do to the modeline.  Part of the issue I think I had was, besides having to calculate the total lines with those values and starting hfreq value, was not running each of those line number values through int() so they were adding up too large of total lines.  From what I could tell I had 2 lines too much and that seemed to fix it when I ran each of the 3 values for the vertical lines through the int() function.

This is definitely interesting since by doing this I'm having to go through the entire logic of that and fully/somewhat understand it, quite interesting stuff.  I'm pretty amazed at your virtualize function just seeing what it can do when I limit calculations to CGA specs and use it on my monitor, haven't looked at it too deeply but seems to do the job really well at getting the best resolution to expand/shrink the game into.  Much nicer than what I did originally at just trying 640x480 or some other things I tried similar but never got these kind of results.  I also am amazed at how complicated lrmc makes this stuff and how actually way off it is to the desired target compared to your methods.


Also I just did a test, and the positive polarity values for vsync/hsync do matter actually in higher resolutions like 800x600 on the d9800. Without those the picture gets a bit wavy on the edge.  Also the monitor really doesn't like anything above 38Khz horizontal, else it's curved in like an hourglass on one side.  Basically following the specs they used for 800x600 on the data sheet, it is nice at 60Hz vertical and 37.8Khz horizontal, also the calculations are very nice for SVGA so your stuff does work for this.  When I use the specs for vertical from the sheet it uses the 37Khz horizontal and looks square, when I don't and use the generic verticalblank it goes up to 39Khz and starts getting the curve inward.  So I'm suspecting that means I'm somewhat using these vertical timings right, at least seems to make it act right for SVGA mode.


Just to double check, here's the code where I'm setting up the vertical values, I'm not sure the interlaced case works exactly the same for the second vertical value on the modeline.  Your using 5 when interlaced and 3 when not, what should I do and am I doing the other numbers right (seems to center it vertically, guessing it's correct from that)...
Code: [Select]
       
        if ($HaveVerTiming) {
                $LineTime = 1.0 / ( $newDC / $newHt ) * 1000000;
                $B = int(($VFP*1000)/$LineTime);
                $C = int(($VSP*1000)/$LineTime);
                $E = int(($VBP*1000)/$LineTime);
                if ($VERBOSE > 1) {
                        print "Linetime=$LineTime B=$B C=$C E=$E Lines=" . int(($B + $C + $E)+0.5) . "\n";
                }

                $VBlankLines = int($HFreq * $VerticalBlank);
                if ($interlace == 2) {
                        $VBlankLines += 0.5;
                }
                my $margen = $vtotal - $va - $VBlankLines * $interlace;
                if ($VERBOSE > 1) {
                        print "Using VBlankLines: $VBlankLines with Margen: $margen ($vtotal - $va - $VBlankLines * $interlace) to calculate Vblanking\n";
                }

                $vb = $va + $B + (int(($margen / 2)+0.5) + 1 * $interlace);
                $vc = int($vb+$C);
        } else {
                $VBlankLines = int($HFreq * $VerticalBlank);
                if ($interlace == 2) {
                        $VBlankLines += 0.5;
                }
                my $margen = $vtotal - $va - $VBlankLines * $interlace;
                if ($VERBOSE > 1) {
                        print "Using VBlankLines: $VBlankLines with Margen: $margen ($vtotal - $va - $VBlankLines * $interlace) to calculate Vblanking\n";
                }

                $vb = $va + int(($margen / 2)+0.5) + 1 * $interlace;
                $vc = $vb;
                if ($interlace == 2) {
                        $vc += 5;
                } else {
                        $vc += 3;
                }
        }

Also here's the whole function now, with the logic changed...
Code: [Select]
sub get_modeline() {
        my $OriginalWidth = shift(@_);
        my $OriginalHeight = shift(@_);
        my $OriginalRefresh = shift(@_);
        my @flags = ();
        my $PHSYNC = 0;
        my $PVSYNC = 0;
        my $ha = 0;
        my $hb = 0;
        my $hc = 0;
        my $htotal = 0;
        my $va = 0;
        my $vb = 0;
        my $vc = 0;
        my $vtotal = 0;
        my $ModeName = "";
        my $DotClock = 0;
        my $ModeNum = -1;
        my $ModeBase = 0;
        my $interlace = 1;
        my $doublescan = 1;
        my $VBlankLines = 0;
        my $HfreqTolerance = 0.010 * 1000;
        my $HFreq = 0;
        my $LineTime = 0;
        my ($B, $C, $E);
        my $HaveVerTiming = 0;
        my $output = "";
        my ($newDC, $newHh, $newHi, $newHf, $newHt);
        my $VT = 0;

        # Check width/height restrictions
        if ($OriginalWidth < $XresMin) {
                $OriginalWidth = $XresMin;
        }
        if ($OriginalHeight < $YresMin) {
                $OriginalHeight = $YresMin;
        }

        # Check vertical refresh limits
        if ($OriginalRefresh < $MonitorModes[$ModeBase]{'VfreqMin'}) {
                if ((2 * $OriginalRefresh) <= $MonitorModes[$ModeBase]{'VfreqMax'}) {
                        $OriginalRefresh *= 2;
                } else {
                        $OriginalRefresh = $MonitorModes[$ModeBase]{'VfreqMin'};
                }
        } elsif ($OriginalRefresh > $MonitorModes[$ModeBase]{'VfreqMax'}) {
                $OriginalRefresh = $MonitorModes[$ModeBase]{'VfreqMax'};
        }

        if ($OriginalHeight > $ActiveLinesLimit) {
                $interlace = 2;
                if ($OriginalHeight < $VirtualLinesLimit) {
                        my $line = ResVirtualize($OriginalWidth, $OriginalHeight, $OriginalRefresh, $HFreq);
                        ($OriginalWidth, $OriginalHeight, $OriginalRefresh, $HFreq) = split(/\s/, $line);
                        if ($VERBOSE > 0) {
                                print "Height more than active lines limit!!!\n";
                        }
                }
        }

        # Find most fitting mode to begin with
        for (my $i = $ModeBase; $i < scalar(@MonitorModes); $i++) {
                if ($USE_VTIME && $MonitorModes[$ModeBase]{'VFrontPorch'} && $MonitorModes[$ModeBase]{'VSyncPulse'} && $MonitorModes[$ModeBase]{'VBackPorch'}) {
                        $HaveVerTiming = 1;
                        $FP = $MonitorModes[$ModeBase]{'HFrontPorch'};
                        $SP = $MonitorModes[$ModeBase]{'HSyncPulse'};
                        $BP = $MonitorModes[$ModeBase]{'HBackPorch'};
                        $VFP = $MonitorModes[$ModeBase]{'VFrontPorch'};
                        $VSP = $MonitorModes[$ModeBase]{'VSyncPulse'};
                        $VBP = $MonitorModes[$ModeBase]{'VBackPorch'};
                        $VerticalBlank = int((($VFP * 1000) + ($VSP * 1000) + ($VBP * 1000))+0.5) / 1000000;
                }

                $HFreq = int($OriginalRefresh * $OriginalHeight / ($interlace * (1.0 - $OriginalRefresh * $VerticalBlank )));

                # Check minimum horizontal frequency
                if($HFreq < $MonitorModes[$ModeBase]{'HfreqMin'}) {
                        my $old_HFreq = $HFreq;
                        $HFreq = $MonitorModes[$ModeBase]{'HfreqMin'};
                        if ($VERBOSE > 0) {
                                print "Warning: Raised horizontal frequency from " .
                                        sprintf("%.3f", ($old_HFreq/1000)) . "Khz to " . sprintf("%.3f", ($HFreq/1000)) . "Khz\n";
                        }
                }

                if (($HFreq >= $MonitorModes[$i]{'HfreqMin'}) &&
                     ($HFreq <= $MonitorModes[$i]{'HfreqMax'}) &&
                      ($OriginalRefresh >= $MonitorModes[$i]{'VfreqMin'}) &&
                       ($OriginalRefresh <= $MonitorModes[$i]{'VfreqMax'})) {
                                if ($VERBOSE > 0) {
                                        print "horizontal frequency " . sprintf("%.3f", ($HFreq/1000)) .
                                                "Khz matches monitor mode number $i: " .
                                                sprintf("%.3f", ($MonitorModes[$i]{'HfreqMin'}/1000)) . "Khz - " .
                                                sprintf("%.3f", ($MonitorModes[$i]{'HfreqMax'}/1000)) . "Khz\n";
                                }
                                $HfreqMin = $MonitorModes[$i]{'HfreqMin'};
                                $HfreqMax = $MonitorModes[$i]{'HfreqMax'};
                                $VfreqMin = $MonitorModes[$i]{'VfreqMin'};
                                $VfreqMax = $MonitorModes[$i]{'VfreqMax'};
                                $DotClockMin = $MonitorModes[$i]{'DotClockMin'};
                                $DotClockMax = $MonitorModes[$i]{'DotClockMax'};
                                $FP = $MonitorModes[$i]{'HFrontPorch'};
                                $SP = $MonitorModes[$i]{'HSyncPulse'};
                                $BP = $MonitorModes[$i]{'HBackPorch'};
                                $VFP = $MonitorModes[$i]{'VFrontPorch'};
                                $VSP = $MonitorModes[$i]{'VSyncPulse'};
                                $VBP = $MonitorModes[$i]{'VBackPorch'};
                                $PHSYNC = $MonitorModes[$i]{'HsyncPolarity'};
                                $PVSYNC = $MonitorModes[$i]{'VsyncPolarity'};
                                if ($USE_VTIME && $VFP && $VSP && $VBP) {
                                        $HaveVerTiming = 1;
                                        $VerticalBlank = int((($VFP * 1000) + ($VSP * 1000) + ($VBP * 1000))+0.5) / 1000000;
                                } else {
                                        $HaveVerTiming = 0;
                                }
                                $ModeNum = $i;
                                goto GOOD_MODE;
                }

                if ($ModeBase < (scalar(@MonitorModes)-1)) {
                        $ModeBase++;
                }
        }
        GOOD_MODE:
        if ($VERBOSE > 1) {
                print "Calculated vertical blanking to be $VerticalBlank using mode $ModeBase\n";
        }

        # Check if horizontal frequency is above maximum allowed
        if($HFreq > $MonitorModes[$ModeBase]{'HfreqMax'}) {
                if ($OriginalHeight > $ActiveLinesLimit) {
                        my $line = ResVirtualize($OriginalWidth, $OriginalHeight, $OriginalRefresh, $HFreq);
                        ($OriginalWidth, $OriginalHeight, $OriginalRefresh, $HFreq) = split(/\s/, $line);
                        $interlace = 2;
                        if ($VERBOSE > 0) {
                                print "HFreq greater than monitor allows!!!\n";
                        }
                } else {
                        my $oldhf = $HFreq;
                        my $oldvr = $OriginalRefresh;
                        $HFreq = $MonitorModes[$ModeBase]{'HfreqMax'};
                        $VBlankLines = int(($HFreq * $VerticalBlank)+0.5);
                        $OriginalRefresh = $HFreq / ( $OriginalHeight / $interlace + $VBlankLines );
                        if ($VERBOSE > 0) {
                                print "Lowered Hfreq from $oldhf to $HFreq and VRefresh from $oldvr to $OriginalRefresh\n";
                        }
                }
        }

        # Calculate total vertical lines
        if ($HaveVerTiming) {
                # Find horizontal modeline values
                $output = ModelineGetLineParams($HFreq, $OriginalWidth, $FP, $SP, $BP);
                ($newDC, $newHh, $newHi, $newHf, $newHt) = split(/\s/, $output);
                $LineTime = 1.0 / ( $newDC / $newHt ) * 1000000;
                $B = int(($VFP*1000)/$LineTime);
                $C = int(($VSP*1000)/$LineTime);
                $E = int(($VBP*1000)/$LineTime);
                $VT = int(($OriginalHeight+$B+$C+$E)+0.5);
                if ($VERBOSE > 1) {
                        print "Linetime=$LineTime B=$B C=$C E=$E Lines=" . int(($B + $C + $E)+0.5) . "\n";
                }
        } else {
                # Total vertical lines
                $VT = int(($HFreq / $OriginalRefresh)+0.5);
        }
        if ($interlace == 2) {
                $VT += 0.5;
        }
        # If below minimum horizontal refresh increment vertical lines till it isn't
        while (($OriginalRefresh * $VT) < ($MonitorModes[$ModeBase]{'HfreqMin'})) {
                $VT++
        }
        # Horizontal frequency recalculation
        $HFreq = int(($OriginalRefresh * $VT)+0.5);
        if ($VERBOSE > 0) {
                print "Using $VT vertical lines with " . sprintf("%.3f", ($HFreq/1000)) . "Khz horizontal frequency.\n";
        }
        if ($ModeNum < 0) {
                print "ERROR: ($ModeNum) No mode setting in config matches required monitor hfreq $HFreq and vfreq $OriginalRefresh!!!\n";
                exit 1;
        }

        # Find horizontal modeline values
        $output = ModelineGetLineParams($HFreq, $OriginalWidth, $FP, $SP, $BP);
        ($newDC, $newHh, $newHi, $newHf, $newHt) = split(/\s/, $output);

        # Calculate modeline values
        $DotClock = sprintf("%.6f", $newDC / 1000000);
        $ha = $OriginalWidth;
        $hb = $newHi;
        $hc = $newHf;
        $htotal = $newHt;
        $va = $OriginalHeight;
        $vtotal = $VT * $interlace;
        $ModeName = "\"${ha}x${va}\"";

        if ($HaveVerTiming) {
                $LineTime = 1.0 / ( $newDC / $newHt ) * 1000000;
                $B = int(($VFP*1000)/$LineTime);
                $C = int(($VSP*1000)/$LineTime);
                $E = int(($VBP*1000)/$LineTime);
                if ($VERBOSE > 1) {
                        print "Linetime=$LineTime B=$B C=$C E=$E Lines=" . int(($B + $C + $E)+0.5) . "\n";
                }

                $VBlankLines = int($HFreq * $VerticalBlank);
                if ($interlace == 2) {
                        $VBlankLines += 0.5;
                }
                my $margen = $vtotal - $va - $VBlankLines * $interlace;
                if ($VERBOSE > 1) {
                        print "Using VBlankLines: $VBlankLines with Margen: $margen ($vtotal - $va - $VBlankLines * $interlace) to calculate Vblanking\n";
                }

                $vb = $va + $B + (int(($margen / 2)+0.5) + 1 * $interlace);
                $vc = int($vb+$C);
        } else {
                $VBlankLines = int($HFreq * $VerticalBlank);
                if ($interlace == 2) {
                        $VBlankLines += 0.5;
                }
                my $margen = $vtotal - $va - $VBlankLines * $interlace;
                if ($VERBOSE > 1) {
                        print "Using VBlankLines: $VBlankLines with Margen: $margen ($vtotal - $va - $VBlankLines * $interlace) to calculate Vblanking\n";
                }

                $vb = $va + int(($margen / 2)+0.5) + 1 * $interlace;
                $vc = $vb;
                if ($interlace == 2) {
                        $vc += 5;
                } else {
                        $vc += 3;
                }
        }

        # flags
        if ($PHSYNC) {
                push @flags, "+HSync";
        } else {
                push @flags, "-HSync";
        }

        if ($PVSYNC) {
                push @flags, "+VSync";
        } else {
                push @flags, "-VSync";
        }

        # Check for interlace
        if ($interlace == 2) {
                push @flags, "interlace";
        } elsif ($doublescan == 2) {
                push @flags, "doublescan";
        }

        $MODELINE = "$ModeName $DotClock $ha $hb $hc $htotal $va $vb $vc $vtotal @flags";

        if ($VERBOSE > 1) {
                print "New modeline with hfreq: $HFreq refresh: " . (($DotClock*1000000) / ($htotal * $vtotal)) . "\n $MODELINE\n";
        }
        return $MODELINE;
}



« Last Edit: November 10, 2010, 05:29:56 pm by bitbytebit »
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .18)
« Reply #142 on: November 10, 2010, 07:26:11 pm »
These vertical elements can't be very accurate because of the integer issue (you've seen how the key to properly calculate things is always manage integer elements). What's important is the total sum of front/back porches + sync. I've checked my code and the vertical part is really hardcoded for low resolutions I'm afraid. It's assuming front porch is always one line and sync pulses 3/5, leaving the rest for back porch. This actually means:

*progressive:

front porch : 1.5 lines -> rounded to 1 line -> 64 µs
sync pulse: 2.5 lines -> rounded to 3 lines -> 192 µs
back porch: 16 lines -> 16 lines -> 1024 µs
VerticalBlank: 20 lines -> 1280 µs

*interlaced:

front porch : 3(/2) lines -> 96 µs
sync pulse: 5(/2) lines  -> 160 µs
back porch: 33(/2) lines -> 1088 µs
VerticalBlank: 41(/2) lines -> 1344 µs

(this values can be used to support Hantarex MTC 9110 as they should produce the same modelines I am doing. Interlaced values are not the actual used right now but they should be. I'll have a look at this)

So that 3/5 are because TV standars consider sync pulse as 2.5 lines long, so 3 is for the rounding, and 5 because by do multiply by 2 when we interlace. So, the code can be made more generic by calculating these from the above values in µs, for any monitor type. Bear in mind that as we move from the reference mode line lenths change so to do things perfect this must be considered and that's why it's not really correct to precalculate a fixed table with line numbers for vertical porchs/sync or hardcode the values as I was doing.

I've seen your code and the logic looks good. I had imagined another way to deal with multisync monitors as I explained some posts above, by considering each interval/mode as a separate virtual monitor and produce as many versions of each modeline as virtual monitors, and have a system to rate them to choose the best one. For instance, if you ask for 640x480 and use the CGA mode, it will produce an interlaced res (bad rate), after that you use VGA mode and the modeline will be progressive, with a better rate obtained so we select the second. That is all that 'result' stuff about. This was intended for dealing with monitors that have separate hfreq intervals with gaps in the middle, which seems it's not the case with d9800. However, your method seems just as good.

I have to go now, hopefully tomorrow I have some time to look at this and comment. I'm really happy you managed to get this stuff working. I've devoted a lot of hours to think how these calculations should be done, it's incredible how quickly you've figured all of it.

« Last Edit: November 10, 2010, 07:31:09 pm by Calamity »
Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .18)
« Reply #143 on: November 10, 2010, 11:04:35 pm »
These vertical elements can't be very accurate because of the integer issue (you've seen how the key to properly calculate things is always manage integer elements). What's important is the total sum of front/back porches + sync. I've checked my code and the vertical part is really hardcoded for low resolutions I'm afraid. It's assuming front porch is always one line and sync pulses 3/5, leaving the rest for back porch. This actually means:

*progressive:

front porch : 1.5 lines -> rounded to 1 line -> 64 µs
sync pulse: 2.5 lines -> rounded to 3 lines -> 192 µs
back porch: 16 lines -> 16 lines -> 1024 µs
VerticalBlank: 20 lines -> 1280 µs

*interlaced:

front porch : 3(/2) lines -> 96 µs
sync pulse: 5(/2) lines  -> 160 µs
back porch: 33(/2) lines -> 1088 µs
VerticalBlank: 41(/2) lines -> 1344 µs

(this values can be used to support Hantarex MTC 9110 as they should produce the same modelines I am doing. Interlaced values are not the actual used right now but they should be. I'll have a look at this)

So that 3/5 are because TV standars consider sync pulse as 2.5 lines long, so 3 is for the rounding, and 5 because by do multiply by 2 when we interlace. So, the code can be made more generic by calculating these from the above values in µs, for any monitor type. Bear in mind that as we move from the reference mode line lenths change so to do things perfect this must be considered and that's why it's not really correct to precalculate a fixed table with line numbers for vertical porchs/sync or hardcode the values as I was doing.

I've seen your code and the logic looks good. I had imagined another way to deal with multisync monitors as I explained some posts above, by considering each interval/mode as a separate virtual monitor and produce as many versions of each modeline as virtual monitors, and have a system to rate them to choose the best one. For instance, if you ask for 640x480 and use the CGA mode, it will produce an interlaced res (bad rate), after that you use VGA mode and the modeline will be progressive, with a better rate obtained so we select the second. That is all that 'result' stuff about. This was intended for dealing with monitors that have separate hfreq intervals with gaps in the middle, which seems it's not the case with d9800. However, your method seems just as good.

I have to go now, hopefully tomorrow I have some time to look at this and comment. I'm really happy you managed to get this stuff working. I've devoted a lot of hours to think how these calculations should be done, it's incredible how quickly you've figured all of it.



I put up a new version, has quite  few changes past the code I posted, had a few bugs in interlacing when using the vertical values and also had broken CGA mode but figured out the way to do that right.  Also I discovered that the cutoff point on the d9800 for VGA -> SVGA mode is about 32Khz which makes sense and I didn't realize VGA mode was such a small span but the others seem to be able to blanket 8Khz or so each. 

Thanks, I'm hoping it's all going to work right, definitely some tricky stuff to be able to calculate things with the multiple ranges but the only one issue I can see (hopefully) is possibly being able to specify a preferred range or put the ranges in a preferred order.  RIght now I go from lowest to highest and it seems right, since we are trying to calculate the best arcade resolution which most are lower, yet for general resolution calculation it could be opposite of that (which is what lrmc does I think).  Hopefully now that I am starting to understand the interlace calculations a little bit more, from having to get them to work in the vert input mode and your explanation too, hopefully I can start to look at doublescan and figure out how that can be put in. 

Also there seems to be a bug in the Linux DRM stuff with modeswitching, at least seems like it's that.  Basically sometimes, you have to go into another resolution, and back out, then in again to have it display right.  Like it's not really changing all the values of the card output to the monitor.  From what I can tell the exact same modeline is generated and the kernel even prints out messages saying it got the exact same modeline too.  Somewhere in there it seems to not really get to the card itself and usually only games with the 288 vertical resolutions and they end up being wider  than they should (like galaga or pacman do this sometimes, but not often from what I can tell).  It's always done this, did it actually more often with lrmc so it may also have to do with timing calculations and possibly the dotclock value having some leeway. So that's one oddity I want to look into eventually, and doublescan, plus I've now got templates for most of the monitor types that lrmc supported and not sure if they are going to work 100% (especially pal/ntsc ones).

SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .19)
« Reply #144 on: November 11, 2010, 04:21:09 am »
I've seen your vertical calculations and they seem correct. Without running it I don't know if there will be any rounding issue but the logic is correct and anyway monitors are somewhat tolerant with this.

I'd highly appreciate you included the specs for Hantarex MTC 9110, as it's not a pure CGA monitor but has an extended hfreq range I'd like to be able to use:

Code: [Select]
} elsif ($MONITOR eq "h9110") {
# HANTAREX MTC 9110
fill_mode("15625-16670,49.5-65,3000000-40960000,2.000,4.700,8.000,0.064,0.192,1.024,0,0");
$ActiveLinesLimit  = 288;
$VirtualLinesLimit = 448;
$XresMin = 184;
$YresMin = 192;
}

I hope this weekend I have some time to implement the idea of 'virtual monitors', it's something I was planning to do some day but I didn't have the values for a real multisync monitor, I believe it could make things simplier (or not). Even if your monitor has a continuous hfreq range it can be modelled as having 4 adjacent ranges in where different parameters apply.

ActiveLinesLimit and VirtualLinesLimit are not monitor but user specifications. Indeed, a CGA monitor might do 292.5 progressive lines, but for normal arcade monitor operation it involves adjusting a lot our vertical amplitude potenciometer, so for convenience I set that limit that the user can move if desired. Between ActiveLinesLimit and VirtualLinesLimit we have an interval where we need to interlace but still with too few lines to get a decent shaped picture (too low vertical size), that's why I send those resolutions though the virtualize proc to get a 4:3 res where I can stretch. Again, nothing really stops as from attempting a resolution of 300 lines interlaced, it will just have huge vertical margins and will look 'panoramic', but for convenience we stablish that VirtualLinesLimit at a suitable point to avoid odd-looking resolutions. The resolutions above VirtualLinesLimit are interlaced without stretching.

Now, we could also have an user limitation for lower resolutions, opposite to ActiveLinesLimit, in order to activate doublescan in case it was needed. A good value could be ActiveLinesLimit / 2. But these limitations were intended to be applied to separate hfreq range intervals, so you would have ActiveLinesLimit pairs for each of those intervals, instead of a pair for the whole monitor range. For instance, if you try to do 320x240 inside the CGA interval, you'd get 320x240 progressive. Then if you try it inside the SVGA interval, where you have defined ActiveLinesLimit = 600, the lower limit will be 600/2 = 300, so 240 is below that and you will get 320x240 doublescan. Following my logic you don't need to do any range selection inside the modeline generator, but call the modeline generator for each of the 4 ranges you have (each with its proper porches and stuff), so you will get 4 viable modelines with a rate that accounts for their degree of degradation (doublescan is considered a degradation unless you really want it), and you would select the best one of them according to that rate.

Thinking further, monitor and video card capabilities could be separated. Dotclock allowance range is not monitor but videocard related. Doublescan and interlace capabilities are videocard related too (or buggy drivers limited if you prefer), and one might want to disable i.e. doublescan in case it can't be used.

Once you have a solid engine I'd like to comment the dotclock accuracy issues I found with Windows, to check if they are also there with Linux.

(I'm just commenting this stuff in case it can be useful, not trying to drive you to any design decision, as what's important is to get this running.)
« Last Edit: November 11, 2010, 04:54:35 am by Calamity »
Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .19)
« Reply #145 on: November 11, 2010, 10:39:53 am »
I've seen your vertical calculations and they seem correct. Without running it I don't know if there will be any rounding issue but the logic is correct and anyway monitors are somewhat tolerant with this.

I'd highly appreciate you included the specs for Hantarex MTC 9110, as it's not a pure CGA monitor but has an extended hfreq range I'd like to be able to use:

Code: [Select]
} elsif ($MONITOR eq "h9110") {
# HANTAREX MTC 9110
fill_mode("15625-16670,49.5-65,3000000-40960000,2.000,4.700,8.000,0.064,0.192,1.024,0,0");
$ActiveLinesLimit  = 288;
$VirtualLinesLimit = 448;
$XresMin = 184;
$YresMin = 192;
}

I hope this weekend I have some time to implement the idea of 'virtual monitors', it's something I was planning to do some day but I didn't have the values for a real multisync monitor, I believe it could make things simplier (or not). Even if your monitor has a continuous hfreq range it can be modelled as having 4 adjacent ranges in where different parameters apply.

ActiveLinesLimit and VirtualLinesLimit are not monitor but user specifications. Indeed, a CGA monitor might do 292.5 progressive lines, but for normal arcade monitor operation it involves adjusting a lot our vertical amplitude potenciometer, so for convenience I set that limit that the user can move if desired. Between ActiveLinesLimit and VirtualLinesLimit we have an interval where we need to interlace but still with too few lines to get a decent shaped picture (too low vertical size), that's why I send those resolutions though the virtualize proc to get a 4:3 res where I can stretch. Again, nothing really stops as from attempting a resolution of 300 lines interlaced, it will just have huge vertical margins and will look 'panoramic', but for convenience we stablish that VirtualLinesLimit at a suitable point to avoid odd-looking resolutions. The resolutions above VirtualLinesLimit are interlaced without stretching.

Now, we could also have an user limitation for lower resolutions, opposite to ActiveLinesLimit, in order to activate doublescan in case it was needed. A good value could be ActiveLinesLimit / 2. But these limitations were intended to be applied to separate hfreq range intervals, so you would have ActiveLinesLimit pairs for each of those intervals, instead of a pair for the whole monitor range. For instance, if you try to do 320x240 inside the CGA interval, you'd get 320x240 progressive. Then if you try it inside the SVGA interval, where you have defined ActiveLinesLimit = 600, the lower limit will be 600/2 = 300, so 240 is below that and you will get 320x240 doublescan. Following my logic you don't need to do any range selection inside the modeline generator, but call the modeline generator for each of the 4 ranges you have (each with its proper porches and stuff), so you will get 4 viable modelines with a rate that accounts for their degree of degradation (doublescan is considered a degradation unless you really want it), and you would select the best one of them according to that rate.

Thinking further, monitor and video card capabilities could be separated. Dotclock allowance range is not monitor but videocard related. Doublescan and interlace capabilities are videocard related too (or buggy drivers limited if you prefer), and one might want to disable i.e. doublescan in case it can't be used.

Once you have a solid engine I'd like to comment the dotclock accuracy issues I found with Windows, to check if they are also there with Linux.

(I'm just commenting this stuff in case it can be useful, not trying to drive you to any design decision, as what's important is to get this running.)


I've added that monitor in, good to have another range in that extended range I had read about.  I'm going to make the get_mode function take the monitors array into it as a local array, that way we could call it many times with multiple monitor types instead of one single run with them all together.  That would allow it to be called multiple times for each monitor type and then have logic to pick the best one, if desired.  I think the logic I'm using for the choosing of the resolution from the preset file (like with Soft15Khz or AVGA) probably is close to doing the decision making, it at least is able to pick from those lists the best fitting resolution.  I need to see if I accounted for interlace and doublescan though,  I don't think I did but that would be pretty easy I think just making them less likable than an equal progressive. 

Interesting about the active lines limit, I was wondering that, makes sense it's the setting the monitor pots issue more than limitations.  I like the idea of having lower line limits till we do doublescan, which is basically what I was doing with lrmc and is interesting to do doublescan in the higher ranges possibly instead of lower ones since I'm guessing that could make it look somewhat better.  I do see how doublescan is really a last resort and quite bad looking if there's a possible alternative, now seeing the output for 192 high resolution games on my d9800 compared to the doublescan versions, I like them better like they are now.

All sounds really interesting, thanks for all the feedback and information, help and such.  Definitely helping me get this working much better than originally, I'm pretty happy with how well it's working and just a few issues with my monitor currently I see that are somewhat a real problem.  The major issue I see is that old one about certain games like dbz with most likely wrong resolutions in mame, which always seem to suspiciously show a 1.5 or greater resolution aspect ratio.  It always seems to be those games that stretch too wide and look to me like they have definitely gotten the screen size wrong for both width and height.  You can somewhat fiddle around and get a working size, but it's not always clearly only width or height I think.  Maybe they had a bigger blanking interval or something to push it in more?  The dbz case and mk case are both ones I know of at least.  I keep thinking maybe there's something in the calculations wrong but now seeing the same thing with your method instead of lrmc, although it is closer than lrmc could get and I think shows the problem only instead of lrmc problems combined.  So I think it's definitely the games resolutions themselves and might even be somewhat impossible to fix those without some virtualization or changing mame itself like is done with frogger/galaxian to get them to behave properly.
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .19)
« Reply #146 on: November 11, 2010, 11:28:18 am »
Maybe they had a bigger blanking interval or something to push it in more?

Yeah, could be. But as there are many games with the opposite problem (less xres than real) which is even worse, I believe it's just that the resolutions reported by Mame are wrong. Some games also change resolutions several times (see Cabmame option changeres), so another possibility is that the reported resolution is just one that is used at some point but not the main one. In order to find the cause it would be necessary to have a look at involved Mame system drivers... I think the easiest way to solve this by now is using a list of patches for these games/systems resolutions, so your frogger patch could be included there.
Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .19)
« Reply #147 on: November 11, 2010, 11:51:31 am »
Maybe they had a bigger blanking interval or something to push it in more?

Yeah, could be. But as there are many games with the opposite problem (less xres than real) which is even worse, I believe it's just that the resolutions reported by Mame are wrong. Some games also change resolutions several times (see Cabmame option changeres), so another possibility is that the reported resolution is just one that is used at some point but not the main one. In order to find the cause it would be necessary to have a look at involved Mame system drivers... I think the easiest way to solve this by now is using a list of patches for these games/systems resolutions, so your frogger patch could be included there.


Yeah, well it's the frogger patch from Cabmame, not mine :) It gives an idea though of how to possibly solve the issues by defining a smaller area than the drivers visible area.  When it's a bigger area we want than the visible area that might be something different I'm guessing.  Seems in the galaxian/frogger issue they scaled the vertical resolution x 3 times to to get the stars to show properly, which added up to 768, and so we're limiting the resolution but the actual visible resolution is still the huge area and the OSD is that size still for the info menu (so it's useless almost to use the info menu).  Seems like there would be a way to get it all fully correct, but looking into it I couldn't see one that was not hacking the actual game driver and getting really complicated redoing the whole thing (like they did when they changed it in .125 and caused the issue of it being too tall). 

I have moved the dotclock stuff out of the monitor lines, make sense and nicer without that in them, also got a quick working ability to feed the modeline function with each line separately.  Just right now do that when asking to calculate a game resolution without loading it in mame, but it's nice to see each possible resolution now.  Here's the basic diff I've done so far, pretty simple change, but definitely brings some interesting possibilities and ways to test multiple monitor lines.

Code: [Select]
diff --git a/extra/switchres.conf b/extra/switchres.conf
index b15f45f..4f5406c 100644
--- a/extra/switchres.conf
+++ b/extra/switchres.conf
@@ -2,25 +2,33 @@
 #vsync=1
 ff=1
 mon=d9800
+#mon=cga
 modesfile=/home/arcade/modes.txt
 displayart=:0.1 /data/mrq
+#use_vtime=0

 #
 # Monitor Limits format:
-# HfreqMin-HfreqMax,VfreqMin-VfreqMax,DotclockMin-DotclockMax,HfrontPorch,HsyncPulse,HbackPorch,VfrontPorch,VsyncPulse,VbackPorch,HorPolarity,VerPolarity
+# HfreqMin-HfreqMax,VfreqMin-VfreqMax,HfrontPorch,HsyncPulse,HbackPorch,VfrontPorch,VsyncPulse,VbackPorch,HorPolarity,VerPolarity
 #
 # CGA Monitor
-#MonitorLimits=15250-15700,49.5-65,3000000-40960000,2.000,4.700,8.000,0.190,0.191,1.018,0,0
+#MonitorLimits=15250-15700,49.5-65,2.000,4.700,8.000,0.190,0.191,1.018,0,0
+#MonitorLimits=15250-15700,49.5-65,2.000,4.700,8.000,0.064,0.192,1.024,0,0
+#MonitorLines=288,448,184,192
 #
 # Wells Gardner D9800 monitor
 #
-#MonitorLimits=15250-20000,40-80,3000000-40960000,2.187,4.688,6.719,0.190,0.191,1.018,0,0
-#MonitorLimits=20001-30000,40-80,3000000-40960000,2.910,3.000,4.440,0.451,0.164,1.048,0,0
-#MonitorLimits=30001-32000,40-80,3000000-40960000,0.636,3.813,1.906,0.318,0.064,1.048,0,0
-#MonitorLimits=32001-38900,40-80,3000000-40960000,1.000,3.200,2.200,0.020,0.106,0.607,1,1
+#MonitorLimits=15250-20000,40-80,2.187,4.688,6.719,0.190,0.191,1.018,0,0
+#MonitorLimits=20001-30000,40-80,2.910,3.000,4.440,0.451,0.164,1.048,0,0
+#MonitorLimits=30001-32000,40-80,0.636,3.813,1.906,0.318,0.064,1.048,0,0
+#MonitorLimits=32001-38900,40-80,1.000,3.200,2.200,0.020,0.106,0.607,1,1
 #
 #
 # MinVertLine,MinVirtLine,MinWidth,MinHeight
 #
 #MonitorLines=600,600,184,192
+#
+# DotClock limits of video card
+DotClockMin=3000000
+DotClockMax=90000000

diff --git a/switchres b/switchres
index 7010970..29054e3 100755
--- a/switchres
+++ b/switchres
@@ -95,8 +95,6 @@ my $HfreqMin    = 0;
 my $HfreqMax    = 0;
 my $VfreqMin    = 0;
 my $VfreqMax    = 0;
-my $DotClockMin = 0;
-my $DotClockMax = 0;

 my $FP  = 0;
 my $SP  = 0;
@@ -116,6 +114,9 @@ my $VirtualLinesLimit = 448;
 my $XresMin = 184;
 my $YresMin = 192;

+my $DotClockMin = 3000000;
+my $DotClockMax = 40960000;
+
 my @cfgopts = read_config($CONFIG_FILE);
 foreach(@cfgopts) {
        my $line = $_;
@@ -126,6 +127,8 @@ foreach(@cfgopts) {
                fill_mode($value);
        } elsif ($key eq "MonitorLines") {
                ($ActiveLinesLimit, $VirtualLinesLimit, $XresMin, $YresMin) = split(/,/, $value);
+       } elsif ($key eq "DotClockRange") {
+               ($DotClockMin, $DotClockMax) = split(/-/, $value);
        } elsif ($key eq "resfile") {
                if (! -e $value) {
                        print "Error: resfile $value doesn't exist!!!\n";
@@ -422,58 +425,58 @@ if ($MONITOR || !scalar(@MonitorModes)) {
        @MonitorModes = ();
        if ($MONITOR eq "d9800" || $MONITOR eq "d9400") {
                # D9800/D9400
-               fill_mode("15250-20000,40-80,3000000-40960000,2.187,4.688,6.719,0.190,0.191,1.018,0,0");
-               fill_mode("20001-30000,40-80,3000000-40960000,2.910,3.000,4.440,0.451,0.164,1.048,0,0");
-               fill_mode("30001-32000,40-80,3000000-40960000,0.636,3.813,1.906,0.318,0.064,1.048,0,0");
-               fill_mode("32001-38900,40-80,3000000-40960000,1.000,3.200,2.200,0.020,0.106,0.607,1,1");
+               fill_mode("15250-20000,40-80,2.187,4.688,6.719,0.190,0.191,1.018,0,0");
+               fill_mode("20001-30000,40-80,2.910,3.000,4.440,0.451,0.164,1.048,0,0");
+               fill_mode("30001-32000,40-80,0.636,3.813,1.906,0.318,0.064,1.048,0,0");
+               fill_mode("32001-38900,40-80,1.000,3.200,2.200,0.020,0.106,0.607,1,1");
                $ActiveLinesLimit  = 600;
                $VirtualLinesLimit = 600;
                $XresMin = 184;
                $YresMin = 192;
        } elsif ($MONITOR eq "d9200") {
                # D9200
-               fill_mode("15250-20000,40-100,3000000-40960000,2.187,4.688,6.719,0.190,0.191,1.018,0,0");
-               fill_mode("20001-30000,40-100,3000000-40960000,2.910,3.000,4.440,0.451,0.164,1.048,0,0");
-               fill_mode("30001-33000,40-100,3000000-40960000,0.636,3.813,1.906,0.318,0.064,1.048,0,0");
+               fill_mode("15250-20000,40-100,2.187,4.688,6.719,0.190,0.191,1.018,0,0");
+               fill_mode("20001-30000,40-100,2.910,3.000,4.440,0.451,0.164,1.048,0,0");
+               fill_mode("30001-33000,40-100,0.636,3.813,1.906,0.318,0.064,1.048,0,0");
                $ActiveLinesLimit  = 480;
                $VirtualLinesLimit = 600;
                $XresMin = 184;
                $YresMin = 192;
        } elsif ($MONITOR eq "ntsc") {
-               fill_mode("15734.26-15734.26,59.95-59.95,3000000-40960000,0.636,3.813,1.906,0,0,0,0,0");
+               fill_mode("15734.26-15734.26,59.95-59.95,0.636,3.813,1.906,0,0,0,0,0");
                $ActiveLinesLimit  = 240;
                $VirtualLinesLimit = 448;
                $XresMin = 184;
                $YresMin = 192;
        } elsif ($MONITOR eq "pal") {
-               fill_mode("15625-15625,50-50,3000000-40960000,0.636,3.813,1.906,0,0,0,0,0");
+               fill_mode("15625-15625,50-50,0.636,3.813,1.906,0,0,0,0,0");
                $ActiveLinesLimit  = 288;
                $VirtualLinesLimit = 448;
                $XresMin = 184;
                $YresMin = 192;
        } elsif ($MONITOR eq "vga") {
-               fill_mode("30001-32000,40-80,3000000-40960000,0.636,3.813,1.906,0.318,0.064,1.048,0,0");
+               fill_mode("30001-32000,40-80,0.636,3.813,1.906,0.318,0.064,1.048,0,0");
                $ActiveLinesLimit  = 480;
                $VirtualLinesLimit = 600;
                $XresMin = 184;
                $YresMin = 192;
        } elsif ($MONITOR eq "ega") {
                # EGA
-               fill_mode("24960-24960,50-60,3000000-40960000,2.910,3.000,4.440,0.451,0.164,1.048,0,0");
+               fill_mode("24960-24960,50-60,2.910,3.000,4.440,0.451,0.164,1.048,0,0");
                $ActiveLinesLimit  = 384;
                $VirtualLinesLimit = 480;
                $XresMin = 184;
                $YresMin = 192;
        } elsif ($MONITOR eq "h9110") {
                # Hantarex MTC 9110
-               fill_mode("15625-16670,49.5-65,3000000-40960000,2.000,4.700,8.000,0.064,0.192,1.024,0,0");
+               fill_mode("15625-16670,49.5-65,2.000,4.700,8.000,0.064,0.192,1.024,0,0");
                $ActiveLinesLimit  = 288;
                $VirtualLinesLimit = 448;
                $XresMin = 184;
                $YresMin = 192;
        } else {
                # CGA
-               fill_mode("15250-15700,49.5-65,3000000-40960000,2.000,4.700,8.000,0.064,0.192,1.024,0,0");
+               fill_mode("15250-15700,49.5-65,2.000,4.700,8.000,0.064,0.192,1.024,0,0");
                $ActiveLinesLimit  = 288;
                $VirtualLinesLimit = 448;
                $XresMin = 184;
@@ -852,6 +855,21 @@ if ($RESOLUTION) {
                exit 1;
        }

+       if ($VERBOSE > 1 || $CALCRES) {
+               foreach (@MonitorModes) {
+                       my @mmode;
+                       push @mmode, $_;
+                       my $mline = get_modeline($width, $height, $refresh, @mmode);
+                       my $resinfo = get_resinfo($mline);
+                       print "# $GAME $resinfo\n";
+                       print "     $mline\n";
+               }
+               if ($CALCRES) {
+                       print "\n";
+                       #exit 0;
+               }
+       }
+
        # Use LRMC to generate a custom modeline
        if ($GEN_MODELINES) {
                # Only use doublescan when it's a small vertical height
@@ -869,7 +887,7 @@ if ($RESOLUTION) {
                        }
                        $MODELINE = get_modeline_lrmc("$LRMC_CMD");
                } else {
-                       $MODELINE = get_modeline($width, $height, $refresh);
+                       $MODELINE = get_modeline($width, $height, $refresh, @MonitorModes);
                }
                $MODELINE =~ s/\s+/ /g;
                $MODELINE =~ s/^\s+//g;
@@ -953,7 +971,7 @@ if ($RESOLUTION) {
                                        my $LRMC_CMD = $LRMC_BIN . " " . $w . " " . $h . " " . $r . " " . $LRMC_ARGS;
                                        $MODELINE = get_modeline_lrmc("$LRMC_CMD");
                                } else {
-                                       $MODELINE = get_modeline($w, $h, $r);
+                                       $MODELINE = get_modeline($w, $h, $r, @MonitorModes);
                                }
                                $MODELINE =~ s/\s+/ /g;
                                $MODELINE =~ s/^\s+//g;
@@ -1253,6 +1271,7 @@ sub get_modeline() {
        my $OriginalWidth = shift(@_);
        my $OriginalHeight = shift(@_);
        my $OriginalRefresh = shift(@_);
+       my @MonitorModes = @_;
        my @flags = ();
        my $PHSYNC = 0;
        my $PVSYNC = 0;
@@ -1328,8 +1347,6 @@ sub get_modeline() {
                $HfreqMax    = $MonitorModes[$i]{'HfreqMax'};
                $VfreqMin    = $MonitorModes[$i]{'VfreqMin'};
                $VfreqMax    = $MonitorModes[$i]{'VfreqMax'};
-               $DotClockMin = $MonitorModes[$i]{'DotClockMin'};
-               $DotClockMax = $MonitorModes[$i]{'DotClockMax'};
                $PHSYNC      = $MonitorModes[$i]{'HsyncPolarity'};
                $PVSYNC      = $MonitorModes[$i]{'VsyncPolarity'};
                $FP  = $MonitorModes[$i]{'HFrontPorch'};
@@ -1600,18 +1617,15 @@ sub ResVirtualize () {

 sub fill_mode() {
        my $value = shift(@_);
-       my ($hf, $vf, $dc, $hfp, $hsp, $hbp, $vfp, $vsp, $vbp, $hp, $vp) = split(/,/, $value);
+       my ($hf, $vf, $hfp, $hsp, $hbp, $vfp, $vsp, $vbp, $hp, $vp) = split(/,/, $value);
        my ($hfmin, $hfmax) = split(/-/, $hf);
        my ($vfmin, $vfmax) = split(/-/, $vf);
-       my ($dcmin, $dcmax) = split(/-/, $dc);
        my $mode_num = scalar(@MonitorModes);

        $MonitorModes[$mode_num]{'HfreqMin'} = $hfmin;
        $MonitorModes[$mode_num]{'HfreqMax'} = $hfmax;
        $MonitorModes[$mode_num]{'VfreqMin'} = $vfmin;
        $MonitorModes[$mode_num]{'VfreqMax'} = $vfmax;
-       $MonitorModes[$mode_num]{'DotClockMin'} = $dcmin;
-       $MonitorModes[$mode_num]{'DotClockMax'} = $dcmax;
        $MonitorModes[$mode_num]{'HFrontPorch'} = $hfp;
        $MonitorModes[$mode_num]{'HSyncPulse'} = $hsp;



 
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .19)
« Reply #148 on: November 11, 2010, 11:54:12 am »
I've added that monitor in, good to have another range in that extended range I had read about.  I'm going to make the get_mode function take the monitors array into it as a local array, that way we could call it many times with multiple monitor types instead of one single run with them all together.  That would allow it to be called multiple times for each monitor type and then have logic to pick the best one, if desired.  I think the logic I'm using for the choosing of the resolution from the preset file (like with Soft15Khz or AVGA) probably is close to doing the decision making, it at least is able to pick from those lists the best fitting resolution.  I need to see if I accounted for interlace and doublescan though,  I don't think I did but that would be pretty easy I think just making them less likable than an equal progressive.

That's great, I think it will make the process more general, however I haven't tested that.

Interesting about the active lines limit, I was wondering that, makes sense it's the setting the monitor pots issue more than limitations.  I like the idea of having lower line limits till we do doublescan, which is basically what I was doing with lrmc and is interesting to do doublescan in the higher ranges possibly instead of lower ones since I'm guessing that could make it look somewhat better.  I do see how doublescan is really a last resort and quite bad looking if there's a possible alternative, now seeing the output for 192 high resolution games on my d9800 compared to the doublescan versions, I like them better like they are now.

What we'll have to work out are the most suitable active line limits for your monitor modes, as I guess they will have to be carefully selected to have the best results. BTW I wonder if I could still buy one of those D9800 here in Europe.
Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .19)
« Reply #149 on: November 11, 2010, 12:13:47 pm »
Yeah, well it's the frogger patch from Cabmame, not mine :) It gives an idea though of how to possibly solve the issues by defining a smaller area than the drivers visible area.  When it's a bigger area we want than the visible area that might be something different I'm guessing.  Seems in the galaxian/frogger issue they scaled the vertical resolution x 3 times to to get the stars to show properly, which added up to 768, and so we're limiting the resolution but the actual visible resolution is still the huge area and the OSD is that size still for the info menu (so it's useless almost to use the info menu).  Seems like there would be a way to get it all fully correct, but looking into it I couldn't see one that was not hacking the actual game driver and getting really complicated redoing the whole thing (like they did when they changed it in .125 and caused the issue of it being too tall). 

I see, it's a different thing this frogger issue, to be honest I haven't tested this game with newer Mame versions, I'll have a look tonight.

I have moved the dotclock stuff out of the monitor lines, make sense and nicer without that in them, also got a quick working ability to feed the modeline function with each line separately.  Just right now do that when asking to calculate a game resolution without loading it in mame, but it's nice to see each possible resolution now.  Here's the basic diff I've done so far, pretty simple change, but definitely brings some interesting possibilities and ways to test multiple monitor lines.

Yes that's it! The way I thought for rating resolutions was based on setting bits on the result of the function, so each bit means a kind of degradation, which allows to account for several 'defects' at the same time, for instance a resolution can be interlaced and have bad refresh at the same time. Depending on the weight (position) we decide which defects are worse that others, and they can be added up, so evaluating the output modelines can be a matter of just choosing the one with the lower result value.



Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .19)
« Reply #150 on: November 11, 2010, 02:35:27 pm »
Yeah, well it's the frogger patch from Cabmame, not mine :) It gives an idea though of how to possibly solve the issues by defining a smaller area than the drivers visible area.  When it's a bigger area we want than the visible area that might be something different I'm guessing.  Seems in the galaxian/frogger issue they scaled the vertical resolution x 3 times to to get the stars to show properly, which added up to 768, and so we're limiting the resolution but the actual visible resolution is still the huge area and the OSD is that size still for the info menu (so it's useless almost to use the info menu).  Seems like there would be a way to get it all fully correct, but looking into it I couldn't see one that was not hacking the actual game driver and getting really complicated redoing the whole thing (like they did when they changed it in .125 and caused the issue of it being too tall). 

I see, it's a different thing this frogger issue, to be honest I haven't tested this game with newer Mame versions, I'll have a look tonight.

I have moved the dotclock stuff out of the monitor lines, make sense and nicer without that in them, also got a quick working ability to feed the modeline function with each line separately.  Just right now do that when asking to calculate a game resolution without loading it in mame, but it's nice to see each possible resolution now.  Here's the basic diff I've done so far, pretty simple change, but definitely brings some interesting possibilities and ways to test multiple monitor lines.

Yes that's it! The way I thought for rating resolutions was based on setting bits on the result of the function, so each bit means a kind of degradation, which allows to account for several 'defects' at the same time, for instance a resolution can be interlaced and have bad refresh at the same time. Depending on the weight (position) we decide which defects are worse that others, and they can be added up, so evaluating the output modelines can be a matter of just choosing the one with the lower result value.





I had seen the result output you were doing and that sounds really good, I just did a similar thing but the weight of each type of alteration my not be in proper order or weight yet.  Right now I've got it so you can see exactly what changes were made in each mode, but it does tend to choose the lowest value of the ranges.  Definitely nice to have this now, helping me see what happens exactly per range and also now with a -v for verbose added (more added the more verbose it gets)  the -calcgame xxx -v will give a nice informative output of what is going on per range.

I just updated to version .20 that has this and the other changes in it, with the new monitor type too...

Version 0.20 - Multiple ranges resolutions can be compared
* When printing out a resolution, you can now see all the possible ones if
  monitor has multiple ranges
* Added new  Hantarex MTC 9110 Arcade Monitor support
* Print out information on exactly what was changed to create a modeline,
  in future could be used to weight multiple monitor ranges
* Moved dotclock range to separate config from monitor ranges, not used anyways
  and specific to video cards more than anything.
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .20)
« Reply #151 on: November 11, 2010, 06:42:10 pm »
I've attached an Excel table with some calculations based on D9800 values, to try to help figuring out where the transitions between modes could be done. The interesting part is the active lines area. I'll think about this.
Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .20)
« Reply #152 on: November 11, 2010, 11:59:03 pm »
I've attached an Excel table with some calculations based on D9800 values, to try to help figuring out where the transitions between modes could be done. The interesting part is the active lines area. I'll think about this.


Interesting, so those are the calculated out active line and blanking limits for those values. What's strange is how in the documentation they claim 40-100Hz vertical but from what I can tell it's impractical with the 15.250 (they claim 15.725 lower limit but it seems to push down to this just fine) to 38.9 (again they claim 40 here but it seems to get odd anywhere above this) Horizontal Khz limits.  Also on the front page of the manual they claim 15.75-50Khz scanning and 40-100Hz vertical, so of course there they ad another 10Khz to horizontal which I do not see as even possible from what I've seen it do above 40 let alone 38.9.  I think the vertical can go up to 100Hz technically, but I don't see how that could actually happen and at most have seen around mid 70Hz vertical I think max actually get used.  Maybe there's lower resolutions, I don't know tons about the possibilities since I am just learning about this.  Also those ranges I choose for horizontal freq are part speculation and seem to be confirmed from not running into issues yet with them.  Really only issue was the VGA->SVGA point which otherwise my guesses were maybe correct (although I guess the month or two I've been through fiddling with things my guesses are from that experience and some intuition about it from what I've experienced).  What's odd is that this d9800 monitor seems to not be very well documented as so capable, maybe from the bad experiences with the 9200 and people think the 9200 is the same but it's completely limited compared to the 9400/9800 models.  The 9200 seems to be truly fixed around 1Khz at three points and also can sort of go up to SVGA but I guess it's not meant to do it.  I guess the 9200 dies to easily though for them to be of much importance, at least from what I can tell, they are a big hassle to keep alive into older age.  So these line limits, are we basically following them most likely already in the code, jumping from one set to the other as they calculate out too much Horzontal Khz or too little?  I'm pretty amazed at looking at the amount of lines added vertically when too small and other adjustments, where in lrmc I could see nothing and it was a black box it seemed of what had happened.  Also I like how your calculations make it so the actual active lines are the real resolution size we wanted no matter what even if there are margins.  In lrmc it was being 'honest' about this and calling active lines the whole screen visible which of course isn't really what we need because we are trying to create a resolution mame/SDL will actually choose by active lines matching.  I always suspected there was a lot more flexibility in these modelines from studying the ones SailorSat came up with and seeing how they were way better than lrmc but didn't obey the same rules lrmc enforced.  Now I'm seeing how partly that's possible, and neat to have the actual code doing it somewhat understandable to me (last reworking of it moving things around completely really helped me see all the different tests and changes to make things work). 

I'm guessing now that doublescan would essentially be going to everyplace interlace is done/calculated and doing it when smaller instead of bigger than our vertical limits and then dividing by 2 instead of multiplying by 2 in the places where the interlace variable is put into the equation.  Also from what I can tell, though I'm pretty sure, basically every time the virtualization happens interlacing is done? 

Also do you think the dotclock increments you saw are the hardware, just that one chip for that radeon version, or constant on all radeon/ati or other chips, or possibly just the Windows driver?  It's interesting with that because sometimes I suspect from looking at the d9800 OSD with it telling me the values that it'll be off by .10 of what the modeline should be (although also it only is one decimal place out, so pacman is 60.5 sometimes).  I'm not sure if it's the card, linux video drm layer, or monitor or monitor miscalculation that makes it fluxuate like that  (or be different than what it calculates out to).  Just another thing I've been thinking about, and I read before about how I guess the increments of dotclocks are in 250 or something, that modern video cards have some limit to how precise they can be.

Does seem like the modeline output so far has been quite nice though for ranges from 15-40Khz so it does seem like, as long as the monitor specs are in there and maybe the d9800 are good generic ones somewhat, this is the most useful modeline generator I've actually been able to use.  All others are always very specific to a either normal modern monitors or there's lrmc and a few others for arcade monitors, but not anything that really can bridge all them together like I'm seeing.  That's my goal, is to try and make this able to really do all modelines, because that's what I've been hunting for since I got this d9800 and I seriously don't see how anyone else has ever gotten full use of the d9800 monitor because I didn't see it out there in Windows or Linux, something that could go through the whole range and adjust to any resolution and vertical refresh rate.  I think the only vertical refresh rates I can't create and have to throttle on are ones like Tron and Journey that have that odd 512 high vertical lines at 30Hz (which is odd, was there interlacing involved or something?) .  I can even run Starwars at 40Hz with nothrottle, it's a bit odd at first but you realize that's how it looked in the arcade, was the low Vertical refresh that gave it that characteristic it had.

Also that brings up another question about vector games, right now I just go to 480 lines high and width depending on if they are vertical or not (actually 488 because of both 640x480 and 800x600 are either taken up by the X Windows desktop resolution and also there's an odd issue with a phantom 800x600 resolution xrandr seems to not allow, but will allow 801x600, even when I can't see any 800x600 resolution in existence).  Is this something that could be done better, should we just go for max lines and I should try 600 vertical on those since the d9800 can do it at that just fine?
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

SailorSat

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 1208
  • Last login:Yesterday at 11:32:27 pm
    • For Amusement Only e.V.
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .20)
« Reply #153 on: November 12, 2010, 01:55:43 am »
Wow, completely missed this thread.
I haven't read through your scripts yet, but certainly will take a look soon :).

The "biggest" problem I've encountered with generating modelines "on the fly" would be that most games use their own timing rules.

As an example there are those 60Hz 256line game.
Basic math says 15,720kHz / 60Hz leaves 262 lines in total.
262 lines total - 256 lines active = 6! lines for the porches and the sync

So these games most likely silently increased their horizontal frequency up to 16,000kHz, as most monitors out there should work fine when adjusted.
Now if you apply some basic formula like "okay, 10% of active lines for to the sync" you'll end up way higher on those games.

I've tried both calculations based on
- lines formula (V_Total = Height / pVActive {pVActive = 0.912})
- timing based calculations (V_Total = Frequency / Refresh)

Problem with the first is simple... you'll end up with to many lines and combined with the vertical refresh, to high vertical refresh.
The second one on the hand most likely will produce to small vertical sync as the reference Frequency is too low.

Best would be to do BOTH calculations and then use the golden middle of both results.
« Last Edit: November 12, 2010, 01:58:04 am by SailorSat »
I do all that stuff even without a Joystick ;)
Soft-15kHz, cabMAME, For Amusement Only e.V.


Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .20)
« Reply #154 on: November 12, 2010, 08:04:28 am »
Wow, completely missed this thread.
I haven't read through your scripts yet, but certainly will take a look soon :).

The "biggest" problem I've encountered with generating modelines "on the fly" would be that most games use their own timing rules.

As an example there are those 60Hz 256line game.
Basic math says 15,720kHz / 60Hz leaves 262 lines in total.
262 lines total - 256 lines active = 6! lines for the porches and the sync

So these games most likely silently increased their horizontal frequency up to 16,000kHz, as most monitors out there should work fine when adjusted.
Now if you apply some basic formula like "okay, 10% of active lines for to the sync" you'll end up way higher on those games.

I've tried both calculations based on
- lines formula (V_Total = Height / pVActive {pVActive = 0.912})
- timing based calculations (V_Total = Frequency / Refresh)

Problem with the first is simple... you'll end up with to many lines and combined with the vertical refresh, to high vertical refresh.
The second one on the hand most likely will produce to small vertical sync as the reference Frequency is too low.

Best would be to do BOTH calculations and then use the golden middle of both results.

Hi SailorSat,

The basic idea is to have your vertical blank in µs instead of percentages. For my Hantarex 9110, I work with a vertical blank of 1280 µs. So for the particular case you're proposing it would be done like this:

hfreq = vfreq * yres / ( interlace * ( 1 - vfreq * VerticalBlank ) ) = 60 * 256 / ( 1 * ( 1 - 60 * 0.00128 ) ) = 16637.78 Hz
vvt = hfreq / vfreq = 16637,78 / 60 = 277.29 -> 277 lines

So you need to go up to 16.64 KHz to achieve 256 active lines at 60Hz, which can be out of the limits of some monitors, but mine does accept. So this is useful to have 1942 and such games running at real 60 Hz when rotated in a horizontal monitor (that's why I started with all this stuff by the way http://www.marcianitos.in/foro/thread/33/35/13335_1.html).

Nice thing about these algorithms is that they work to get the best (or less bad) solution for any particular monitor. So if your monitor can't deal with 16.64 KHz but only with, say 16.20 KHz, you won't be able to get 256 lines@60Hz but you'll get as close as you can: 256 lines@58,48Hz.

« Last Edit: November 12, 2010, 08:08:42 am by Calamity »
Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

Calamity

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 7411
  • Last login:March 14, 2024, 05:26:05 am
  • Quote me with care
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .20)
« Reply #155 on: November 12, 2010, 01:02:31 pm »
Interesting, so those are the calculated out active line and blanking limits for those values. What's strange is how in the documentation they claim 40-100Hz vertical but from what I can tell it's impractical with the 15.250 (they claim 15.725 lower limit but it seems to push down to this just fine) to 38.9 (again they claim 40 here but it seems to get odd anywhere above this) Horizontal Khz limits.  Also on the front page of the manual they claim 15.75-50Khz scanning and 40-100Hz vertical, so of course there they ad another 10Khz to horizontal which I do not see as even possible from what I've seen it do above 40 let alone 38.9.  I think the vertical can go up to 100Hz technically, but I don't see how that could actually happen and at most have seen around mid 70Hz vertical I think max actually get used.  Maybe there's lower resolutions, I don't know tons about the possibilities since I am just learning about this.  Also those ranges I choose for horizontal freq are part speculation and seem to be confirmed from not running into issues yet with them.  Really only issue was the VGA->SVGA point which otherwise my guesses were maybe correct (although I guess the month or two I've been through fiddling with things my guesses are from that experience and some intuition about it from what I've experienced).  What's odd is that this d9800 monitor seems to not be very well documented as so capable, maybe from the bad experiences with the 9200 and people think the 9200 is the same but it's completely limited compared to the 9400/9800 models.  The 9200 seems to be truly fixed around 1Khz at three points and also can sort of go up to SVGA but I guess it's not meant to do it.  I guess the 9200 dies to easily though for them to be of much importance, at least from what I can tell, they are a big hassle to keep alive into older age.  So these line limits, are we basically following them most likely already in the code, jumping from one set to the other as they calculate out too much Horzontal Khz or too little?  I'm pretty amazed at looking at the amount of lines added vertically when too small and other adjustments, where in lrmc I could see nothing and it was a black box it seemed of what had happened.  Also I like how your calculations make it so the actual active lines are the real resolution size we wanted no matter what even if there are margins.  In lrmc it was being 'honest' about this and calling active lines the whole screen visible which of course isn't really what we need because we are trying to create a resolution mame/SDL will actually choose by active lines matching.  I always suspected there was a lot more flexibility in these modelines from studying the ones SailorSat came up with and seeing how they were way better than lrmc but didn't obey the same rules lrmc enforced.  Now I'm seeing how partly that's possible, and neat to have the actual code doing it somewhat understandable to me (last reworking of it moving things around completely really helped me see all the different tests and changes to make things work).

I have no experience with digital chassis and I'm really interested in the results you get out of this, in order to make a general method for all monitors. Mine is an analog monitor, and Hfreq range is about 1 KHz wide, but you can use a potenciometer to shift that 1 KHz window up or down. Modern monitors as yours should have all of its adjusting functionality done through it's OSD, however, it makes me wonder if that documented 15.725-40.000 window might be shifted down a bit. As you say, without documentation we can just speculate and test. It's the same with these ranges, I believe there must be a cutoff point where the monitor goes for a mode or the other, but if it has some autoadjusting mechanism maybe it can make this transparent for us. I made that Excel table to try to figure out how to solve the overlapping between ranges, as I'm guessing there will be some frontier modes that could be calculated within both adjacent ranges, so we might end up with two modelines with the same rate/score to choose from (maybe, after all, this rating system was too simple to work). I have the feeling (not confirmed) that the monitor will be more 'confortable' when showing that resolution on the lower part of each single range than on the upper part. So, a way to force it to do so can be to actually define one of these ActiveLinesLimit for each or our intervals, based on that values on the table, so that when we reach the area were both ranges overlap, the resulting mode from the lower range will be virtualized, so our method will choose the upper one without doubts. I'm guessing that the optimal value for this ActiveLinesLimit should be between the values named as Max (VfreqMin) and Max (Vfreq 60Hz), that's why I chose 288 for my monitor. However, I still have to think about this.

I'm guessing now that doublescan would essentially be going to everyplace interlace is done/calculated and doing it when smaller instead of bigger than our vertical limits and then dividing by 2 instead of multiplying by 2 in the places where the interlace variable is put into the equation.  Also from what I can tell, though I'm pretty sure, basically every time the virtualization happens interlacing is done?

Yes, in a way doublescan can be considered opposite to interlace but it's not so simple, I think it should divide dotclocks not lines.

Also do you think the dotclock increments you saw are the hardware, just that one chip for that radeon version, or constant on all radeon/ati or other chips, or possibly just the Windows driver?  It's interesting with that because sometimes I suspect from looking at the d9800 OSD with it telling me the values that it'll be off by .10 of what the modeline should be (although also it only is one decimal place out, so pacman is 60.5 sometimes).  I'm not sure if it's the card, linux video drm layer, or monitor or monitor miscalculation that makes it fluxuate like that  (or be different than what it calculates out to).  Just another thing I've been thinking about, and I read before about how I guess the increments of dotclocks are in 250 or something, that modern video cards have some limit to how precise they can be.

Well, this is a highly interesting stuff I'd like to test when possible. First, at least in Windows we have a limitation on the precision of the dotclock value, as it is stored using integers were each unit stands for 0.01 MHz, so 375 -> 3.75 MHz, 376 -> 3.76 MHz and so on. I don't know if this is a hardware limitation or not. But these values have to be converted to the dividers we talked about somewhere in the driver, and that's were we could see if it's possible to be more precise or not (not a trivial task for what I saw). Second, when you program a Radeon 9250 card for 3.75 MHz, you really get 3.749904, 376 gives 3.764327, etc.... but I haven't been able to find the logic and it seemed a little bit random, as the increments are not constant. It is almost sure it has to do with the dividers stuff. So I ended up making a table that stores all input dotclocks with their corresponding actual tested dotclock. That way I can predict the resulting Vfreq for my modelines with 0.002 Hz accuracy. It doesn't mean I can go so close for any input Vfreq, but at least I know what the result will be and how close to the requested Vfreq I'll get. You may wonder how I got those values. The only possible way (without an oscilloscope I believe) is by making a program that switches to your just created video mode and does vsync, then you measure resulting Vfreq as accurate as possible, and finally use that value to find the real dotclock by doing the calculations backwards. So you need to create a test modeline for any single input dotclock value... the test took hours to end. I have confirmed the same values for two different Radeon 9250, and also they seem to be correct with a Radeon X300, however, I don't know if they can be used with other Radeon.

Does seem like the modeline output so far has been quite nice though for ranges from 15-40Khz so it does seem like, as long as the monitor specs are in there and maybe the d9800 are good generic ones somewhat, this is the most useful modeline generator I've actually been able to use.  All others are always very specific to a either normal modern monitors or there's lrmc and a few others for arcade monitors, but not anything that really can bridge all them together like I'm seeing.  That's my goal, is to try and make this able to really do all modelines, because that's what I've been hunting for since I got this d9800 and I seriously don't see how anyone else has ever gotten full use of the d9800 monitor because I didn't see it out there in Windows or Linux, something that could go through the whole range and adjust to any resolution and vertical refresh rate.  I think the only vertical refresh rates I can't create and have to throttle on are ones like Tron and Journey that have that odd 512 high vertical lines at 30Hz (which is odd, was there interlacing involved or something?) .  I can even run Starwars at 40Hz with nothrottle, it's a bit odd at first but you realize that's how it looked in the arcade, was the low Vertical refresh that gave it that characteristic it had.

I really went through several different methods until I definitely got to that one working, starting from an Excel table, and understood that any algorithm that really intended to be as good as oneself doing the stuff by hand should somehow operate in the same manner as a person would do, adding line by line and checking results, so it needed to be iterated. What I hardly imagined is that it could be adapted so quickly to support multisync monitors. So definitely we should try to extend it to do all modelines, as this combined with the Linux modeline support you've achieved can be nearly perfect.

I've also wondered about those 30Hz modes, maybe they were interlaced. However, you can double Vfreq and use CabMame Redraw patch.

Also that brings up another question about vector games, right now I just go to 480 lines high and width depending on if they are vertical or not (actually 488 because of both 640x480 and 800x600 are either taken up by the X Windows desktop resolution and also there's an odd issue with a phantom 800x600 resolution xrandr seems to not allow, but will allow 801x600, even when I can't see any 800x600 resolution in existence).  Is this something that could be done better, should we just go for max lines and I should try 600 vertical on those since the d9800 can do it at that just fine?

Well, vector games are going to be stretched anyway, so I think the best approach is to virtualize their resolution. I think you asked before if virtualization involves interlacing. It does now, as it was designed for lowres monitors, however, we can make a progressive version of that algorithm, to be used within your upper ranges. The idea behind virtualization is to produce the biggest possible resolution with a given Vfreq. It came because at the beginning I also used a fixed resolution when stretching, say 640x480@60, but I found that if the game's original Vfreq was lower, say 57Hz, I had more lines to play with so could use a 512 lines or more resolution, producing a better and more defined picture. So the lower the Vfreq, the higher your vertical resolution can be, and the better the result of stretching will be. I used this specially for vertical games that were above 288 lines, however the same idea can be applied to vector games.
« Last Edit: November 12, 2010, 01:17:31 pm by Calamity »
Important note: posts reporting GM issues without a log will be IGNORED.
Steps to create a log:
 - From command line, run: groovymame.exe -v romname >romname.txt
 - Attach resulting romname.txt file to your post, instead of pasting it.

CRT Emudriver, VMMaker & Arcade OSD downloads, documentation and discussion:  Eiusdemmodi

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .20)
« Reply #156 on: November 12, 2010, 02:21:06 pm »
Wow, completely missed this thread.
I haven't read through your scripts yet, but certainly will take a look soon :).

The "biggest" problem I've encountered with generating modelines "on the fly" would be that most games use their own timing rules.

As an example there are those 60Hz 256line game.
Basic math says 15,720kHz / 60Hz leaves 262 lines in total.
262 lines total - 256 lines active = 6! lines for the porches and the sync

So these games most likely silently increased their horizontal frequency up to 16,000kHz, as most monitors out there should work fine when adjusted.
Now if you apply some basic formula like "okay, 10% of active lines for to the sync" you'll end up way higher on those games.

I've tried both calculations based on
- lines formula (V_Total = Height / pVActive {pVActive = 0.912})
- timing based calculations (V_Total = Frequency / Refresh)

Problem with the first is simple... you'll end up with to many lines and combined with the vertical refresh, to high vertical refresh.
The second one on the hand most likely will produce to small vertical sync as the reference Frequency is too low.

Best would be to do BOTH calculations and then use the golden middle of both results.

Glad to have your interest in this, have read through the whole Soft15Khz thread (took a few days) and it helped me get a lot  of the basic ideas on what needed to be done in  Linux and about modeline generation in general.  Actually the pacman modeline you generated at around 18Khz on a horizontal monitor setup for someone that got the correct 60.61Hz refresh rate originally inspired me/proved to me that my d9800 could actually do better than I had been doing and needed to get modelines that were better than the generic lrmc was doing (or any other modeline generators).  Fortunately Calamity has educated me with his code on the ways to get that kind of precision to both meet normal arcade monitors requirements and also fully use a d9800 type monitor to it's maximum potential.  I actually used switchres, have it working (think it still should work) in Windows with Soft15Khz, basically able to generate new modelines and eliminate the whole .ini file need which is just a simple matching the mame xml output res to what the Soft15Khz mode files contain/best match.  Definitely interested in what you think of the code and any knowledge you have to help improve the modelines generated by it, or if it can help Soft15Khz in any way.
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .20)
« Reply #157 on: November 12, 2010, 02:43:36 pm »
Interesting, so those are the calculated out active line and blanking limits for those values. What's strange is how in the documentation they claim 40-100Hz vertical but from what I can tell it's impractical with the 15.250 (they claim 15.725 lower limit but it seems to push down to this just fine) to 38.9 (again they claim 40 here but it seems to get odd anywhere above this) Horizontal Khz limits.  Also on the front page of the manual they claim 15.75-50Khz scanning and 40-100Hz vertical, so of course there they ad another 10Khz to horizontal which I do not see as even possible from what I've seen it do above 40 let alone 38.9.  I think the vertical can go up to 100Hz technically, but I don't see how that could actually happen and at most have seen around mid 70Hz vertical I think max actually get used.  Maybe there's lower resolutions, I don't know tons about the possibilities since I am just learning about this.  Also those ranges I choose for horizontal freq are part speculation and seem to be confirmed from not running into issues yet with them.  Really only issue was the VGA->SVGA point which otherwise my guesses were maybe correct (although I guess the month or two I've been through fiddling with things my guesses are from that experience and some intuition about it from what I've experienced).  What's odd is that this d9800 monitor seems to not be very well documented as so capable, maybe from the bad experiences with the 9200 and people think the 9200 is the same but it's completely limited compared to the 9400/9800 models.  The 9200 seems to be truly fixed around 1Khz at three points and also can sort of go up to SVGA but I guess it's not meant to do it.  I guess the 9200 dies to easily though for them to be of much importance, at least from what I can tell, they are a big hassle to keep alive into older age.  So these line limits, are we basically following them most likely already in the code, jumping from one set to the other as they calculate out too much Horzontal Khz or too little?  I'm pretty amazed at looking at the amount of lines added vertically when too small and other adjustments, where in lrmc I could see nothing and it was a black box it seemed of what had happened.  Also I like how your calculations make it so the actual active lines are the real resolution size we wanted no matter what even if there are margins.  In lrmc it was being 'honest' about this and calling active lines the whole screen visible which of course isn't really what we need because we are trying to create a resolution mame/SDL will actually choose by active lines matching.  I always suspected there was a lot more flexibility in these modelines from studying the ones SailorSat came up with and seeing how they were way better than lrmc but didn't obey the same rules lrmc enforced.  Now I'm seeing how partly that's possible, and neat to have the actual code doing it somewhat understandable to me (last reworking of it moving things around completely really helped me see all the different tests and changes to make things work).

I have no experience with digital chassis and I'm really interested in the results you get out of this, in order to make a general method for all monitors. Mine is an analog monitor, and Hfreq range is about 1 KHz wide, but you can use a potenciometer to shift that 1 KHz window up or down. Modern monitors as yours should have all of its adjusting functionality done through it's OSD, however, it makes me wonder if that documented 15.725-40.000 window might be shifted down a bit. As you say, without documentation we can just speculate and test. It's the same with these ranges, I believe there must be a cutoff point where the monitor goes for a mode or the other, but if it has some autoadjusting mechanism maybe it can make this transparent for us. I made that Excel table to try to figure out how to solve the overlapping between ranges, as I'm guessing there will be some frontier modes that could be calculated within both adjacent ranges, so we might end up with two modelines with the same rate/score to choose from (maybe, after all, this rating system was too simple to work). I have the feeling (not confirmed) that the monitor will be more 'confortable' when showing that resolution on the lower part of each single range than on the upper part. So, a way to force it to do so can be to actually define one of these ActiveLinesLimit for each or our intervals, based on that values on the table, so that when we reach the area were both ranges overlap, the resulting mode from the lower range will be virtualized, so our method will choose the upper one without doubts. I'm guessing that the optimal value for this ActiveLinesLimit should be between the values named as Max (VfreqMin) and Max (Vfreq 60Hz), that's why I chose 288 for my monitor. However, I still have to think about this.

I'm guessing now that doublescan would essentially be going to everyplace interlace is done/calculated and doing it when smaller instead of bigger than our vertical limits and then dividing by 2 instead of multiplying by 2 in the places where the interlace variable is put into the equation.  Also from what I can tell, though I'm pretty sure, basically every time the virtualization happens interlacing is done?

Yes, in a way doublescan can be considered opposite to interlace but it's not so simple, I think it should divide dotclocks not lines.

Also do you think the dotclock increments you saw are the hardware, just that one chip for that radeon version, or constant on all radeon/ati or other chips, or possibly just the Windows driver?  It's interesting with that because sometimes I suspect from looking at the d9800 OSD with it telling me the values that it'll be off by .10 of what the modeline should be (although also it only is one decimal place out, so pacman is 60.5 sometimes).  I'm not sure if it's the card, linux video drm layer, or monitor or monitor miscalculation that makes it fluxuate like that  (or be different than what it calculates out to).  Just another thing I've been thinking about, and I read before about how I guess the increments of dotclocks are in 250 or something, that modern video cards have some limit to how precise they can be.

Well, this is a highly interesting stuff I'd like to test when possible. First, at least in Windows we have a limitation on the precision of the dotclock value, as it is stored using integers were each unit stands for 0.01 MHz, so 375 -> 3.75 MHz, 376 -> 3.76 MHz and so on. I don't know if this is a hardware limitation or not. But these values have to be converted to the dividers we talked about somewhere in the driver, and that's were we could see if it's possible to be more precise or not (not a trivial task for what I saw). Second, when you program a Radeon 9250 card for 3.75 MHz, you really get 3.749904, 376 gives 3.764327, etc.... but I haven't been able to find the logic and it seemed a little bit random, as the increments are not constant. It is almost sure it has to do with the dividers stuff. So I ended up making a table that stores all input dotclocks with their corresponding actual tested dotclock. That way I can predict the resulting Vfreq for my modelines with 0.002 Hz accuracy. It doesn't mean I can go so close for any input Vfreq, but at least I know what the result will be and how close to the requested Vfreq I'll get. You may wonder how I got those values. The only possible way (without an oscilloscope I believe) is by making a program that switches to your just created video mode and does vsync, then you measure resulting Vfreq as accurate as possible, and finally use that value to find the real dotclock by doing the calculations backwards. So you need to create a test modeline for any single input dotclock value... the test took hours to end. I have confirmed the same values for two different Radeon 9250, and also they seem to be correct with a Radeon X300, however, I don't know if they can be used with other Radeon.

Does seem like the modeline output so far has been quite nice though for ranges from 15-40Khz so it does seem like, as long as the monitor specs are in there and maybe the d9800 are good generic ones somewhat, this is the most useful modeline generator I've actually been able to use.  All others are always very specific to a either normal modern monitors or there's lrmc and a few others for arcade monitors, but not anything that really can bridge all them together like I'm seeing.  That's my goal, is to try and make this able to really do all modelines, because that's what I've been hunting for since I got this d9800 and I seriously don't see how anyone else has ever gotten full use of the d9800 monitor because I didn't see it out there in Windows or Linux, something that could go through the whole range and adjust to any resolution and vertical refresh rate.  I think the only vertical refresh rates I can't create and have to throttle on are ones like Tron and Journey that have that odd 512 high vertical lines at 30Hz (which is odd, was there interlacing involved or something?) .  I can even run Starwars at 40Hz with nothrottle, it's a bit odd at first but you realize that's how it looked in the arcade, was the low Vertical refresh that gave it that characteristic it had.

I really went through several different methods until I definitely got to that one working, starting from an Excel table, and understood that any algorithm that really intended to be as good as oneself doing the stuff by hand should somehow operate in the same manner as a person would do, adding line by line and checking results, so it needed to be iterated. What I hardly imagined is that it could be adapted so quickly to support multisync monitors. So definitely we should try to extend it to do all modelines, as this combined with the Linux modeline support you've achieved can be nearly perfect.

I've also wondered about those 30Hz modes, maybe they were interlaced. However, you can double Vfreq and use CabMame Redraw patch.

Also that brings up another question about vector games, right now I just go to 480 lines high and width depending on if they are vertical or not (actually 488 because of both 640x480 and 800x600 are either taken up by the X Windows desktop resolution and also there's an odd issue with a phantom 800x600 resolution xrandr seems to not allow, but will allow 801x600, even when I can't see any 800x600 resolution in existence).  Is this something that could be done better, should we just go for max lines and I should try 600 vertical on those since the d9800 can do it at that just fine?

Well, vector games are going to be stretched anyway, so I think the best approach is to virtualize their resolution. I think you asked before if virtualization involves interlacing. It does now, as it was designed for lowres monitors, however, we can make a progressive version of that algorithm, to be used within your upper ranges. The idea behind virtualization is to produce the biggest possible resolution with a given Vfreq. It came because at the beginning I also used a fixed resolution when stretching, say 640x480@60, but I found that if the game's original Vfreq was lower, say 57Hz, I had more lines to play with so could use a 512 lines or more resolution, producing a better and more defined picture. So the lower the Vfreq, the higher your vertical resolution can be, and the better the result of stretching will be. I used this specially for vertical games that were above 288 lines, however the same idea can be applied to vector games.


Thanks, I know I asked a lot of questions so will take me awhile to digest this and hopefully push some of it into the code, basically that was most of my current issues/questions I had.  I did just figure out how to do the rating/weighting of resolutions to where it should give the lowest score to the best, I had to push all those values for the codes to above 2048 and then use the bottom 2047 for storing the number of vertical lines padded with (and should have room for more) also the weights are actually not those values but I calculate them according to what values are stored in that result and then use the vertical padding to increase the weight more per 8 lines high.  That way a really padded resolution will not be as good as a lighter padded one yet they both have the same atributes.  Also weighted any vertical refresh rate more than most else, and not really weight a horizontal refresh rate change anything since as long as it's in range it shouldn't matter I'm guessing (maybe side padding though, I haven't looked at accounting for that yet I guess). 

I made the d9200 monitor config sections more exact to what it should be capable of, where each range is about 1Khz wide so it basically is a good test case.  From what I can tell it works pretty nice calculating for that and weighting it, so is good still even when it's more fixed freq than a d9800 is. 

Good to know about doublescan, I figured it wasn't that easy, looking at lrmc and doublescan and interlace stuff in there, it's quite a tangled mess and takes up most of the code actually adjusting for each of them.  Your way of doing interlaced is much simpler/cleaner and produces better results, I'm hoping to make doublescan the same way too since the main thing in lrmc that makes the code hard to read is the doublescan/interlace support.

Those 30Hz modes are really the only games I have to use throttle on now from what I can tell, since it's impossible to do otherwise, but will take a look at those cabmame patches again and see if that one works already in Linux or is one I can possibly port into the linux mame patch too. 

I'll try to get a virtualization function that is just for vector games, sounds interesting and will help me understand that virtualization function more.  I wondered why it always interlaced and that now makes sense, so sounds like the vector game one could be a function that either tries the maximum resolution progressive or closest vertical resolution to the game progressive.  When that is possible, otherwise do the interlaced version.

Also I tested my ubuntu kernel packages, and well they boot but they didn't have all the ubuntu patches that allow the best smoothest working with the system.  I just figured out how to get the newest patches for ubuntu kernels, actually they have a directory of them for the mainline Linux kernels so I was able to grab a clean applying 2.6.37-rc1 patch and it looks like I'll hopefully have real genuine working correctly Ubuntu 10.10 kernel packages with the arcade resolution patches applied.  I still think in Ubuntu 10.10 there's a bit of hacking at the xorg.conf to turn off the default modelines and possibly the grub.cfg cmd line to the kernel to enable the 640x480 interlaced arcade resolution framebuffer for the console (although if my fix works, it'll autodetect that for us).  It's easy stuff for anyone half familiar with Linux, but sadly a bit technical for anyone just using Linux since messing up your grub.cfg file or xorg.conf can be a painful thing to fix (at least grub.cfg, actually ubuntu doesn't use an xorg.conf file by default because Xorg mostly autodetects stuff.  That actually somewhat makes it a pain because then people need to create an xorg.conf first although Xorg -configure should output one that works and the default modeline thing can be added).  So when I get these newer ubuntu packages uploaded tonight or tomorrow, they take a few hours each to build, I hopefully will have something workable for people wanting to just install Ubuntu 10.10 and avoid building a new X Windows and patching/compiling the latest Linux kernel.
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .20)
« Reply #158 on: November 12, 2010, 10:13:06 pm »
Here's something interesting where I am guessing the mame info is way off on the vertical refresh rate. Saw zookeeper mentioned in another thread and I tried calculating and playing it, found a real odd one that must be masked by most setups with predefined modelines and/or using throttle.  Also this shows my weighting system when fed with the d9200 monitor stats, Basically mame reports a crazy refresh rate of 76.2 which makes it touch the sides of the screen at 256x256 and look ok, but it runs at 125% speed on nothrottle, so of course when I hardcode it with an .ini file to 60Hz it runs 100% perfect and some side borders but looks just as good.  So I don't see how in this case we could really ever know it was wrong, unless you push f11 or hear the audio and see it's running about 25% too fast at the reported mame stats (which also make no sense, they have 256 put into every field like it had no vertical or horizontal more than the active ones, just all is really odd or someone just rushed through shoving in values which are wrong).

256x256@76Hz calculations:
Code: [Select]
arcade@arcade ~/src/SwitchRes $ ./switchres -calcgame zookeep -mon d9200 -v
Display line for zookeep is:
  type: raster
  rotate: 0
  width: 256
  height: 256
  refresh: 76.293945
  pixclock: 5000000
  htotal: 256
  hbend: 0
  hbstart: 256
  vtotal: 256
  vbend: 0
  vbstart: 256

Using mame xml: [1 screen] zookeep horizontal 256x256@76.293945 --> 256x256@76.293945 aspect ratio 1.000

#  | Vertical refresh lowered | Horizontal frequency lowered |
# zookeep 256x256@59.14 16.500Khz score: 20
     "256x256" 5.676000 256 272 304 344 256 260 263 279 -HSync -VSync

*** Horizontal frequency 23.900Khz matches monitor range [0]: 23.900Khz - 24.420Khz
#  | Horizontal frequency raised | 18 lines Vertical padding |
# zookeep 256x256@76.29 23.955Khz score: 2
     "256x256" 8.240864 256 280 304 344 256 277 281 314 -HSync -VSync

*** Horizontal frequency 31.000Khz matches monitor range [0]: 31.000Khz - 32.000Khz
#  | Horizontal frequency raised | 107 lines Vertical padding |
# zookeep 256x256@76.29 31.050Khz score: 13
     "256x256" 10.185056 256 264 304 328 256 320 322 407 -HSync -VSync

*** Horizontal frequency 37.500Khz matches monitor range [0]: 37.500Khz - 38.500Khz
#  | Horizontal frequency raised | 209 lines Vertical padding |
# zookeep 256x256@76.29 37.535Khz score: 26
     "256x256" 12.912728 256 272 312 344 256 362 366 492 +HSync +VSync


*** Horizontal frequency 23.900Khz matches monitor range [1]: 23.900Khz - 24.420Khz
# zookeep 256x256@76.29 23.955Khz
     "256x256" 8.240864 256 280 304 344 256 277 281 314 -HSync -VSync


256x256@60Hz
Code: [Select]
arcade@arcade ~/src/SwitchRes $ ./switchres -calcgame zookeep -mon d9200 -v
Using game ini: zookeep 256x256@60.00 aspect ratio 1.000

#  | Vertical refresh lowered | Horizontal frequency lowered |
# zookeep 256x256@59.14 16.500Khz score: 20
     "256x256" 5.676000 256 272 304 344 256 260 263 279 -HSync -VSync

*** Horizontal frequency 23.900Khz matches monitor range [0]: 23.900Khz - 24.420Khz
#  | Horizontal frequency raised | 103 lines Vertical padding |
# zookeep 256x256@60.00 23.940Khz score: 12
     "256x256" 8.235360 256 280 304 344 256 319 323 399 -HSync -VSync

*** Horizontal frequency 31.000Khz matches monitor range [0]: 31.000Khz - 32.000Khz
#  | Horizontal frequency raised | 217 lines Vertical padding |
# zookeep 256x256@60.00 31.020Khz score: 27
     "256x256" 10.174560 256 264 304 328 256 375 377 517 -HSync -VSync

*** Horizontal frequency 37.500Khz matches monitor range [0]: 37.500Khz - 38.500Khz
#  | Horizontal frequency raised | 342 lines Vertical padding |
# zookeep 256x256@60.00 37.500Khz score: 42
     "256x256" 12.900000 256 272 312 344 256 428 432 625 +HSync +VSync


*** Horizontal frequency 23.900Khz matches monitor range [1]: 23.900Khz - 24.420Khz
# zookeep 256x256@60.00 23.940Khz
     "256x256" 8.235360 256 280 304 344 256 319 323 399 -HSync -VSync




I've been doing a ton of cleaning of code of the old cruft, minimalizing lrmc leaning so it eventually can be ripped out easily when no longer needing it, making all the output in verbose modes somewhat nice and readable to help debugging.  Figured now that the newer modeline generator seems less alpha and working pretty good, need to get things cleaner so it'll be easier to move into doing doublescan and figuring out ways to look at lower line limits and possibly using the weighting system more.  So far the weighting system oddly is always pointing at the resolution we autopicked, but if there was a case where we had different ranges of vertical frequencies for 2 fixed horizontal frequency ranges on a monitor (does that ever happen?) then it most likely fail right now at picking the right one.  I currently assume the monitor can do any vertical frequency in it's range for each of the horizontal frequency ranges.

Oh and for tron and other 30Hz games it looks like that redraw patch from Cabmame looks great and OS independent so I can put it into my linux mame patch, and start using it on the mame commmand line for the games like tron and get them to not need throttle hopefully.  Haven't tested that, but looks like it'll all work great, which makes that many fewer games that need throttling when following the monitors vertical refresh rate with waitvsync in Linux and the newer DRM kernel stuff.




Update: The Ubuntu packages for the patched kernel are up on the sourceforge site now, hopefully work nicer with the Ubuntu flavor of Linux and their patches to the system.

« Last Edit: November 12, 2010, 11:54:20 pm by bitbytebit »
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization

bitbytebit

  • Moderator
  • Trade Count: (0)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 896
  • Last login:August 02, 2019, 11:07:16 am
    • The Groovy Organization
Re: Switchres arcade monitor modeline generator and mame wrapper (ver .21)
« Reply #159 on: November 13, 2010, 03:49:58 am »
Ok, now has the framework to do weighting and does it if given the command line option, so there to play with and do tests although mostly gives the same result until we add more checks in the future for lines and such.  The cabmame redraw patch works great and is in the linux patch now, ported to Linux and compatible with the hi_score patch in there too (had a conflict with the standard hi_score patch I had applied since didn't patch both functions they duplicated).  Oddly the redraw patch doesn't help that zookeeper game, although I'm guessing it's a whole different thing going on there, but of course still works fine/great when forcing the .ini to 60Hz.  The code is cleaner, I hopefully made both the output with the verbose -v options much more helpful and

Version 0.21 -
* Major code cleanup, readability and verbose output now much better and informative
* depreciated lrmc even more, most options are gone specific for it (can still use -lrmc command line option for them)
* Merged in cabmame redraw patch to allow nothrottle on games at 30Hz and generally any game not meeting perfect vertical refresh values.
* -useweight option added to test/use new method of using weights for modelines generated when multiple ranges are set (like a d9800)
* d9200 monitor specs made more strict, good example of a trisync monitor with 3-4 fixed 1Khz wide horizontal freq points.
* Rating of modelines is there, really doesn't do anything different than normal checking through them (unless you manually put monitor ranges in the config file and they are out of order of horizontal freq values, then it would be a better choice to weight them).
SwitchRes / GroovyMame - http://arcade.groovy.org
Modeline Generator and Mame Wrapper for Windows or Linux
LiveCD of Groovy Arcade Linux for Arcade Monitors
GroovyMame - generate arcade resolutions like advancemame
--
The Groovy Organization