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.
So I'm trying to make a platformer for GameBoy. Working on multilevel support and noticed when adding a second level game wouldn't run. I assume that its due to memory overload. I started researching Banking.
I want to use the new Auto banking feature with MBC5. Ideally i want to put everything relating to a level (background tileset, background map, collectable data etc.) within a source file and when I load a level switch banks and access all of that levels data.
Trying to follow the GBDK examples I created a source file named something like LevelSourceFile.c and added just the tileset and map data initially. So with auto banking I know I'm supposed to use #pragma bank an the max bank value. In the case of MBC5 its 255.
Here's where i start having problems. I know that you are supposed to use BANKREF() so that you can switch to this bank elsewhere but I'm confused on what the value is supposed to be. Initially I thought it was some arbitrary value for the bank, but looking at the examples and reading docs they use variables stored in the source file now does that mean I have to have a BANKREF() for each variable? Does that give them different banks? Either way no matter what I put in there it throws an error saying its expecting a '{'. For the record the main thing I want is to retrieve a few arrays of map data.
Then with my compile.bat i know of the settings to set the cartridge to MBC5 using Wm-yt0x19 and I have to set it to auto-banking using -autobank but where does that go? and size to -Wm-yoA to denote auto bank size. In a few examples I noticed them combining the source files with the main before generating the .gb but in those cases they set the bank so and that was for RAM and I want ROM so what do I do for Auto-Banking and ROM.
For actually using the data You use BANK(bank_ref_value) and that swaps the bank to the one referenced, but to use the data i still use an #include and include the source file as i would before right?
I apologize for how wordy this is alot of it was me brain dumping so that I can get my thoughts together. I appreciate any insight and I apologize if these are stupid questions lol. Let me know if you need any more info. Thanks!
Offline
you can use any identifier with BANKREF()/BANKREF_EXTERN() macros, existing or not - that is up to you. that depend on your design, whether you want to associate bank with each of your objects or with the group of objects. i suggest the first approach, because that provide flexibility, and BANKREF() does not allocate any ROM or RAM at all.
you are correct in most of your statements above, i only point you, that you should include header files with declarations only, not c files with definitions. it should be like:
some.c:
#pragma bank 255 const char[] hello = "hello_world!"; BANKREF(hello)
some.h:
#ifndef __HELLO_H__ #define __HELLO_H__ extern const char[] hello; BANKREF_EXTERN(hello) #endif
then when you need to use your hello identifier somewhere, you include the header file.
Offline
the general idea is that each c file is compiled into the separate object and those objects are put into arbitrary banks on the linking stage, just before the ROM file generation. banks are not known at the compiling stage, so instead of putting immediate values into the code, like SWITCH_ROM(5); which is fixed at the compile stage and could not be changed later, you put some reference like SWITCH_ROM(BANK(hello)); which is substituted when the rom is actually composed.
Offline
Thanks for the replies. I generally understand the concepts but I couldn't get rid of a few errors regarding BANKREF() for some reason. Ultimately I decided to shift gears and went with non auto banking. I figure I'll only have a few levels and i can easily just set the banks myself and store all data for a level on one bank. Found out one of the biggest errors I was getting before was due to the fact that I was using the old version of GBMB and didn't realize it so it wasn't using the 'const' for the map. I got things working with the banks and I can transfer between banks and actually transfer between scenes but I have a few issues.
whenever I move the player and the screen shifts it slows down the game ever so slightly. I assume this is due to the fact that now its having to read from a banked ROM. Any ideas on how to speed that up?
The other big issue I'm having is if I try to have a map larger than 136x32 tiles the initial screen looks fine but the moment i start moving its all corrupted and glitchy. Not sure whats going on there.
Last edited by McAvalnch (2023-11-03 22:44:44)
Offline
not sure what errors you were getting, but automatic banking is suggested way to manage large code and data.
banked calls have some penalty, but not sufficient to make your game slow down by themselves. something else is wrong, probably poor design.
for large maps implementation you may loog into the gbdk-2020 examples: gbdk-2020/examples/cross-platform/large_map/ or, say, gbdk-2020/examples/cross-platform/rle_map/
Offline
Ok Yea you are probably right my code is probably janky somewhere, but its weird cause there was no issue with those maps before I added banking individually. Thanks I'll look over that example.
Offline
So ok I was going through my code. I didn't find any issues regarding the slow down but I was tackling the issue on level size. I looked through the code example about large maps and I couldn't see anything wrong so I went back to the tutorial I followed to set it up and there wasn't much modified from the tutorial.
I decided to look at the VRAM to see what exactly was happening.
This is right after the level is loaded into and the player is set in place the initial screen looks fine. for the record its a 250x32 tile map. when the map is only 128x32 it works fine.
This is after I walk forward a bit the stuff that isn't loaded in initially loads in all glitchy not sure why looking at the VRAM it trying to use the addresses that I'm not using for the background. What's throwing me off is the fact that it isn consistent like it works with 128x32 but any bigger it suddenly stops working.
UPDATE: so uhhh... I'm dumb lol found the problem. the tutorial I followed for the large map scrolling didn't specify the min function so I quickly wrote my own and accidentally made the return value a int8_t instead of uint8_t so that the returned value could not go above 127 which would explain that it would freak out if I made a level any larger than 128. NGL I'm embarrassed but also happy things are working. Also that was causing the weird slowdown I was getting.
Last edited by McAvalnch (2023-11-07 22:53:35)
Offline
without seeing any code, it is more like fortune telling by pictures
Offline