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.
Hello,
I recently started development for GB/GBC.
Learned a lot so far. Now I want to create a map system for maps bigger than 32x32.
Unfortunately, I can't get bank switching working. Ofcourse this is needed to achieve a lot of things.
Yes, I looked at all those threads on here and all the answers. Tried everything, nothing works...
So I use GBDK for the development and I use C. Also tried to mix C with asm for the map data, but even that didn't work...
I am wondering if I miss something here or if there is something else happening.
The files can be downloaded via these links:
https://mega.nz/#!5lhwRLJC!svtYqIpQx--e … zUnH-nR-FI
https://mega.nz/#!YhRXCQ5J!pEMGSTgsaVs2 … kYgVH06aIM
https://mega.nz/#!UtIgAJIA!e8tkNruVaL6Z … _ZoA6GkcxM
The compiler also throws an error; Multiple definitions of _TestMap/_TestBG/BackgroundPalette/Set_Bkg
Which are all in bank2.c
Help would be greatly appreciated!
Thank you,
Pikpol
Offline
Hi, sorry for coming back to you only after a week. Anyway, I think the problem with the double definition is in bank.h, which you haven't uploaded.
I think you already took a look at the older thread, but just in case link to old thread.
I think you should try to get that example working first before continuing.
pikpol's Email wrote:
Though, the weird thing is, it worked when all my code was in 1 file and so in 1 bank.
But it started failing on me when I added a third bank.
In general, it's weird that you include all of your c files in main.c. While not unheard of, this might present its own set of problems. lcc writes the RAM and ROM bank the code is supposed to use inside the object file, so it will have trouble when you compile code that is meant for multiple bank all in the same c file.
The traditional way is to only include header files or character data that is used one time only. Compile each c file into an object file and link them all together in a final step, kind of like in this thread.
Offline
Tauwasser wrote:
Hi, sorry for coming back to you only after a week. Anyway, I think the problem with the double definition is in bank.h, which you haven't uploaded.
I think you already took a look at the older thread, but just in case link to old thread.
I think you should try to get that example working first before continuing.pikpol's Email wrote:
Though, the weird thing is, it worked when all my code was in 1 file and so in 1 bank.
But it started failing on me when I added a third bank.In general, it's weird that you include all of your c files in main.c. While not unheard of, this might present its own set of problems. lcc writes the RAM and ROM bank the code is supposed to use inside the object file, so it will have trouble when you compile code that is meant for multiple bank all in the same c file.
The traditional way is to only include header files or character data that is used one time only. Compile each c file into an object file and link them all together in a final step, kind of like in this thread.
Well, I got the example to work already. Therefore I started to look into it and into the other bank example. From there I copied bank.h.
I include all the .c files, otherwise I get an error on the compiler. Something like undefined global ...
I removed the bank.c reference in the main.c file and the compiler at least compiles it without errors. My character also appears on screen again, but the background is nowhere to be seen.
Gonna try some things now with the header files. Thank you so far! Really appreciate the help.
EDIT: So I found out how to include only the .h files and not the .c files. Thank you for that.
Unfortunately, the code in bank2 doesn't seem to work at all. Or better said, it is like bank2 gets skipped. Bank1 works just as intended, it draws the main character, it sets some palettes. And afterwards in main.c the player can 'move' the character with the D-pad. But in between drawing the main character and changing it's direction it is facing, there should be code to display the background.
I know the code for the background works, so it can't be it. I am also not sure if the content is really pushed into bank 1 and 2.
ALso, bank2 seems to be in bank 1 according to the .sym file
; Area: _CODE_1
01:4000 _Set_Sprite
01:418E _spritePalette
01:419E _UpdateSprite
; Area: _CODE_2
01:4000 _Set_Bkg
01:4049 _TestBG
01:4079 _TestMap
Last edited by pikpol (2017-08-14 16:35:33)
Offline
Maybe you should upload the whole source, personally I'm a bit confused by the errors you say the compiler throws when you don't include the C files.
My guess is that you declare a variable in one of the C files, and you re-use it in another one. Just add the declaration to a .h file instead, or include an "extern int var;" in the other .c, or something.
(That's how C works, btw.)
Offline
ISSOtm wrote:
Maybe you should upload the whole source, personally I'm a bit confused by the errors you say the compiler throws when you don't include the C files.
My guess is that you declare a variable in one of the C files, and you re-use it in another one. Just add the declaration to a .h file instead, or include an "extern int var;" in the other .c, or something.
(That's how C works, btw.)
So here you can download the whole source.
https://mega.nz/#F!d8YhRaiS!ihTkfwO2SWnMYUcZp9NjLw
But I now know how it works with the .h and .c files. At least I think so
As I put everything in the correct bank when I compile it, I don't understand why bank2.c still gets thrown into bank 1 and that no code is being run from bank2.c
Offline
I see the problem, which is why I said you should look at the banked example in gbdk's folder. Basically, here's a quote form the gbdk README:
Banked function support
-----------------------
2.95 and above supports banked functions.
[...]
Some notes:
* Currently only works with rgbds and isas. asxxxx doesn't support
resolving the bank of a function at link time
[...]
rgbds support
-------------
[...]
* lcc does not work with rgbds. You have to call sdcc directly, setting
up the include path and making the libraries local as appropriate.
The Makefile in the "examples\gb\banked" directory correctly sets this up. The problem really is that lcc calls asxxx, which does insert banking code, but does not currently resolve the bank correctly at link time.
Just an FYI: the code that is generated for your init() looks like this:
call $095D // call DISPLAY_OFF ld de, $2000 // SWITCH_ROM_MBC1(1); ld a, $01 ld [de], a call $0A48 // library function banked_call dw $4000 // address of Set_Sprite() db $00 // supposed bank of Set_Sprite() db $00 // filler ld de, $2000 // SWITCH_ROM_MBC1(2); ld a, $02 ld [de], a call $0A48 // library function banked_call dw $4000 // address of Set_Bkg() db $00 // supposed bank of Set_Bkg() db $00 // filler call @0225 // call MainGame() ret
Since you did the bank management by hand (using SWITCH_ROM_MBC1) anyway, you might as well have declared the Set_Sprite() and Set_Bkg() functions NONBANKED.
Offline
Tauwasser wrote:
I see the problem, which is why I said you should look at the banked example in gbdk's folder. Basically, here's a quote form the gbdk README:
Banked function support
-----------------------
2.95 and above supports banked functions.
[...]
Some notes:
* Currently only works with rgbds and isas. asxxxx doesn't support
resolving the bank of a function at link time
[...]
rgbds support
-------------
[...]
* lcc does not work with rgbds. You have to call sdcc directly, setting
up the include path and making the libraries local as appropriate.The Makefile in the "examples\gb\banked" directory correctly sets this up. The problem really is that lcc calls asxxx, which does insert banking code, but does not currently resolve the bank correctly at link time.
Just an FYI: the code that is generated for your init() looks like this:Code:
call $095D // call DISPLAY_OFF ld de, $2000 // SWITCH_ROM_MBC1(1); ld a, $01 ld [de], a call $0A48 // library function banked_call dw $4000 // address of Set_Sprite() db $00 // supposed bank of Set_Sprite() db $00 // filler ld de, $2000 // SWITCH_ROM_MBC1(2); ld a, $02 ld [de], a call $0A48 // library function banked_call dw $4000 // address of Set_Bkg() db $00 // supposed bank of Set_Bkg() db $00 // filler call @0225 // call MainGame() retSince you did the bank management by hand (using SWITCH_ROM_MBC1) anyway, you might as well have declared the Set_Sprite() and Set_Bkg() functions NONBANKED.
Okay, I misunderstood that part. But now I know that using c I can't implement bank switching?
As I don't know asm at all, I don't understand how I could fix this issue. Would changing to gbdk-n and sdcc help resolve this issue?
Offline
Well, you can still write some ASM functions yourself. I'm not sure which MBC you're planning to use, so until I know that I can't really help you...
Offline
But the weird thing I don't understand is that at least one tutorial I saw used SWITCH_ROM_MBC1() and it worked ofcourse.
So why doesn't it work (anymore?) for me?
As you almost always need bank switching, but if you use gbdk, you should also always use asm together with c?
Offline
Maybe the tutorial you saw used an older version of GBDK.
No, it's not needed, but GBDK as a whole is, imo, a crappy development environment, partly because it's somewhat unfinished, so in the meantime I'd recommend using some ASM.
Or at least understanding how bank switching works.
Offline
That's not what I said at all! I said the older gbdk releases come with asxxx, which cannot resolve the banks functions were put in at link time. To improve this, version 2.95 added the rgbds backend, which can resolve banks and can be used with C code. However, you cannot rely on lcc anymore. Instead, you have to call sdcc directly with the appropriate flags. You can use a different makefile that switches to the rgbds libraries. An example of which is given in the readme itself as well as in examples/gb/banked.
SRC = main.c bank2.c bank3.c BIN = banked.gb TOPDIR = ../../.. GBLIB = $(TOPDIR)/lib/medium/rgbds LIB = $(GBLIB)/gbz80/gbz80.lib $(GBLIB)/gb/gb.lib CRT0 = $(GBLIB)/gb/crt0.o OBJ = $(SRC:.c=.o) CC = $(TOPDIR)/bin/sdcc -mgbz80 --asm=rgbds -I$(TOPDIR)/include all: $(BIN) clean: rm $(OBJ) %.o: %.s $(BIN): $(OBJ) $(CC) -v $(CRT0) $(OBJ) $(LIB) rgbfix -p 255 -v a.gb $(LIB): $(LIBOBJ) xlib $@ a $(LIBOBJ) %.o: %.c $(CC) -c $< %.asm: %.s astorgb.pl $< > $@ %.o: %.asm rgbasm -o$@ $< %.s: %.ms maccer -o $@ $<
If you get the paths right and change the first line to
SRC = Main.c MainCharacterOverlap.c TestMap.c TestBG.c bank1.c bank2.c
then it will work after you made CharacterOverlap const.
Offline
Sorry guys to bother you again with this, but I don't understand what I am missing and it's the first time I actually use makefiles like this.
So I tried to run the makefile with nmake from the development command prompt from Visual Studio Community 2017.
I copied the makefile from the banked example, made sure that TOPDIR pointed to my gbdk folder and replaced SRC with the one mentioned by @Tauwasser
When I run it, I get
Microsoft (R) Program Maintenance Utility Version 14.11.25506.0
Copyright (C) Microsoft Corporation. All rights reserved.
NMAKE : fatal error U1073: don't know how to make 'Main.o'
Stop.
I already did some googling, but couldn't find any helpful information for my problem.
I can only imagine that the part where the makefile says how to convert .c to .o isn't correctly setup. But it's hard to believe as the makefile is just a copy of the banked example makefile.
I hope you guys can help me out, so I can finally continue with this project.
Thank you so far.
Offline
This error means that the Makefile is requested to "brew" Main.o, but it has no recipe for that.
What does the Makefile look like ?
Offline
SRC = Main.c MainCharacterOverlap.c TestMap.c TestBG.c bank1.c bank2.c
BIN = banked.gb
TOPDIR = ../../..
GBLIB = $(TOPDIR)/lib/medium/rgbds
LIB = $(GBLIB)/gbz80/gbz80.lib $(GBLIB)/gb/gb.lib
CRT0 = $(GBLIB)/gb/crt0.o
OBJ = $(SRC:.c=.o)
CC = $(TOPDIR)/bin/sdcc -mgbz80 --asm=rgbds -I$(TOPDIR)/include
all: $(BIN)
clean:
del $(OBJ)
%.o: %.s
$(BIN): $(OBJ)
$(CC) -v $(CRT0) $(OBJ) $(LIB)
rgbfix -p 255 -v a.gb
$(LIB): $(LIBOBJ)
xlib $@ a $(LIBOBJ)
%.o: %.c
$(CC) -c $<
%.asm: %.s
astorgb.pl $< > $@
%.o: %.asm
rgbasm -o$@ $<
%.s: %.ms
maccer -o $@ $<
Offline
IIRC how Makefiles work, let's break it down a bit.
You ask for "make", thus it is implied "make all" because it's the first target.
To make "all", "banked.gb" is required.
To make "banked.gb", "Main.o MainCharacterOverlap.o TestMap.o TestBG.o bank1.o bank2.o" are required (all items in "SRC" but replacing ".c" with ".o")
Thus, it will start by looking for a recipe for "Main.o".
There are only 3 recipes that can produce a ".o" file : "%.o: %.s", "%.o: %.c" and "%.o: %.asm".
make will try finding a "Main.s" file, then a "Main.c" file, then a "Main.asm" file.
But it finds none, thus it outputs an error "I don't know how I'm supposed to make it ! "
So that means you have neither of these 3 files in the same directory as the Makefile (I guess, since I never used GBDK) ; from the "SRC" variable I assert that you have a "Main.c" file.
Before you do anything, where is it located relative to the directory you're using "make" in ?
Offline
ISSOtm wrote:
IIRC how Makefiles work, let's break it down a bit.
You ask for "make", thus it is implied "make all" because it's the first target.
To make "all", "banked.gb" is required.
To make "banked.gb", "Main.o MainCharacterOverlap.o TestMap.o TestBG.o bank1.o bank2.o" are required (all items in "SRC" but replacing ".c" with ".o")
Thus, it will start by looking for a recipe for "Main.o".
There are only 3 recipes that can produce a ".o" file : "%.o: %.s", "%.o: %.c" and "%.o: %.asm".
make will try finding a "Main.s" file, then a "Main.c" file, then a "Main.asm" file.
But it finds none, thus it outputs an error "I don't know how I'm supposed to make it ! :("
So that means you have neither of these 3 files in the same directory as the Makefile (I guess, since I never used GBDK) ; from the "SRC" variable I assert that you have a "Main.c" file.
Before you do anything, where is it located relative to the directory you're using "make" in ?
What do you mean by it?
If you mean, where is Main.c located, then I can say that Main.c is in the same folder as the make file. And also the folder I first go into in the command prompt before I use nmake.
But if you mean nmake. Then I can answer with; C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\bin\HostX64\x64.
EDIT: What I forgot to tell you is that I also can't make the banked example. It gives the same error.
Last edited by pikpol (2017-08-19 08:58:25)
Offline
Personally since I use Windows 10, I installed the Windows Subsystem for Linux (which allows running some Ubuntu things on your NT kernel, yaaay). I know, boo at me how much you want. I like it anyways.
So, since I installed it I can use the Linux bins if RGBDS, GNU make and Git. It's pretty darn cool !
Offline
Well I installed gnuwin32. But still, nothing works. I feel like a total noob right now
So basically what happened is, I tried make from within the make directory. That ofcourse didn't work. Then I went into the banked example folder and tried it again. and now i get the error "cannot exec process no such file or directory"v
any ideas?...
Offline
Make sure the rgbds bin directory is in your path. sdcc expects to be able to call rgbds directly.
Offline
Tauwasser wrote:
Make sure the rgbds bin directory is in your path. sdcc expects to be able to call rgbds directly.
The documantation is talking about an autoexec.bat. But I don' t have that file anywhere and I never set any environment variables. So I don't understand to which path I should add it to?
Offline
I can't help with the "banking" part (way beyond my current skills), but as newbie GB dev, I too struggled to get Make running on windows.
Installing GNUMake alone isn't enough, because makefiles often call other Linux prompt commands. To have it running on windows you'll actually need to install MSYS, which is a port of the whole Linux prompt commands to the Windows environment:
http://www.mingw.org/wiki/MSYS
However, the Make version coming with MSYS has a bug preventing it from reporting compiler errors.
So first, download and install MSYS:
https://sourceforge.net/projects/mingw- … p/download
Then, download Make for windows and copy the "make.exe" you've just downloaded over the "/bin" dir of your fresh MSYS installation.
http://gnuwin32.sourceforge.net/packages/make.htm
Make sure that the "/bin" folder is also added to your PATH environment variable.
Then, you should be able to run makefile on Windows much like on Linux.
Thanks a lot to Zalo's ZGB installation tutorial for helping me out with this "make on windows" issue in the first place.
https://github.com/Zal0/ZGB/wiki/Installation
Last edited by drludos (2017-08-21 18:08:05)
Offline
drludos wrote:
I can't help with the "banking" part (way beyond my current skills), but as newbie GB dev, I too struggled to get Make running on windows.
Installing GNUMake alone isn't enough, because makefiles often call other Linux prompt commands. To have it running on windows you'll actually need to install MSYS, which is a port of the whole Linux prompt commands to the Windows environment:
http://www.mingw.org/wiki/MSYS
However, the Make version coming with MSYS has a bug preventing it from reporting compiler errors.
So first, download and install MSYS:
https://sourceforge.net/projects/mingw- … p/download
Then, download Make for windows and copy the "make.exe" you've just downloaded over the "/bin" dir of your fresh MSYS installation.
http://gnuwin32.sourceforge.net/packages/make.htm
Make sure that the "/bin" folder is also added to your PATH environment variable.
Then, you should be able to run makefile on Windows much like on Linux.
Thanks a lot to Zalo's ZGB installation tutorial for helping me out with this "make on windows" issue in the first place.
https://github.com/Zal0/ZGB/wiki/Installation
Thanks, it is a bit easier now. But I still get the error
So I did exactly as you said. Install msys(in c:\msys\). I downloaded it and just put it in there, so I think I installed it. Then I copied make with the .dll files to the bin folder of msys. And then I ran make again, resulting in the same error as before: make: *** [main.o] Error 1
Offline
Got a sort of new error.
So I added the gbdk\bin folder and the msys\bin folder to PATH.
And than this appeared:
Cannot exec process : No such file or directory
Cannot exec assember: No such file or directory
make: *** [main.o] Error 1
Instead of make saying "Cannot exec preprocessor: No such file or directory"
Make now says, "Cannot exec assember: No such file or directory"
So it has found some stuff and I hope someone knows what I am missing right now.
Thanks again guys, even though this goes very slowly, I still want to make a gameboy game.
Last edited by pikpol (2017-09-07 09:37:05)
Offline