luckytyphlosion

pokeemerald Smooth optimized palettes

Oct 8th, 2025
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.76 KB | None | 0 0
  1. #include "global.h"
  2. #include "palette.h"
  3. #include "util.h"
  4. #include "decompress.h"
  5. #include "gpu_regs.h"
  6. #include "task.h"
  7. #include "constants/rgb.h"
  8.  
  9. // include/palette.h
  10. struct PaletteFadeControl
  11. {
  12.     /* 0x00 */ u32 multipurpose1;
  13.  
  14.     /* 0x04 */ u8 delayCounter:6;
  15.     /* 0x04 */ u16 mode:2;
  16.  
  17.     /* 0x05 */ u16 deltaY:6; // rate of change of blend coefficient
  18.     /* 0x05 */ bool16 active:1;
  19.     /* 0x05 */ bool16 yDec:1; // whether blend coefficient is decreasing
  20.  
  21.     /* 0x06 */ u16 targetY:6; // target blend coefficient
  22.     /* 0x06 */ bool16 bufferTransferDisabled:1;
  23.     /* 0x06 */ bool16 shouldResetBlendRegisters:1;
  24.  
  25.     /* 0x07 */ u16 multipurpose2:6;
  26.     /* 0x07 */ bool16 hardwareFadeFinishing:1;
  27.     /* 0x07 */ bool16 objPaletteToggle:1;
  28.  
  29.     /* 0x08 */ u16 blendColor:15;
  30.     /* 0x08 */ u8 yChanged:1;
  31.  
  32.     /* 0x09 */ u16 softwareFadeFinishingCounter:3;
  33.     /* 0x09 */ u16 doEndDelay:1;
  34.  
  35.     /* 0x0a */ u16 y; // blend coefficient
  36.     /* 0x0c */ u16 denominator;
  37. };
  38.  
  39. // src/palette.c
  40.  
  41. static bool8 BeginNormalPaletteFadeInternal(u32 selectedPalettes, u8 startY, u8 targetY, u16 blendColor, u32 denominator, u32 doEndDelay, u32 dontCopy);
  42.  
  43. enum
  44. {
  45.     NORMAL_FADE,
  46.     FAST_FADE,
  47.     HARDWARE_FADE,
  48. };
  49.  
  50.  
  51. bool8 BeginNormalPaletteFade(u32 selectedPalettes, s8 delay, u8 startY, u8 targetY, u16 blendColor)
  52. {
  53.     // all this is to make fades more smooth
  54.     // while keeping the same delay as vanilla
  55.     // in case some code relies on timing
  56.     u8 diff;
  57.     u16 denominator;
  58.  
  59.     if (startY < targetY) {
  60.         diff = targetY - startY;
  61.     } else {
  62.         diff = startY - targetY;
  63.     }
  64.  
  65.     if (delay >= 0) {
  66.         if (delay > 63) {
  67.             delay = 63;
  68.         }
  69.         denominator = ((diff + 1)/2) * (delay + 2) + 1;
  70.     } else {
  71.         u8 i;
  72.         u8 deltaY;
  73.         s8 y;
  74.         if (delay < -14) {
  75.             delay = -14;
  76.         }
  77.         deltaY = 2 + (delay * -1);
  78.         y = startY;
  79.  
  80.         if (y < targetY) {
  81.             for (i = 0; y < targetY; i++) {
  82.                 y += deltaY;
  83.             }
  84.         } else {
  85.             for (i = 0; y > targetY; i++) {
  86.                 y -= deltaY;
  87.             }
  88.         }
  89.  
  90.         denominator = i * 2 + 1;
  91.     }
  92.  
  93.     return BeginNormalPaletteFadeInternal(selectedPalettes, startY * 2, targetY * 2, blendColor, denominator, TRUE, FALSE);
  94. }
  95.  
  96. static bool8 BeginNormalPaletteFadeForDuration_Common(u32 selectedPalettes, u16 fadeDuration, u8 startY, u8 targetY, u16 blendColor, u32 doEndDelay, bool32 dontCopy);
  97.  
  98. bool8 BeginNormalPaletteFadeForDuration_DontImmediatelyCopy(u32 selectedPalettes, u16 fadeDuration, u8 startY, u8 targetY, u16 blendColor, u32 doEndDelay)
  99. {
  100.     return BeginNormalPaletteFadeForDuration_Common(selectedPalettes, fadeDuration, startY, targetY, blendColor, doEndDelay, TRUE);
  101. }
  102.  
  103. bool8 BeginNormalPaletteFadeForDuration(u32 selectedPalettes, u16 fadeDuration, u8 startY, u8 targetY, u16 blendColor, u32 doEndDelay)
  104. {
  105.     return BeginNormalPaletteFadeForDuration_Common(selectedPalettes, fadeDuration, startY, targetY, blendColor, doEndDelay, FALSE);
  106. }
  107.  
  108. static bool8 BeginNormalPaletteFadeForDuration_Common(u32 selectedPalettes, u16 fadeDuration, u8 startY, u8 targetY, u16 blendColor, u32 doEndDelay, bool32 dontCopy)
  109. {
  110.     if (fadeDuration > 1) {
  111.         fadeDuration--;
  112.     } else {
  113.         fadeDuration = 1;
  114.     }
  115.  
  116.     return BeginNormalPaletteFadeInternal(selectedPalettes, startY, targetY, blendColor, fadeDuration, doEndDelay, dontCopy);
  117. }
  118.  
  119. static bool8 BeginNormalPaletteFadeInternal(u32 selectedPalettes, u8 startY, u8 targetY, u16 blendColor, u32 denominator, u32 doEndDelay, u32 dontCopy)
  120. {
  121.     u8 temp;
  122.     u16 color = blendColor;
  123.  
  124.     if (gPaletteFade.active)
  125.     {
  126.         return FALSE;
  127.     }
  128.     else
  129.     {
  130.         gPaletteFade_selectedPalettes = selectedPalettes;
  131.         gPaletteFade.y = startY * denominator;
  132.         gPaletteFade.targetY = targetY;
  133.         gPaletteFade.denominator = denominator;
  134.         gPaletteFade.blendColor = color;
  135.         gPaletteFade.active = TRUE;
  136.         gPaletteFade.mode = NORMAL_FADE;
  137.         gPaletteFade.objPaletteToggle = 0;
  138.         gPaletteFade.yChanged = TRUE;
  139.         gPaletteFade.doEndDelay = doEndDelay;
  140.  
  141.         if (startY < targetY) {
  142.             gPaletteFade.deltaY = targetY - startY;
  143.             gPaletteFade.yDec = 0;
  144.         } else {
  145.             gPaletteFade.deltaY = startY - targetY;
  146.             gPaletteFade.yDec = 1;
  147.         }
  148.  
  149.         UpdatePaletteFade();
  150.  
  151.         temp = gPaletteFade.bufferTransferDisabled;
  152.         gPaletteFade.bufferTransferDisabled = TRUE;
  153.         if (!dontCopy) {
  154.             CpuFastCopy(gPlttBufferFaded, (void *)PLTT, PLTT_SIZE);
  155.         }
  156.         sPlttBufferTransferPending = 0;
  157.         if (gPaletteFade.mode == HARDWARE_FADE && gPaletteFade.active)
  158.             UpdateBlendRegisters();
  159.         gPaletteFade.bufferTransferDisabled = temp;
  160.         return TRUE;
  161.     }
  162. }
  163.  
  164. void ResetPaletteFadeControl(void)
  165. {
  166.     gPaletteFade.multipurpose1 = 0;
  167.     gPaletteFade.multipurpose2 = 0;
  168.     gPaletteFade.delayCounter = 0;
  169.     gPaletteFade.y = 0;
  170.     gPaletteFade.targetY = 0;
  171.     gPaletteFade.blendColor = 0;
  172.     gPaletteFade.active = 0;
  173.     gPaletteFade.multipurpose2 = 0; // assign same value twice
  174.     gPaletteFade.yDec = 0;
  175.     gPaletteFade.bufferTransferDisabled = 0;
  176.     gPaletteFade.shouldResetBlendRegisters = 0;
  177.     gPaletteFade.hardwareFadeFinishing = 0;
  178.     gPaletteFade.softwareFadeFinishingCounter = 0;
  179.     gPaletteFade.objPaletteToggle = 0;
  180.     gPaletteFade.deltaY = 2;
  181. }
  182.  
  183. static u8 UpdateNormalPaletteFade(void)
  184. {
  185.     if (!gPaletteFade.active)
  186.         return PALETTE_FADE_STATUS_DONE;
  187.  
  188.     if (IsSoftwarePaletteFadeFinishing())
  189.     {
  190.         return gPaletteFade.active ? PALETTE_FADE_STATUS_ACTIVE : PALETTE_FADE_STATUS_DONE;
  191.     }
  192.     else
  193.     {
  194.         u16 targetY = gPaletteFade.targetY * gPaletteFade.denominator;
  195.         u16 yWholeValue = gPaletteFade.y / gPaletteFade.denominator;
  196.         if (gPaletteFade.yChanged) {
  197.             BlendPalettesFine(gPaletteFade_selectedPalettes, yWholeValue, gPaletteFade.blendColor);
  198.         }
  199.  
  200.         if (gPaletteFade.y == targetY)
  201.         {
  202.             gPaletteFade_selectedPalettes = 0;
  203.             gPaletteFade.softwareFadeFinishingCounter = 1;
  204.             if (!gPaletteFade.doEndDelay) {
  205.                 gPaletteFade.active = 0;
  206.                 gPaletteFade.softwareFadeFinishingCounter = 0;
  207.             }
  208.         }
  209.         else
  210.         {
  211.             u16 newY;
  212.  
  213.             if (!gPaletteFade.yDec)
  214.             {
  215.                 newY = gPaletteFade.y + gPaletteFade.deltaY;
  216.  
  217.                 if (newY > targetY) {
  218.                     newY = targetY;
  219.                 }
  220.             }
  221.             else
  222.             {
  223.                 newY = gPaletteFade.y - gPaletteFade.deltaY;
  224.  
  225.                 if (newY < targetY) {
  226.                     newY = targetY;
  227.                 }
  228.             }
  229.  
  230.             gPaletteFade.yChanged = (newY / gPaletteFade.denominator) != yWholeValue;
  231.             gPaletteFade.y = newY;
  232.         }
  233.  
  234.         // gPaletteFade.active cannot change since the last time it was checked. So this
  235.         // is equivalent to `return PALETTE_FADE_STATUS_ACTIVE;`
  236.         return gPaletteFade.active ? PALETTE_FADE_STATUS_ACTIVE : PALETTE_FADE_STATUS_DONE;
  237.     }
  238. }
  239.  
  240. static bool8 IsSoftwarePaletteFadeFinishing(void)
  241. {
  242.     if (gPaletteFade.softwareFadeFinishingCounter > 0)
  243.     {
  244.         if (!gPaletteFade.doEndDelay || gPaletteFade.softwareFadeFinishingCounter == 5)
  245.         {
  246.             gPaletteFade.active = 0;
  247.             gPaletteFade.softwareFadeFinishingCounter = 0;
  248.         }
  249.         else
  250.         {
  251.             gPaletteFade.softwareFadeFinishingCounter++;
  252.         }
  253.  
  254.         return TRUE;
  255.     }
  256.     else
  257.     {
  258.         return FALSE;
  259.     }
  260. }
  261.  
Advertisement
Add Comment
Please, Sign In to add comment