Skeetendo

’Cause all games were better on the GBC

You are not logged in.

#1 2018-08-30 15:06:19

NobodySociety
Member
Registered: 2018-07-26
Post 7/10

Boulder replaces ball sprite in pokered

In Mt.Moon B2 I wanted to add a way to walk around the extra area at the bottom, since it always seemed unnecessary to have that much unused space. I decided to hide an item in that space as well, that I didn't want the player to have access to until later so I tried adding a boulder in front of it, which would give the player reason to return to figure what exactly is over there. When I first did this in pokered everything seemed to work fine. But now getting close to finishing the rom hack I've ran into this problem:

qcVGfCA.png

Here is the section in mapObjects for mtmoon3.asm:
        db 10 ; objects
object SPRITE_BLACK_HAIR_BOY_2, 12, 8, STAY, RIGHT, 1, OPP_SUPER_NERD, 2
object SPRITE_ROCKET, 11, 16, STAY, DOWN, 2, OPP_ROCKET, 1
object SPRITE_ROCKET, 15, 22, STAY, DOWN, 3, OPP_ROCKET, 2
object SPRITE_ROCKET, 29, 11, STAY, UP, 4, OPP_ROCKET, 3
object SPRITE_ROCKET, 29, 17, STAY, LEFT, 5, OPP_ROCKET, 4
  object SPRITE_OMANYTE, 12, 6, STAY, NONE, 6 ; person
object SPRITE_OMANYTE, 13, 6, STAY, NONE, 7 ; person
object SPRITE_BALL, 25, 21, STAY, NONE, 8, HP_UP
object SPRITE_BALL, 29, 5, STAY, NONE, 9, TM_01
object SPRITE_BOULDER, 33, 34, STAY, BOULDER_MOVEMENT_BYTE_2, 10 ; person

I did also try and update some ow sprites with things like the added sprites from pokeyellow, officer jenny, bulbasaur, oddish, and sandshrew, and a bunch of stuff from the space world demo. And in sprites_sets.asm boulder is listed after ball. I'm sure its something elsewhere that's causing the issue but I have no idea where to begin looking for it.

Last edited by NobodySociety (2018-08-30 15:07:58)

Offline

#2 2018-09-07 00:40:08

Danny-E 33
Administrator
Registered: 2012-06-09
Post 1,111/1,119

Re: Boulder replaces ball sprite in pokered

The issue is caused by 'LoadMapSpriteTilePatterns:' in engine/overworld/map_sprites.asm

All the sprites from SPRITE_BALL and beyond are 4-tile sprites instead of the usual 12 tiles.

const SPRITE_BALL                      ; $3d
const SPRITE_OMANYTE                   ; $3e
const SPRITE_BOULDER                   ; $3f
const SPRITE_PAPER_SHEET               ; $40
const SPRITE_BOOK_MAP_DEX              ; $41
const SPRITE_CLIPBOARD                 ; $42
const SPRITE_SNORLAX                   ; $43
const SPRITE_OLD_AMBER_COPY            ; $44
const SPRITE_OLD_AMBER                 ; $45
const SPRITE_LYING_OLD_MAN_UNUSED_1    ; $46
const SPRITE_LYING_OLD_MAN_UNUSED_2    ; $47
const SPRITE_LYING_OLD_MAN             ; $48

When a normal 12-tile sprite is loaded for a map, the game calculates the VRAM address to copy the sprite into based on the first available sprite slot.
But for the few 4-tiles sprites, it hard codes the VRAM addresses and only allows 2 maximum.

.fourTileSpriteVRAMAddr
    ld hl, vSprites + $7c0 ; address for second 4-tile sprite
    ld a, [hFourTileSpriteCount]
    and a
    jr nz, .loadStillTilePattern
; if it's the first 4-tile sprite
    ld hl, vSprites + $780 ; address for first 4-tile sprite
    inc a
    ld [hFourTileSpriteCount], a
.loadStillTilePattern

