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.
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):
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
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
If you're targeting Game Boy Color, you could use HDMA:
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.
Offline
@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)
Offline
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
Maybe later on you'd be able to enable GBC compatibility to use the GBC features ? I dunno. (Biggest issue is palette management, tho)
Offline
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
Yeah, for the default GBC palettes, do you know you can choose them by setting the New Licensee to something ?
Offline
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
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
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
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
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
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
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
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
Ah, OK, thanks for clearing this up, Tauwasser :-)
Offline