Gameboy Development Forum

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.

Ads

#1 2019-04-21 15:42:04

ben0910
Member
Registered: 2019-04-21
Posts: 12

MBC1 unkown address, possibly caused by banking issues

Hello all!
I am very excited to get going on my game. I have been working on a demo. I am trying to add some new tile data to my build and when i add the file containing the data array the screen goes blue. There is also an error in the logs "MBC1 unknown address". I believe the issue has to do with banking. It seems that my banks are not setup correctly. Below is a link to the code. you can run make to build a working rom. If you look in the make file you can comment out lines 34,35 and uncomment 38,39 to make the build break.

Link: https://drive.google.com/file/d/1xu94HH … sp=sharing

Thanks!

Offline

 

#2 2019-04-22 17:08:03

ben0910
Member
Registered: 2019-04-21
Posts: 12

Re: MBC1 unkown address, possibly caused by banking issues

I think i found out how to fix it, but i am a little confused. I changed the  " unsigned char" to "static const unsigned char" in hud-font.c This seemed to force the compiler to store the code under _CODE_4 instead of _DATA. Can anyone shed some light on this?

Offline

 

#3 2019-04-27 18:53:42

Tauwasser
Member
Registered: 2010-10-23
Posts: 160

Re: MBC1 unkown address, possibly caused by banking issues

Which version of gbdk are you using? I'm using gbdk3-2.93 and get a better error message:

Code:

lcc -Wl-yt3 -Wl-yo8 -Wl-ya0 -o build/first.gb ./src2/bank-1/my-world-map.o ./src2/bank-1/my-world-tiles.o ./src2/bank-2/astroid-tiles.o ./src2/bank-2/ShipTiles.o ./src2/bank-3/hud-border.o ./src2/bank-3/hud-window.o obj/main.o
ERROR: address overflow (addr cbd6 >= 8000)

This error message is trying to tell you that you ran out of space in one of the rom banks, as it calculated that address 0xCBD6 is still within one of the ROM banks, which usually are from 0x4000--0x7FFF resp. 0x0000--0x3FFF for Rom Bank 0.

The reason is that you data is much too big, as you never tell the compiler that the data is constant. Thus, it correctly assumes that you could change the data at one point in time and it needs to reside in RAM.

Constant data is put into the ROM directly, whereas pre-initialized non-constant data needs to be copied to RAM when the program is initially booted up. Thus, each ROM bank must hold a copy of the data and RAM needs to be big enough to hold it, too. Because the initialization happens in ROM bank 0, the compiler tries to copy all the initialization data to ROM bank 0 first and ran out of space there as well. I actually noticed that the compiler doesn't care if it runs from ROM bank 0 into ROM bank 1 as it assumes to be able to do that. The initialization code for RAM is very bad as it produces code copy single bytes to target locations instead of doing a memcpy, at least for me.

That's why changing data to const works in your case. The static keyword does something else: It changes linkage from default external linkage to internal linkage. Internal symbols are only visible within one compilation unit (one C file), whereas external symbols are visible globally. You cannot define a variable to have internal linkage and external linkage at the same time. Doing so will result in a linker error if the variable is used anywhere:

Code:

?ASlink-Warning-Undefined Global _WorldTiles referenced by module lcc70320

You can find and debug these errors using the map and listing files. See the GBDK docs for help how to activate them. This way you can know the RAM usage and the ROM usage of your data.

You should also know that your Makefile does not actually work, as the default compilation rule is used for all your sources:

Code:

lcc    -c -o src2/bank-1/my-world-map.o src2/bank-1/my-world-map.c

The default rule is $(CC) -c -o $@ $<. As you see, the flags specifying RAM and ROM banks are missing. Use make -r to run make without default rules. Let's check the rules:

Code:

./src2/bank-1/%.c.o: %.c

