Jump to content
IGNORED

I don't understand screen synchronisation


gorgh

Recommended Posts

Hi there folks, yesterday I started learning how to code on VCS and I'm having trouble understanding how VBLANK and VSYNC work.
On Atari 8 bit computers VBLANK is is generated by the hardware and it's simply an interrupt.
On VCS we need to keep track of the screen lines by either counting them or setting timer.

My question is... how can I tell in which scanline am I currently in? For example at the start of the program how do I know that I should do this:

               lda #0
               sta VBLANK
               lda #2
               sta VSYNC
 
               sta WSYNC
               sta WSYNC
               sta WSYNC      ; 3 scanlines of VSYNC signal
 
               lda #0
               sta VSYNC


If I understand correctly the code must have exactly the number of cycles that the frame has (including WSYNC waiting) otherwise it will make the screen to flip... or won't?
Or maybe writing to VBLANK stops the processor so it can start execution at the start of the VBLANK period?
I'm quite confused here, any help will be appreciated, thanks!

EDIT: What I am missing is understanding how to synchronise my program with the current frame, how to tell that Overscan or Vblank are taking place right now

Edited by gorgh
Link to comment
Share on other sites

You are not syncing your code to a frame, your code is creating the frame. The number of cycles your code needs, defines where you are and how many scanlines a frame has. To create a valid frame (e.g. 262 scanlines), you have to make sure your code requires the correct number scanlines for execution. Usually that means that the VBlank and Overscan areas above and below the kernel use a timer (so that the code is does not need to sync to scanlines), while the display kernel itself counts scanlines.

  • Like 2
Link to comment
Share on other sites

As Thomas says, YOU are effectively the graphics hardware that creates the correct signals that tell the TV what a frame is.

The VBLANK tells the TV to reset the electron beam to the top of the screen and begin scanning.  The actual timing and generation of the rest of the frame is what your code does. The simplest way is to start a timer (look at TIM64T) and wait for it to expire. Then you send the appropriate "end of frame" stuff (overscan).  You can/should replace the "wait for stuff" with your code that sets the registers for playfield/sprites on each and every scanline. By adjusting the timer, you can adjust the total number of scanlines the "wait" encompasses. By adjusting the number of scanlines, you adjust the frame frequency.  PAL uses 312 scanlines and is 50Hz.  NTSC uses 262 scanlines and is close to 60Hz. So a typical frame you generate might be...   do VBLANK, set TIM64T, do some blank scanlines, do about 200 scanlines of content, wait for timer to expire, do the overscan stuff, repeat.

Link to comment
Share on other sites

13 hours ago, gorgh said:

On Atari 8 bit computers VBLANK is is generated by the hardware and it's simply an interrupt.
On VCS we need to keep track of the screen lines by either counting them or setting timer.

 

13 hours ago, gorgh said:

What I am missing is understanding how to synchronise my program with the current frame, how to tell that Overscan or Vblank are taking place right now

The Atari 8 bit computers have an extra graphics chip, ANTIC, allowing frame synchronization and DLI's.

 

You may find Flashback or SuperCharger BASIC a more familiar environment because it includes a soft ANTIC that can drive the TIA independently allowing you to synchronize your BASIC or Assembly program with the current frame and create display list interrupts that scroll sections of the screen in different directions and modes like the Atari 8 bit computers. Here is a recent example from SillyVenture2020+1. 

 

  • Like 1
Link to comment
Share on other sites

thanks for the answers. My question was about something else, though. I spoke with my friend and he told me that setting D1 of VSYNC for 3 scanlines force TV display to wait for vertical synchronisation, which means that it synchronises with a frame, could you confirm that? What about the situation where my program has let's say 260 or 258 scanlines?

Link to comment
Share on other sites

I've got another question... I try to animate the sprites but sometimes when I run the file on Stella emolator the it works good and sometimes horizontal positioning of the sprites seem to be wrong. Here's my code:

               SEG
               ORG $F000

 

fineAdjustBegin
           .byte %01110000; Left 7  
           .byte %01100000; Left 6
           .byte %01010000; Left 5
           .byte %01000000; Left 4
           .byte %00110000; Left 3
           .byte %00100000; Left 2
           .byte %00010000; Left 1
           .byte %00000000; No movement.
           .byte %11110000; Right 1
           .byte %11100000; Right 2
           .byte %11010000; Right 3
           .byte %11000000; Right 4
           .byte %10110000; Right 5
           .byte %10100000; Right 6
           .byte %10010000; Right 7           
           
fineAdjustTable EQU fineAdjustBegin - %11110001

