Discussion about software development for the old-school Gameboys, ranging from the "Gray brick" to Gameboy Color
(Launched in 2008)
You are not logged in.
Pages: 1
I just picked up programming for the Game Boy earlier this week so I'm still a bit of a novice to all of this and I ran across an issue with my first game (a vertical scrolling space shooter.)
I tried using the LCD interrupt code found on these forums to mask out the lower portions of the window layer but ran across an odd issue.
It seems to be loading in an extra row of tiles about 2/3rds of the way down the screen. These tiles sit over the background layer and under the sprite layer (window layer) and flicker constantly. What they are changes with the LYC_REG which I've been using for an interrupt on the window layer.
If I set it to the 16th line (LYC_REG = 10,) it creates seemingly random bkg tiles that flicker as the screen scrolls.
If I set it to interrupt to the 8th row of tiles (LYC_REG = 0x08,) the flickering row becomes the 9th-16th rows of the HUD.
If I do 16th and set my window to load a third row (I have two versions of the HUD; one with two rows and one with a third row of blank tiles,) it flickers the third row instead of background tiles.
From what it's looking like, it's displaying a few lines past the interrupt at that point further down the screen because starting the interrupt earlier causes it to push lines of the HUD there instead of background tiles.
It's doing something else here, pushing the bottom line of the HUD to that screen height I mentioned. The actual issue is hard to screenshot as it just looks like flickering stars against the background. (The HUD isn't functioning yet, those tiles are just placeholders so I can figure out a layout I like.)
To make this easier to read, I'm omitting a lot of the unrelated code. Here's the code I think is relevant:
void smartDelay(UINT8 interval){ UINT8 ii; for(ii=0; ii < interval; ii++){ if (gameActive == 1){ //Keeps the HUD from window layer HUD during smart delays during gameplay. SHOW_WIN; } wait_vbl_done(); } } void interruptLCD(){ HIDE_WIN; } void main(){ STAT_REG = 0x45; //45 is stable, but has strange extra tiles over the bkg layer. LYC_REG = 0x10; //LCD interrupt 16th scan line NR52_REG = 0x80; //turns sound on NR50_REG = 0x77; //sets volume for left and right sound channels to max of 0x77 NR51_REG = 0xFF; //tells hardware to use all sound channels for both left and right disable_interrupts(); ... //Other stuff add_LCD(interruptLCD); enable_interrupts(); set_interrupts(VBL_IFLAG | LCD_IFLAG); while(ship.health > 0 && toTarget > 0){ SHOW_WIN; ... //more other code smartDelay(2); wait_vbl_done; }
Offline
The only things I can think of is to tell you to move SHOW_WIN; to a VBL interrupt handler, and to not use HIDE_WIN; until you are sure you are in HBL. Basically, for the HBL thing, set your interrupt to go off the line before, and then have a wait loop until the STAT mode is 0, then hide the window.
Offline
I had to read through the wiki and some other sources to be able to understand that, but I couldn't find anything on how to check the STAT mode to know when it's doing horizontal or vertical blanking.
Offline
I'm still new to programming in C and using GBDK. How would I go about writing a while loop that checks for the stat mode?
Offline
http://bgb.bircd.org/pandocs.htm#lcdstatusregister
void interruptLCD() { while ((STAT_REG & 3) != 0); HIDE_WIN; } void interruptVBL() { SHOW_WIN; } int main(void) { LYC_REG = 0x10 - 1; //LCD interrupt 15th scan line add_LCD(interruptLCD); add_VBL(interruptVBL); }
Offline
Initially, I entered the code in wrong and got something a little off...
What I got instead was the HUD with one layer of background tiles, seemingly on the window layer, then nothing. It looks like it's displaying the entire window layer (and the UI map only covers the first two rows. That third is an anomaly...)
After getting the code entered in properly, it still shows that row of tiles flickering over the window layer. I don't think I implemented it correctly, but that line of background tiles got me thinking...
I wanted to catch a screenshot of the flickering stars both on and off, so I froze the emulator (BGB) by right clicking the screen and took more screenshots of the issue and found something interesting.
Flickering stars off (What it should look like):
Flickering stars on:
That flickering row of tiles matches the row of tiles from there. Somehow the window layer is getting split and pushed further down screen. It isn't just that one row of tiles, it's the entire window layer and it masks out the background from there down, but at such a rate that my eyes don't pick it up.
However, showing me that STAT_REG is something that I can check in a logic statement really helped.
void smartDelay(UINT8 interval){ UINT8 ii; for(ii=0; ii < interval; ii++){ if (gameActive == 1 && STAT_REG == 0){ //Keeps the HUD from window layer HUD during smart delays during gameplay. SHOW_WIN; } wait_vbl_done(); } }
BREAKTHROUGH! Fixed it.
Mostly.
The extra row of pixels very briefly flashes in at the halfway point on the screen when you pause the game, but it's not as bothersome. If I can't fix it or it becomes too big of a problem, I'll just make it hide the window layer when you pause. This isn't as big of an issue, so I can focus on the rest of the game now.
I might try to see if I can manipulate that row of tiles later and turn it into a pause banner of some kind.
Offline
The problem is that you end up missing a frame sometimes and therefore the window keeps being shown longer than you intend (or not at all for the first frame of activation).
What games usually do is the following: They reserve two variables in high ram (0xFF80+) for window start and window stop line respectively.
Then they'll use the LYC interrupt to switch the window on and off at the correct times. You still need pretty tight code or else the last line of the window might flicker (as it might show one line too many sometimes).
Offline
The part I found most confusing was that the window layer was somehow getting split in two and starts up again partway down the screen (which was why the stars in the lower portion of the screen were missing in the last screenshot in my previous post.)
Offline
"STAT_REG == 0" this is incorrect. You need to mask out the bits you don't need, like the interrupt enable bits. "(STAT_REG & 3) == 0" is the correct way to check the STAT mode.
Offline
Pages: 1