Merge branch 'lighting' into lighting-expanded-id

This commit is contained in:
Ariel A 2023-06-28 00:11:59 -04:00
commit 4a3f6ba2fe
52 changed files with 382 additions and 255 deletions

View File

@ -35,6 +35,23 @@ Additional branches to mention:
To set up the repository, see [INSTALL.md](INSTALL.md). To set up the repository, see [INSTALL.md](INSTALL.md).
## FAQ
### Q: How do I mark certain colors in a palette as light-blended?
A: Create a `.pla` file in the same folder as the `.pal` with the same name.
In this file you can enter color indices [0,15]
on separate lines to mark those colors as being light-blended, i.e:
`06.pla:`
```
# A comment
0 # if color 0 is listed, uses it to blend with instead of the default!
1
9
10
```
You might have to `make mostlyclean` or change the `.pal` file to pick up the changes.
## See also ## See also
Other disassembly and/or decompilation projects: Other disassembly and/or decompilation projects:

View File

@ -719,10 +719,8 @@ Common_EventScript_OutOfCenterPartyHeal::
playfanfare MUS_HEAL playfanfare MUS_HEAL
waitfanfare waitfanfare
special HealPlayerParty special HealPlayerParty
@ start fade then immediately load following pokemon, and wait for fade
fadescreenswapbuffers FADE_FROM_BLACK, 1
callnative UpdateFollowingPokemon callnative UpdateFollowingPokemon
callfunc ScrFunc_WaitPaletteNotActive fadescreenswapbuffers FADE_FROM_BLACK
return return
EventScript_RegionMap:: EventScript_RegionMap::

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
232 0 128 0 0 0
216 224 232 216 224 232
222 230 238 222 230 238
184 200 224 184 200 224

View File

@ -0,0 +1,6 @@
# Color indices to set high bit
1
3
4
5
15

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
0 197 0 0 0 0
246 197 123 246 197 123
238 156 90 238 156 90
205 115 41 205 115 41

View File

@ -0,0 +1,3 @@
# Color indices to set high bit
9
10

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
0 192 0 0 0 0
222 230 164 222 230 164
180 197 115 180 197 115
148 156 82 148 156 82

View File

@ -0,0 +1,3 @@
# Color indices to set high bit
9
10

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
0 96 8 176 184 200
255 255 255 255 255 255
246 238 189 246 238 189
230 213 172 230 213 172

View File

@ -0,0 +1,6 @@
# Color indices to set high bit
0
8
9
11
15

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
0 192 24 224 40 0
64 72 104 64 72 104
192 200 0 192 200 0
224 232 232 224 232 232

View File

@ -0,0 +1,7 @@
# Color indices to set high bit
0
9
10
11
12
15

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
24 200 0 0 0 0
168 184 240 168 184 240
112 144 208 112 144 208
115 148 213 115 148 213

View File

@ -0,0 +1,6 @@
# Color indices to set high bit
1
2
6
9
10

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
8 0 128 123 180 189
255 255 180 255 255 180
238 238 90 238 238 90
213 213 65 213 213 65

View File

@ -0,0 +1,3 @@
# Color indices to set high bit
1
15

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
8 192 0 123 180 189
255 255 255 255 255 255
148 222 205 148 222 205
123 180 172 123 180 172

View File

@ -0,0 +1,4 @@
# Color indices to set high bit
1
9
10

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
0 48 0 123 180 189
255 255 255 255 255 255
222 230 238 222 230 238
164 180 197 164 180 197

View File

@ -0,0 +1,3 @@
# Color indices to set high bit
7
8

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
0 192 0 0 0 0
255 255 255 255 255 255
205 205 197 205 205 197
180 180 164 180 180 164

View File

@ -0,0 +1,3 @@
# Color indices to set high bit
9
10

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
0 0 128 0 0 0
222 230 164 222 230 164
180 189 123 180 189 123
156 164 98 156 164 98

View File

@ -0,0 +1,2 @@
# Color indices to set high bit
15

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
0 192 0 0 0 0
255 255 255 255 255 255
230 222 222 230 222 222
213 213 197 213 213 197

View File

@ -0,0 +1,3 @@
# Color indices to set high bit
9
10

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
0 192 0 0 0 0
213 222 172 213 222 172
0 0 0 0 0 0
189 189 131 189 189 131

View File

@ -0,0 +1,3 @@
# Color indices to set high bit
9
10

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
0 192 0 0 0 0
232 224 200 232 224 200
208 200 144 208 200 144
200 176 120 200 176 120

View File

@ -0,0 +1,3 @@
# Color indices to set high bit
9
10

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
240 192 0 115 197 164
255 255 255 255 255 255
216 224 232 216 224 232
184 200 224 184 200 224

View File

@ -0,0 +1,7 @@
# Colors in palette to set high (alpha) bit
2
3
4
5
9
10

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
0 32 0 0 0 0
255 255 255 255 255 255
230 230 238 230 230 238
205 205 222 205 205 222

View File

