Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object Events added after a FadeScreen aren't affected by the fade. #4

Open
BLourenco opened this issue Jun 22, 2021 · 7 comments
Open

Comments

@BLourenco
Copy link

BLourenco commented Jun 22, 2021

Since palettes are loaded dynamically, any object added after a screen fade isn't affected by the fade.

pokeemerald_modern-0
dops

Snippet from the Sootopolis script:

fadescreenspeed FADE_TO_BLACK, 8
call SootopolisCity_EventScript_SetRoughWater
removeobject LOCALID_GROUDON
removeobject LOCALID_KYOGRE
addobject LOCALID_RAYQUAZA
setvar VAR_0x8004, TRUE
special Script_DoRayquazaScene
waitstate
@Jaizu
Copy link

Jaizu commented Jun 23, 2021

I think the bug is related that, even if you do load the NPC, it won't load it's palette.
I have a command to instantly move the camera and I get the same bug
Image: https://cdn.discordapp.com/attachments/442465020291317760/857212347433484298/Lqw2TXnoRa.gif
Script:

    fadescreen(FADE_TO_BLACK)
    setvar(VAR_0x8004, 29)
    setvar(VAR_0x8005, 21)
    special(TeleportCamera)
    delay(16)
    fadescreen(FADE_FROM_BLACK)
    textcolor(TC_RED)
    namebox("Lucy")
    msgbox(format("I hate waiting reeeee"))
    closeboth

Command post: https://www.pokecommunity.com/showthread.php?p=10211150#post10211150

@ExpoSeed
Copy link
Owner

the issue is that the loaded palette is copied to both the faded and unfaded buffers. when the screen has faded to white or black, it is only safe to copy to the unfaded buffer, and the faded buffer must be left alone.

however, the game has no notion of "in between" a fade and unfade, and it is not necessary that a fade to white/black must be followed by a corresponding fade from white/black.

there is likely not a way to fix this seamlessly. for more context: https://discord.com/channels/419213663107416084/419214240277200898/880594471874605086 on rhh server

@Jaizu
Copy link

Jaizu commented Aug 27, 2021

Is there a reason to not implement something like SBird said?
Afaik he has two solutions:

  • His hacky workaround, which is in sots, which is open source.
  • Adding this:
    image

Ofc I'm not a coder and I can't force anyone to do it, just curious of what do you think about it.

@ExpoSeed
Copy link
Owner

The hacky workaround won't fix fades that are not paired with a fade back

The image there requires editing scripts

@LOuroboros
Copy link

The hacky workaround won't fix fades that are not paired with a fade back

I don't think there's a single instance where someone would ever fade to black/white without ever fading back though?

@LOuroboros
Copy link

LOuroboros commented Jan 3, 2022

His hacky workaround, which is in sots, which is open source.

By "hacky workaround" you're talking about the overworld script specific fadescreen-related buffer for the event objects' palettes that SotS uses, yes?

I gave that a shot, and while it solves the problem with Rayquaza, it generates another problem right after, although there's a chance I screwed up while backporting it.

%pn_3146

Here's the diff:

diff --git a/data/maps/SootopolisCity/scripts.inc b/data/maps/SootopolisCity/scripts.inc
index efeae33d1..6cbc4cc84 100644
--- a/data/maps/SootopolisCity/scripts.inc
+++ b/data/maps/SootopolisCity/scripts.inc
@@ -523,7 +523,7 @@ SootopolisCity_EventScript_RayquazaSceneFromPokeCenter::
 	waitmovement 0
 	special RemoveCameraObject
 	delay 60
-	fadescreenspeed FADE_TO_BLACK, 8
+	fadescreenswapbuffers FADE_TO_BLACK
 	call SootopolisCity_EventScript_SetRoughWater
 	removeobject LOCALID_GROUDON
 	removeobject LOCALID_KYOGRE
@@ -576,7 +576,7 @@ SootopolisCity_EventScript_RayquazaSceneFromDive::
 	waitmovement 0
 	special RemoveCameraObject
 	delay 60
-	fadescreenspeed FADE_TO_BLACK, 8
+	fadescreenswapbuffers FADE_TO_BLACK
 	call SootopolisCity_EventScript_SetRoughWater
 	removeobject LOCALID_GROUDON
 	removeobject LOCALID_KYOGRE
diff --git a/include/gba/macro.h b/include/gba/macro.h
index 3b35a1946..db2415843 100644
--- a/include/gba/macro.h
+++ b/include/gba/macro.h
@@ -32,13 +32,16 @@
 #define CpuFastCopy(src, dest, size) CpuFastSet(src, dest, ((size)/(32/8) & 0x1FFFFF))
 
 #define DmaSet(dmaNum, src, dest, control)        \
