Animations in Machine Language

Basic and Machine Language

Moderator: Moderators

Post Reply
randolph.pickle
Vic 20 Amateur
Posts: 55
Joined: Thu Nov 27, 2014 10:50 am

Animations in Machine Language

Post by randolph.pickle »

Hi everyone,

I'm in the middle of learning machine language and I would like to start programming some simple animations. For example, I want to clear the screen and have a character move back and forth horizontally from one edge of the screen to the next. The problem is that (as you might imagine) this happens way too fast! But, if I add a busy loop, what's to ensure that the part of the screen with my bouncing character won't be drawn when I have erased the character at its old location and have not drawn the character at its new location.

What can I do in my main loop to both slow it down, and ensure that the screen is drawn in a state that I want?
User avatar
beamrider
Vic 20 Scientist
Posts: 1447
Joined: Sun Oct 17, 2010 2:28 pm
Location: UK

Re: Animations in Machine Language

Post by beamrider »

The best way to pace animations is to use interupts and lock them to the raster beam. In the handler set a flag every time the raster leaves the screen and use this as a queue to kick off your code.

You can then vary the animation speed of your objects by either a divider on the calls to slow down or increasing the pixel stepping to speed up. If you hunt around on the net you should be able to find a stable raster routine for the vIC - there is one in the source code of the Vic SSS library for instance.
User avatar
pixel
Vic 20 Scientist
Posts: 1330
Joined: Fri Feb 28, 2014 3:56 am
Website: http://hugbox.org/
Location: Berlin, Germany
Occupation: Pan–galactic shaman

Re: Animations in Machine Language

Post by pixel »

If you don't want to get into interrupt programming right away you can also use this simple loop to sync it with the video output:

Code: Select all

wait:	lda $9004 ; Currently displayed raster line.
	bne wait ; Repeat until it's 0.
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
randolph.pickle
Vic 20 Amateur
Posts: 55
Joined: Thu Nov 27, 2014 10:50 am

Re: Animations in Machine Language

Post by randolph.pickle »

Thanks for the replies guys. I've been doing more research into this and am at the very least aware of what I should be searching around for :) .

Would I need to check bit 7 of $9003 pixel, in addition to $9004. I would assume if I didn't I could lose one raster line initially? Also, I assume when the raster counter is at 0, vertical blanking has started, and I'm free to change the screen however I wish until some further value I'm not sure of. And of course, I better have everything done before the next redraw or my frame rate will drop.
User avatar
Mike
Herr VC
Posts: 4816
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Animations in Machine Language

Post by Mike »

pixel wrote:If you don't want to get into interrupt programming right away you can also use this simple loop to sync it with the video output:

Code: Select all

wait:	lda $9004 ; Currently displayed raster line.
	bne wait ; Repeat until it's 0.
The reasons why this isn't a particularly good solution, especially on NTSC, are explained in the thread 'QUIKMAN 2008 for the unexpanded VIC 20'. Further down the thread, a small example shows how to utilize a VIA timer for a better solution ...
beamrider wrote:If you hunt around on the net you should be able to find a stable raster routine for the VIC [...]
... which actually doesn't even require a 'stable', i.e. jitter-free/cycle-exact interrupt. Both VIC chip and VIA run on the same clock, so they can't drift, and for this application raster-accuracy is sufficient.
randolph.pickle
Vic 20 Amateur
Posts: 55
Joined: Thu Nov 27, 2014 10:50 am

Re: Animations in Machine Language

Post by randolph.pickle »

Thanks Mike. The explanation as to why it is a bad idea was very clear, but I'm having some trouble digesting the solution. I'll keep at it though and post any future questions I might have.
User avatar
pixel
Vic 20 Scientist
Posts: 1330
Joined: Fri Feb 28, 2014 3:56 am
Website: http://hugbox.org/
Location: Berlin, Germany
Occupation: Pan–galactic shaman

Re: Animations in Machine Language

Post by pixel »

