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
Hobbyist coder for over 37 years! Last 20 years: C/C++, Windows, DirectX, OpenGL, Newton, JUCE, Godot.
Current collection: Atari; 2600, 800xl, 130xe, XEGS, 520stfm, 1040stfm, Lynx. SNES. Megadrive. GBA. PSP. 48k Speccy. C64, Amiga 500+. PS1, 2 & 3