pret / pokecrystal

Disassembly of Pokémon Crystal
https://pret.github.io/pokecrystal/
2.1k stars 795 forks source link

Unable to place 'Pics 1' (ROMX section) at $4624 in bank $48 #392

Closed lesliesuhm closed 6 years ago

lesliesuhm commented 7 years ago
$ make -j4
make -C tools/
rgblink -n pokecrystal.sym -m pokecrystal.map -l pokecrystal.ld -o pokecrystal.gbc wram.o main.o lib/mobile/main.o home.o audio.o maps.o engine/events.o engine/credits.o data/egg_moves.o data/evos_attacks.o data/pokedex/entries.o misc/crystal_misc.o text/common_text.o gfx/pics.o
error: Unable to place 'Pics 1' (ROMX section) at $4624 in bank $48
make: *** [Makefile:68: pokecrystal.gbc] Error 1

Is this decipherable? My guess is that I have surpassed the max file size limit, because that piece compiled before and I have not touched it. Any help would be appreciated.

yenatch commented 7 years ago

You haven't reached a filesize limit, but you have reached the size limit for that bank.

Sections are an assembler abstraction that lets you put code or data in a specific spot. Banks are a cartridge abstraction that lets the rom be bigger by splitting it up into 0x4000-byte chunks. One or more sections can end up in one bank.

In the linkerscript (pokecrystal.ld) the Pics 1 section is told to be in bank 0x48.

ROMX $48
    "Pic Pointers"
    "Pics 1"

The assembler is trying to put Pics 1 in bank 0x48, but either it or Pic Pointers has gotten too big for both to fit in 0x4000 bytes.

Unfortunately, the banks containing pokemon sprites in particular are crammed to the last byte, so any increase in size at all in these areas will cause this error without intervention. This is a common gotcha that isn't easy to prevent (but it is easy to fix).

There are a couple reasons this could happen without touching this section.

  1. You added something to the Pic Pointers section.
  2. You changed a sprite in this section, causing it to be slightly bigger when recompressed.

There are two ways you can fix this. 2. is what you should do, but in case you're interested I'll put both:

  1. (short-term fix) Remove Pics from the linkerscript, which will let rgblink put it somewhere that it does fit. This won't help you if it happens to one of the other sections, which have the whole bank to themselves.
  2. (long-term fix) Make a new section (you don't need to add it to the linkerscript) and move some sprites from the offending section into the new one.

In either case, there's one more step. There's completely pointless code in gfx/load_pics.asm that will load a pokemon sprite as garbage data unless it's in one of the existing Pics banks. All you have to do is stub it:

FixPicBank: ; 511c5
; This is a thing for some reason.

PICS_FIX EQU $36
GLOBAL PICS_FIX

+   add PICS_FIX
+   ret
-   push hl
-   push bc
-   sub BANK(Pics_1) - PICS_FIX
-   ld c, a
-   ld b, 0
-   ld hl, .PicsBanks
-   add hl, bc
-   ld a, [hl]
-   pop bc
-   pop hl
-   ret
-
-.PicsBanks: ; 511d4
-   db BANK(Pics_1) + 0
-   db BANK(Pics_1) + 1
-   db BANK(Pics_1) + 2
-   db BANK(Pics_1) + 3
-   db BANK(Pics_1) + 4
-   db BANK(Pics_1) + 5
-   db BANK(Pics_1) + 6
-   db BANK(Pics_1) + 7
-   db BANK(Pics_1) + 8
-   db BANK(Pics_1) + 9
-   db BANK(Pics_1) + 10
-   db BANK(Pics_1) + 11
-   db BANK(Pics_1) + 12
-   db BANK(Pics_1) + 13
-   db BANK(Pics_1) + 14
-   db BANK(Pics_1) + 15
-   db BANK(Pics_1) + 16
-   db BANK(Pics_1) + 17
-   db BANK(Pics_1) + 18
-   db BANK(Pics_1) + 19
-   db BANK(Pics_1) + 20
-   db BANK(Pics_1) + 21
-   db BANK(Pics_1) + 22
-   db BANK(Pics_1) + 23

Then the game won't care what bank it's in.

Pokechu22 commented 7 years ago

There's completely pointless code in gfx/load_pics.asm that will load a pokemon sprite as garbage data unless it's in one of the existing Pics banks

Is that what causes all variants of ????? to look the same, instead of loading a random garbage graphic like is done in gen 1?

yenatch commented 7 years ago

No, the pointers are the same for each unused slot. This just changes the bank from 0xff (effectively bank 0x7f) to an undefined value. But since the address for unused slots is also 0xffff (which wraps around to 0x0000) it will always read from bank 0. So the unused slots are unaffected by this function.

roukaour commented 6 years ago

So can this be closed?

lesliesuhm commented 6 years ago

Yeah sorry