Game loops and Vertical Blank interupts

Ask anything your want about Megadrive/Genesis programming.

Moderator: BigEvilCorporation

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Re: Game loops and Vertical Blank interupts

Post by Chilly Willy » Tue May 15, 2018 1:54 am

You also need some protection around that code in the vblank to keep from getting recursion in the vblank int. Set a flag before changing the sr, and in the vblank routine, just do the dma and exit if the flag is set. The code after the game loop should clear the flag.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Game loops and Vertical Blank interupts

Post by Stef » Tue May 15, 2018 8:47 am

Ah yeah indeed you should keep track you are inside the vint handler to avoid recursion if your vint code take more than one frame...

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Game loops and Vertical Blank interupts

Post by Miquel » Tue May 15, 2018 12:01 pm

Stef wrote:
Mon May 14, 2018 10:09 pm
Yeah i understand but just lowering interrupt mask level in SR register right after doDMAstuff and before jumping to gameloop should be enough to produce the same result, you can read/write SR register... or i'm missing something ?
When you are INSIDE an exception, can you attend another exception of the same priority (vint) or lower (hint)? I thought no, but maybe I'm mistaken... Let me search for it...

edit:
Ok! yes! interrupt priority mask is set to 6 inside vertical exception, so if I lower it to 3 again it will be able to attend more exceptions without doing a "rte", is that what do you mean ?
That simplifies things!
HELP. Spanish TVs are brain washing people to be hostile to me.

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Game loops and Vertical Blank interupts

Post by Miquel » Tue May 15, 2018 1:53 pm

It works! thanks Stef!

New version:

Code: Select all

reset:
	jsr initialization
	jmp backgroundTasks

vertException:
	tst.b gameState
	jeq 0f
	addq.w #1, framesLost
	rte
0:
	movem.l %d?/%a?, -(%sp)
	jsr doDMAThings
	move.b #1, gameState
	move.w #0x2300, %sr		/* enable exceptions */
	jsr gameLoop
	movem.l (%sp)+,%d?/%a?
	move.b #0, gameState
	rte
Chilly Willy wrote:
Tue May 15, 2018 1:54 am
You also need some protection around that code in the vblank to keep from getting recursion in the vblank int. Set a flag before changing the sr, and in the vblank routine, just do the dma and exit if the flag is set. The code after the game loop should clear the flag.
Correct! I already said that. Hope the new code suits you.
HELP. Spanish TVs are brain washing people to be hostile to me.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Game loops and Vertical Blank interupts

Post by Stef » Tue May 15, 2018 2:27 pm

You made it in a brutal way (moving 0x23 directly to SR) but yeah that was the idea ;)
Also you can test gameState after the DMA processing (as it should never be set before).

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Game loops and Vertical Blank interupts

Post by Miquel » Tue May 15, 2018 3:20 pm

Stef wrote:
Tue May 15, 2018 2:27 pm
You made it in a brutal way (moving 0x23 directly to SR) but yeah that was the idea ;)
Which fields/flags you think worth of preserving? At this precise point condition codes (Z,X,...) are not useful at all and all the other ones I set them as I want to be.
Stef wrote:
Tue May 15, 2018 2:27 pm
Also you can test gameState after the DMA processing (as it should never be set before).
I disagree. You can't allow DMA jobs to be launched at any time because the data could be malformed (the exception can be launched when you are setting the data).
Perhaps if you could make the code in a way that only one instruction makes the difference between a job is fully queued or not...
Another problem is you will be updating only partially a frame... could be visual artefacts...
HELP. Spanish TVs are brain washing people to be hostile to me.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Game loops and Vertical Blank interupts

Post by Stef » Wed May 16, 2018 10:01 am

Miquel wrote: Which fields/flags you think worth of preserving? At this precise point condition codes (Z,X,...) are not useful at all and all the other ones I set them as I want to be.
Well, just for security i would always prefer to just modify interrupt mask level part of register but indeed using 0x2300 should definitely not hurt here ;)
Miquel wrote: I disagree. You can't allow DMA jobs to be launched at any time because the data could be malformed (the exception can be launched when you are setting the data).
Perhaps if you could make the code in a way that only one instruction makes the difference between a job is fully queued or not...
Another problem is you will be updating only partially a frame... could be visual artefacts...
Well it's all up to your game logic. I guess the doDMAJobs(..) method use kind of DMA queue system. If only gameLoop actually queues data for DMA there is no use in separating them but if your main background loop is also queuing data then DMA should always happen here (or you will loss some precious DMA bandwidth).

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Game loops and Vertical Blank interupts

Post by Miquel » Wed May 16, 2018 8:27 pm

Queuing DMA jobs from the background "thread", that's really the problem!

I particularly use a buffer to queue commands and data to the vertical "thread". But I think I just have found a solution: use a MOVEM to fill that buffer all at once.

The only problem is, to perform DMA operation you need to set 7 registers, this way it will be setting 8... I need a trouble free writing to 0x00C00004... I think I could set any register to any value except the one that fires the dma...
HELP. Spanish TVs are brain washing people to be hostile to me.