@ -0,0 +1,2 @@
# Color indices to set high bit
8

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
96 160 72 0 0 0
222 205 148 222 205 148
184 168 80 184 168 80
168 224 200 168 224 200

View File

@ -0,0 +1,6 @@
# Color indices to set high bit
3
4
8
10
11

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
0 192 0 248 240 176
255 255 255 255 255 255
238 238 213 238 238 213
222 222 180 222 222 180

View File

@ -0,0 +1,5 @@
# Color indices to set high bit
0
9
10
15

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
0 230 25 246 74 65
139 115 106 139 115 106
115 90 82 115 90 82
90 65 65 90 65 65

View File

@ -0,0 +1,8 @@
# Color indices to set high bit
0
8
9
10
11
12
15

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
0 8 248 197 65 0
255 255 255 255 255 255
255 238 74 255 238 74
255 197 16 255 197 16
@ -16,4 +16,4 @@ JASC-PAL
197 65 0 197 65 0
139 32 0 139 32 0
90 0 0 90 0 0
197 65 0 255 0 255

View File

@ -0,0 +1,7 @@
# Color indices to set high bit
0
6
11
12
13
14

View File

@ -1,7 +1,7 @@
JASC-PAL JASC-PAL
0100 0100
16 16
0 8 248 65 106 205
255 255 255 255 255 255
246 180 213 246 180 213
213 148 180 213 148 180
@ -16,4 +16,4 @@ JASC-PAL
65 106 205 65 106 205
32 65 156 32 65 156
49 74 139 49 74 139
65 106 205 255 0 255

View File

@ -0,0 +1,7 @@
# Color indices to set high bit
0
6
11
12
13
14

View File

