Skip to content

Fix normal (non-swap) dup path - #383

Draft
MrPowerGamerBR wants to merge 3 commits into
mainfrom
dup-fix
Draft

Fix normal (non-swap) dup path#383
MrPowerGamerBR wants to merge 3 commits into
mainfrom
dup-fix

Conversation

@MrPowerGamerBR

@MrPowerGamerBR MrPowerGamerBR commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

While developing Starfait I've noticed that the Butterscotch's handleDup path is completely borked

This is a WIP because the swap path also needs to be updated, I haven't done the research on how the swap path should ACTUALLY work

Explanation:

image image image image image

@Un1q32

Un1q32 commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

light mode discord jumpscare

Comment thread src/vm.c
@@ -1846,13 +1849,15 @@ static int32_t bytesToSlotCount(VMContext* ctx, int32_t nativeBytes, int32_t sta
require(remaining == 0); // Byte count must align exactly to slot boundaries

@Fancy2209 Fancy2209 Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Chapter 4 Test Hits this now

@Ananim353

Copy link
Copy Markdown

type1 is the unit of measurement, not the type of each element.

obj_parallax_castle_top, layers[i].xoffset -= n:

Push.v self.layers [Array]      ; VARIABLE, 16 bytes
PushI.e -9                      ; STACKTOP marker, 4 bytes
Dup.i 5                         ; operand=4 -> 20 bytes
Push.v self.xoffset [StackTop]  ; eats marker + instance = 20 bytes
Pop.i.v self.xoffset [StackTop] ; eats the second copy

16 + 4 = the 20 bytes requested, and exactly what both consumers eat. No int32 in the window, nothing mistagged.
Counting elements takes 5 slots — three too deep.

@MrPowerGamerBR

Copy link
Copy Markdown
Collaborator Author

type1 is the type of the element on the top of the stack, the YoYo Runner does not use tagged elements, so it relies on the type1 to figure out how many bytes will be removed from the stack

The issue is that the compiler sometimes emits a INT32 type even though the top of the stack is VARIABLE

Butterscotch tags the original stack type for each element, but in reality it wouldn't need that, because dup only duplicates the same type always, you can just peek the top of the stack for what is the type that is being used and then figure out the byte size for that

For the integer type, it would require to peek the top to see if it is a variable and, if the type1 is a integer, divide the dup size by 4

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

Successfully merging this pull request may close these issues.

4 participants