diff options
author | PikalaxALT <PikalaxALT@users.noreply.github.com> | 2019-10-02 19:36:19 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-02 19:36:19 -0400 |
commit | 872d5eaf4ad70598f597a64469cdf5cd32d44ba4 (patch) | |
tree | 9fc3ae3161a9d675659ceb892a5f18440f0f441a /src | |
parent | 3ab2de40cf164a86af27eff7a46215d3d927f47f (diff) | |
parent | ed2e58282155ad0a754449dcdc41fbd52855444c (diff) |
Merge pull request #105 from jiangzhengwenjz/palette
palette
Diffstat (limited to 'src')
-rw-r--r-- | src/palette.c | 989 |
1 files changed, 989 insertions, 0 deletions
diff --git a/src/palette.c b/src/palette.c new file mode 100644 index 000000000..6609c9baa --- /dev/null +++ b/src/palette.c @@ -0,0 +1,989 @@ +#include "global.h" +#include "palette.h" +#include "util.h" +#include "decompress.h" +#include "gpu_regs.h" +#include "task.h" + +enum +{ + NORMAL_FADE, + FAST_FADE, + HARDWARE_FADE, +}; + +#define NUM_PALETTE_STRUCTS 16 + +// unused palette struct +struct PaletteStructTemplate +{ + u16 uid; + u16 *src; + u16 pst_field_8_0:1; + u16 pst_field_8_1:9; + u16 size:5; + u16 pst_field_9_7:1; + u8 pst_field_A; + u8 srcCount:5; + u8 pst_field_B_5:3; + u8 pst_field_C; +}; + +struct PaletteStruct +{ + const struct PaletteStructTemplate *base; + u32 ps_field_4_0:1; + u16 ps_field_4_1:1; + u32 baseDestOffset:9; + u16 destOffset:10; + u16 srcIndex:7; + u8 ps_field_8; + u8 ps_field_9; +}; + +static void sub_8070790(struct PaletteStruct *, u32 *); +static void sub_80708F4(struct PaletteStruct *, u32 *); +static void sub_80709B4(struct PaletteStruct *); +static u8 GetPaletteNumByUid(u16); +static u8 UpdateNormalPaletteFade(void); +static void BeginFastPaletteFadeInternal(u8); +static u8 UpdateFastPaletteFade(void); +static u8 UpdateHardwarePaletteFade(void); +static void UpdateBlendRegisters(void); +static bool8 IsSoftwarePaletteFadeFinishing(void); +static void sub_80718B8(u8 taskId); + +ALIGNED(4) EWRAM_DATA u16 gPlttBufferUnfaded[PLTT_BUFFER_SIZE] = {0}; +ALIGNED(4) EWRAM_DATA u16 gPlttBufferFaded[PLTT_BUFFER_SIZE] = {0}; +static EWRAM_DATA struct PaletteStruct sPaletteStructs[NUM_PALETTE_STRUCTS] = {0}; +EWRAM_DATA struct PaletteFadeControl gPaletteFade = {0}; +static EWRAM_DATA u32 sPlttBufferTransferPending = 0; +EWRAM_DATA u8 gPaletteDecompressionBuffer[PLTT_DECOMP_BUFFER_SIZE] = {0}; + +static const struct PaletteStructTemplate gDummyPaletteStructTemplate = +{ + .uid = 0xFFFF, + .pst_field_B_5 = 1 +}; + +static const u8 sRoundedDownGrayscaleMap[] = +{ + 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, + 11, 11, 11, 11, 11, + 16, 16, 16, 16, 16, + 21, 21, 21, 21, 21, + 27, 27, 27, 27, 27, + 31, 31 +}; + +void LoadCompressedPalette(const u32 *src, u16 offset, u16 size) +{ + LZDecompressWram(src, gPaletteDecompressionBuffer); + CpuCopy16(gPaletteDecompressionBuffer, gPlttBufferUnfaded + offset, size); + CpuCopy16(gPaletteDecompressionBuffer, gPlttBufferFaded + offset, size); +} + +void LoadPalette(const void *src, u16 offset, u16 size) +{ + CpuCopy16(src, gPlttBufferUnfaded + offset, size); + CpuCopy16(src, gPlttBufferFaded + offset, size); +} + +void FillPalette(u16 value, u16 offset, u16 size) +{ + CpuFill16(value, gPlttBufferUnfaded + offset, size); + CpuFill16(value, gPlttBufferFaded + offset, size); +} + +void TransferPlttBuffer(void) +{ + if (!gPaletteFade.bufferTransferDisabled) + { + void *src = gPlttBufferFaded; + void *dest = (void *)PLTT; + DmaCopy16(3, src, dest, PLTT_SIZE); + sPlttBufferTransferPending = 0; + if (gPaletteFade.mode == HARDWARE_FADE && gPaletteFade.active) + UpdateBlendRegisters(); + } +} + +u8 UpdatePaletteFade(void) +{ + u8 result; + u8 dummy = 0; + + if (sPlttBufferTransferPending) + return PALETTE_FADE_STATUS_LOADING; + if (gPaletteFade.mode == NORMAL_FADE) + result = UpdateNormalPaletteFade(); + else if (gPaletteFade.mode == FAST_FADE) + result = UpdateFastPaletteFade(); + else + result = UpdateHardwarePaletteFade(); + sPlttBufferTransferPending = gPaletteFade.multipurpose1 | dummy; + return result; +} + +void ResetPaletteFade(void) +{ + u8 i; + + for (i = 0; i < 16; ++i) + ResetPaletteStruct(i); + ResetPaletteFadeControl(); +} + +void ReadPlttIntoBuffers(void) +{ + u16 i; + u16 *pltt = (u16 *)PLTT; + + for (i = 0; i < PLTT_SIZE / 2; ++i) + { + gPlttBufferUnfaded[i] = pltt[i]; + gPlttBufferFaded[i] = pltt[i]; + } +} + +bool8 BeginNormalPaletteFade(u32 selectedPalettes, s8 delay, u8 startY, u8 targetY, u16 blendColor) +{ + u8 temp; + u16 color = blendColor; + + if (gPaletteFade.active) + { + return FALSE; + } + else + { + gPaletteFade.deltaY = 2; + if (delay < 0) + { + gPaletteFade.deltaY += (delay * -1); + delay = 0; + } + gPaletteFade_selectedPalettes = selectedPalettes; + gPaletteFade.delayCounter = delay; + gPaletteFade_delay = delay; + gPaletteFade.y = startY; + gPaletteFade.targetY = targetY; + gPaletteFade.blendColor = color; + gPaletteFade.active = TRUE; + gPaletteFade.mode = NORMAL_FADE; + if (startY < targetY) + gPaletteFade.yDec = FALSE; + else + gPaletteFade.yDec = TRUE; + UpdatePaletteFade(); + temp = gPaletteFade.bufferTransferDisabled; + gPaletteFade.bufferTransferDisabled = FALSE; + CpuCopy32(gPlttBufferFaded, (void *)PLTT, PLTT_SIZE); + sPlttBufferTransferPending = 0; + if (gPaletteFade.mode == HARDWARE_FADE && gPaletteFade.active) + UpdateBlendRegisters(); + gPaletteFade.bufferTransferDisabled = temp; + return TRUE; + } +} + +// not used +static bool8 sub_80706D0(u32 a1, u8 a2, u8 a3, u8 a4, u16 a5) +{ + ReadPlttIntoBuffers(); + return BeginNormalPaletteFade(a1, a2, a3, a4, a5); +} + +// not used +static void sub_8070718(u8 a1, u32 *a2) +{ + u8 i; + + for (i = 0; i < NUM_PALETTE_STRUCTS; ++i) + { + struct PaletteStruct *palstruct = &sPaletteStructs[i]; + + if (palstruct->ps_field_4_0) + { + if (palstruct->base->pst_field_8_0 == a1) + { + u8 val1 = palstruct->srcIndex; + u8 val2 = palstruct->base->srcCount; + + if (val1 == val2) + { + sub_80709B4(palstruct); + if (!palstruct->ps_field_4_0) + continue; + } + if (palstruct->ps_field_8 == 0) + sub_8070790(palstruct, a2); + else + --palstruct->ps_field_8; + sub_80708F4(palstruct, a2); + } + } + } +} + +// not used +static void sub_8070790(struct PaletteStruct *a1, u32 *a2) +{ + s32 srcIndex; + s32 srcCount; + u8 i = 0; + u16 srcOffset = a1->srcIndex * a1->base->size; + + if (!a1->base->pst_field_8_0) + { + while (i < a1->base->size) + { + gPlttBufferUnfaded[a1->destOffset] = a1->base->src[srcOffset]; + gPlttBufferFaded[a1->destOffset] = a1->base->src[srcOffset]; + ++i; + ++a1->destOffset; + ++srcOffset; + } + } + else + { + while (i < a1->base->size) + { + gPlttBufferFaded[a1->destOffset] = a1->base->src[srcOffset]; + ++i; + ++a1->destOffset; + ++srcOffset; + } + } + a1->destOffset = a1->baseDestOffset; + a1->ps_field_8 = a1->base->pst_field_A; + ++a1->srcIndex; + srcIndex = a1->srcIndex; + srcCount = a1->base->srcCount; + if (srcIndex >= srcCount) + { + if (a1->ps_field_9) + --a1->ps_field_9; + a1->srcIndex = 0; + } + *a2 |= 1 << (a1->baseDestOffset >> 4); +} + +// not used +static void sub_80708F4(struct PaletteStruct *a1, u32 *a2) +{ + if (gPaletteFade.active && ((1 << (a1->baseDestOffset >> 4)) & gPaletteFade_selectedPalettes)) + { + if (!a1->base->pst_field_8_0) + { + if (gPaletteFade.delayCounter != gPaletteFade_delay) + BlendPalette(a1->baseDestOffset, + a1->base->size, + gPaletteFade.y, + gPaletteFade.blendColor); + } + else + { + if (!gPaletteFade.delayCounter) + { + if (a1->ps_field_8 != a1->base->pst_field_A) + { + u32 srcOffset = a1->srcIndex * a1->base->size; + u8 i; + + for (i = 0; i < a1->base->size; ++i) + gPlttBufferFaded[a1->baseDestOffset + i] = a1->base->src[srcOffset + i]; + } + } + } + } +} + +// not used +static void sub_80709B4(struct PaletteStruct *a1) +{ + if (!a1->ps_field_9) + { + s32 val = a1->base->pst_field_B_5; + + if (!val) + { + a1->srcIndex = 0; + a1->ps_field_8 = a1->base->pst_field_A; + a1->ps_field_9 = a1->base->pst_field_C; + a1->destOffset = a1->baseDestOffset; + } + else + { + if (val < 0) + return; + if (val > 2) + return; + ResetPaletteStructByUid(a1->base->uid); + } + } + else + { + --a1->ps_field_9; + } +} + +void ResetPaletteStructByUid(u16 a1) +{ + u8 paletteNum = GetPaletteNumByUid(a1); + if (paletteNum != 16) + ResetPaletteStruct(paletteNum); +} + +void ResetPaletteStruct(u8 paletteNum) +{ + sPaletteStructs[paletteNum].base = &gDummyPaletteStructTemplate; + sPaletteStructs[paletteNum].ps_field_4_0 = 0; + sPaletteStructs[paletteNum].baseDestOffset = 0; + sPaletteStructs[paletteNum].destOffset = 0; + sPaletteStructs[paletteNum].srcIndex = 0; + sPaletteStructs[paletteNum].ps_field_4_1 = 0; + sPaletteStructs[paletteNum].ps_field_8 = 0; + sPaletteStructs[paletteNum].ps_field_9 = 0; +} + +void ResetPaletteFadeControl(void) +{ + gPaletteFade.multipurpose1 = 0; + gPaletteFade.multipurpose2 = 0; + gPaletteFade.delayCounter = 0; + gPaletteFade.y = 0; + gPaletteFade.targetY = 0; + gPaletteFade.blendColor = 0; + gPaletteFade.active = FALSE; + gPaletteFade.multipurpose2 = 0; // assign same value twice + gPaletteFade.yDec = FALSE; + gPaletteFade.bufferTransferDisabled = FALSE; + gPaletteFade.shouldResetBlendRegisters = FALSE; + gPaletteFade.hardwareFadeFinishing = FALSE; + gPaletteFade.softwareFadeFinishing = FALSE; + gPaletteFade.softwareFadeFinishingCounter = 0; + gPaletteFade.objPaletteToggle = 0; + gPaletteFade.deltaY = 2; +} + +// not used +static void sub_8070AFC(u16 uid) +{ + u8 paletteNum = GetPaletteNumByUid(uid); + if (paletteNum != 16) + sPaletteStructs[paletteNum].ps_field_4_1 = 1; +} + +// not used +static void sub_8070B28(u16 uid) +{ + u8 paletteNum = GetPaletteNumByUid(uid); + if (paletteNum != 16) + sPaletteStructs[paletteNum].ps_field_4_1 = 0; +} + +// not used +static u8 GetPaletteNumByUid(u16 uid) +{ + u8 i; + + for (i = 0; i < NUM_PALETTE_STRUCTS; ++i) + if (sPaletteStructs[i].base->uid == uid) + return i; + return 16; +} + +static u8 UpdateNormalPaletteFade(void) +{ + u16 paletteOffset; + u16 selectedPalettes; + + if (!gPaletteFade.active) + return PALETTE_FADE_STATUS_DONE; + if (IsSoftwarePaletteFadeFinishing()) + { + return gPaletteFade.active ? PALETTE_FADE_STATUS_ACTIVE : PALETTE_FADE_STATUS_DONE; + } + else + { + if (!gPaletteFade.objPaletteToggle) + { + if (gPaletteFade.delayCounter < gPaletteFade_delay) + { + ++gPaletteFade.delayCounter; + return 2; + } + gPaletteFade.delayCounter = 0; + } + paletteOffset = 0; + if (!gPaletteFade.objPaletteToggle) + { + selectedPalettes = gPaletteFade_selectedPalettes; + } + else + { + selectedPalettes = gPaletteFade_selectedPalettes >> 16; + paletteOffset = 256; + } + while (selectedPalettes) + { + if (selectedPalettes & 1) + BlendPalette(paletteOffset, + 16, + gPaletteFade.y, + gPaletteFade.blendColor); + selectedPalettes >>= 1; + paletteOffset += 16; + } + gPaletteFade.objPaletteToggle ^= 1; + if (!gPaletteFade.objPaletteToggle) + { + if (gPaletteFade.y == gPaletteFade.targetY) + { + gPaletteFade_selectedPalettes = 0; + gPaletteFade.softwareFadeFinishing = TRUE; + } + else + { + s8 val; + + if (!gPaletteFade.yDec) + { + val = gPaletteFade.y; + val += gPaletteFade.deltaY; + if (val > gPaletteFade.targetY) + val = gPaletteFade.targetY; + gPaletteFade.y = val; + } + else + { + val = gPaletteFade.y; + val -= gPaletteFade.deltaY; + if (val < gPaletteFade.targetY) + val = gPaletteFade.targetY; + gPaletteFade.y = val; + } + } + } + // gPaletteFade.active cannot change since the last time it was checked. So this + // is equivalent to `return PALETTE_FADE_STATUS_ACTIVE;` + return gPaletteFade.active ? PALETTE_FADE_STATUS_ACTIVE : PALETTE_FADE_STATUS_DONE; + } +} + +void InvertPlttBuffer(u32 selectedPalettes) +{ + u16 paletteOffset = 0; + + while (selectedPalettes) + { + if (selectedPalettes & 1) + { + u8 i; + + for (i = 0; i < 16; ++i) + gPlttBufferFaded[paletteOffset + i] = ~gPlttBufferFaded[paletteOffset + i]; + } + selectedPalettes >>= 1; + paletteOffset += 16; + } +} + +void TintPlttBuffer(u32 selectedPalettes, s8 r, s8 g, s8 b) +{ + u16 paletteOffset = 0; + + while (selectedPalettes) + { + if (selectedPalettes & 1) + { + u8 i; + + for (i = 0; i < 16; ++i) + { + struct PlttData *data = (struct PlttData *)&gPlttBufferFaded[paletteOffset + i]; + + data->r += r; + data->g += g; + data->b += b; + } + } + selectedPalettes >>= 1; + paletteOffset += 16; + } +} + +void UnfadePlttBuffer(u32 selectedPalettes) +{ + u16 paletteOffset = 0; + + while (selectedPalettes) + { + if (selectedPalettes & 1) + { + u8 i; + + for (i = 0; i < 16; ++i) + gPlttBufferFaded[paletteOffset + i] = gPlttBufferUnfaded[paletteOffset + i]; + } + selectedPalettes >>= 1; + paletteOffset += 16; + } +} + +void BeginFastPaletteFade(u8 submode) +{ + gPaletteFade.deltaY = 2; + BeginFastPaletteFadeInternal(submode); +} + +static void BeginFastPaletteFadeInternal(u8 submode) +{ + gPaletteFade.y = 31; + gPaletteFade_submode = submode & 0x3F; + gPaletteFade.active = TRUE; + gPaletteFade.mode = FAST_FADE; + if (submode == FAST_FADE_IN_FROM_BLACK) + CpuFill16(RGB_BLACK, gPlttBufferFaded, PLTT_SIZE); + if (submode == FAST_FADE_IN_FROM_WHITE) + CpuFill16(RGB_WHITE, gPlttBufferFaded, PLTT_SIZE); + UpdatePaletteFade(); +} + +static u8 UpdateFastPaletteFade(void) +{ + u16 i; + u16 paletteOffsetStart, paletteOffsetEnd; + s8 r0, g0, b0, r, g, b; + + if (!gPaletteFade.active) + return PALETTE_FADE_STATUS_DONE; + if (IsSoftwarePaletteFadeFinishing()) + return gPaletteFade.active ? PALETTE_FADE_STATUS_ACTIVE : PALETTE_FADE_STATUS_DONE; + if (gPaletteFade.objPaletteToggle) + { + paletteOffsetStart = 256; + paletteOffsetEnd = 512; + } + else + { + paletteOffsetStart = 0; + paletteOffsetEnd = 256; + } + switch (gPaletteFade_submode) + { + case FAST_FADE_IN_FROM_WHITE: + for (i = paletteOffsetStart; i < paletteOffsetEnd; ++i) + { + struct PlttData *unfaded; + struct PlttData *faded; + + unfaded = (struct PlttData *)&gPlttBufferUnfaded[i]; + r0 = unfaded->r; + g0 = unfaded->g; + b0 = unfaded->b; + faded = (struct PlttData *)&gPlttBufferFaded[i]; + r = faded->r - 2; + g = faded->g - 2; + b = faded->b - 2; + if (r < r0) + r = r0; + if (g < g0) + g = g0; + if (b < b0) + b = b0; + gPlttBufferFaded[i] = r | (g << 5) | (b << 10); + } + break; + case FAST_FADE_OUT_TO_WHITE: + for (i = paletteOffsetStart; i < paletteOffsetEnd; ++i) + { + struct PlttData *data = (struct PlttData *)&gPlttBufferFaded[i]; + + r = data->r + 2; + g = data->g + 2; + b = data->b + 2; + if (r > 31) + r = 31; + if (g > 31) + g = 31; + if (b > 31) + b = 31; + gPlttBufferFaded[i] = r | (g << 5) | (b << 10); + } + break; + case FAST_FADE_IN_FROM_BLACK: + for (i = paletteOffsetStart; i < paletteOffsetEnd; ++i) + { + struct PlttData *unfaded; + struct PlttData *faded; + + unfaded = (struct PlttData *)&gPlttBufferUnfaded[i]; + r0 = unfaded->r; + g0 = unfaded->g; + b0 = unfaded->b; + faded = (struct PlttData *)&gPlttBufferFaded[i]; + r = faded->r + 2; + g = faded->g + 2; + b = faded->b + 2; + if (r > r0) + r = r0; + if (g > g0) + g = g0; + if (b > b0) + b = b0; + gPlttBufferFaded[i] = r | (g << 5) | (b << 10); + } + break; + case FAST_FADE_OUT_TO_BLACK: + for (i = paletteOffsetStart; i < paletteOffsetEnd; ++i) + { + struct PlttData *data = (struct PlttData *)&gPlttBufferFaded[i]; + + r = data->r - 2; + g = data->g - 2; + b = data->b - 2; + if (r < 0) + r = 0; + if (g < 0) + g = 0; + if (b < 0) + b = 0; + gPlttBufferFaded[i] = r | (g << 5) | (b << 10); + } + } + gPaletteFade.objPaletteToggle ^= 1; + if (gPaletteFade.objPaletteToggle) + // gPaletteFade.active cannot change since the last time it was checked. So this + // is equivalent to `return PALETTE_FADE_STATUS_ACTIVE;` + return gPaletteFade.active ? PALETTE_FADE_STATUS_ACTIVE : PALETTE_FADE_STATUS_DONE; + if (gPaletteFade.y - gPaletteFade.deltaY < 0) + gPaletteFade.y = 0; + else + gPaletteFade.y -= gPaletteFade.deltaY; + if (gPaletteFade.y == 0) + { + switch (gPaletteFade_submode) + { + case FAST_FADE_IN_FROM_WHITE: + case FAST_FADE_IN_FROM_BLACK: + CpuCopy32(gPlttBufferUnfaded, gPlttBufferFaded, PLTT_SIZE); + break; + case FAST_FADE_OUT_TO_WHITE: + CpuFill32(0xFFFFFFFF, gPlttBufferFaded, PLTT_SIZE); + break; + case FAST_FADE_OUT_TO_BLACK: + CpuFill32(0x00000000, gPlttBufferFaded, PLTT_SIZE); + break; + } + gPaletteFade.mode = NORMAL_FADE; + gPaletteFade.softwareFadeFinishing = TRUE; + } + // gPaletteFade.active cannot change since the last time it was checked. So this + // is equivalent to `return PALETTE_FADE_STATUS_ACTIVE;` + return gPaletteFade.active ? PALETTE_FADE_STATUS_ACTIVE : PALETTE_FADE_STATUS_DONE; +} + +void BeginHardwarePaletteFade(u8 blendCnt, u8 delay, u8 y, u8 targetY, u8 shouldResetBlendRegisters) +{ + gPaletteFade_blendCnt = blendCnt; + gPaletteFade.delayCounter = delay; + gPaletteFade_delay = delay; + gPaletteFade.y = y; + gPaletteFade.targetY = targetY; + gPaletteFade.active = TRUE; + gPaletteFade.mode = HARDWARE_FADE; + gPaletteFade.shouldResetBlendRegisters = shouldResetBlendRegisters & 1; + gPaletteFade.hardwareFadeFinishing = FALSE; + if (y < targetY) + gPaletteFade.yDec = FALSE; + else + gPaletteFade.yDec = TRUE; +} + +static u8 UpdateHardwarePaletteFade(void) +{ + if (!gPaletteFade.active) + return PALETTE_FADE_STATUS_DONE; + if (gPaletteFade.delayCounter < gPaletteFade_delay) + { + ++gPaletteFade.delayCounter; + return PALETTE_FADE_STATUS_DELAY; + } + gPaletteFade.delayCounter = 0; + if (!gPaletteFade.yDec) + { + ++gPaletteFade.y; + if (gPaletteFade.y > gPaletteFade.targetY) + { + ++gPaletteFade.hardwareFadeFinishing; + --gPaletteFade.y; + } + } + else + { + if (gPaletteFade.y-- - 1 < gPaletteFade.targetY) + { + ++gPaletteFade.hardwareFadeFinishing; + ++gPaletteFade.y; + } + } + + if (gPaletteFade.hardwareFadeFinishing) + { + if (gPaletteFade.shouldResetBlendRegisters) + { + gPaletteFade_blendCnt = 0; + gPaletteFade.y = 0; + } + gPaletteFade.shouldResetBlendRegisters = FALSE; + } + // gPaletteFade.active cannot change since the last time it was checked. So this + // is equivalent to `return PALETTE_FADE_STATUS_ACTIVE;` + return gPaletteFade.active ? PALETTE_FADE_STATUS_ACTIVE : PALETTE_FADE_STATUS_DONE; +} + +static void UpdateBlendRegisters(void) +{ + SetGpuReg(REG_OFFSET_BLDCNT, (u16)gPaletteFade_blendCnt); + SetGpuReg(REG_OFFSET_BLDY, gPaletteFade.y); + if (gPaletteFade.hardwareFadeFinishing) + { + gPaletteFade.hardwareFadeFinishing = FALSE; + gPaletteFade.mode = 0; + gPaletteFade_blendCnt = 0; + gPaletteFade.y = 0; + gPaletteFade.active = FALSE; + } +} + +static bool8 IsSoftwarePaletteFadeFinishing(void) +{ + if (gPaletteFade.softwareFadeFinishing) + { + if (gPaletteFade.softwareFadeFinishingCounter == 4) + { + gPaletteFade.active = FALSE; + gPaletteFade.softwareFadeFinishing = FALSE; + gPaletteFade.softwareFadeFinishingCounter = 0; + } + else + { + ++gPaletteFade.softwareFadeFinishingCounter; + } + return TRUE; + } + else + { + return FALSE; + } +} + +void BlendPalettes(u32 selectedPalettes, u8 coeff, u16 color) +{ + u16 paletteOffset; + + for (paletteOffset = 0; selectedPalettes; paletteOffset += 16) + { + if (selectedPalettes & 1) + BlendPalette(paletteOffset, 16, coeff, color); + selectedPalettes >>= 1; + } +} + +void BlendPalettesUnfaded(u32 selectedPalettes, u8 coeff, u16 color) +{ + // This copy is done via DMA in both RUBY and EMERALD + CpuFastCopy(gPlttBufferUnfaded, gPlttBufferFaded, 0x400); + BlendPalettes(selectedPalettes, coeff, color); +} + +void TintPalette_GrayScale(u16 *palette, u16 count) +{ + s32 r, g, b, i; + u32 gray; + + for (i = 0; i < count; ++i) + { + r = (*palette >> 0) & 0x1F; + g = (*palette >> 5) & 0x1F; + b = (*palette >> 10) & 0x1F; + gray = (r * Q_8_8(0.3) + g * Q_8_8(0.59) + b * Q_8_8(0.1133)) >> 8; + *palette++ = (gray << 10) | (gray << 5) | (gray << 0); + } +} + +void TintPalette_GrayScale2(u16 *palette, u16 count) +{ + s32 r, g, b, i; + u32 gray; + + for (i = 0; i < count; ++i) + { + r = (*palette >> 0) & 0x1F; + g = (*palette >> 5) & 0x1F; + b = (*palette >> 10) & 0x1F; + gray = (r * Q_8_8(0.3) + g * Q_8_8(0.59) + b * Q_8_8(0.1133)) >> 8; + + if (gray > 0x1F) + gray = 0x1F; + gray = sRoundedDownGrayscaleMap[gray]; + *palette++ = (gray << 10) | (gray << 5) | (gray << 0); + } +} + +void TintPalette_SepiaTone(u16 *palette, u16 count) +{ + s32 r, g, b, i; + u32 gray; + + for (i = 0; i < count; ++i) + { + r = (*palette >> 0) & 0x1F; + g = (*palette >> 5) & 0x1F; + b = (*palette >> 10) & 0x1F; + gray = (r * Q_8_8(0.3) + g * Q_8_8(0.59) + b * Q_8_8(0.1133)) >> 8; + r = (u16)((Q_8_8(1.2) * gray)) >> 8; + g = (u16)((Q_8_8(1.0) * gray)) >> 8; + b = (u16)((Q_8_8(0.94) * gray)) >> 8; + if (r > 31) + r = 31; + *palette++ = (b << 10) | (g << 5) | (r << 0); + } +} + +void TintPalette_CustomTone(u16 *palette, u16 count, u16 rTone, u16 gTone, u16 bTone) +{ + s32 r, g, b, i; + u32 gray; + + for (i = 0; i < count; ++i) + { + r = (*palette >> 0) & 0x1F; + g = (*palette >> 5) & 0x1F; + b = (*palette >> 10) & 0x1F; + gray = (r * Q_8_8(0.3) + g * Q_8_8(0.59) + b * Q_8_8(0.1133)) >> 8; + r = (u16)((rTone * gray)) >> 8; + g = (u16)((gTone * gray)) >> 8; + b = (u16)((bTone * gray)) >> 8; + if (r > 31) + r = 31; + if (g > 31) + g = 31; + if (b > 31) + b = 31; + *palette++ = (b << 10) | (g << 5) | (r << 0); + } +} + +void sub_80716F8(const u16 *src, u16 *dst, u16 count, u8 a4) +{ + s32 r, g, b, i; + u32 gray; + + if (!a4) + { + for (i = 0; i < count; ++i) + *dst++ = *src++; + } + else + { + for (i = 0; i < count; ++src, ++dst, ++i) + { + r = (*src >> 0) & 0x1F; + g = (*src >> 5) & 0x1F; + b = (*src >> 10) & 0x1F; + gray = (r * Q_8_8(0.3) + g * Q_8_8(0.59) + b * Q_8_8(0.1133)) >> 8; + r += (a4 * (gray - r) >> 4); + g += (a4 * (gray - g) >> 4); + b += (a4 * (gray - b) >> 4); + *dst = (b << 10) | (g << 5) | (r << 0); + } + } +} + +void sub_80717A8(u32 a1, s8 a2, u8 a3, u8 a4, u16 a5, u8 a6, u8 a7) +{ + u8 taskId; + + taskId = CreateTask(sub_80718B8, a6); + gTasks[taskId].data[0] = a3; + gTasks[taskId].data[1] = a4; + if (a2 >= 0) + { + gTasks[taskId].data[3] = a2; + gTasks[taskId].data[2] = 1; + } + else + { + gTasks[taskId].data[3] = 0; + gTasks[taskId].data[2] = -a2 + 1; + } + if (a4 < a3) + gTasks[taskId].data[2] *= -1; + SetWordTaskArg(taskId, 5, a1); + gTasks[taskId].data[7] = a5; + gTasks[taskId].data[8] = a7; + gTasks[taskId].func(taskId); +} + +bool32 sub_807185C(u8 var) +{ + s32 i; + + for (i = 0; i < NUM_TASKS; ++i) + if (gTasks[i].isActive == TRUE + && gTasks[i].func == sub_80718B8 + && gTasks[i].data[8] == var) + return TRUE; + return FALSE; +} + +void sub_8071898(void) +{ + u8 taskId; + + while (TRUE) + { + taskId = FindTaskIdByFunc(sub_80718B8); + if (taskId == TASK_NONE) + break; + DestroyTask(taskId); + } +} + +static void sub_80718B8(u8 taskId) +{ + u32 wordVar; + s16 *data; + s16 temp; + + data = gTasks[taskId].data; + wordVar = GetWordTaskArg(taskId, 5); + if (++data[4] > data[3]) + { + data[4] = 0; + BlendPalettes(wordVar, data[0], data[7]); + temp = data[1]; + if (data[0] == temp) + { + DestroyTask(taskId); + } + else + { + data[0] += data[2]; + if (data[2] >= 0) + { + if (data[0] < temp) + return; + } + else if (data[0] > temp) + { + return; + } + data[0] = temp; + } + } +} |