Game main loops in Machine Language

Basic and Machine Language

Moderator: Moderators

Post Reply
nippur72
de Lagash
Posts: 574
Joined: Thu Sep 07, 2006 8:35 am

Game main loops in Machine Language

Post by nippur72 »

Hi, my second post here :)

I have a question:

When developing a BASIC game, the main loop usually consists in a GETA$ cycle with sprite update on the screen with NO control of timings. (timings being defined by the slowness of BASIC itself so one does not concerns about them).

In machine language instead timings are critical because the game can be too fast. So how does one control them in the "main" cycle? It's necessary to link to IRQ so that your main cycle is executed at precise intervals? Is there any other technique? And what does happen if your main cycle last longer than IRQ frequency?

Please share your comments, I'm getting again into vic20 programming.

Tony
carlsson
Class of '6502
Posts: 5516
Joined: Wed Mar 10, 2004 1:41 am

Post by carlsson »

In one of my mini games, I begin the main loop like this:

Code: Select all

loop: lda $9004
      bne loop
which will wait until the raster line equals zero. Not that the game relies on raster synchronizing, but it was an easy way to get some kind of slow down. Otherwise, you can always busy wait for a little while, or have some counters that calls external routines regularly:

Code: Select all

main: jsr $ffe4 ; get keypress
      beq cont1
      jsr handlekeypress
cont1: dec enemycounter
      bne cont2
      jsr handleenemy
cont2: dec othercounter
      bne cont3:
      jsr otheraction
cont3: jsr ending ; check for game ending
      beq main ; routine should return zero if not game over
      jmp gameover
If you need constant updating, you can put some code in the IRQ routine itself, but not the whole game as it would slow down the rest of the IRQ stuff IMHO.
Anders Carlsson

Image Image Image Image Image
User avatar
Mike
Herr VC
Posts: 5130
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Game main loops in Machine Language

Post by Mike »

nippur72 wrote:It's necessary to link to IRQ so that your main cycle is executed at precise intervals? [...]
This is often done. An interrupt server is installed, and the main program then only executes '.loop JMP loop'. Everything is done within the IRQ.

In that case it is preferable to synchronise the IRQ with the raster beam. On the C64, this is easy as the video-chip supplies such an IRQ, on the VIC-20 you use a VIA timer instead.
Is there any other technique?
Busy-waiting for a cyclic condition, as Carlsson wrote. Technically spoken, an inferior method - you should still be able to use the main program for doing things, that:

- don't require exact timing, or even
- possibly need longer to complete than a full IRQ cycle, because:
And what does happen if your main cycle last longer than IRQ frequency?
Case 1: The speed of the game will suddenly drop by half. The next IRQ happens within the processing of the first IRQ, but you acknowledge both IRQ's at the end of your handler. Thus, every second IRQ is lost. But you've kept the synchronisation to the raster beam. Edit: The foreground process outside the IRQ is allowed to execute till the next IRQ.

Case 2: You acknowledge the first IRQ at the beginning of your handler. In that case, the next IRQ will be honored immediately as your processing of the first one ends. You'll lose the synchronisation to the raster beam, and get a flickery display. Edit: The foreground process will grind to a halt.

Michael
Last edited by Mike on Tue Sep 12, 2006 2:40 am, edited 2 times in total.
nippur72
de Lagash
Posts: 574
Joined: Thu Sep 07, 2006 8:35 am

Post by nippur72 »

thank you for the programming tips... I'm trying to get used again to Vic 20 programming.

Talking of "main loops" I was thinking of implementing the same loop that is done in PLCs (microcontrollers) with the SFC/ladder language. It's used to keep track easily of several things running in parallel (perhaps useful in video games where several objects move on the screen at the same time).
User avatar
Mike
Herr VC
Posts: 5130
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Post by Mike »

Ah, yes! :)
PLCs (microcontrollers) with the SFC/ladder language
For those who don't know, that's a typical "Hello World!" program in ladder logic (or KOP in German):

Code: Select all

|   E 0.0       E 0.1  A 4.0
+----| |----+----|/|----( )----|
|           |
+----| |----+
|   A 4.0
It implements a SR-flipflop with relays.

Greetings,

Michael
nippur72
de Lagash
Posts: 574
Joined: Thu Sep 07, 2006 8:35 am

Post by nippur72 »

