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 > HBlank and Bios WaitVBL

#9457 - Wanderer - Tue Aug 05, 2003 11:54 am

Hi,

I'm having a bit of trouble getting some of my code to work on hardware, although it seems to work fine with VisualBoyAdvance 1.5.1

The code is using HBlank interrupts and is also calling the Bios VBlankIntrWait function. On the emu this works fine, however on the GBA the HBlank seems to get serviced but the code never returns from the Bios call (as far as I can tell).

Here's the code that seems to be at the centre of the problem:

Code:

void WaitForVsyncSetup() {
   GBA_INTERPROC = (u16*)&interProc;
   
   GBA_REG_IE  |= GBA_VBLANK_INTR;
   GBA_REG_DISPSTAT |= 0x0008;
   GBA_REG_IME = 0x01;
}

void OnHBlankSetup(void (*HProc)(void)) {
   GBA_INTERPROC = (u16*)&interProc;
   
   MyHProc = HProc;
   
   GBA_REG_IE  |= GBA_HBLANK_INTR;
   GBA_REG_DISPSTAT |= 0x0010;
   GBA_REG_IME = 0x01;
}

// Wait for the Vertical sync.
void WaitForVsync()
{
   asm volatile("swi 0x50000");
}

void interProc() {
   GBA_REG_IME = 0x00;
   
   if(GBA_REG_IF & GBA_VBLANK_INTR) {
      (*(volatile u32*)0x03fffff8) = GBA_VBLANK_INTR;
      GBA_REG_IF |= GBA_VBLANK_INTR;
   }
   
   if(GBA_REG_IF & GBA_HBLANK_INTR) {
      (*(volatile u32*)0x03fffff8) = GBA_HBLANK_INTR;
      GBA_REG_IF |= GBA_HBLANK_INTR;
     
      MyHProc();
   }
   
   GBA_REG_IME = 0x01;
}


From what I understand this should all work, but it doesn't. Can someone please tell me what I'm doing wrong?

cheers,


Wanderer.

#9468 - tepples - Tue Aug 05, 2003 3:41 pm

It seems that the BIOS is not returning to your code after the ISR finishes. Does your program run correctly in VBA when using a BIOS file (Options > Emulator > Use BIOS), or only with VBA's default high-level emulation of the BIOS in native code?

You might also want to try the following ISR, modeled after my boilerplate master ISR, which is a bit simpler than the one you gave:
Code:

void interProc() {
  u16 got_if;

  GBA_REG_IME = 0x00;
  /* capture what interrupts occurred so that we need to read REG_IF
     only once */
  got_if = GBA_REG_IF;
   
  if(got_if & GBA_VBLANK_INTR) {
  }
   
  if(GBA_REG_IF & GBA_HBLANK_INTR) {
    /* ... */
    MyHProc();
  }

  /* change sky colour on every interrupt, for debug purposes */
  (*(volatile u16*)0x05000000) ^= 0x4210;

  /* the hardware automatically ORs in the bits you write to GBA_REG_IF,
     so don't use the read-modify-write |= instruction when writing to
     GBA_REG_IF but do use |= when writing to the mirror of it in IWRAM */
  GBA_REG_IF = got_if;
  (*(volatile u16*)0x03fffff8) |= got_if;
  GBA_REG_IME = 0x01;
}

_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#9472 - Wanderer - Tue Aug 05, 2003 5:16 pm

Thanks!!,

it was the |= on REF_IF that was causing it to hang. I'd had it writing direct to the register a while back but unfortunately it got 'corrected' when I was tidying my code up a bit, and I didn't notice immediately because the emu was accepting it.

cheers,


Wanderer.