randolph.pickle wrote: Would I need to check bit 7 of $9003 pixel, in addition to $9004. I would assume if I didn't I could lose one raster line initially? Also, I assume when the raster counter is at 0, vertical blanking has started, and I'm free to change the screen however I wish until some further value I'm not sure of. And of course, I better have everything done before the next redraw or my frame rate will drop.
If you wanted to show Mike & Co what graphics programming is about you'd certainly have to check that low bit as well. I'm sure no-one here will live to see it. ;)
Depending on what you're hacking it might even be a good idea to synchronize everything in the middle of the screen. But don't get hung up in the details too early. Get it roughly done and THEN optimize. No-one can foresee the complexity of a non-trivial program.
"Pulse" for example (sorry, don't have anything else to pull out yet) is doing it totally "wrong". ;) It doesn't ever wait for any raster line. Instead it tries to spend about the same time for each frame to keep everything steady, draws a new frame over the old one and then removes what's left of the old frame.
It's working nicely because the best rendering engine is between the ears.

I'm pretty sure that, if we want to see new magic after all these years, we have to allow for flaws.
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
randolph.pickle
Vic 20 Amateur
Posts: 55
Joined: Thu Nov 27, 2014 10:50 am

Re: Animations in Machine Language

Post by randolph.pickle »

After digging into several games, I found that there are many ways to slow down a ML loop. Everything from the classic busy loop using the index registers, to reading $A2 until the jiffy clock is updated, to polling $9004 until the value there sets the negative flag. However, I'm still curious about your solution Mike, so I have a question. How did you come up with the values for the T1 counter and the scan line you wait for? I understand what the code is doing, but my lack of knowledge prevents me from really understanding why $4243 and $75.
User avatar
Mike
Herr VC
Posts: 4816
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Animations in Machine Language

Post by Mike »

First of all, those two values, $4243 and $75, only apply to NTSC with the display window set at standard position. For PAL, you'd use $5686 and $82, respectively.

It should be clear, that the number of cycles between VIA T1 interrupts must be the same as number of cycles per frame, so the interrupt is issued at exactly the same position for each frame. Actually, the timer underflows to 0 and -1 before it is reloaded from the latch value, which is the reason you have to load the number of cycles minus 2 into the latch.

NTSC has 261 lines with 65 cycles each, PAL has 312 lines with 71 cycles each. And 261*65-2 = 16963 = $4243, 312*71-2 = 22150 = $5686. A constructive way to verify those values would be to use a slightly different one, then you'll see that the interrupt position begins to drift: upwards for smaller values (as it takes less time for subsequent interrupts) or downwards for larger values (as it then takes more time for the next interrupt to occur).

The values $75 (NTSC) and $82 (PAL) were more or less derived by experiment. They have been chosen so the interrupt happens in the first raster line below the display area, to maximize the time until the display area of the next frame begins. Other applications might require to sync the VIA interrupt to a raster line shortly before a certain effect is supposed to happen.

The exact begin of interrupt processing can be delayed by up to 7 cycles, depending on when the current instruction ends. Furthermore, the initial sync to the raster line can introduce another (permanent!) inaccuracy of another 7 cycles because of the CMP/BNE loop. And actually, the initial sync should first check for the raster value being *not* in the register, so it doesn't trigger already first time the loop has been entered and so puts the interrupt position somewhere in the (double) line up to its end (but not near the beginning anymore).

However, these considerations in the last paragraph are only important for cycle exact/stable interrupts. You'd need these only for much more demanding applications than syncing an animation to the frame. For these more involved applications, methods exist to sync the interrupt position with single cycle accuracy (i.e., better than the 7 cycle accuracy of the simple CMP/BNE loop) and, when the interrrupt has happened, introduce an own variable delay to compensate the interrupt delay, so the own interrupt routine begins processing at the exact same position (not only raster!) on screen each frame.

For one example, take a look at the VFLI panning slide show. Here, the interrupt is synced to a position slightly above the display window. For another example, Victragic's version of Pitfall! draws the background entirely by changing the background register as the raster beams races along the screen, in a *big* cycle exact interrupt routine. :)
randolph.pickle
Vic 20 Amateur
Posts: 55
Joined: Thu Nov 27, 2014 10:50 am

Re: Animations in Machine Language

Post by randolph.pickle »

Wow. Thank you very much for taking the time to explain it Mike. Also, thanks for pointing out Pitfall!, as I didn't know about it.
Post Reply