This rule expects to find a my-world-map.c file at the root of your tree next to the Makefile. It also expects a dependency to file ./src2/bank-1/my-world-map.c.o, which isn't there either.
There are many ways to solve this. I chose a somewhat generic way where you specify each file by hand and each attribute for each file by hand but provide a generic rule for all files:

Code:

CC = lcc
TARGET ?= build/first.gb
BUILD_DIR ?= ./build
MKDIR_P ?= mkdir -p
ASSETS_FOLDER = assets

SRC = \
    main.c \
    bank-1/my-world-map.c \
    bank-1/my-world-tiles.c \
    bank-2/astroid-tiles.c \
    bank-2/ShipTiles.c \
    bank-3/hud-border.c \
    bank-3/hud-window.c \
    bank-4/hud-font.c

OBJS = $(addprefix obj/, $(SRC:.c=.o))

rebuild: clean $(TARGET) cleanafter

# # Link banks
# #      ROM+MBC1+RAM : -Wl-yt2
# #      4 ROM banks  : -Wl-yo4
# #      1 RAM banks  : -Wl-ya0
# # Make Byte 0x0143 in Header 0xC0 for CGB exclusive title.
$(TARGET): $(OBJS)
    $(CC) -Wl-m -Wl-yt3 -Wl-yo8 -Wl-ya0 -Wl-yp0x143=0xC0 -o $@ $(OBJS)

# --------------------------

# enable secondexpansion used to depend on directories
.SECONDEXPANSION:
# keep listing and map files
.PRECIOUS: *.lst *.map

# Compilation-unit-specific flags
obj/main.o: BANKS :=
obj/bank-1/%.o: BANKS := -Wf-bo1 -Wf-ba0
obj/bank-2/%.o: BANKS := -Wf-bo2 -Wf-ba0
obj/bank-3/%.o: BANKS := -Wf-bo3 -Wf-ba0
obj/bank-4/%.o: BANKS := -Wf-bo4 -Wf-ba0

# Generic compilation rule
# depend on directory being created first using second expansion
obj/%.o: src2/%.c | $$(dir $$@)
    $(CC) -Wa-l $(BANKS) -c -o $@ $<

# Rule to create directories
.PRECIOUS: %/
%/:
    mkdir -p $@

# --- cleans ---
clean:
    rm -rf $(OBJS) $(OBJS:.o:.lst)

cleanafter:
    rm -rf $(OBJS)

Btw, it's kind of bad style to include c files in other c files. You might want to rethink that.
Also, there's an error in hud.c where you switch to the wrong ROM bank and the palette data references palette 0x00 instead of 0x02.

Before:
https://pics.tauwasser.eu/images/2019/04/28/bgb00011.png

After:
https://pics.tauwasser.eu/images/2019/04/28/bgb00013.png

cYa,

Tauwasser

Last edited by Tauwasser (2019-04-27 19:00:42)

Offline

 

#4 2019-05-08 17:20:59

ben0910
Member
Registered: 2019-04-21
Posts: 12

Re: MBC1 unkown address, possibly caused by banking issues

Thanks for the reply. I am using GBDK  2.96a

Offline

 

#5 2019-05-31 01:32:28

bbbbbr
Member
Registered: 2019-03-04
Posts: 124

Re: MBC1 unkown address, possibly caused by banking issues

Here's a shell script that gives a RAM/ROM summary such as below. It's helpful for tracking how much space is available in given banks.

Code:

$ bash linker_report.bash

GroupBy(Seg),sum(Size)
CABS,0
CODE,10625
CODE_1,15027
CODE_2,14931
CODE_3,14712
DABS,0
DATA,1574
GSFINAL,0
GSINIT,1232
HOME,0

The script is written for Linux but should work on Windows if you install binaries for perl, grep and datamash (they exist).

I didn't see a way to get LCC to generate this kind of report on it's own, but maybe it's just buried somewhere.

Code:

#!/bin/bash

# find all the data allocation rows in the linker symbol output
# dump them into a csv
# display them in a table (datamash) or load the csv in libre office calc