Since you attempted to use SPRITE_OMANYTE, SPRITE_BALL, and SPRITE_BOULDER, the game first...
* Loaded SPRITE_OMANYTE into position 1 because position 1 was available
* Loaded SPRITE_BALL into position 2 because position 1 was taken
* Loaded SPRITE_BOULDER into position 2 because position 1 was taken

So SPRITE_BOULDER ended up overwriting SPRITE_BALL in VRAM.

Your two solutions are either:
1. Only use 2 of the 4-tile sprites instead of 3
2. Modify the 'LoadMapSpriteTilePatterns:' routine to allow for more than 2 4-tile sprites. The best way to do this is to modify this code so that it loads a third 4-tile sprite immediately before the first 4-tile sprite in VRAM (overlapping part of the last 12-tile sprite). In this case, you also have to make sure you don't load so many 12-tile sprites that you overwrite the first 4-tile sprite, which will be at an earlier memory address than usual. But with your current list of game objects for this map, this won't be an issue. Just make sure you write the code so that you only use the earliest VRAM address for a 4-tile sprite when it is needed. That way you don't screw up other maps that use the maximum number of 12-tile sprites.

Offline

#3 2018-09-07 02:38:46

Danny-E 33
Administrator
Registered: 2012-06-09
Post 1,113/1,119

Re: Boulder replaces ball sprite in pokered

I made an attempt at getting this to work.

I changed this code in engine/overworld/map_sprites.asm:

.fourTileSpriteVRAMAddr
    ld hl, vSprites + $7c0 ; address for second 4-tile sprite
    ld a, [hFourTileSpriteCount]
    and a
    jr nz, .loadStillTilePattern
; if it's the first 4-tile sprite
    ld hl, vSprites + $780 ; address for first 4-tile sprite
    inc a
    ld [hFourTileSpriteCount], a
.loadStillTilePattern

To this:

.fourTileSpriteVRAMAddr
    ld hl, vSprites + $740 ; address for new, third 4-tile sprite
    ld a, [hFourTileSpriteCount]
    cp 2
    jr z, .loadStillTilePattern
; if it's the first or second 4-tile sprite
    ld hl, vSprites + $7c0 ; address for second 4-tile sprite
    cp 1
    jr z, .incrementCount
; if it's the first 4-tile sprite
    ld hl, vSprites + $780 ; address for first 4-tile sprite
.incrementCount
    inc a
    ld [hFourTileSpriteCount], a
.loadStillTilePattern

Normal 12-tile sprites are sprites $0 through $9. The two 4-tile sprites are sprites $a and $b.
This places a new sprite "$c" at address vSprites + $740 (the last 4 tiles of sprite $9).
(remember this solution makes sprite $9 unusable if you use all 3 4-tile sprites at the same time)

Then you have to modify the code that calculates the tile number of the sprite data when it's actually needed on screen (when preparing OAM).
This is in engine/overworld/oam.asm in 'PrepareOAMData:'
Change this code:

; Sprites $a and $b have one face (and therefore 4 tiles instead of 12).
    ; As a result, sprite $b's tile offset is less than normal.
    cp $b
    jr nz, .notFourTileSprite
    ld a, $a * 12 + 4
    jr .next2

.notFourTileSprite

To this:

; Sprites $a and $b have one face (and therefore 4 tiles instead of 12).
    ; As a result, sprite $b's tile offset is less than normal.
    cp $b
    jr nz, .notFourTileSprite1
    ld a, $a * 12 + 4
    jr .next2

.notFourTileSprite1
    ; new sprite $c, bonus 4-tile sprite, also has custom offset
    cp $c
    jr nz, .notFourTileSprite2
    ld a, $a * 12 - 4
    jr .next2

.notFourTileSprite2

I didn't fully test this to make sure it didn't break things in any other maps, but here is the result with your example:

W7nYu1g.png

Offline

#4 2018-09-10 13:10:15

NobodySociety
Member
Registered: 2018-07-26
Post 8/10

Re: Boulder replaces ball sprite in pokered

Thanks so much! It worked wonderfully. Now I just need to figure out how to arrange the texts in the script file so that the boulder doesn't proclaim "All right. Then this is mine!"

Offline

Board footer

Powered by FluxBB