VOGONS


Dosbox-x vga vsync issue

Topic actions

First post, by hornet1990

User metadata
Rank Newbie
Rank
Newbie

Hi

Not sure if this just a me problem but I unearthed some of my earliest VGA coding experiments from 30 years ago so tried recompiling (Watcom 10.6) and running it in dosbox-x (2nd May release, Visual Studio SDL1 - pretty much out of the box config) but it runs way too fast. The animation rate is tied to the vsync and should be updating every 4 frames (~67ms at 60Hz). The code in question is running double buffered and waiting for the retrace (reading port 0x03da) to copy the back buffer to the VGA memory (0xA0000), so in theory it should be running at ~60 to 75Hz but isn't.

The only way I can get it animating at a sensible speed is to massively drop the cpu cycles. I initially picked the "emulate P100" setting to match my machine of the day, but 53k cycles is way too high, 12k is better although arguably still a bit too quick, but then that drops it to 30fps, 6k drops it to 15fps. The vsync option under the video menu seems to make absolutely zero difference.

I tried another experiment (using Open Watcom 2 beta as my Watcom 10.6 refused to emit RDTSC) reading the RDTSC around the retrace and usually get ridiculously low and/or consistent values indicating that it isn't really waiting, or somehow 0x03da is being set according to the cpu cycles rather than real time of 1 second / refresh rate.

What am I missing? I then tried another test which just writes a pixel to the buffer, waits for the retrace, then copies the changed scanline to the display memory before plotting another pixel. In theory that should be taking 4 to 5 seconds to write a single line of 320 pixels (since it is writing 60-75 pixels per second in theory), but is taking less than a second per line with the same 12k cycle configuration.

The retrace code is this, and as far as I can remember worked fine on real hardware back in the day:

#pragma wait_retrace =  \
"mov dx,0x03da" \
"l1: in al,dx" \
"test al,0x08" \
"jnz l1" \
"l2: in al,dx" \
"test al,0x08" \
"jz l2" \
modify [edx eax] ;

Any ideas? Didn't many games and demos back in the 90's use vsync for their timing?

Thanks

https://rogueone.uk Kyro and other things

Reply 1 of 1, by MagefromAntares

User metadata
Rank Member
Rank
Member

Hi,

There is one of the functions I have used with Watcom C/C++ to wait for vsync, it is very similar, but there might be some difference in the way it is actually compiled as it uses the inline assembler syntax instead of the header pragma assembler syntax:

void wait_for_vsync()
{
_asm
{
push ax
push dx
mov dx, 0x3DAh
wait_vsync_1:
in al, dx
test al, 0x08h
jne wait_vsync_1
wait_vsync_2:
in al, dx
test al, 0x08h
je wait_vsync_2
pop dx
pop ax
}
}

Also note that the VGA refresh frequency for the standard 320x200 256 colour mode is 70Hz not 75Hz.

EDIT:

hornet1990 wrote on Today, 16:30:

The only way I can get it animating at a sensible speed is to massively drop the cpu cycles. I initially picked the "emulate P100" setting to match my machine of the day, but 53k cycles is way too high, 12k is better although arguably still a bit too quick, but then that drops it to 30fps, 6k drops it to 15fps. The vsync option under the video menu seems to make absolutely zero difference.

If it drops to exactly 30 and 15 fps then it means that it vsyncs to half or quarter of 60Hz instead of the 70Hz that the original VGA has, but Dosbox might emulate the VGA mode running the actual display of the computer you are using with a 60Hz refresh mode, and dropping down to 30 and 15 fps is a behaviour very possible when the CPU is too overloaded to get to the vsync loop with enough cycles to spare, so it syncs to half or quarter of the actual vsync frequency instead.

"A process cannot be understood by stopping it. Understanding must move with the flow of the process, must join it and flow with it." - Dune