-{                                                 \
-    vu32 *dmaRegs = (vu32 *)REG_ADDR_DMA##dmaNum; \
-    dmaRegs[0] = (vu32)(src);                     \
-    dmaRegs[1] = (vu32)(dest);                    \
-    dmaRegs[2] = (vu32)(control);                 \
-    dmaRegs[2];                                   \
-}
+do {                                              \
+    vu32 *_dmaRegs = (vu32 *)REG_ADDR_DMA##dmaNum; \
+    u32 _eval_src = (u32)(src);                   \
+    u32 _eval_dst = (u32)(dest);                  \
+    u32 _eval_ctl = (u32)(control);               \
+    register u32 _r_src asm("r0") = _eval_src;    \
+    register u32 _r_dst asm("r1") = _eval_dst;    \
+    register u32 _r_ctl asm("r2") = _eval_ctl;    \
+    asm volatile("stmia %0!, {%1, %2, %3}" : "+l" (_dmaRegs) : "l" (_r_src), "l" (_r_dst), "l" (_r_ctl) : "memory");  \
+} while (0)
 
 #define DMA_FILL(dmaNum, value, dest, size, bit)                                              \
 {                                                                                             \
diff --git a/include/palette.h b/include/palette.h
index 072edef56..cbce597e2 100644
--- a/include/palette.h
+++ b/include/palette.h
@@ -51,6 +51,7 @@ extern u32 gPlttBufferTransferPending;
 extern u8 gPaletteDecompressionBuffer[];
 extern u16 gPlttBufferUnfaded[];
 extern u16 gPlttBufferFaded[];
+extern bool8 gScriptBufferedFadeActive;
 
 void LoadCompressedPalette(const u32 *, u16, u16);
 void LoadPalette(const void *, u16, u16);
diff --git a/src/palette.c b/src/palette.c
index cbaae8da2..25fb1f487 100644
--- a/src/palette.c
+++ b/src/palette.c
@@ -63,6 +63,7 @@ EWRAM_DATA struct PaletteFadeControl gPaletteFade = {0};
 static EWRAM_DATA u32 sFiller = 0;
 static EWRAM_DATA u32 sPlttBufferTransferPending = 0;
 EWRAM_DATA u8 gPaletteDecompressionBuffer[PLTT_DECOMP_BUFFER_SIZE] = {0};
+EWRAM_DATA bool8 gScriptBufferedFadeActive = FALSE;
 
 static const struct PaletteStructTemplate gDummyPaletteStructTemplate = {
     .uid = 0xFFFF,
@@ -88,8 +89,11 @@ void LoadCompressedPalette(const u32 *src, u16 offset, u16 size)
 
 void LoadPalette(const void *src, u16 offset, u16 size)
 {
-    CpuCopy16(src, gPlttBufferUnfaded + offset, size);
-    CpuCopy16(src, gPlttBufferFaded + offset, size);
+    DmaCopy16(3, src, gPlttBufferUnfaded + offset, size);
+    if (gScriptBufferedFadeActive)
+        DmaCopy16(3, src, gPaletteDecompressionBuffer + offset * 2, size);
+    else
+        DmaCopy16(3, src, gPlttBufferFaded + offset, size);
 }
 
 void FillPalette(u16 value, u16 offset, u16 size)
diff --git a/src/scrcmd.c b/src/scrcmd.c
index f53483978..924d16a48 100644
--- a/src/scrcmd.c
+++ b/src/scrcmd.c
@@ -653,11 +653,13 @@ bool8 ScrCmd_fadescreenswapbuffers(struct ScriptContext *ctx)
         default:
             CpuCopy32(gPlttBufferUnfaded, gPaletteDecompressionBuffer, PLTT_DECOMP_BUFFER_SIZE);
             FadeScreen(mode, 0);
+            gScriptBufferedFadeActive = TRUE;
             break;
         case FADE_FROM_BLACK:
         case FADE_FROM_WHITE:
             CpuCopy32(gPaletteDecompressionBuffer, gPlttBufferUnfaded, PLTT_DECOMP_BUFFER_SIZE);
             FadeScreen(mode, 0);
+            gScriptBufferedFadeActive = FALSE;
             break;
     }

The changes to DmaSet were required to build a ROM.

EDIT: Here's a pic of mGBA's palette viewer, in case it's useful.

firefox_3147

Is it normal that there's many duplicates of colors such as black, yellow or sea green taking up extra palette slots?

@xirosrh
Copy link

xirosrh commented Feb 3, 2022

@LOuroboros @Jaizu @ExpoSeed

I was just able to make sots solution work. You were missing a change. I did not try that vanilla example, but it solved the errors for my hackrom's use cases.

On method Fade_Screen of field_weather.c, you have to remove (or just comment) the following line:
Weather_SetBlendCoeffs(gWeatherPtr->currBlendEVA, gWeatherPtr->currBlendEVB);

Sorry for not using a fancy diff :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants