I always loved the tricks used for the Sega Gensis providing a few more colors in different circunstances.
Just to set the context there're a few examples from licenced games:
Blastem's CRAM debug screen is a wonderful tool to peek what's cooking into the Sega Genesis color table.
Samurai Showdown can be considered a "famous" case.
It was so clever to split colors for two "items" from the game wich will never share an horizontal coordinate: the time and energy hud and the battle referee. Six color are reloaded a bit after the HUD is drawn, meaning a bit lower. A few lines below the HUD the color reloading starts.
It is achieved dumping pairs of colors into the CRAM during three scanlines. Two is the maximum number of colors you can send at one hint time avoiding the appearance of CRAM dots trash on the screen.
The colors used for the HUD are not gonna be needed any more so this color room will be taken for six new colors for the referee sprite.
Depite not being "ingame", the selection screens makes an even more impressive use of this technique. Three of the four palettes are rewritten, keeping just the one dedicated to the background texture. Colors are sent two by two during 24 scanlines. Doing that they achieved to have 15 exclusive colors for the lower row of faces, the upper ones are drawn with two palettes: 15 + 15 colors; those two become the palettes of the sprites at the bottom of the screen.
There're a couple of cram dots dancing around but it was a quite impressive tricky-work on that screen.
Toughman Contest make use of color reloading in a way I discovered NBA Hangtime also did.
The palettes (one in Toughman, two in a row in Hangtime) are reloaded with new colors in order to gain new ones for the faces of the contenders and team players.
In one game, the same palette is used to colourize the arena and afterwards, bellow, the contenders. The other has the same palettes used to dispose colors for the team badges first, and then for the players faces and the avatars background.
A difference between the re-colouring at those two games is that the boxing game sends the new colors to the CRAM one by one instead of two by two as NBA Hangtime and most other games do.
Also, rewriting colors one by one works this effect in Sub-Terrania. Unlike the previous games, this time there is not only one batch (of single or pairs of colors) dumped scanline after scanline. We have three lots dumped, two times the CRAM is rewriten with a few colors at the background palette and one time, in between, giving a few new color values into the palette set for the foreground.
Very special mention, althouth this breathtaking coding falls out of the context of what we want to achieve, to Mickey Mania and its Moose Chase level. Jon Burtonback then found the way to send 16 colors during one scanline and with that he built a dinamic texture into CRAM (sooooooo crazy but worked flawlessly). It is quite cool watching it reel into the CRAM debug screen.
There are some others games like Comix Zone (1 palette color reloading ingame) or Addam's Family Values (1 color
-------------------------
And for an introduction ... I guess it's enough.
So I felt Iike trying to find a simple method for everyone to make use of hscan color reloading.
At the very beggining I was not aware, didn't have a clue, of how SGDK could lead with this kind of routines. I started trying this:
Code: Select all
#include <genesis.h>
#include "gfx.h"
// GLOBAL DATA ///////////////////////////////////////////
const u16 colors[24] =
{
0x0E06, 0x0E04, 0x0E02, 0x0E00, 0x0C00, 0x0A00, 0x0800, 0x0600,
0x0400, 0x0200, 0x0000, 0x0200, 0x0400, 0x0600, 0x0800, 0x0A00,
0x0C00, 0x0E00, 0x0E02, 0x0E04, 0x0ECC, 0x0EAA, 0x0E88, 0x0E66
};
u16 *p_color;
u16 color;
// /////////////////////////////////////////////
//---------------------------------------------------------
// TEST HINT COLOR
//---------------------------------------------------------
void HBlankColorLandscape()
{
color = *p_color++;
asm("move.l #0xc0000000, 0xc00004.l");
asm("move.w color, 0xc00000.l");
}
/**********************************************************
MAIN
**********************************************************/
int main( )
{
// Initialization lot _____________________________________________________
VDP_setScreenWidth320();
VDP_setReg(10, 0x08); // HInt routine callback ecah 8 lines
// Process ________________________________________________________________
// Dump the image to A plan
VDP_drawImageEx(PLAN_A, &backalley_image, TILE_ATTR_FULL(PAL0, FALSE, FALSE, FALSE, TILE_USERINDEX), 0, 0, FALSE, TRUE);
// HInt config
VDP_setHInterrupt(1);
SYS_setHIntCallback(HBlankColorLandscape);
// MAIN LOOP
while(1)
{
// Restore pointer to first color from the array
puntero_color = &colores[0];
VDP_waitVSync();
// Reload palette
VDP_setPaletteColors(0, (u16*) backalley_image.palette->data, 16);
}
return (0);
}
Some colleagues point me out that sending two colors in a row was an actual possibility as well. That made us think of dithered fadings such as this:
It looked not so bad at Ryu's stage.
And I also did a quick non dithered test using that "two color row by row reloading" with this gameboy Taz screenshot.
BUT ...
CRAM DOTS everytime. Code was too slow jumping from the first callback routine to the asm HINT routine, code takes more than a scanline drawing time to be completed.
Prettending to fit this code into the Hint Callback ... too much dreaming.
The assembler code I got was this:
Code: Select all
.align 2
*--------------------------------------------------*
* LABELS *
*--------------------------------------------------*
.set VDP_CTRL, 0xC00004
.set VDP_DATA, 0xC00000
.set PAL0_COL0, 0xC0000000
.set PAL0_COL1, 0xC0020000
.set PAL0_COL2, 0xC0040000
.set PAL0_COL3, 0xC0060000
.set PAL0_COL4, 0xC0080000
.set PAL0_COL5, 0xC00A0000
.set PAL0_COL6, 0xC00C0000
.set PAL0_COL7, 0xC00E0000
.set PAL0_COL8, 0xC0100000
.set PAL0_COL9, 0xC0120000
.set PAL0_COLA, 0xC0140000
.set PAL0_COLB, 0xC0160000
.set PAL0_COLC, 0xC0180000
.set PAL0_COLD, 0xC01A0000
.set PAL0_COLE, 0xC01C0000
.set PAL0_COLF, 0xC01E0000
*--------------------------------------------------*
* DATA *
*--------------------------------------------------*
.data
| Color pointer
.globl pcolores
.comm pcolores, 4, 4
| Color pairs array
.globl Colores
.type Colores, @object
.size Colores, 24
Colores:
.long 0x00E0000E, 0X026A0026, 0X0E000A00, 0X0600000E
.long 0X000A0006, 0X00EE00AA, 0X0EEE0AEA, 0X06E60000
.long 0x0EAA0EAA, 0x0C880A66, 0x08440622, 0x04000EE8
.long 0x0EEE0200, 0x06420C84, 0x0EC60448, 0x0A0E022E
.long 0x0246068A, 0x04680246, 0x00240002, 0x000008AC
.long 0x00060004, 0x04440888, 0x0EEE0222, 0x008E0CCC
/****************************************************
* HBLANKFONDOCOLORES *
*--------------------------------------------------*
* *
* *
****************************************************/
.align 2
.text
.globl HBlankFondoColores
.type HBlankFondoColores, @function
HBlankFondoColores:
move.l #PAL0_COL0, VDP_CTRL
move.l pcolores, %a0
move.l (%a0)+, VDP_DATA
move.l %a0, pcolores
rts
Code: Select all
******************************************************************************/
#include <genesis.h>
#include "gfx.h"
#include "hintcode.h"
/**********************************************************
MAIN
**********************************************************/
int main( )
{
// Initialization lot _____________________________________________________
VDP_setScreenWidth320();
VDP_setReg(10, 0x08);
// Proceso ________________________________________________________________
SPR_init(16, 256, 256);
VDP_drawImageEx(PLAN_A, &backalley_image, TILE_ATTR_FULL(PAL0, FALSE, FALSE, FALSE, TILE_USERINDEX), 0, 0, FALSE, TRUE);
VDP_setPaletteColors(0, (u16*) backalley_image.palette->data, 16);
VDP_setHInterrupt(1);
SYS_setHIntCallback(HBlankFondoColores);
// MAIN LOOP
while(1)
{
pcolores = Colores[0];
//SPR_update();
VDP_waitVSync();
}
return (0);
}
Any ideas about making SGDK a bit more friendly for hint-color routines?
At least for those "two color reload each row, always same indexe" and also for "any colors, 2 by 2, increasing color index".