Sik
Very interested
Posts: 939
Joined: Thu Apr 10, 2008 3:03 pm
Contact:

Re: Game loops and Vertical Blank interupts

Post by Sik » Wed May 16, 2018 11:51 pm

Throw autoincrement into the mix. Usually you'd use 2, but if you want to write vertically to a tilemap you may want to use 128 (assuming 64×32 or 64×64), and for the horizontal scroll table you may want to use 4 so you can keep each plane separate in your buffers in RAM. And possibly some other uses. That should pad it out to eight words and provide an useful feature.

By the way: if you disable an interrupt and it tries to fire while disabled, then it'll fire immediately as soon as you reenable it, no matter how long it has taken to be reenabled. So you could use that as some sort of mutex from the background thread.
Sik is pronounced as "seek", not as "sick".

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Re: Game loops and Vertical Blank interupts

Post by Chilly Willy » Thu May 17, 2018 1:21 pm

Yeah, I was going to mention that any time you write data to a structure (like a queue) that is read from an int, you NEED to disable ints while setting it, not just rely on "indivisible" instructions. Learned a lot about that while working on the Amiga. You don't need to fully disable ints in some cases, just the ones that use the queue. Unfortunately, SEGA got the priorities of the vblank and hblank backwards, so using the vbint means effectively disabling ints while working on critical structs. :( You could have done a lot more with vbints on the Genny if they had swapped the two priorities, making hblank 6 and vblank 4.

Sik
Very interested
Posts: 939
Joined: Thu Apr 10, 2008 3:03 pm
Contact:

Re: Game loops and Vertical Blank interupts

Post by Sik » Thu May 17, 2018 2:30 pm

Disabling the vblank interrupt from the VDP itself (i.e. register $81xx) has the same delaying effect as masking it away with SR (i.e. it's not discarded). So yes, you can disable vblank without disabling hblank.

The implication of the above is that if you're enabling them for the first time then you better get ready to cope with an immediately firing interrupt that shouldn't have been there :v (so make sure to either dummy them out or that their side-effects are not dangerous)
Sik is pronounced as "seek", not as "sick".

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Re: Game loops and Vertical Blank interupts

Post by Chilly Willy » Thu May 17, 2018 2:42 pm

Sik wrote:
Thu May 17, 2018 2:30 pm
Disabling the vblank interrupt from the VDP itself (i.e. register $81xx) has the same delaying effect as masking it away with SR (i.e. it's not discarded). So yes, you can disable vblank without disabling hblank.

The implication of the above is that if you're enabling them for the first time then you better get ready to cope with an immediately firing interrupt that shouldn't have been there :v (so make sure to either dummy them out or that their side-effects are not dangerous)
That's probably the better way to handle it if you use hblank ints, then. :D

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Game loops and Vertical Blank interupts

Post by Miquel » Thu May 17, 2018 7:43 pm

Chilly Willy wrote:
Thu May 17, 2018 1:21 pm
Yeah, I was going to mention that any time you write data to a structure (like a queue) that is read from an int, you NEED to disable ints while setting it, not just rely on "indivisible" instructions. Learned a lot about that while working on the Amiga. You don't need to fully disable ints in some cases, just the ones that use the queue.
In theory, after reading some documentation on Internet, the second group of interruptions, were vint and hint belong fires only after the finalization of the current instruction. So if you can queue with only one instruction you don't need to disable interrupts.

But in my case I also need to update a "pointer to next position", so that's what I ended up doing:

Code: Select all

move.w	#0x2700, %sr			/* disable exceptions */
move.l	pVideoBufferPos, %a0
movem.l	%d0-%d5, (%a0)			/* copy data to buffer */
lea	20(%a0), %a0
move.l	%a0, pVideoBufferPos
move.w	#0x2300, %sr			/* enable exceptions */
With that code I can setup a DMA job anywhere, then the vertical exception takes this buffer and begins to write directly, without any data manipulation, to vdp registers.
HELP. Spanish TVs are brain washing people to be hostile to me.

walker7
Interested
Posts: 45
Joined: Tue Jul 24, 2012 6:27 am

Re: Game loops and Vertical Blank interupts

Post by walker7 » Wed May 30, 2018 11:45 pm

One thing a lot of NES games do is set a variable to $00 until VBlank has fired, and then during VBlank, it gets set to $FF. At the end of VBlank, it returns to $00. This could be easily adapted to the Sega Genesis.

This could be checked for at the beginning of the VBlank routine: If the flag is $00, make it $FF and run VBlank code. If the flag is $FF, immediately jump to the RTE (restoring registers if you saved them).
When programming, you can do it if you put your mind to it.

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Game loops and Vertical Blank interupts

Post by Miquel » Thu May 31, 2018 2:15 am

Unless I misunderstand you that's more or less how my last example works, or how SGDK works.

Since 68K has bit specialized instructions could be better to just use a bit of a variable.
HELP. Spanish TVs are brain washing people to be hostile to me.

Post Reply