All issues have been solved with this version, I'll keep testing...
One question I have about the doublescan vtotal amount, seems weird, I always get these .5 values to it and rounding up seemed to be bad and change the vertical refresh rate, seems like the linux DRM stuff rounds down or chops the decimal anyways, so should I just do that for something like this...
# transfrm 256x192@60.00 25.620Khz
Modeline "256x192x60.00" 9.223200 256 288 320 360 192 198 200 213.5 -HSync -VSync doublescan
You can either round up or chop, I prefer rounding up to avoid reducing the back porch. But always use integer elements if you want to properly predict the resulting vfreq, if you let Linux chop the values for you, your pre-calculated frequencies won't be accurate. So, what you have to do is convert to integers, and then, calculate your dotclock only once you have your definitive vvt and hht values.
So once you have vvt and hht, you can adjust dotclock so it fits your initial vfreq. Until now, you've been using granularity-free dotclocks, that's good for now, as it allows you to properly adjust to your initial vfreq whatever vvt and hht you have. However, that may not be true, and if it turns out that the dotclock has also a discrete nature, as it happens with Windows drivers, then if you want to be really accurate you have to deal with the problem of achieving a required vfreq out of three discrete values: dotclock, hht, vvt. That's why I made that interative loop, to test different combinations of discrete values for dotclock, hht, vvt, to see which one produced the closest vfreq. Using just 5 iterations, you can usually go as close as 0.02 Hz. But the disadvantage is that this method introduces additional verical padding, that even if it doesn't affect the picture at all, can colide with our brand new weighting system...
Cool, here's a diff that recalculates it and seems to work and get the integer vtotal and still the right vrefresh (seems this is only going to happen during doublescan from what I can tell)...
Also this fixes the padding value, I realized it needed a 2x since it was just one of the top/bottom values.
diff --git a/switchres b/switchres
index de15d1b..1417441 100755
--- a/switchres
+++ b/switchres
@@ -1216,7 +1216,7 @@ sub get_modeline($ $ $ @) {
my $interlace = 1;
my $VBlankLines = 0;
- my $margen = 0;
+ my $margin = 0;
my $VT = 0;
my $HFreq = 0;
my ($newDC, $newHh, $newHi, $newHf, $newHt);
@@ -1445,32 +1445,36 @@ sub get_modeline($ $ $ @) {
if ($interlace == 2) {
$VBlankLines += 0.5;
}
- $margen = (($VT * $interlace) - $OriginalHeight - ($VBlankLines * $interlace)) / 2;
- if ($margen) {
+ $margin = (int($VT * $interlace) - $OriginalHeight - ($VBlankLines * $interlace)) / 2;
+ if ($margin) {
$MODELINE_RESULT |= $VRES_PAD;
}
- $vb = $OriginalHeight + int(((($HFreq/1000)*$Mode[$ModeBase]{'VFrontPorch'}) * $interlace + $margen)+0.5);
+ $vb = $OriginalHeight + int(((($HFreq/1000)*$Mode[$ModeBase]{'VFrontPorch'}) * $interlace + $margin)+0.5);
$vc = $vb + int(((($HFreq/1000)*$Mode[$ModeBase]{'VSyncPulse'}) * $interlace)+0.5);
+ # Total vertical lines
+ $vtotal = int(($VT * $interlace)+0.5);
+
+ # Recalculate dotclock
+ $HFreq = $Refresh * ($vtotal/$interlace);
+ $DotClock = sprintf("%.6f", ($htotal * $HFreq)/1000000);
+
if ($VERBOSE > 1) {
- print "Modeline Calculation of " . sprintf("%.3f", $Refresh) . "Hz " .
+ print "Modeline Calculation of " . $DotClock . "Mhz " . sprintf("%.3f", $Refresh) . "Hz " .
sprintf("%.3f", $HFreq/1000) . "Khz " .
- $VT . " vtotal " . $VBlankLines . " vblank " . $margen . " vpad\n\n";
+ $VT . " vtotal " . $VBlankLines . " vblank " . ($margin*2) . " vpad\n\n";
}
- # Total vertical lines
- $vtotal = ($VT * $interlace);
-
# Modeline structure
- my $label = sprintf("%.3f", ($Mode[$ModeBase]{'HfreqMin'}/1000)) . "Khz - " .
+ my $label = sprintf("%.3f", ($Mode[$ModeBase]{'HfreqMin'}/1000)) . "Khz --> " .
sprintf("%.3f", ($Mode[$ModeBase]{'HfreqMax'}/1000)) . "Khz";
my %mline = ( 'name' => "$ModeName", 'pclock' => "$DotClock",
'hactive' => "$ha", 'hbegin' => "$hb", 'hend' => "$hc", 'htotal' => "$htotal",
'vactive' => "$va", 'vbegin' => "$vb", 'vend' => "$vc", 'vtotal' => "$vtotal",
'interlace' => '', 'doublescan' => '', 'hp' => '-HSync', 'vp' => '-VSync',
'hfreq' => "$HFreq", 'vfreq' => "$Refresh",
- 'result' => "$MODELINE_RESULT", 'vpad' => $margen, 'hpad' => 0,
+ 'result' => "$MODELINE_RESULT", 'vpad' => ($margin*2), 'hpad' => 0,
'label' => "$label");
# flags
I'm interested in creating a function to do your same figuring based upon dotclock values not being granular. One thing I read somewhere, on why the cvt calculations always are in 250 aligned amounts, is because modern video cards they claim aren't often able to get more fine grained than that. So it would be interesting for that, at least to see how that affects the line padding. Also then I could test plugging in your table of ATI values and really see if my d9800 suddenly perfectly hits the vrefresh rates on the OSD, I'm not sure if it's an accurate calculation it's doing though so it'd be interesting since if it did suddenly show perfect values it'd prove both the need for the dotclock check and that the OSD is accurate.
Also two other things I've been seeing. One is that it seems that the Linux DRM stuff requires the vertical height, only active lines, to be a division of 8 or else it will cause mame to lock until forcibly killed off, just gets stuck in a black screen and then have to restart X cause the OpenGL/SDL layer is all messed up and fonts are weird (really small). That's something that started happening on certain games after I started using the DRM stuff, and took a heck of a time to finally figure out that it was the height not being multiples of 8 and those were the games I was seeing this on. So for now it seems to work and maybe be better anyways to align the height, but figured I should mention that since it's something different I've seen.
The second is about the certain games I see that are possibly the wrong resolutions, like mk dbz and any game that reports a 1.5 or greater aspect ratio, that always seems to indicate it'll be too wide. I checked what the utilities like AVres do for these, and kind of figured out a way to make them work and seems to be what AVres does too. For these games I have a hack, but it's not enabled by default, where we walk up the height of the active lines till the aspect is 1.3 again. It seems to always equal what AVres does and actually makes games like dbz pretty close to perfect, then I also enable the 'unevenstretch' to make them utilize that screen size and at that they fit right since otherwise they are top/bottom boxed and seem a little wide I think (at least don't think they'd be letter boxed on an arcade machine unless were really on a 16:9 monitor, doubtful). These variables I use are $ASPECT_LARGE_HACK and there's a _SMALL_HACK version which I'm less sure of but does make games like Golden Tee which are oddly boxed on top and bottom fill up the screen. It's the opposite and has the less than 1.2 aspect ratio and for some reason gets big top/bottom right/left margins.
So those are the two odd cases I see with the either too big or two small games, and always seems to follow aspect ratio even though there are plenty of course which work fine with smaller aspect ratios than 1.3 and seem like they were just meant to stretch and have non-square pixels (would be nice to know a way to figure out which are right and which are needing the hack). I think the AVRes utility somewhat figures these things out, although not sure, the utility doesn't make a lot of great decisions from what I've experienced but this is one area it seems to somehow know something I don't about guessing how to get the games to fit right. Also I don't like the use of unevenstretch and that bothers me I have to do that, I have figured out that giving DBZ a 400x288 resolution works too without stretch but to get there automatically from the default of 384x256 seems really a bit unpredictable since I don't see an easy way to have calculated that (this sort of seems like what I did with the raise the height till 1.3 aspect then multiply that times the original odd 1.5 aspect and it would maybe get that 400x288, yet I didn't fully like doing that and might have found it not to be 100% correct).