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 2017-08-13 18:21:48

cloudZz
Member
Registered: 2017-08-08
Posts: 13

Updating player sprite in Tile RAM every VBlank

So, I was looking at some games and some of them seem to recopy the player's current sprite every vblank into the same spot in Tile RAM
instead of having the whole spritesheet in Tile RAM permanently and just changing the sprite number in OAM.
I figure this is done to save space for other non-player sprites/tiles, since there are many different animations for the player character, but I don't get how this
can be done without pretty much wasting one whole vblank period (which are just 1140 cycles, right?)?

The fastest way I came up was this for a 16x16 sprite (number of cycles in comments):

Code:

ld hl, SpriteStartAddress ;3
ld de, VRAM_SpriteTileDest ;3
REPT 256
ldi a, (hl) ;2
ld (de), a ;2
ENDR

which still should take 1030 cylces to complete (and is a bit of a waste
of cart ROM). Can this be improved or am I making wrong assumptions (I think the game logic of
those games is also updated at 60fps, but maybe that's not the case..?)?

Offline

 

#2 2017-08-13 19:50:35

DonaldHays
Member
From: Seattle
Registered: 2016-08-01
Posts: 36
Website

Re: Updating player sprite in Tile RAM every VBlank

I think you're reasoning about this as if Game Boy tiles are one byte per pixel, when they're actually two bits per pixels. An 8x8 pixel Game Boy tile is 16 bytes, not 64. So if you want to copy four tiles (four 8x8 pixel tiles in a 2x2 arrangement for 16x16 pixels total), you want to copy 64 bytes, not 256.

Still takes an appreciable fraction of VBlank, but not almost the entire thing.

Offline

 

#3 2017-08-14 12:52:08

DevEd
New member
Registered: 2015-11-04
Posts: 9

Re: Updating player sprite in Tile RAM every VBlank

If you're targeting Game Boy Color, you could use HDMA:

Code:

    ld    hl,SpriteStartAddress
    ld    a,h
    ldh    [$FF51],a    ; HDMA source high
    ld    a,l
    ldh    [$FF52],a    ; HDMA source low
    ld    hl,VRAM_SpriteTileDest
    ld    a,d
    ldh    [$FF53],a    ; HDMA destination high
    ld    a,e
    ldh    [$FF54],a    ; HDMA destination low
    ld    a,$5        ; transfer length = 5 (64 bytes)
    ldh    [$FF55],a    ; start DMA transfer

HDMA basically transfers the graphics to VRAM automatically (you don't even need to worry about keeping within VBlank!) Note that with this method, the source and destination address must both be aligned to $10 bytes, otherwise the transfer won't work properly. Also, this will not work on an original Game Boy, as the HDMA registers were added to the Game Boy Color.


You know, the DevSound guy.

Offline

 

#4 2017-08-14 21:35:53

ISSOtm
Member
From: Somewhere in Echo RAM
Registered: 2017-04-18
Posts: 160
Website

Re: Updating player sprite in Tile RAM every VBlank

@cloudZz, first, if you're making a 16x16 sprite, this means you're using 4 tiles. A tile is only 16 bytes long, but you perform a 256-byte copy, ie. 16 tiles ?
Your copy only needs to be 16 * 4 = 64 bytes long, as DonaldHays suggested.

Also to clarify why you need to write "5" to $FF55 to use HDMA, it's "transfer (5 - 1) * 16 bytes.
Plus, this is GDMA, which transfers all bytes in a bulk, but if used outside of VBlank, it will probably fail. The other solution is HDMA, where 16 bytes (1 tile) are transferred per HBlank, ie. scanline.
If the player is touching Y=00, this might produce slight graphical issues, but it's reasonable imo.
Also if you're targeting the GBC specifically, you might want to use VRAM bank 1, which doubles the number of tiles available. (My game stores all player tiles at once, "standing" tiles in VRAM bank 0 and "walking" tiles in bank 1. Also makes animating the player easier.)

Last edited by ISSOtm (2017-08-14 21:45:40)


The French Lord Of Laziness.
Legend of Zelda and Undertale fan, I also tend to break Pokémon R/B/Y a little too much.

Twitter | Me on GCL | Discord : ISSOtm#9015 | Skype : isso.tm (I don't login anymore)

Offline

 

#5 2017-08-16 17:54:55

cloudZz
Member
Registered: 2017-08-08
Posts: 13

Re: Updating player sprite in Tile RAM every VBlank

Sorry for the late reply.
@DonaldHays @ISSOtm, thanks for pointing out my mistake.

@DevEd @ISSOtm
Currently I intend to target old brick GB, I want to see how far I can get with its limitations and copying 64 bytes with my method should result in 262 cycles which doesn't sound too bad. (I intend to do all game logic outside of VBlank).
I'll definitely check out HDMA/GDMA if I ever do switch, so thanks for explaining!

Offline

 

#6 2017-08-16 19:31:24

ISSOtm
Member
From: Somewhere in Echo RAM
Registered: 2017-04-18
Posts: 160
Website

Re: Updating player sprite in Tile RAM every VBlank

Maybe later on you'd be able to enable GBC compatibility to use the GBC features ? I dunno. (Biggest issue is palette management, tho)


The French Lord Of Laziness.
Legend of Zelda and Undertale fan, I also tend to break Pokémon R/B/Y a little too much.

Twitter | Me on GCL | Discord : ISSOtm#9015 | Skype : isso.tm (I don't login anymore)

Offline

 

#7 2017-08-17 16:00:36

cloudZz
Member
Registered: 2017-08-08
Posts: 13

Re: Updating player sprite in Tile RAM every VBlank

Not wanting to deal with color palette management is also one of the reason I chose the original GB...makes things simpler, haha.
And I quite like the different options the GBC gives for coloring old games :-)

Offline

 

#8 2017-08-18 05:20:33

ISSOtm
Member
From: Somewhere in Echo RAM
Registered: 2017-04-18
Posts: 160
Website

Re: Updating player sprite in Tile RAM every VBlank

Yeah, for the default GBC palettes, do you know you can choose them by setting the New Licensee to something ?


The French Lord Of Laziness.
Legend of Zelda and Undertale fan, I also tend to break Pokémon R/B/Y a little too much.

Twitter | Me on GCL | Discord : ISSOtm#9015 | Skype : isso.tm (I don't login anymore)

Offline

 

#9 2017-08-21 08:23:35

cloudZz
Member
Registered: 2017-08-08
Posts: 13

Re: Updating player sprite in Tile RAM every VBlank

Interesting! I thought the default palette depends on the game name and was somehow hard coded into the hardware.
Is there a list somewhere which licensee code gives which palette?

Offline

 

#10 2017-08-21 14:47:12

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

Re: Updating player sprite in Tile RAM every VBlank

There's a hash table in the CGB bootstrap ROM and a hard-coded color table. Check this out: TCRF page, specifically the notes section.

For games with licensee code Nintendo the bootstrap calculates a hash of the internal name (0x10 bytes) and in case of collisions uses the 4th byte of the name (at 0x0137) to disambiguate games.

Last edited by Tauwasser (2017-08-21 15:29:05)

Offline

 

#11 2017-08-22 15:30:13

cloudZz
Member
Registered: 2017-08-08
Posts: 13

Re: Updating player sprite in Tile RAM every VBlank

Awesome, thanks!!
There're far more palettes than I expected  :-)
....I always thought the ones you can choose at start up are the only ones.

Offline

 

#12 2017-09-07 07:36:37

Jonas
Member
From: Frankfurt, Germany
Registered: 2016-06-06
Posts: 112
Website

Re: Updating player sprite in Tile RAM every VBlank

Tauwasser wrote:

There's a hash table in the CGB bootstrap ROM and a hard-coded color table. Check this out: TCRF page, specifically the notes section.

For games with licensee code Nintendo the bootstrap calculates a hash of the internal name (0x10 bytes) and in case of collisions uses the 4th byte of the name (at 0x0137) to disambiguate games.

Is there a way to actually use these palettes in a game? If I wanted my game to use the palette of, let's say F-1 Race, I could probably set the name and licensee code in the ROM header to F-1 Race/Nintendo to make the GBC identify it respectively. But is there any other way (that would maybe even give access the unused palettes)?

Last edited by Jonas (2017-09-07 07:47:18)

Offline

 

#13 2017-09-07 12:51:02

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

Re: Updating player sprite in Tile RAM every VBlank

Set the licensee to Nintendo, choose a Name with one or two bytes less than 0x10 bytes. Adjust the the last bytes so the checksum matches the table entry. If you're lucky, you can get away with just editing the last byte if the top two bits aren't set.

Offline

 

#14 2017-09-07 13:15:43

Jonas
Member
From: Frankfurt, Germany
Registered: 2016-06-06
Posts: 112
Website

Re: Updating player sprite in Tile RAM every VBlank

Thanks Tauwasser! smile But how do I calculate the checksum? I didn't find information on that on the site you mentioned in your previous post.

Offline

 

#15 2017-09-08 12:57:09

cloudZz
Member
Registered: 2017-08-08
Posts: 13

Re: Updating player sprite in Tile RAM every VBlank

To calculate the checksum just sum up the ASCII values from the games title (and modulo 0x100 the result so it's just 1 byte), this gives the hash value that maps onto a specific palette. For example "ZELDA" would give the sum 0x70, which you can then look up.
I just played around with it myself a bit, but I wasn't able to get access to any of the "unused" palettes, is that even possible?

Offline

 

#16 2017-09-08 15:46:03

Jonas
Member
From: Frankfurt, Germany
Registered: 2016-06-06
Posts: 112
Website

Re: Updating player sprite in Tile RAM every VBlank

Aaah, now I got it. Sometimes life can be so easy...

Well, then you probably can't access the unused palettes by simply adjusting the game title in the ROM header. Maybe you could take a look at a disassembly of the boot ROM, analyze what it does to select the palette and then include some amended code in the first lines of your own game to change the palette? I'm just guessing.

Offline

 

#17 2017-09-08 18:35:32

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

Re: Updating player sprite in Tile RAM every VBlank

Sorry for not being more clear about the hashes. No, there is no easy way of using the unused palettes. Some of them appear to be real palette entries, but some of them are just artifacts of the way the table was created (duplicates, shifted colors, etc.). If you want to include code in your game to change the palettes, then I suggest going all the way and creating a Game Boy Color game -- then your choice of colors is free.

Offline

 

#18 2017-09-09 14:58:31

cloudZz
Member
Registered: 2017-08-08
Posts: 13

Re: Updating player sprite in Tile RAM every VBlank

Ah, OK, thanks for clearing this up, Tauwasser :-)

Offline

 

#19 2017-09-10 07:12:08

Jonas
Member
From: Frankfurt, Germany
Registered: 2016-06-06
Posts: 112
Website

Re: Updating player sprite in Tile RAM every VBlank

Found a palette that works for me. smile Thanks both of you.

Offline

 

Board footer

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson