gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Coding > Water effect

#23170 - ProblemBaby - Tue Jul 06, 2004 1:37 pm

Hi I want to do a water/wave effect.
For now I use a HBLANK-interrupt (that actually doesnt work ive no idea why but the code in the interrupt should work)
Its freezing after all setup code here is how I enable the interrupt
Code:

IntrTable[1] = WaterEffect;
REG_DISPSTAT |= 0x10;
REG_IE |= 0x2;
REG_IME = 1;

void WaterEffect()
{
REG_BG0HOFS = 20;  // this just to check if the code comes to this place
REG_IF |= 0x2;
}


Whats wrong, ive worked with interuppts before and it have worked but now it something really strange going on.

I also wonder if HDMA is that faster than an interrupt and is it possible to use in this case?


Last edited by ProblemBaby on Tue Jul 06, 2004 2:10 pm; edited 2 times in total

#23171 - poslundc - Tue Jul 06, 2004 1:44 pm

HDMA has less overhead than an interrupt, so it will go somewhat faster, but is recommended if you are only doing a single raster effect, since you can't perform multiple tasks with it.

To use it, set up an array during VBlank with 160 entries that have the register values you want to set for each scanline. Set DMA0 with the source as your array, the destination as the control register, and tell it to increment the source, leave the destination the same, and set its mode to fire automatically on HBlank. Turn it on, and voila. Make sure you turn the DMA off again during VBlank (REG_DMA0CNT = 0) before trying to fiddle with the registers.

Dan.

#23173 - tepples - Tue Jul 06, 2004 3:20 pm

Another tip for hblank DMA: You'll want to set up the first scanline's data during vblank and then point the DMA source address to the second scanline's data.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#23206 - ProblemBaby - Wed Jul 07, 2004 1:53 pm

poslundc wrote:

To use it, set up an array during VBlank with 160 entries that have the register values you want to set for each scanline. Set DMA0 with the source as your array, the destination as the control register, and tell it to increment the source, leave the destination the same, and set its mode to fire automatically on HBlank. Turn it on, and voila. Make sure you turn the DMA off again during VBlank (REG_DMA0CNT = 0) before trying to fiddle with the registers.
Dan.


So Ive to set 2x160 entries (I change both the XOFS and YOFS) each VBlank it feels a bit slow. Maybe I can stick to the interrupt.

My interrupt look like this:
Code:

REG_BG3HOFS = 8 + (SIN[((REG_VCOUNT + counter) & 0x7) << 5] >> 8);
REG_BG3VOFS = 8 + (COS[((REG_VCOUNT + counter) & 0xF) << 4] >> 8);


counter is incremented each twelve VBlank this give me a good effect.
It isnt somehow possible to make a DMACOPY of it without arrays?

#23208 - poslundc - Wed Jul 07, 2004 2:56 pm

Are you testing it on hardware? Speed on emulation in no way reflects actual speed on hardware.

Dan.

#23209 - col - Wed Jul 07, 2004 3:47 pm

ProblemBaby wrote:
poslundc wrote:

To use it, set up an array during VBlank with 160 entries that have the register values you want to set for each scanline. Set DMA0 with the source as your array, the destination as the control register, and tell it to increment the source, leave the destination the same, and set its mode to fire automatically on HBlank. Turn it on, and voila. Make sure you turn the DMA off again during VBlank (REG_DMA0CNT = 0) before trying to fiddle with the registers.
Dan.


So Ive to set 2x160 entries (I change both the XOFS and YOFS) each VBlank it feels a bit slow. Maybe I can stick to the interrupt.

My interrupt look like this:
Code:

REG_BG3HOFS = 8 + (SIN[((REG_VCOUNT + counter) & 0x7) << 5] >> 8);
REG_BG3VOFS = 8 + (COS[((REG_VCOUNT + counter) & 0xF) << 4] >> 8);


counter is incremented each twelve VBlank this give me a good effect.
It isnt somehow possible to make a DMACOPY of it without arrays?


If you are worried about efficiency, and are only updating the counter every 12 lines, you can use the vCount interrupt to manage the hBlank interrupt. It goes somthing like this: Each vcount interrupt sets up the data for the next line down, switches on the hblank interrupt and sets the vCount interrupt to fire again in 12 lines time. The hblank handler switches hBlank interrupts off at the end of its process.
If you set it up this way, there is some extra overhead because you are using 2 interrupts. There is also some extra book-keeping to do. However you are only doing it 13 times per frame instead of 160.
Its possible to set this up in a dynamic way so it's not hardwired to 12 line steps, but there comes a point where its not worth the extra overhead and its best to switch to pure hBlank interrupts or hBlankDMA.

Something you might want to try (i've not tested this idea myself) is using hblank DMA, but with a fixed data source. You could then use the vcount interrupt to update the source every 12(or whatever) lines..
(maybe even try switching the hBlank DMA on/off using the vcount? although that brings in extra management code and more hassle)

cheers

Col