@ -2,6 +2,13 @@
// Whether a palette has a night version, located at ((x + 9) % 16).pal // Whether a palette has a night version, located at ((x + 9) % 16).pal
#define SWAP_PAL(x) ((x) < NUM_PALS_IN_PRIMARY ? 1 << (x) : 1 << ((x) - NUM_PALS_IN_PRIMARY)) #define SWAP_PAL(x) ((x) < NUM_PALS_IN_PRIMARY ? 1 << (x) : 1 << ((x) - NUM_PALS_IN_PRIMARY))
// NOTE: Instead of using LIGHT_PAL,
// consider taking a look at the .pla files
// to mark colors as lights, instead.
// The old method *should* still work, however.
// See the README for details.
// Whether a palette has lights // Whether a palette has lights
// the color indices to blend are stored in the palette's color 0 // the color indices to blend are stored in the palette's color 0
#define LIGHT_PAL(x) ((x) < NUM_PALS_IN_PRIMARY ? 1 << (x) : 1 << ((x) - NUM_PALS_IN_PRIMARY)) #define LIGHT_PAL(x) ((x) < NUM_PALS_IN_PRIMARY ? 1 << (x) : 1 << ((x) - NUM_PALS_IN_PRIMARY))
@ -11,7 +18,6 @@ const struct Tileset gTileset_General =
.isCompressed = TRUE, .isCompressed = TRUE,
.swapPalettes = SWAP_PAL(4), .swapPalettes = SWAP_PAL(4),
.isSecondary = FALSE, .isSecondary = FALSE,
.lightPalettes = LIGHT_PAL(4),
.tiles = gTilesetTiles_General, .tiles = gTilesetTiles_General,
.palettes = gTilesetPalettes_General, .palettes = gTilesetPalettes_General,
.metatiles = gMetatiles_General, .metatiles = gMetatiles_General,
@ -24,7 +30,6 @@ const struct Tileset gTileset_Petalburg =
.isCompressed = TRUE, .isCompressed = TRUE,
.swapPalettes = SWAP_PAL(9), .swapPalettes = SWAP_PAL(9),
.isSecondary = TRUE, .isSecondary = TRUE,
.lightPalettes = LIGHT_PAL(6) | LIGHT_PAL(7) | LIGHT_PAL(9),
.tiles = gTilesetTiles_Petalburg, .tiles = gTilesetTiles_Petalburg,
.palettes = gTilesetPalettes_Petalburg, .palettes = gTilesetPalettes_Petalburg,
.metatiles = gMetatiles_Petalburg, .metatiles = gMetatiles_Petalburg,
@ -36,7 +41,6 @@ const struct Tileset gTileset_Rustboro =
{ {
.isCompressed = TRUE, .isCompressed = TRUE,
.isSecondary = TRUE, .isSecondary = TRUE,
.lightPalettes = LIGHT_PAL(6),
.tiles = gTilesetTiles_Rustboro, .tiles = gTilesetTiles_Rustboro,
.palettes = gTilesetPalettes_Rustboro, .palettes = gTilesetPalettes_Rustboro,
.metatiles = gMetatiles_Rustboro, .metatiles = gMetatiles_Rustboro,
@ -60,7 +64,6 @@ const struct Tileset gTileset_Slateport =
.isCompressed = TRUE, .isCompressed = TRUE,
.swapPalettes = SWAP_PAL(6), .swapPalettes = SWAP_PAL(6),
.isSecondary = TRUE, .isSecondary = TRUE,
.lightPalettes = LIGHT_PAL(6) | LIGHT_PAL(12),
.tiles = gTilesetTiles_Slateport, .tiles = gTilesetTiles_Slateport,
.palettes = gTilesetPalettes_Slateport, .palettes = gTilesetPalettes_Slateport,
.metatiles = gMetatiles_Slateport, .metatiles = gMetatiles_Slateport,
@ -72,7 +75,6 @@ const struct Tileset gTileset_Mauville =
{ {
.isCompressed = TRUE, .isCompressed = TRUE,
.isSecondary = TRUE, .isSecondary = TRUE,
.lightPalettes = LIGHT_PAL(7) | LIGHT_PAL(10) | LIGHT_PAL(11),
.tiles = gTilesetTiles_Mauville, .tiles = gTilesetTiles_Mauville,
.palettes = gTilesetPalettes_Mauville, .palettes = gTilesetPalettes_Mauville,
.metatiles = gMetatiles_Mauville, .metatiles = gMetatiles_Mauville,
@ -84,8 +86,6 @@ const struct Tileset gTileset_Lavaridge =
{ {
.isCompressed = TRUE, .isCompressed = TRUE,
.isSecondary = TRUE, .isSecondary = TRUE,
.lightPalettes = LIGHT_PAL(6),
.customLightColor = LIGHT_PAL(6),
.tiles = gTilesetTiles_Lavaridge, .tiles = gTilesetTiles_Lavaridge,
.palettes = gTilesetPalettes_Lavaridge, .palettes = gTilesetPalettes_Lavaridge,
.metatiles = gMetatiles_Lavaridge, .metatiles = gMetatiles_Lavaridge,
@ -98,7 +98,6 @@ const struct Tileset gTileset_Fallarbor =
.isCompressed = TRUE, .isCompressed = TRUE,
.swapPalettes = SWAP_PAL(7), .swapPalettes = SWAP_PAL(7),
.isSecondary = TRUE, .isSecondary = TRUE,
.lightPalettes = LIGHT_PAL(7),
.tiles = gTilesetTiles_Fallarbor, .tiles = gTilesetTiles_Fallarbor,
.palettes = gTilesetPalettes_Fallarbor, .palettes = gTilesetPalettes_Fallarbor,
.metatiles = gMetatiles_Fallarbor, .metatiles = gMetatiles_Fallarbor,
@ -110,8 +109,6 @@ const struct Tileset gTileset_Fortree =
{ {
.isCompressed = TRUE, .isCompressed = TRUE,
.isSecondary = TRUE, .isSecondary = TRUE,
.lightPalettes = LIGHT_PAL(8),
.customLightColor = LIGHT_PAL(8),
.tiles = gTilesetTiles_Fortree, .tiles = gTilesetTiles_Fortree,
.palettes = gTilesetPalettes_Fortree, .palettes = gTilesetPalettes_Fortree,
.metatiles = gMetatiles_Fortree, .metatiles = gMetatiles_Fortree,
@ -124,7 +121,6 @@ const struct Tileset gTileset_Lilycove =
.isCompressed = TRUE, .isCompressed = TRUE,
.swapPalettes = SWAP_PAL(6), .swapPalettes = SWAP_PAL(6),
.isSecondary = TRUE, .isSecondary = TRUE,
.lightPalettes = LIGHT_PAL(6),
.tiles = gTilesetTiles_Lilycove, .tiles = gTilesetTiles_Lilycove,
.palettes = gTilesetPalettes_Lilycove, .palettes = gTilesetPalettes_Lilycove,
.metatiles = gMetatiles_Lilycove, .metatiles = gMetatiles_Lilycove,
@ -137,7 +133,6 @@ const struct Tileset gTileset_Mossdeep =
.isCompressed = TRUE, .isCompressed = TRUE,
.swapPalettes = SWAP_PAL(8), .swapPalettes = SWAP_PAL(8),
.isSecondary = TRUE, .isSecondary = TRUE,
.lightPalettes = LIGHT_PAL(8),
.tiles = gTilesetTiles_Mossdeep, .tiles = gTilesetTiles_Mossdeep,
.palettes = gTilesetPalettes_Mossdeep, .palettes = gTilesetPalettes_Mossdeep,
.metatiles = gMetatiles_Mossdeep, .metatiles = gMetatiles_Mossdeep,
@ -154,7 +149,6 @@ const struct Tileset gTileset_EverGrande =
.metatiles = gMetatiles_EverGrande, .metatiles = gMetatiles_EverGrande,
.metatileAttributes = gMetatileAttributes_EverGrande, .metatileAttributes = gMetatileAttributes_EverGrande,
.callback = InitTilesetAnim_EverGrande, .callback = InitTilesetAnim_EverGrande,
.lightPalettes = LIGHT_PAL(8),
.swapPalettes = SWAP_PAL(8), .swapPalettes = SWAP_PAL(8),
}; };
@ -163,7 +157,6 @@ const struct Tileset gTileset_Pacifidlog =
.isCompressed = TRUE, .isCompressed = TRUE,
.swapPalettes = SWAP_PAL(9), .swapPalettes = SWAP_PAL(9),
.isSecondary = TRUE, .isSecondary = TRUE,
.lightPalettes = LIGHT_PAL(9),
.tiles = gTilesetTiles_Pacifidlog, .tiles = gTilesetTiles_Pacifidlog,
.palettes = gTilesetPalettes_Pacifidlog, .palettes = gTilesetPalettes_Pacifidlog,
.metatiles = gMetatiles_Pacifidlog, .metatiles = gMetatiles_Pacifidlog,
@ -176,8 +169,6 @@ const struct Tileset gTileset_Sootopolis =
.isCompressed = TRUE, .isCompressed = TRUE,
.swapPalettes = SWAP_PAL(6), .swapPalettes = SWAP_PAL(6),
.isSecondary = TRUE, .isSecondary = TRUE,
.lightPalettes = LIGHT_PAL(6) | LIGHT_PAL(10),
.customLightColor = LIGHT_PAL(6) | LIGHT_PAL(10),
.tiles = gTilesetTiles_Sootopolis, .tiles = gTilesetTiles_Sootopolis,
.palettes = gTilesetPalettes_Sootopolis, .palettes = gTilesetPalettes_Sootopolis,
.metatiles = gMetatiles_Sootopolis, .metatiles = gMetatiles_Sootopolis,

View File

@ -1781,13 +1781,8 @@ static u8 LoadDynamicFollowerPalette(u16 species, u8 form, bool8 shiny) {
if ((paletteNum = IndexOfSpritePaletteTag(spritePalette->tag)) == 0xFF) { // Load compressed palette if ((paletteNum = IndexOfSpritePaletteTag(spritePalette->tag)) == 0xFF) { // Load compressed palette
LoadCompressedSpritePalette(spritePalette); LoadCompressedSpritePalette(spritePalette);
paletteNum = IndexOfSpritePaletteTag(spritePalette->tag); // Tag is always present paletteNum = IndexOfSpritePaletteTag(spritePalette->tag); // Tag is always present
if (species == SPECIES_AMPHAROS) { // palette should be light-blended TODO: Add more glowing pokemon // TODO: Add more glowing pokemon besides Ampharos
// CHARIZARD LINE ? CHINCHOU LANTERN FLAAFY MAREEP UMBREON VOLBEAT ? // CHARIZARD LINE ? CHINCHOU LANTERN FLAAFY MAREEP UMBREON VOLBEAT ?
u16 * palette = &gPlttBufferUnfaded[(paletteNum+16)*16];
palette[0] |= 0x8000;
if (palette[0] & 0x4000) // If color 15 is blended, use it as the alternate color
palette[15] |= 0x8000;
}
UpdateSpritePaletteWithWeather(paletteNum, FALSE); UpdateSpritePaletteWithWeather(paletteNum, FALSE);
} }
return paletteNum; return paletteNum;

View File

@ -904,14 +904,17 @@ void LoadTilesetPalette(struct Tileset const *tileset, u16 destOffset, u16 size,
LoadCompressedPalette((const u32 *)tileset->palettes, destOffset, size); LoadCompressedPalette((const u32 *)tileset->palettes, destOffset, size);
ApplyGlobalTintToPaletteEntries(destOffset, size >> 1); ApplyGlobalTintToPaletteEntries(destOffset, size >> 1);
} }
if (tileset->isSecondary == FALSE || tileset->isSecondary == TRUE) { // convert legacy light palette system to current
u32 i; if (tileset->lightPalettes) {
u32 i, j, color;
for (i = low; i < high; i++) { for (i = low; i < high; i++) {
if (tileset->lightPalettes & (1 << (i - low))) { // Mark as light palette if (tileset->lightPalettes & (1 << (i - low))) { // Mark light colors
u32 index = i * 16; for (j = 1, color = gPlttBufferUnfaded[PLTT_ID(i)]; j < 16 && color; j++, color >>= 1) {
gPlttBufferFaded[index] = gPlttBufferUnfaded[index] |= 0x8000; if (color & 1)
if (tileset->customLightColor & (1 << (i - low))) // Mark as custom light color gPlttBufferFaded[PLTT_ID(i)+j] = gPlttBufferUnfaded[PLTT_ID(i)+j] |= RGB_ALPHA;
gPlttBufferFaded[index+15] = gPlttBufferUnfaded[index+15] |= 0x8000; }
if (tileset->customLightColor & (1 << (i - low))) // Copy old custom light color to index 0
gPlttBufferFaded[PLTT_ID(i)] = gPlttBufferUnfaded[PLTT_ID(i)] = gPlttBufferUnfaded[PLTT_ID(i)+15] | RGB_ALPHA;
} }
} }
} }

View File

@ -1016,15 +1016,15 @@ void BlendPalettesFine(u32 palettes, u16 *src, u16 *dst, u32 coeff, u32 color) {
do { do {
if (palettes & 1) { if (palettes & 1) {
u16 *srcEnd = src + 16; u16 *srcEnd = src + 16;
while (src != srcEnd) { // Transparency is blended because it can matter for tile palettes while (src != srcEnd) { // Transparency is blended (for backdrop reasons)
u32 srcColor = *src; u32 srcColor = *src;
s32 r = (srcColor << 27) >> 27; s32 r = (srcColor << 27) >> 27;
s32 g = (srcColor << 22) >> 27; s32 g = (srcColor << 22) >> 27;
s32 b = (srcColor << 17) >> 27; s32 b = (srcColor << 16) >> 26;
*dst++ = ((r + (((newR - r) * coeff) >> 5)) << 0) *dst++ = ((r + (((newR - r) * (s32)coeff) >> 5)) << 0)
| ((g + (((newG - g) * coeff) >> 5)) << 5) | ((g + (((newG - g) * (s32)coeff) >> 5)) << 5)
| ((b + (((newB - b) * coeff) >> 5)) << 10); | ((b + (((newB - (b & 31)) * (s32)coeff) >> 5)) << 10);
src++; src++;
} }
} else { } else {
@ -1049,47 +1049,40 @@ void TimeBlendPalette(u16 palOffset, u32 coeff, u32 blendColor) {
u16 * dst = gPlttBufferFaded + palOffset; u16 * dst = gPlttBufferFaded + palOffset;
u32 defaultBlendColor = DEFAULT_LIGHT_COLOR; u32 defaultBlendColor = DEFAULT_LIGHT_COLOR;
u16 *srcEnd = src + 16; u16 *srcEnd = src + 16;
u16 altBlendIndices = *dst++ = *src++; // color 0 is copied through unchanged u32 altBlendColor = *dst++ = *src++; // color 0 is copied through unchanged
u32 altBlendColor;
coeff *= 2; coeff *= 2;
newR = (blendColor << 27) >> 27; newR = (blendColor << 27) >> 27;
newG = (blendColor << 22) >> 27; newG = (blendColor << 22) >> 27;
newB = (blendColor << 17) >> 27; newB = (blendColor << 17) >> 27;
if (altBlendIndices >> 15) { // High bit set; bitmask of which colors to alt-blend if (altBlendColor >> 15) { // Transparency high bit set; alt blend color
// Note that bit 0 of altBlendIndices specifies color 1
altBlendColor = src[14]; // color 15
if (altBlendColor >> 15) { // Set alternate blend color
defR = (altBlendColor << 27) >> 27; defR = (altBlendColor << 27) >> 27;
defG = (altBlendColor << 22) >> 27; defG = (altBlendColor << 22) >> 27;
defB = (altBlendColor << 17) >> 27; defB = (altBlendColor << 17) >> 27;
} else { // Set default blend color } else {
defR = (defaultBlendColor << 27) >> 27; defR = (defaultBlendColor << 27) >> 27;
defG = (defaultBlendColor << 22) >> 27; defG = (defaultBlendColor << 22) >> 27;
defB = (defaultBlendColor << 17) >> 27; defB = (defaultBlendColor << 17) >> 27;
} altBlendColor = 0;
} else {
altBlendIndices = 0;
} }
while (src != srcEnd) { while (src != srcEnd) {
u32 srcColor = *src; u32 srcColor = *src;
s32 r = (srcColor << 27) >> 27; s32 r = (srcColor << 27) >> 27;
s32 g = (srcColor << 22) >> 27; s32 g = (srcColor << 22) >> 27;
s32 b = (srcColor << 17) >> 27; s32 b = (srcColor << 16) >> 26;
if (altBlendIndices & 1) { if (srcColor >> 15) {
*dst = ((r + (((defR - r) * coeff) >> 5)) << 0) *dst = ((r + (((defR - r) * (s32)coeff) >> 5)) << 0)
| ((g + (((defG - g) * coeff) >> 5)) << 5) | ((g + (((defG - g) * (s32)coeff) >> 5)) << 5)
| ((b + (((defB - b) * coeff) >> 5)) << 10); | ((b + (((defB - (b & 31)) * (s32)coeff) >> 5)) << 10);
} else { // Use provided blend color } else { // Use provided blend color
*dst = ((r + (((newR - r) * coeff) >> 5)) << 0) *dst = ((r + (((newR - r) * (s32)coeff) >> 5)) << 0)
| ((g + (((newG - g) * coeff) >> 5)) << 5) | ((g + (((newG - g) * (s32)coeff) >> 5)) << 5)
| ((b + (((newB - b) * coeff) >> 5)) << 10); | ((b + (((newB - (b & 31)) * (s32)coeff) >> 5)) << 10);
} }
src++; src++;
dst++; dst++;
altBlendIndices >>= 1;
} }
} }
@ -1099,7 +1092,6 @@ void TimeMixPalettes(u32 palettes, u16 *src, u16 *dst, struct BlendSettings *ble
s32 r0, g0, b0, r1, g1, b1, defR, defG, defB, altR, altG, altB; s32 r0, g0, b0, r1, g1, b1, defR, defG, defB, altR, altG, altB;
u32 color0, coeff0, color1, coeff1; u32 color0, coeff0, color1, coeff1;
bool8 tint0, tint1; bool8 tint0, tint1;
u16 weight1;
u32 defaultColor = DEFAULT_LIGHT_COLOR; u32 defaultColor = DEFAULT_LIGHT_COLOR;
if (!palettes) if (!palettes)
@ -1133,54 +1125,50 @@ void TimeMixPalettes(u32 palettes, u16 *src, u16 *dst, struct BlendSettings *ble
defR = (defaultColor << 27) >> 27; defR = (defaultColor << 27) >> 27;
defG = (defaultColor << 22) >> 27; defG = (defaultColor << 22) >> 27;
defB = (defaultColor << 17) >> 27; defB = (defaultColor << 17) >> 27;
weight1 = 256 - weight0;
do { do {
if (palettes & 1) { if (palettes & 1) {
u16 *srcEnd = src + 16; u16 *srcEnd = src + 16;
u16 altBlendIndices = *dst++ = *src++; // color 0 is copied through u32 altBlendColor = *dst++ = *src++; // color 0 is copied through
u32 altBlendColor; if (altBlendColor >> 15) { // Transparency high bit set; alt blend color
if (altBlendIndices >> 15) { // High bit set; bitmask of which colors to alt-blend
// Note that bit 0 of altBlendIndices specifies color 1
altBlendColor = src[14]; // color 15
if (altBlendColor >> 15) { // Set alternate blend color
altR = (altBlendColor << 27) >> 27; altR = (altBlendColor << 27) >> 27;
altG = (altBlendColor << 22) >> 27; altG = (altBlendColor << 22) >> 27;
altB = (altBlendColor << 17) >> 27; altB = (altBlendColor << 17) >> 27;
} else { } else {
altBlendColor = 0; altBlendColor = 0;
} }
} else {
altBlendIndices = 0;
}
while (src != srcEnd) { while (src != srcEnd) {
u32 srcColor = *src; u32 srcColor = *src;
s32 r = (srcColor << 27) >> 27; s32 r = (srcColor << 27) >> 27;
s32 g = (srcColor << 22) >> 27; s32 g = (srcColor << 22) >> 27;
s32 b = (srcColor << 17) >> 27; s32 b = (srcColor << 17) >> 27;
s32 r2, g2, b2;
if (altBlendIndices & 1) { if (srcColor >> 15) {
if (altBlendColor) { // Use alternate blend color if (altBlendColor) { // Use alternate blend color
r = (weight0*(r + (((altR - r) * coeff0) >> 5)) + weight1*(r + (((altR - r) * coeff1) >> 5))) >> 8; r2 = r + (((altR - r) * (s32)coeff1) >> 5);
g = (weight0*(g + (((altG - g) * coeff0) >> 5)) + weight1*(g + (((altG - g) * coeff1) >> 5))) >> 8; g2 = g + (((altG - g) * (s32)coeff1) >> 5);
b = (weight0*(b + (((altB - b) * coeff0) >> 5)) + weight1*(b + (((altB - b) * coeff1) >> 5))) >> 8; b2 = b + (((altB - b) * (s32)coeff1) >> 5);
*dst = RGB2(r, g, b); r = r + (((altR - r) * (s32)coeff0) >> 5);
g = g + (((altG - g) * (s32)coeff0) >> 5);
b = b + (((altB - b) * (s32)coeff0) >> 5);
} else { // Use default blend color } else { // Use default blend color
r = (weight0*(r + (((defR - r) * coeff0) >> 5)) + weight1*(r + (((defR - r) * coeff1) >> 5))) >> 8; r2 = r + (((defR - r) * (s32)coeff1) >> 5);
g = (weight0*(g + (((defG - g) * coeff0) >> 5)) + weight1*(g + (((defG - g) * coeff1) >> 5))) >> 8; g2 = g + (((defG - g) * (s32)coeff1) >> 5);
b = (weight0*(b + (((defB - b) * coeff0) >> 5)) + weight1*(b + (((defB - b) * coeff1) >> 5))) >> 8; b2 = b + (((defB - b) * (s32)coeff1) >> 5);
*dst = RGB2(r, g, b); r = r + (((defR - r) * (s32)coeff0) >> 5);
g = g + (((defG - g) * (s32)coeff0) >> 5);
b = b + (((defB - b) * (s32)coeff0) >> 5);
} }
} else { // Use provided blend colors } else { // Use provided blend colors
s32 r2, g2, b2, r3, g3, b3; if (!tint1) { // blend-based
if (!tint0) { // blend-based r2 = (r + (((r1 - r) * (s32)coeff1) >> 5));
r2 = (r + (((r0 - r) * coeff0) >> 5)); g2 = (g + (((g1 - g) * (s32)coeff1) >> 5));
g2 = (g + (((g0 - g) * coeff0) >> 5)); b2 = (b + (((b1 - b) * (s32)coeff1) >> 5));
b2 = (b + (((b0 - b) * coeff0) >> 5));
} else { // tint-based } else { // tint-based
r2 = (u16)((r0 * r)) >> 8; r2 = (u16)((r1 * r)) >> 8;
g2 = (u16)((g0 * g)) >> 8; g2 = (u16)((g1 * g)) >> 8;
b2 = (u16)((b0 * b)) >> 8; b2 = (u16)((b1 * b)) >> 8;
if (r2 > 31) if (r2 > 31)
r2 = 31; r2 = 31;
if (g2 > 31) if (g2 > 31)
@ -1188,29 +1176,28 @@ void TimeMixPalettes(u32 palettes, u16 *src, u16 *dst, struct BlendSettings *ble
if (b2 > 31) if (b2 > 31)
b2 = 31; b2 = 31;
} }
if (!tint1) { // blend-based if (!tint0) { // blend-based
r3 = (r + (((r1 - r) * coeff1) >> 5)); r = (r + (((r0 - r) * (s32)coeff0) >> 5));
g3 = (g + (((g1 - g) * coeff1) >> 5)); g = (g + (((g0 - g) * (s32)coeff0) >> 5));
b3 = (b + (((b1 - b) * coeff1) >> 5)); b = (b + (((b0 - b) * (s32)coeff0) >> 5));
} else { // tint-based } else { // tint-based
r3 = (u16)((r1 * r)) >> 8; r = (u16)((r0 * r)) >> 8;
g3 = (u16)((g1 * g)) >> 8; g = (u16)((g0 * g)) >> 8;
b3 = (u16)((b1 * b)) >> 8; b = (u16)((b0 * b)) >> 8;
if (r3 > 31) if (r > 31)
r3 = 31; r = 31;
if (g3 > 31) if (g > 31)
g3 = 31; g = 31;
if (b3 > 31) if (b > 31)
b3 = 31; b = 31;
} }
r = (weight0*r2 + weight1*r3) >> 8;
g = (weight0*g2 + weight1*g3) >> 8;
b = (weight0*b2 + weight1*b3) >> 8;
*dst = RGB2(r, g, b);
} }
r = r2 + (((r - r2) * (s32)weight0) >> 8);
g = g2 + (((g - g2) * (s32)weight0) >> 8);
b = b2 + (((b - b2) * (s32)weight0) >> 8);
*dst++ = RGB2(r, g, b);
// *dst++ = RGB2(r, g, b) | (srcColor >> 15) << 15;
src++; src++;
dst++;
altBlendIndices >>= 1;
} }
} else { } else {
src += 16; src += 16;
@ -1223,7 +1210,6 @@ void TimeMixPalettes(u32 palettes, u16 *src, u16 *dst, struct BlendSettings *ble
// Apply weighted average to palettes, preserving high bits of dst throughout // Apply weighted average to palettes, preserving high bits of dst throughout
void AvgPaletteWeighted(u16 *src0, u16 *src1, u16 *dst, u16 weight0) { void AvgPaletteWeighted(u16 *src0, u16 *src1, u16 *dst, u16 weight0) {
u16 *srcEnd = src0 + 16; u16 *srcEnd = src0 + 16;
u16 weight1 = 256 - weight0;
src0++; src0++;
src1++; src1++;
dst++; // leave dst transparency unchanged dst++; // leave dst transparency unchanged
@ -1238,10 +1224,10 @@ void AvgPaletteWeighted(u16 *src0, u16 *src1, u16 *dst, u16 weight0) {
s32 b1 = (src1Color << 17) >> 27; s32 b1 = (src1Color << 17) >> 27;
// Average and bitwise-OR // Average and bitwise-OR
r0 = (weight0*r0 + weight1*r1) >> 8; r0 = r1 + (((r0 - r1) * weight0) >> 8);
g0 = (weight0*g0 + weight1*g1) >> 8; g0 = g1 + (((g0 - g1) * weight0) >> 8);
b0 = (weight0*b0 + weight1*b1) >> 8; b0 = b1 + (((b0 - b1) * weight0) >> 8);
*dst++ = (*dst & 0x8000) | RGB2(r0, g0, b0); // preserve high bit of dst *dst++ = (*dst & RGB_ALPHA) | RGB2(r0, g0, b0); // preserve high bit of dst
} }
} }

View File

@ -14,6 +14,7 @@
#define GET_GBA_PAL_BLUE(x) (((x) >> 10) & 0x1F) #define GET_GBA_PAL_BLUE(x) (((x) >> 10) & 0x1F)
#define SET_GBA_PAL(r, g, b) (((b) << 10) | ((g) << 5) | (r)) #define SET_GBA_PAL(r, g, b) (((b) << 10) | ((g) << 5) | (r))
#define SET_GBA_PAL_RGBA(r, g, b, a) (((a) << 15) | ((b) << 10) | ((g) << 5) | (r))
#define UPCONVERT_BIT_DEPTH(x) (((x) * 255) / 31) #define UPCONVERT_BIT_DEPTH(x) (((x) * 255) / 31)
@ -516,8 +517,9 @@ void WriteGbaPalette(char *path, struct Palette *palette)
unsigned char red = DOWNCONVERT_BIT_DEPTH(palette->colors[i].red); unsigned char red = DOWNCONVERT_BIT_DEPTH(palette->colors[i].red);
unsigned char green = DOWNCONVERT_BIT_DEPTH(palette->colors[i].green); unsigned char green = DOWNCONVERT_BIT_DEPTH(palette->colors[i].green);
unsigned char blue = DOWNCONVERT_BIT_DEPTH(palette->colors[i].blue); unsigned char blue = DOWNCONVERT_BIT_DEPTH(palette->colors[i].blue);
bool alpha = palette->colors[i].alpha;
uint16_t paletteEntry = SET_GBA_PAL(red, green, blue); uint16_t paletteEntry = SET_GBA_PAL_RGBA(red, green, blue, alpha);
fputc(paletteEntry & 0xFF, fp); fputc(paletteEntry & 0xFF, fp);
fputc(paletteEntry >> 8, fp); fputc(paletteEntry >> 8, fp);

View File

@ -10,6 +10,7 @@ struct Color {
unsigned char red; unsigned char red;
unsigned char green; unsigned char green;
unsigned char blue; unsigned char blue;
bool alpha;
}; };
struct Palette { struct Palette {

View File

@ -22,7 +22,7 @@
// Blue - "0 0 255\r\n" // Blue - "0 0 255\r\n"
// Brown - "150 75 0\r\n" // Brown - "150 75 0\r\n"
#define MAX_LINE_LENGTH 11 #define MAX_LINE_LENGTH 64
void ReadJascPaletteLine(FILE *fp, char *line) void ReadJascPaletteLine(FILE *fp, char *line)
{ {
@ -152,6 +152,43 @@ void ReadJascPalette(char *path, struct Palette *palette)
FATAL_ERROR("Garbage after color data.\n"); FATAL_ERROR("Garbage after color data.\n");
fclose(fp); fclose(fp);
// Try to parse alpha/high bit info for colors from auxiliary .pla file
char *dot = strrchr(path, '.');
if (strcmp(dot, ".pal") != 0)
return;
strcpy(dot, ".pla"); // replace .pal with .pla
fp = fopen(path, "rb");
if (fp == NULL)
return;
// fprintf(stderr, "Opened auxiliary .pla file for reading: %s\n", path);
int i = 0;
// Keep reading lines until number of colors is reached or we run out
while (i < palette->numColors && fgets(line, MAX_LINE_LENGTH, fp) != NULL)
{
if (line[0] == '#') // comment line; ignore
continue;
char *s = line;
char *end;
int colorIndex;
if (!ParseNumber(s, &end, 10, &colorIndex))
FATAL_ERROR("Failed to parse aux color index.\n");
s = end;
if (colorIndex >= palette->numColors)
FATAL_ERROR("Aux color index %d out of bounds.\n", colorIndex);
palette->colors[colorIndex].alpha = 1; // set alpha color
// fprintf(stderr, "Color index: %d\n", colorIndex);
i++;
}
fclose(fp);
} }
void WriteJascPalette(char *path, struct Palette *palette) void WriteJascPalette(char *path, struct Palette *palette)

View File

@ -247,7 +247,7 @@ void HandlePngToGbaCommand(char *inputPath, char *outputPath, int argc, char **a
void HandlePngToJascPaletteCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) void HandlePngToJascPaletteCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED)
{ {
struct Palette palette = {}; struct Palette palette = {0};
ReadPngPalette(inputPath, &palette); ReadPngPalette(inputPath, &palette);
WriteJascPalette(outputPath, &palette); WriteJascPalette(outputPath, &palette);
@ -255,7 +255,7 @@ void HandlePngToJascPaletteCommand(char *inputPath, char *outputPath, int argc U
void HandlePngToGbaPaletteCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) void HandlePngToGbaPaletteCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED)
{ {
struct Palette palette = {}; struct Palette palette = {0};
ReadPngPalette(inputPath, &palette); ReadPngPalette(inputPath, &palette);
WriteGbaPalette(outputPath, &palette); WriteGbaPalette(outputPath, &palette);
@ -263,7 +263,7 @@ void HandlePngToGbaPaletteCommand(char *inputPath, char *outputPath, int argc UN
void HandleGbaToJascPaletteCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) void HandleGbaToJascPaletteCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED)
{ {
struct Palette palette = {}; struct Palette palette = {0};
ReadGbaPalette(inputPath, &palette); ReadGbaPalette(inputPath, &palette);
WriteJascPalette(outputPath, &palette); WriteJascPalette(outputPath, &palette);
@ -296,7 +296,7 @@ void HandleJascToGbaPaletteCommand(char *inputPath, char *outputPath, int argc,
} }
} }
struct Palette palette = {}; struct Palette palette = {0};
ReadJascPalette(inputPath, &palette); ReadJascPalette(inputPath, &palette);