rm linker_summary.csv
echo "File,Seg,Size" > linker_summary.csv;
grep -R "flags" Release/* | grep ".sym" | perl -pe 's/(.*)\.sym\:\s*\d+\s_([0-9A-Z_]*)\s*size\s*([0-9A-F]*)\s*flags.*/ /; print
 $1 . "," . $2 . "," . hex($3) . ","' >> linker_summary.csv
datamash --headers --field-separator=, --no-strict --ignore-case --narm  --sort --group 2 sum 3 < linker_summary.csv
#loffice -calc linker_summary.csv

Offline

 

#6 2019-05-31 16:20:46

ben0910
Member
Registered: 2019-04-21
Posts: 12

Re: MBC1 unkown address, possibly caused by banking issues

Thank you soooo much! I will put this to good use.

Offline

 

#7 2019-06-01 23:45:05

ben0910
Member
Registered: 2019-04-21
Posts: 12

Re: MBC1 unkown address, possibly caused by banking issues

Here is the makefile i ended up with, any thoughts?

Code:

CC = lcc  -Wa-l -Wl-m
TARGET ?= build/game.gb
BUILD_DIR ?= ./build
MKDIR_P ?= mkdir -p
ASSETS_FOLDER = assets

GAME_PATH ?= game-src
TARGET ?= build/game.gb

ROOT_SRCS = $(shell find src -name '*.c')
ROOT_SRCS :=  $(subst src/,,$(ROOT_SRCS))
ROOT_OBJS = $(addprefix obj/, $(ROOT_SRCS:.c=.o))

BANK_1_SRCS = $(shell find src/assets/bank-1 -name '*.c')
BANK_1_SRCS :=  $(subst src/,,$(BANK_1_SRCS))
BANK_1_OBJS = $(addprefix obj/, $(BANK_1_SRCS:.c=.o))

OBJS = $(ROOT_OBJS) $(BANK_1_OBJS)

game: clean $(TARGET) cleanafter


# Link banks
#      ROM+MBC1+RAM : -Wl-yt2
#      4 ROM banks  : -Wl-yo4
#      1 RAM banks  : -Wl-ya0
# Make Byte 0x0143 in Header 0xC0 for CGB exclusive title.
$(TARGET): $(OBJS)
    $(CC) -Wl-yt2 -Wl-yo4 -Wl-ya0 -Wl-yp0x143=0xC0 -o $@ $(OBJS)


# enable secondexpansion used to depend on directories
.SECONDEXPANSION:
# keep listing and map files
.PRECIOUS: *.lst *.map

obj/assets/bank-1/%.o: src/assets/bank-1/%.c | $$(dir $$@)
    $(CC) -Wf-bo1 -Wf-ba0 -c -o $@ $<

obj/%.o: src/%.c
    $(CC) -c -o $@ $<

# Rule to create directories
.PRECIOUS: %/
%/: mkdir -p $@

# --- cleans ---
clean:
    rm -r $(OBJS) $(OBJS:.o:.lst) 2>/dev/null || true

cleanafter:
    rm -rf $(OBJS) 2>/dev/null || true

Last edited by ben0910 (2019-06-01 23:46:05)

Offline

 

#8 2019-06-02 09:51:00

bbbbbr
Member
Registered: 2019-03-04
Posts: 124

Re: MBC1 unkown address, possibly caused by banking issues

To target MBC1, I think you will want :

Code:

-Wl-yt1

instead of:
-Wl-yt2

And if you want 1 RAM bank on the MBC (in addition to the built-in RAM):

Code:

-Wl-ya1

instead of:
-Wl-ya0

http://gbdk.sourceforge.net/tools.html
  -yo  Number of rom banks (default: 2)
  -ya  Number of ram banks (default: 0)
  -yt  MBC type (default: no MBC)

Last edited by bbbbbr (2019-06-02 09:58:38)

Offline

 

Board footer

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson