So over at the Lost Legacy Discord we've caught wind of an LUB file that's apparently not possible to decompile without heavy editing, as it allegedly contains non-LUA data that the XEX needs for the game to run. It seems to be an absolutely massive file - from what we can see, it might hold relevant data to Super forms, the Rainbow gem, homing attack delay/flips, and tons of other stuff that was cut from the final game. Problem is that none of us can find exactly where said non-LUA data is in the file, to strip it and create a normal LUB. Here's the link - if this isn't okay, feel free to obliterate me :v: Attempting to decompile it using ShadowLag's 06 SDK leads to a massive file that loops a conditional after a certain point - and luadec just straight up doesn't work. So, if anyone wants to take a crack at it... Yeah.
if I remember correctly the PS3 uses (mostly) the same files. I'm sure it's the same with PS3 only code bolted onto the front of it. The game is an alpha at best. As far as Standard.lub, it's not the only lua that can't be decompiled. There's a few others. Of course this extends beyond my knowledge but if someone wants to have a crack at it
The reason standard.lub can't be decoded is because Sonic '06 SDK for some reason has trouble decoding the embedded for loop in the file, which is strange because I'm pretty sure there are other LUB files in the game that use the same for loops. Ironically, after reaching the loop, it'll just repeat the contents of the file infinitely until it finishes 'decoding' to the file's intended size. Both the Xbox 360 and PlayStation 3 use an identical file structure. The only differences being the xenon folder has been renamed to 'ps3' for obvious reasons. The only code I've come across in other files around Sonic '06 that suggests differences between both versions is in cache.arc, but it only changes how things are rendered to accommodate for how differently the game needs to be rendered on both systems. The PlayStation 3 also uses ATRAC 3 audio, rather than the Xbox's XMA format, again for obvious reasons.
Yes, so PS3 only changes bolted onto it :v:. I don't recall off the top of my head, but I think I've ran into a few files getting into an infinite loop. So the assumption is that it isn't a standard "version" of lua?
Some speculate that some LUB files contain more than just text data, but I doubt that'd result in the SDK refusing to decode for loops. =P
It's not that they can't read it, they're perfectly capable of doing so. It just has trouble getting past the for loop, which is the purpose of this thread, because we literally have no idea why it refuses. There could be many reasons for why, such as; an unsupported Lua version, miscellaneous data stored in the file interfering with the decoding process, etc.
After so long of not knowing exactly what was in this file, I came across a pre-decompiled version of it on GitHub and it works perfectly fine when used in-game. Contents: Spoiler Code (Text): ActionStage.Start = inherits_from(State) function ActionStage.Start.constructor(_ARG_0_) Game.Log("construct ActionStage.Start") end function ActionStage.Start.Main(_ARG_0_, _ARG_1_) Game.Log("Start:Main") if _ARG_1_.titleHud ~= nil then _ARG_1_.titleHud:ProcessMessage("HudHide") end if _ARG_1_.bgm ~= nil then Game.PlayBGM(_ARG_1_.bgm) end _ARG_1_:ChangeState("playing") end ActionStage.Retry = inherits_from(State) function ActionStage.Retry.constructor(_ARG_0_) Game.Log("construct ActionStage.Retry") end function ActionStage.Retry.Main(_ARG_0_, _ARG_1_) Game.Sleep(1.5) Game.Retry() Game.Sleep(0) _ARG_1_:ChangeState("playing") end ActionStage.Playing = inherits_from(State) function ActionStage.Playing.Main(_ARG_0_, _ARG_1_) _ARG_1_:StartPlaying() if _ARG_1_.mainHud ~= nil then _ARG_1_.mainHud:ProcessMessage("HudSetPlayerCount", { value = _ARG_1_:GetLife() }) while true do Game.Sleep(10) end end end function ActionStage.Playing.PlayerDies(_ARG_0_, _ARG_1_) if _ARG_1_._life > 0 then _ARG_1_._life = _ARG_1_._life - 1 Game.Log("miss!!") _ARG_1_:ChangeState("retry") else _ARG_1_:ChangeState("gameover") end end ActionStage.Clear = inherits_from(State) function ActionStage.Clear.Main(_ARG_0_, _ARG_1_) Game.Log("Clear:Main") _ARG_1_:ControlPause(false) CreateTask("missioncompleted") Game.PlayBGM("clear") if _ARG_1_.mainHud ~= nil then _ARG_1_.mainHud:ProcessMessage("HudHide") end Game.Sleep(5) _ARG_1_.notify = false -- For loop reconstructed for r = 1, 4 do if ({ stage = _ARG_1_.result_name, score = _ARG_1_:GetScore(), time = _ARG_1_:GetPlayTime(), ring = _ARG_1_:GetRingCount(), timeBonus = _ARG_1_:CalcTimeBonus(), rank = r, totalScore = self.score + self.timeBonus, }).totalScore > _ARG_1_:GetRankTable()[r] then break end end while _ARG_1_.notify == false do Game.Sleep(0) end Game.End() end function ActionStage.Clear.HudNotify(_ARG_0_, _ARG_1_, _ARG_2_) Game.Log("notify") _ARG_1_.notify = true end ActionStage.GameOver = inherits_from(State) function ActionStage.GameOver.Main(_ARG_0_, _ARG_1_) Game.Log("GameOver:Main") Game.Sleep(5) Game.End() end
Am I the only one that finds this disappointing? All it seems to do is determine what happens when a stage begins, when you lose a life or game over, and when a stage is cleared.