VOGONS


First post, by Blackthorn00

User metadata
Rank Newbie
Rank
Newbie

I have the screen filled with 40x25 8x8 tiles and I'm trying to implement tile-based (NOT pixel based) scrolling. I want to scroll by 8 pixel at a time.
I'm using 86Box and an emulated 386SX with a ISA16 video card for testing.

I'm using mode 13h and basically I write in a memory buffer. Then I wait for the retrace and do a rep movsw to copy to VRAM. It mostly works, but there is a consistent flickering on around line 16-20. With movsd, the flickering line moves down.

What I think it's happening is that my movs gets an head start and then the beam catches up. I changed the retrace code to wait for a transition from 1 to 0 to avoid the head start (which I assume I got from the VBI time), but what I got is that the flickering line is now around row 6-8 instead. My guess is that it's the overscan that is giving me a headstart that I don't need. I really want to just be behind the beam, not ahead of it.

I kinda fixed my issue with the following code. Basically I wait for the retrace to finish (transition from 1 to 0) and then:

mov cx, 2000
skip_time:
loop skip_time

rep movsw

This fixes the problem. Basically I just wait for the beam to go ahead and then start the copy.

The issue is that that 2000 changes based on the processor. With a 486, it needs to be 12000, and various speeds of 386 need different values.
(BTW a 486DX/2 with PCI video card doesn't have this issue at all. Either there is no overscan or the copy is so fast that can finish during the VBI, 🤣).

I'm curious about how old games fixed this. I know about mode-x, but before Doom popularized it, games used plain 13h, and yet they managed to have no flickering at all.

One way I'm thinking is that, during startup, I could measure how long it takes between two retraces and then create a formula to retrieve the magic value to used in an active loop to wait for. That would work, I guess, but a better way would be to find a way to poll for the scanline and start the movsw only after the overscan is over. Is there a way to do this?

If not, I'll just bite the bullet and learn mode-x.

Reply 1 of 3, by wbahnassi

User metadata
Rank Oldbie
Rank
Oldbie

I think the vblank period is too short to do the full move on a 386 SX (16?). Games back then relied on dirty rectangle updates and CRTC scrolling, so I think you are expecting too much here.
Scrolling 8 pixels at a time is possible both horizontally and vertically with CRTC start address registers. Then you only need to update one column/or row.. so much less work than entire screen copy.

Turbo XT 12MHz, 8-bit VGA, Dual 360K drives
Intel 386 DX-33, Speedstar 24X, SB 1.5, 1x CD
Intel 486 DX2-66, CL5428 VLB, SBPro 2, 2x CD
Intel Pentium 90, Matrox Millenium 2, SB16, 4x CD
HP Z400, Xeon 3.46GHz, YMF-744, Voodoo3, RTX2080Ti

Reply 2 of 3, by Blackthorn00

User metadata
Rank Newbie
Rank
Newbie

It's a 25 Mhz, but yeah, the vblank it's just too short for the whole copy. I'd be content to just follow the beam, but I can't know the starting moment due to overscan.

Reply 3 of 3, by wbahnassi

User metadata
Rank Oldbie
Rank
Oldbie

It's not a great idea in general to do continuous full-screen blits for such hardware generation, because once you have consumed all that time for executing one blit, what did you leave for other parts of the game? Logic, sound, input,...etc.
If you are willing to half the update frequency, then yes.. you can have maybe a full 12ms to do the blit.. but the game's smoothness will suffer of course.

Turbo XT 12MHz, 8-bit VGA, Dual 360K drives
Intel 386 DX-33, Speedstar 24X, SB 1.5, 1x CD
Intel 486 DX2-66, CL5428 VLB, SBPro 2, 2x CD
Intel Pentium 90, Matrox Millenium 2, SB16, 4x CD
HP Z400, Xeon 3.46GHz, YMF-744, Voodoo3, RTX2080Ti