argument[0][i] and 32bit colour fix (Platformer mode fix) - #385
Open
Ananim353 wants to merge 2 commits into
Open
argument[0][i] and 32bit colour fix (Platformer mode fix)#385Ananim353 wants to merge 2 commits into
Ananim353 wants to merge 2 commits into
Conversation
The V17 first step of a multi-dimensional access (VARTYPE_ARRAYPUSHAF/POPAF) resolved the variable only through selfVars and localVars. Built-ins live in neither: argument[] is the call frame, not a member. So the chain fell through to getOrInsertUndefined, found nothing, materialised a FRESH EMPTY array in that slot and drilled into it -- argument[0][i] came back undefined, while plain argument[0] (which goes through resolveVariableRead) was correct. Both opcode forms are fixed. handlePush has the first index on the stack and reads the variable at it; handlePushBltn carries no index, so it reads the variable whole. Only a borrowed array becomes a weak ref: freeing an owned one there would leave the stack pointing at released memory, and anything else keeps the old path, so this cannot turn a working case into an abort. Found in DELTARUNE Chapter 5, where the platforming floor passes its tile layer names as scr_floortex_setFloorLayers(["TILES_Grass", ...]) and reads them back as argument[0][i]: layer_get_id received the string "undefined", the floor layer list stayed empty, and the untrimmed floor covered the party. snd_play_random reads its sound bank the same way.
A GML colour lives in an RValue as a double and is quite happily wider than a signed int32: DELTARUNE Chapter 5 stores 4294967295 (0xFFFFFFFF) in the tint of the platforming floor. Casting that through int32 saturates to INT32_MIN (0x80000000), whose three colour bytes are all zero, so merge_color(c_white, 4294967295, 1) returned 0 and the wall behind the floor came out black. RValue_toColour takes the bits instead of the sign: values inside the int32 range behave exactly as before, negative ones keep their bit pattern. Applied to every colour argument in vm_builtins.c, since the defect belonged to the drawing API as a whole and the floor simply happened to feed it such a value first. Color_lerp rounds now instead of truncating: merge_color(c_black, c_white, 0.5) is 0x808080 in GameMaker, and truncation gave 0x7F7F7F -- every half-and-half blend came out one step dark per channel. Not to be confused with vertex alpha in floatToUnormByte, where the runtime does truncate; that one is left alone.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix 1: argument[0][i] returned undefined (src/vm.c)
Fix 2: colours that do not fit a signed int32 turned black (rvalue.h, utils.h, vm_builtins.c)
Also fix Color_lerp truncated instead of rounding (0x7F7F7F vs GameMaker's 0x808080 at t = 0.5),