PosObject  
           sta WSYNC      ; 00     Sync to start of scanline. 
           sec            ; 02     Set the carry flag so no 
                          ;        borrow will be applied  
                          ;        during the division. 
divideby15 sbc #15       ; 04     Waste the necessary amount  
                          ;      of time dividing X-pos by 15! 
           bcs divideby15  
                    ; 06/07   
                    ; 11/16/21/26/31/36/41/46/51/56/61/66 
           tay 
           lda fineAdjustTable,y  ; 13 -> Consume 5 cycles by 
                                     ; guaranteeing we cross a 
                                     ; page boundary 
           sta HMP0,x 
           sta RESP0,x   ; 21/ 26/31/36/41/46/51/56/61/66/71 
						; Set the rough position. 
           rts 

 

 


I invoke the horizontal positioning procedure after the kernel, and it goes like this:

                lda #%00000010
                sta VBLANK
                
                sta WSYNC
               
                lda $91
                bmi decr1
incr1
                inc $8c
                lda $8c
                cmp #150
                bcc fine1
                pha
                lda $91
                eor #$ff
                sta $91
                pla
                jmp fine1
decr1                
                lda $8c
                dec $8c
                cmp #2
                bcs fine1
                pha
                lda $91
                eor #$ff
                sta $91
                pla
                
fine1                
                sta GRP0
                ldx #0                ;player 0                
                jsr PosObject

                lda $92
                bmi decr2
incr2
                inc $8d
                lda $8d
                cmp #150
                bcc fine2
                pha
                lda $92
                eor #$ff
                sta $92
                pla
                jmp fine2
decr2                
                lda $8d
                dec $8d
                cmp #2
                bcs fine2
                pha
                lda $92
                eor #$ff
                sta $92
                pla
                
fine2                
                sta GRP1
                ldx #1                ;player 1                
                jsr PosObject

                sta WSYNC
                sta HMOVE
                
               ldx #0
Overscan       sta WSYNC
               inx
               cpx 25
               bne Overscan

 

 

 

glitch.gif

 

 

good.gif

spr.asm spr.bin

Edited by gorgh
Link to comment
Share on other sites

4 hours ago, gorgh said:

thanks for the answers. My question was about something else, though. I spoke with my friend and he told me that setting D1 of VSYNC for 3 scanlines force TV display to wait for vertical synchronisation, which means that it synchronises with a frame, could you confirm that? What about the situation where my program has let's say 260 or 258 scanlines?

Well, you're still not quite getting it.

The TV has no internal concept of "a frame". It simply responds to electrical signals of the TV signal.

When you write VSYNC, you effectively adjust the signal that the TV sees, which causes an *immediate* start of new frame.

There's no "waiting" by the TV, because the TV doesn't have some sort of "state" or concept of how long a frame it. It just response, as I mentioned, to the signal that it is fed. You can, therefore, send all sorts of weird stuff to it.  So "what about ...260/258" -- well, most TVs will display this happily. At a higher frame rate because you are sending less scanlines per second, so your frame rate increases proportionally. The TV doesn't *know*... it is simply responding to the signal that you effectively send it by writing registers on the '2600. Again, there is no concept of the TV "waiting" for vertical synchronisation.

Link to comment
Share on other sites

thank you for your answer, if I may I have some more questions...
If there's immediate start of a new frame after the VSYNC change then what happens with the electron beam gun of the TV display? As far as I know it takes some time for the beam to return to its original start position.

Edited by gorgh
Link to comment
Share on other sites

41 minutes ago, gorgh said:

thank you for your answer, if I may I have some more questions...
If there's immediate start of a new frame after the VSYNC change then what happens with the electron beam gun of the TV display? As far as I know it takes some time for the beam to return to its original start position.

 

Have a look at some sample kernel code for the exact process on the '2600.

At the bottom of the screen, after you've drawn your scanlines (say, 200 of them), then the electron beam is turned off (via VBLANK) and you have a fairly hefty delay (the vertical blank). When that delay is done, then you toggle VSYNC (it's a 3 scanline-long toggle) that starts the new frame. You'll need to verify this next bit; but as I understand it, at that point you are at the top of the screen and effectively drawing stuff.  From the Stella Programming Manual...

 

"All horizontal timing is taken care of by hardware, but the microprocessor must “manually” control vertical timing to signal the start of the next frame. When the last line of the previous frame is detected, the microprocessor must generate 3 lines of VSYNC, 37 lines of VBLANK, 192 lines of actual TV picture, and 30 lines of overscan. "

 

I'd say the vertical retrace of the beam happens at the start of the VSYNC, but someone may very well correct me on this one.

 

 

 