this IRQ thing is interesting, I think I'll have one to manage sound effects for the tetris game that I'm writing (at the moment it's soundless). I will keep the game main loop outside of IRQ because it's quite long and I doubt it can be executed in one IRQ cycle.

As regards the sounds, I still have to figure how can I turn basic sound effects (done with FOR..NEXT) into ML. Can you suggest me some source code to PEEK at?
Thomas Hechelhammer
Vic 20 Dabbler
Posts: 79
Joined: Thu Jun 09, 2005 11:51 pm
Location: Germany

Post by Thomas Hechelhammer »

nippur72 wrote:this IRQ thing is interesting, I think I'll have one to manage sound effects for the tetris game that I'm writing (at the moment it's soundless). I will keep the game main loop outside of IRQ because it's quite long and I doubt it can be executed in one IRQ cycle.
You have between 17000 and 22000 machine-cyles in one frame. This depends on the type of your machine, NTSC or PAL. Timing is very different.

And you will have to do some synchronizing:
1. to avoid flicker
2. to make sure the thing is running the same speed on PAL and NTSC-machines.

# NTSC-M: 6560-101, 65 cycles/line * 261 lines. Processor clock = 14318181/14 Hz = 1022727 Hz
-> one frame = 60.2845 Hz = 16965 cycles/frame

# PAL-B: 6561-101, 71 cycles/line * 312 lines. Processor clock = 17734472/16 Hz = 1108404 Hz
-> one frame = 50.0363 Hz = 22152 cycles/frame

(I hope my calculations are correct).
nippur72 wrote: As regards the sounds, I still have to figure how can I turn basic sound effects (done with FOR..NEXT) into ML. Can you suggest me some source code to PEEK at?
You'll need an IRQ-Player.
With some different counters in the Z-page to control sound-effects and playtime of the voices.

Do yourself a favor and examine the IRQ-Routine in the super-expander module which contains a sound-handler which is located from $A5D1 to $A6D1.

Very complex thing, for my needs I would write my own.


-- Thomas
bills442
Vic 20 Amateur
Posts: 69
Joined: Mon Aug 07, 2006 5:12 pm

sound driver

Post by bills442 »

I have some code that I've just written for doing multi-voice sounds using a "track" that you specify. Although it's not hooked into any interrupt, it's designed to have a "service" routine called every so often. I was going to call the service routine from the VBI or similar.

I'm sure it's kinda lame as it's the first 6502 code I've ever written. I'm using it in my pacman clone, lol. My musician friend put the MS pacman theme into it and it didn't sound too bad, except for the vic's crazy 7 bit sound, that even my feeble untrained ear could hear as flat sometimes ... but that only endeared the whole project to me all the much more as it sounded so .... 80s to me.

I'll try to clean the dasm code up a little and post it if you are interested.
nippur72
de Lagash
Posts: 574
Joined: Thu Sep 07, 2006 8:35 am

Post by nippur72 »

yup, please post it, thank you, it will be very useful.
carlsson
Class of '6502
Posts: 5516
Joined: Wed Mar 10, 2004 1:41 am

Post by carlsson »

Are you planning to play music, or just sounds whenever you rotate the piece etc? If the former, an IRQ routine is a good idea, preferrably synchronized to the raster using VIA timers. See Marko Mäkelä's code in Veni Vidi VIC! or any of the other demos with source code.

I also have a couple of music players you could get to try out, but maybe the music format is not too easy to work with (and the efficiency could possibly be argued).
Anders Carlsson

Image Image Image Image Image
nippur72
de Lagash
Posts: 574
Joined: Thu Sep 07, 2006 8:35 am

Post by nippur72 »

I am going to add sound effects only, no music for the moment. Nonetheless I don't want the game "freeze" when the effect is on, so I was thinking to link to IRQ. Basically I need 3 or 4 effects: 1 for piece move/rotate, 1 for piece drop, 1 for line complete and one for "game over". What do you suggest?
Thomas Hechelhammer
Vic 20 Dabbler
Posts: 79
Joined: Thu Jun 09, 2005 11:51 pm
Location: Germany

Post by Thomas Hechelhammer »

nippur72 wrote:I am going to add sound effects only, no music for the moment. Nonetheless I don't want the game "freeze" when the effect is on, so I was thinking to link to IRQ. Basically I need 3 or 4 effects: 1 for piece move/rotate, 1 for piece drop, 1 for line complete and one for "game over". What do you suggest?
Did you notice my post I wrote a few days ago :?:

Here again the only working solution:

You'll need an IRQ-Player.
With some different counters in the Z-page to control sound-effects and playtime of the voices.

Do yourself a favor and examine the IRQ-Routine in the super-expander module which contains a sound-handler which is located from $A5D1 to $A6D1.


Very complex thing, for my needs I would write my own.

-- Thomas
nippur72
de Lagash
Posts: 574
Joined: Thu Sep 07, 2006 8:35 am

Post by nippur72 »

Talking of raster line synchronization, I was thinking that waiting for line zero isn't the best way to minimize flickering. This because your program has to update the display in very short time (betwen line 0 and start of video display).

I was thinking to synchronize instead to the end of video page (let's say around line 150) or less so to have much more time for screen update. Even in case of an IRQ call, there would be less flicker because the raster would be out of sight for most of the time.

Has anyone tried this before? I've tried it in my new sprite routine and it seems to work, but I am not sure how to take into account PAL/NTSC screens and overscan.

I also have a question: is it better to have IRQ turned off during game main loops? (perhaps it could be turned on only for the raster wait loop).

What is common programming practice?
Post Reply