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.
Hi toxa,
yes, I nearly finished the game. Had some problems with platforms moving left and right. There is still a small bug with those platforms but I think its not worth to fix it.
Offline
I finished now the game and there is a 3rd level available. I compiled it with an older version of GBDK2020. The latest version is causing some glitches when using a real hardware, not on BGB. You can see the glitches in the picture below. Not sure whats going on here. It happens when the player is behind the HUD.
Final ROM: https://drive.google.com/file/d/1vs1VbR … sp=sharing
Last edited by 0x7f (2020-10-24 06:24:28)
Offline
seems that you are using HBlank interrupt to scroll background to 0, 0 for HUD and disable/enable sprites. i don't see your code, but probably new sdcc produces faster code and you switch sprites or update scroll a bit earlier. when there are sprites on the scanline the hblank periods are different:
please, show your HBlank ISR.
maybe it is much easier to use window for HUD: you switch it on at VBlank together with sprites off, then you switch sprites on and window off at scanline N. very short routine.
i also suggest to use the new style for LCD ISR's:
void scanline_isr_C() __critical __interrupt { // your ISR payload here }
and a tiny asm source for the vector:
.area _LCDVEC_HEADER (ABS) .org 0x48 ; LCD .int_LCD: JP _scanline_isr_C
if you don't use add/remove_LCD, then standard handler is not linked and there is an ability to write dedicated handlers without built-in handler chains iteration which is too long for HBlank.
compiling that is easy with LCC, just do
LCC -o my.gb file1.c file2.asm file3.c
Last edited by toxa (2020-10-26 08:36:09)
Offline
Hi toxa,
thanks for you answer. First I wanted to realize the HUD with the window but recognized some glitches. Thats why I changed it and put the HUD on the background layer which worked well. I use the add_LCD function to implement the scanline interrupt and configured it to happen during VBlank (mode flag = 01b). To be honest I did not understand the mechanism completely.
LYC_REG = 0x0F; STAT_REG = 0xC1; add_LCD(lcd_isr); add_VBL(vbl_isr); set_interrupts( VBL_IFLAG | LCD_IFLAG ); ... void lcd_isr() { if( game_state == GS_LEVEL ) { scroll_bkg(scroll_pos,0); SHOW_SPRITES; if( shake != 0 ) { shake--; if( (shake & 1) == 1 ) { scroll_bkg(0,1); } else { scroll_bkg(0,-1); } } } } void vbl_isr() { if( game_state == GS_LEVEL ) { move_bkg(0,0); HIDE_SPRITES; } }
Find below the complete source code. Then you can also make the UP key as jump button
https://drive.google.com/file/d/1vL6XI6 … sp=sharing
Offline
0xc1 is 0b11000001 while stat has only 7 meaningful bits and bit0 is readonly. so bit 7 and bit 0 are set for nothing here.
that is too much code for HBlank. 20 cycles of mode2 is only 5 PUSH commands.
1. you have HUD in the game only. so you just disable HBlank interrupt in menu (no need to manipulate handler, just set the mask). you don't need to check game states in the ISR itself.
2. use shadow background scroll registers, copy them in th isr.
3. VBL is long, you can never disable it and check your states there.
isr becomes very straightforward:
void lcd_isr() __critical __interrupt {
SCX_REG = shadowSCX, SCY_REG = shadowSCY;
SHOW_SPRITES;
}
you can modify shadowSCY to make shaking in VBlank ISR, if you wish.
Last edited by toxa (2020-10-27 06:34:05)
Offline
the alternative - is to make isr slower, so the effect of your ISR code becomes visible next scanline only. you set LYC = 0x0f, not 0x10. so, you just need to wait while drawing (mode3) of scanline 0x0f finishes:
void lcd_isr() { if( game_state == GS_LEVEL ) { while (STAT_REG & 3); // wait until drawing of scanline finishes scroll_bkg(scroll_pos,0); SHOW_SPRITES; if( shake != 0 ) { shake--; if( (shake & 1) == 1 ) { scroll_bkg(0,1); } else { scroll_bkg(0,-1); } } } }
that solves the problem on the real hardware.
conclusion is that new sdcc produses a bit slow code to fit into 20 cycles together with crt0 interrupt chain calling mechanism, but it is enough fast to reach scroll_bkg or SHOW_SPRITES in the middle of mode3, so effect becomes visible near the end of the scanline. old sdcc with old library had no chance to fit there.
Last edited by toxa (2020-10-26 19:08:15)
Offline
your game is almost perfect! i'm very impressed! the only flaw i managed to find is reading of uninitialized variable in
#define SET_BANK(N) SWITCH_ROM_MBC1(N); old_bank = bank; bank = N
old_bank is initialized by garbage value from bank on the first use. the same with input. i noticed that because i changed the crt behaviour in the latest update of gbdk-2020, older versions filled all wram with zeros on start. i think new behaviour is better because it forces good habit of initializing values before using. fix:
//input UBYTE input = 0; UBYTE old_input; //bank UBYTE bank = 1; UBYTE old_bank;
ps: you don't need bank variable at all, because there is already built-in bank tracking variable _current_bank. you only need old_bank here.
Offline
Hi toxa,
thanks for your suggestions.
Yes, you are right. It is enough to set the STAT_REG = 0x40 to activate the scanline check. I tried now your 2nd solution and set LYC = 0x0F and then wait in the interrupt for HBLANK. I also reduced the interrupt size by using the shadow variables as you suggested. It works also on real hardware now. But I recognized now one more strange failure I can't explain. When picking up a new weapon sometimes the displayed weapon in the HUD has some graphical artifacts. This also happens in BGB.
void lcd_isr() { if( game_state == GS_LEVEL ) { while( STAT_REG & 3 ); scroll_bkg(scroll_pos,shake); SHOW_SPRITES; } }
Offline
i just passed 1/2 of the game picking all the weapons, but was unable to catch that glitch.
probably it's "Inaccessable VRAM" issue. try enable them in BGB settings. i just enabled and see exeptions raised. maybe i should slow down set_*_data functions a bit.
Offline
ah! my bad. i forgot about that...
in gbdk-2020 v4 LCD interrupt does not wait for compatible mode, because it is too long and you miss next scanline for sure. if you want to wait for compatible mode, you should add wait handler (opposite to VBL, where you add nowait handler). so your code will be:
LYC_REG = 0x0F; STAT_REG = 0x40; add_LCD(lcd_isr); add_LCD(wait_int_handler); add_VBL(vbl_isr); set_interrupts( VBL_IFLAG | LCD_IFLAG );
but. the problem is that wait handler is a bit broken in 4.0. correct handler must be:
_wait_int_handler:: ADD SP,#4 POP DE POP BC POP HL 1$: LDH A, (#_STAT_REG) AND #0x02 JR NZ, 1$ POP AF RETI
ps: you have two different issues with LCD. first: you should not update scroll or sprite visibility in mode3, because you will see the changes at the end of scanline, and you need them to be visible only next scanline, so you need to wait inside the ISR. and the second one: interrupt itself should return in mode 0 or mode1, because if you have data copy routine working in main(), return from the interrupt must not mess its timing, so you need to add "wait terminator" handler to the LCD ISR chain. both points are important.
Last edited by toxa (2020-10-27 18:08:46)
Offline
i fixed some issues, please try it with RC1: https://github.com/chrismaltby/gb-studi … 0-v401.zip
Offline
Hi toxa,
thanks for all your investigation. The pixel failure in the HUD weapon only happens when the "while( STAT_REG & 3 );" loop is in the isr and it appears when I collect the first weapon. Nevermind, maybe I have time to check your RC in the weekend.
Offline
Tried out the new version a couple days ago.
I like the new levels, the difficulty level feels good. In particular I'm a fan of the new second boss and the secret passages.
Thanks again for sharing it!
Offline
0x7f wrote:
The pixel failure in the HUD weapon only happens when the "while( STAT_REG & 3 );"
that's "Inaccessible VRAM" issue. Solution:
add_LCD(lcd_isr); add_LCD(wait_int_handler);
ps: maybe color version?
Last edited by toxa (2020-10-28 16:47:29)
Offline
Hi bbbbbr, thanks for your feedback.
Hi toxa, a color version is not planned at the moment. I am working on a 4th level which can still fit into the 64kB ROM. Is the wait handler also necessry with your new RC1?
Offline
you need that with RC1 from the zip-file above. you won't need that in later releases.
Offline
0x7f, i know how to explain. look:
without "while( STAT_REG & 3 );" you have this picture:
or this (if glitsh is always visible):
or even this (if glitch is always visible and candles AND inventory gets corrupted):
first cross is "scroll_bkg(scroll_pos,shake);" the second cross is exit from the ISR.
if you do "while( STAT_REG & 3 );" just before "scroll_bkg(scroll_pos,shake);" the picture becomes this:
glitch goes away, but you get inventory corruption because set_*_data() timing is spoiled by interrupt. and if you use both "while( STAT_REG & 3 );" and "add_LCD(wait_int_handler);" scrolling and exit points are both in safe areas:
the red-green area is "green" when there are no sprites in that scanline, and "red" when there are. that's why you see glitches when you have sprites overlapping the HUD.
Last edited by toxa (2020-10-30 06:36:34)
Offline
Hi toxa,
thanks for your detailed explanation. I think I got it now. I also tested your RC1 and all problems seem to be fixed!
Offline
0x7f, why don't you use BANKED calls? your code is designed for that, you access banked data from code located in the same bank, say *_music. just declare those functions as BANKED and you don't have to care about saving/restoring the banks. another thing - you don't have to track bank number in code: if you decide to move music from bank3 into bank4, you don't have to search all the places where you do SET_BANK(3) before *_music and change it to SET_BANK(4). i also suggest "#pragma bank N" directive rather than a commandline switches.
Last edited by toxa (2020-11-05 09:15:59)
Offline
Hi toxa,
ah, I was not aware this is possible. I will test it but at the moment I am busy with the additional level.
Offline
I have a new version now ready. There a one additional level and also a new weapon.
https://user0x7f.itch.io/black-castle
Last edited by 0x7f (2020-11-29 11:59:39)
Offline
WOW! all that is really impressive! Congratulations! Looking forward for new games!
Offline
Pretty cool game!
Could have an option to switch weapons by using Select button.
Offline
Hi, thanks!
The option to change the weapon is no good idea. The level design offers you sometimes two ways. An easy one and a harder one where you can get a powerful weapon. Or the easy way forces you to take a weak weapon. Giving the player the option to change weapons will destroy this design.
Offline