Link to comment
Share on other sites

Thanks for the answer Andrew, Im passionate about vcs coding and all the help is appreciated.
Now I have a problem with sprites as I mentioned above. Even when I do not change the position of the sprite it tends to change it's HMPx position..all I do is to rewrite  the same position to the RESPx and HMPx but still at some runs of Stella emulator it works differently - sometimes it moves and sometimes it stays still. It's bothering me because I can't find a solution to this... all I know is that writing to HMPx couple times may alone change the position of the sprite.

spr.bin

Link to comment
Share on other sites

On 9/5/2021 at 9:19 AM, Andrew Davie said:

When you write VSYNC, you effectively adjust the signal that the TV sees, which causes an *immediate* start of new frame.

There's no "waiting" by the TV, because the TV doesn't have some sort of "state" or concept of how long a frame it. It just response, as I mentioned, to the signal that it is fed. You can, therefore, send all sorts of weird stuff to it.  So "what about ...260/258" -- well, most TVs will display this happily. At a higher frame rate because you are sending less scanlines per second, so your frame rate increases proportionally.

What you're saying sounds like you could write a 2600 game that generates a 120 FPS display (on a CRT) by only outputting, say, 100 lines per field.

 

This seems... unlikely.

Link to comment
Share on other sites

3 minutes ago, ZylonBane said:

What you're saying sounds like you could write a 2600 game that generates a 120 FPS display (on a CRT) by only outputting, say, 100 lines per field.

 

This seems... unlikely.

The frame rate varies by the number of total lines, but as you get farther from spec, less TVs will display it properly. No TV is going to display a 120 FPS display this way, I'm pretty sure.

Link to comment
Share on other sites

2 hours ago, ZylonBane said:

What you're saying sounds like you could write a 2600 game that generates a 120 FPS display (on a CRT) by only outputting, say, 100 lines per field.

 

This seems... unlikely.

Pretty interesting idea I'll have to try that :) 

2 hours ago, Karl G said:

The frame rate varies by the number of total lines, but as you get farther from spec, less TVs will display it properly. No TV is going to display a 120 FPS display this way, I'm pretty sure.

To generate a full screen NTSC display we are limited to a maximum of 60 FPS which is double the framerate of classic CRT Television, the nonstandard Atari video signal not offsetting the encapsulated 30 Hz fields in the subcarrier so they become full frames.

 

It is possible to subdivide the frame rate from this spec. STARBLITZ plays at 60,30,20,15,12,10,8.57 and 7.5 Hz sequencing for the video and audio with the frame rate matching the Hz on all but the 60 Hz mode.  When it doesn't match we get another type of flicker called motion blur, there's a thread here on the BlurBusters forum with a parallel researcher taking 120,240 and 480 Hz experiments into the stratosphere with more powerful CRT kit.

 

Link to comment
Share on other sites

14 hours ago, Karl G said:

The frame rate varies by the number of total lines, but as you get farther from spec, less TVs will display it properly. No TV is going to display a 120 FPS display this way, I'm pretty sure.

 

I created a test program when I added jitter support to Stella, it lets you interactively control the number of scanlines.  The default output of 128 rainbow lines creates a total of 262 scanlines @ 60 Hz.

 

163867409_ScreenShot2021-09-11at11_36_53AM.thumb.png.15748edb245d67d81df917ec43587bf4.png

 

Use your joystick to adjust the count, then hold FIRE for it to be active.  Example counts and HZ:

  • 1 = 135 total scanlines @ 116.4 Hz
  • 64 = 198 @ 79.4 Hz
  • 128 = 262 @ 60 Hz (NTSC)
  • 178 = 312 @ 50 Hz (PAL, Stella needs to be in PAL mode for a stable image)
  • 192 = 326 @ 47.9 Hz (Stella in PAL mode)
  • 225 = 359 @ 43.5 Hz (Stella in PAL mode, largest image that's stable in Stella)
  • 0 = 390 @ 40 Hz (0 outputs 256 rainbow scanlines)

I posted some tests here with my Commodore 1084S monitor and found that 51 was stable (185 scanlines @ 85.0 Hz):

 

image.thumb.jpeg.32169e374ceba4dba2152aea815d7639.jpeg

 

You can see the VSYNC at the top of the screen, this could be hidden by adjusting the monitor to expand the image vertically.

 

50 and 49 were unstable on the 1084S, while from 48 down to 1 it was stable but would generate 2 images:

 

image.thumb.jpeg.6bff3178a5bb56d443a8afab2127ca8c.jpeg

 

Different displays will support a different range of total scanlines.

 

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...