Drawing line with use of $9004 blinks

Post Reply
Posts: 1
Joined: Mon Nov 29, 2021 6:41 am

Drawing line with use of $9004 blinks

Post by stenlik » Tue Dec 14, 2021 4:35 pm


I have made a simple VIC-20 program (attached), which waits for the raster beam, changes the color once the line is detected and on the next line it changes it back, so it draws a line. And it should stay like that. It loops forever, but sometimes SOMETHING goes wrong, so the background is filled with line color and itn result it blinks.

I cannot find what can possibly go wrong.
Or could that be caused by the VICE emulator (I have not tested it on real VIC-20)?

I have recorded a video: https://youtu.be/Df-67EqRFkY

Here is the code:

Code: Select all


  BYTE $0B, $10, $0A, $00, $9E, $34, $31, $30, $39, $00, $00, $00

SCREEN_COL_BORDER equ $900F     ; Screen and border register
RASTER_BEAM_LINE  equ $9004     ; Currently drawn raster beam line


        lda #%01011011          ; Black background and border
        ldy #%00001011          ; Red background and border
        ldx #50                 

red_line:                       ; Draw red line
        cpx RASTER_BEAM_LINE    ; Wait for raster line 30
        bne red_line
        sty SCREEN_COL_BORDER   ; Set the red color

        ldx #51

rest_black:                     ; Fill rest with the black color
        cpx RASTER_BEAM_LINE    ; Wait for raster line 31
        bne rest_black
        sta SCREEN_COL_BORDER   ; Set the red color
        jmp loop               ; Go tot start

Posts: 17
Joined: Mon Feb 17, 2020 6:09 pm

Re: Drawing line with use of $9004 blinks

Post by matibee » Wed Dec 22, 2021 1:56 pm

Hey Stenlik,
I know nothing about the Vic-20 so I've been reluctant to wade in. Hopefully your issue is more generic than that..

I assume $9004 is being updated during a scan line interrupt (or horizontal blank). This is the fraction of time it takes a CRT beam to finish at the right hand side of the screen, switch off (hence the term 'blank') return to the left edge of the screen (but on the line below) and begin drawing again. (There's a bit of overscan and underscan on each side of the display buying a little more precious time.)
These must be very small routines to avoid the code over-running and corrupting the next scan line - probably something as small as 12 cpu cycles (not instructions! cycles) or less.

Assume the scan line interrupt is very robust and updates the $9004 counter as expected, every time and on time, there's still no way of timing your code with the execution of the interrupt.

By the time the CPU comes around to running your comparison and realises you're on scan line $50, the raster beam could be at or very near the right edge of the screen. Your code will then be paused while the interrupt runs and by the time your code resumes and sets the background colour the system is already on the scanline below. And by the time your code has jumped to "rest_black" $9004 has updated again so you'll never see a positive direct comparison with $51 during this screen refresh.

Safest thing to do (if it's possible on the Vic-20) is to write a custom horizontal blank routine to do this instead. But as these routines have to be so small you won't be able to to take this existing code and run it as an interrupt. You're probably limited to having a look up table of colours for each scan line where you use the value at $9004 as an offset into that table and copy the value to "SCREEN_COL_BORDER". A really simple test of a custom interrupt handler would be to simply take the value at $9004 and copy it into the colour register -- that might even be all the cpu cycles the Vic-20 has to spare during a horizontal blank!

Timing anything with the horizontal blank is really tricky because of the speed it executes and the fact you can't control when it executes in relation to your own code.

Hope that helps :ThumbsUp

Post Reply

Return to “VIC-20 Assembly Programming”