-
Habbo V1 CSTs w/ Bytecode
Greetz
So I was on Discord talking to some of y'all and apparently I've had like, a jewel laying around in my archives that I never bothered to pay attention towards.
My Public Shockwave Library was created to store Shockwave-era contributions to the community I found deep within RaGEZONE /f353/
It also contained some unprotected Habbo V1 CST's. But they're special.
So what? recover-cct.exe will generate an unprotected cast file. You've only saved me like, 10 minutes.
Like I said, these are special. The original bytecode has been left in-tact.
AND AGAIN I SAY: SO WHAT? We can't do SHIT with bytecode.
Up until a few weeks ago, this would be the appropriate, annoyed question to ask.
But a GitHub project has been performing strong work to unpack the Lingo bytecode and guess the Lingo scripts. It does a really good job of this, and I've seen DIRs and CSTs be completely read in full from other games.
How 2 get moar unprotected CSTs? V5? V18? R26?
Not sure. A lot of these came from @Cecer's generous donations, so he may have a clue. But there are some reverse-engineering wizards among us, who secretly practice their magic on Shockwave files, whose names I shall not utter here (lurk moar :wink:)
Anyways. Here you go.
UNPROTECTED V1
http://nodebay.com/archives/Habbo/DC...ECTED%20V1.zip
-
Re: Habbo V1 CSTs w/ Bytecode
You Sir, have just blown my mind.
Nice release!
-
Re: Habbo V1 CSTs w/ Bytecode
Yeah, I had these in my collection for ages. I never released it because I thought it was just your typical recover-cct full of files. I didn't realise until today that these were special and contained bytecode, and that's when I told @FullmetalPride, of which I got the archive from.
We could do so much more if we could recover the bytecode from CCT files. Unfortunately, the person who created these seems to be a bit of a mystery...
You can get some pretty neat code out of it. :):
Code:
on handleMessageContent(content)
if not stringp(content) or content.length <= 1 then
return()
end if
firstline = content.line[1]
if firstline contains "STATUS" then
st = the ticks
if voidp(gLastStatusOK) or the ticks - gLastStatusOK > 25 * 60 then
sendFuseMsg("STATUSOK")
gLastStatusOK = the ticks
end if
i = 2
repeat while i <= the number of line in content
the itemDelimiter = "/"
ln = content.line[i]
if ln.length > 2 then
if not ln.char[1] = "*" then
itemsCount = the number of item in ln
user = doSpecialCharConversion(ln.word[1])
locParam = ln.word[2]
the itemDelimiter = ","
currentMobilX = integer(locParam.item[1])
currentMobilY = integer(locParam.item[2])
currentMobilHeight = integer(locParam.item[3])
dirHead = integer(locParam.item[4])
dirBody = integer(locParam.item[5])
moved = 0
objectSpr = getObjectSprite(user)
if objectSpr > 0 then
sendSprite(objectSpr, #initiateForSync)
if not voidp(currentMobilX) and not voidp(currentMobilY) then
sendSprite(objectSpr, #setLocAndDir, currentMobilX, currentMobilY, currentMobilHeight, dirHead, dirBody)
end if
j = 2
repeat while j <= itemsCount
the itemDelimiter = "/"
parseItem = ln.item[j]
sendSprite(objectSpr, symbol("fuseAction_" & parseItem.word[1]), parseItem)
if gConnectionShouldBeKilled = 1 then
return()
end if
j = 1 + j
end repeat
else
put("STATUS for nonexistent user!", user)
end if
else
handleActiveObjects(ln)
end if
end if
i = 1 + i
end repeat
if objectp(hiliter) then
hiliteExitframe(hiliter)
end if
else
if firstline contains "CHAT" then
user = content.word[1]
Message = content.word[2..the number of word in content.line[2]]
createBalloon(user, Message, #normal)
else
if firstline contains "SHOUT" then
user = content.word[1]
Message = content.word[2..the number of word in content.line[2]]
createBalloon(user, Message, #shout)
else
if firstline contains "WHISPER" then
user = content.word[1]
Message = content.word[2..the number of word in content.line[2]]
createBalloon(user, Message, #whisper)
else
if firstline contains "LOGOUT" then
userName = doSpecialCharConversion(content.word[1])
put("LOGOUT", userName, getObjectSprite(userName))
put("before", availablePuppetSpr.count)
sendSprite(getObjectSprite(userName), #die)
put("after", availablePuppetSpr.count)
else
if firstline contains "HELLO" then
put(firstline)
gKryptausOn = 0
sendFuseMsg("versionid" && field(0))
sendFuseMsg("CLIENTIP" && getNetAddressCookie(gConnectionInstance, 1))
else
if firstline contains "ENCRYPTION_ON" then
gKryptausOn = #waiting
else
if firstline contains "ENCRYPTION_OFF" then
gKryptausOn = 0
else
if firstline contains "SECRET_KEY" then
decodedKey = secretDecode(content.line[2])
RC4 = new(script("RC4"))
RC4.setKey(decodedKey)
if gKryptausOn = #waiting then
gKryptausOn = 1
put("Encryption enabled...!")
else
gKryptausOn = 0
put("Encryption disabled...!")
end if
sendFuseMsg("KEYENCRYPTED" && decodedKey)
gConnectionsSecured = 1
else
if firstline contains "ERROR" then
put(content)
if content contains "not move there" then
else
if content contains "inproper" and content contains "WARNING" = 0 then
ShowAlert(content.getProp(#line, 2))
else
if content contains "user already" then
ShowAlert("NameAlreadyUse")
e = 1
repeat while e <= 99
sprite(e).visible = 1
e = 1 + e
end repeat
go(1)
else
if content contains "incorrect flat password" or content contains "password required" then
flatPasswordIncorrect()
else
if content contains "login in" then
ShowAlert("WrongPassword")
e = 1
repeat while e <= 99
sprite(e).visible = 1
e = 1 + e
end repeat
go(1)
else
if content contains "Version not correct" then
ShowAlert("Old client version, please reload." & "\r" & "Clear browser's cache if necessary.")
else
if content contains "the room owner" then
ShowAlert(content.getProp(#line, 2))
else
put("Error message:" && content)
end if
end if
end if
end if
end if
end if
end if
else
if firstline contains "USERS" then
content = doSpecialCharConversion(content)
the itemDelimiter = "\t"
i = 2
repeat while i <= the number of line in content
ln = content.item[1]
if the number of word in ln <> 0 then
user = ln.word[1]
figure = ln.word[2]
locX = integer(ln.word[3])
locY = integer(ln.word[4])
locHeight = integer(ln.word[5])
if ln.word[ln.count(#word)] starts "ch=" then
Custom = doSpecialCharConversion(ln.word[6..ln.count(#word) - 1])
swimsuit = ln.word[ln.count(#word)]
else
Custom = doSpecialCharConversion(ln.word[6..the number of word in ln])
swimsuit = ""
end if
if content.item[2] <> "" then
score = content.word[1]
ranking = content.word[2]
Custom = Custom & "\r" & "\r" & "pisteet:" & score & " sijoitus:" & ranking & "."
end if
if not the movieName contains "pellehyppy" then
createAvatar(user, figure, locX, locY, locHeight, Custom)
else
if gpObjects.findPos(user) then
sendSprite(gpObjects.getProp(user), #updateSwimSuit, figure, swimsuit)
else
createAvatar(user, figure, locX, locY, locHeight, Custom, swimsuit)
end if
end if
end if
i = 1 + i
end repeat
the itemDelimiter = ","
else
if firstline contains "USEROBJECT" then
the itemDelimiter = "="
content = doSpecialCharConversion(content)
i = 2
repeat while i <= the number of line in content
ln = content.line[i]
sfield = ln.item[1]
sdata = ln.item[2]
put(sfield, sdata)
if sfield = "name" then
end if
if sprite(0).number > 0 and sfield.length > 0 then
if sdata <> "null" then
else
end if
end if
i = 1 + i
end repeat
the itemDelimiter = ","
goToFrame("change1")
else
if firstline contains "SYSTEMBROADCAST" then
ShowAlert("MessageFromAdmin", content.line[2])
else
if firstline contains "SHOWPROGRAM" then
commandLine = content.line[2]
spr = getaProp(gpShowSprites, commandLine.word[1])
if spr > 0 then
sendSprite(spr, symbol("fuseShow_" & commandLine.word[2]), commandLine.word[3..the number of word in commandLine])
end if
else
if firstline contains "TRIGGER" then
if content contains "openSplashKiosk" then
openSplashKiosk()
end if
else
if firstline contains "DOOR_IN" then
tItemDelim = the itemDelimiter
the itemDelimiter = "/"
tDoorID = content.getPropRef(#line, 2).getProp(#item, 1)
tUsername = content.getPropRef(#line, 2).getProp(#item, 2)
tDoorType = content.getPropRef(#line, 2).getProp(#item, 3)
the itemDelimiter = tItemDelim
tDoorObj = sprite(gpObjects.getAt(tDoorType & tDoorID)).getProp(#scriptInstanceList, 1)
tDoorObj.animate(void(), #in)
if gMyName = tUsername then
tDoorObj.prepareToKick(tUsername)
end if
else
if firstline contains "DOOR_OUT" then
tItemDelim = the itemDelimiter
the itemDelimiter = "/"
tDoorID = content.getPropRef(#line, 2).getProp(#item, 1)
tUsername = content.getPropRef(#line, 2).getProp(#item, 2)
tDoorType = content.getPropRef(#line, 2).getProp(#item, 3)
the itemDelimiter = tItemDelim
tDoorObj = sprite(gpObjects.getAt(tDoorType & tDoorID)).getProp(#scriptInstanceList, 1)
tDoorObj.animate(void(), #out)
else
if firstline contains "HEIGHTMAP" then
loadHeightMap(content.line[2..the number of line in content])
else
if firstline contains " OBJECTS" then
content = doSpecialCharConversion(content)
type = the last word in undefined
AddStatistic(the movieName, type)
if not the movieName contains "private" and type contains "model_" then
goMovie("gf_private", type)
init()
end if
sprMan_clearAll()
gUserSprites = []
gpObjects = []
gWorldType = type
goToFrame(type)
checkOffsets()
clickedUrl = 0
sprite(99).visible = 1
i = 2
repeat while i <= the number of line in content
ln = content.line[i]
name = ln.word[1]
objectClass = ln.word[2]
if not objectClass contains "stair" and not objectClass contains "ignore" then
locX = integer(ln.word[3])
locY = integer(ln.word[4])
locHeight = integer(ln.word[5])
direction = void()
dimensions = void()
if the number of word in ln = 6 then
dir = integer(ln.word[6])
direction = [dir, dir, dir]
else
width = integer(ln.word[6])
height = integer(ln.word[7])
locX = locX + width - 1
locY = locY + height - 1
dimensions = [width, height]
end if
createFuseObject(name, objectClass, "0,0,0", locX, locY, locHeight, direction, dimensions)
if rollover(2) and the mouseDown and clickedUrl <> 1 then
clickedUrl = 1
sendSprite(2, #mouseDown)
end if
end if
if i mod 10 = 0 then
sendFuseMsg("STATUSOK")
end if
i = 1 + i
end repeat
if getmemnum(gWorldType & ".firstAction") > 0 then
sendFuseMsg(field(0))
end if
updateStage()
sendEPFuseMsg("GETADFORME general")
else
handleSpecialMessages(content)
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
exit
end
Code:
on handleSpecialMessages(Data)
ln1 = Data.line[1]
Data = doSpecialCharConversion(Data)
if ln1 contains "OPEN_UIMAKOPPI" then
openUimakoppi()
else
if ln1 contains "CLOSE_UIMAKOPPI" then
closeUimaKoppi()
else
if ln1 contains "PH_TICKETS_BUY" then
put(Data)
member("JumpTICKETS").text = Data.getPropRef(#line, 2).getProp(#word, 1)
if the movieName contains "pellehyppy" then
openHyppylippu()
end if
else
if ln1 contains "PH_TICKETS" then
put(Data)
member("JumpTICKETS").text = ln1.getProp(#word, 2)
else
if ln1 contains "PH_NOTICKETS" then
if the movieName contains "pellehyppy" then
openHyppylippu()
end if
else
if ln1 contains "JUMPDATA" then
goJumper = void()
gPellePlayer = void()
sprite(40).undefined = []
if the frameLabel contains "jumpingplace" then
gPellePlayer = new(script("PellePlayerParent"), Data.getProp(#line, 2), Data.getProp(#line, 3))
go("jumpplay")
else
if the frameLabel contains "pool_b" then
gPellePlayer = new(script("PellePlayerParent"), Data.getProp(#line, 2), Data.getProp(#line, 3))
end if
end if
else
if ln1 contains "JUMPLIFTDOOR_OPEN" then
sendSprite(gElevatorDoorSprite, #open)
else
if ln1 contains "JUMPLIFTDOOR_CLOSE" then
sendSprite(gElevatorDoorSprite, #close)
else
if ln1 contains "JUMPINGPLACE_OK" then
go("jumpingplace")
else
if ln1 contains "FLAT_RESULTS" then
s1 = ""
s2 = ""
s3 = ""
s4 = ""
oldDelim = the itemDelimiter
if ln1 contains "BUSY" then
member("flat_results.description").text = AddTextToField("MostPopularRooms")
else
if ln1 contains "FAVORITE" then
member("flat_results.description").text = AddTextToField("FavoriteRooms")
else
member("flat_results.description").text = AddTextToField("SearchResults")
end if
end if
member("flat_results.doorstatus").text = ""
member("flat_results.names").text = ""
member("flat_results.load").text = ""
member("flats_go").text = ""
gFlats = []
the itemDelimiter = "/"
i = 2
repeat while i <= the number of line in Data
flat = Data.line[i]
if flat.length > 1 then
ownerName = flat.item[3]
if ownerName = "-" then
ownerName = ""
else
ownerName = "(" & ownerName & ")"
end if
doorMode = flat.item[4]
if doorMode = "open" then
else
if doorMode = "password" then
if the platform contains "mac" then
else
end if
else
if the platform contains "mac" then
else
end if
end if
end if
add(gFlats, [Data.line[i]])
end if
i = 1 + i
end repeat
the itemDelimiter = oldDelim
member("flat_results.load").text = s1
member("flat_results.names").text = s2
member("flat_results.doorstatus").text = s3
member("flats_go").text = s4
else
if ln1 contains "NOFLATS" then
put(Data)
if not the movieName contains "entry" then
return()
end if
member("flat_results.doorstatus").text = ""
member("flat_results.names").text = ""
member("flat_results.load").text = ""
member("flats_go").text = ""
gFlats = []
else
if ln1 contains "FLATINFO" then
p = keyValueToPropList(Data, "\r")
if voidp(gProps) then
gProps = []
end if
put(gProps)
setaProp(gProps, #doorMode, symbol(getaProp(p, "doormode")))
setaProp(gProps, #showOwnerName, getaProp(p, "showOwnerName") = "true")
setaProp(gProps, #superuser, getaProp(p, "allsuperuser") = "true")
sFrame = "roominfochange"
goContext(sFrame, gPopUpContext2)
else
if ln1 contains "YOUAREOWNER" then
gIAmOwner = 1
else
if ln1 contains "FLAT_LETIN" then
if the movieName contains "entry" then
member("flat_load.status").text = AddTextToField("DoorOpenLoading")
end if
if gChosenFlatDoorMode = "closed" then
goContext("flat_locked_opens", gPopUpContext2)
end if
if gChosenFlatDoorMode = "x" then
goContext("flat_password_ok", gPopUpContext2)
end if
updateStage()
gIAmOwner = 0
gFlatLetIn = 1
member("loading_txt").text = AddTextToField("LoadingRoom")
setBanner()
hiliter = 0
NowinUnit = "Private Room:" && member("goingto_roomname").text
member(getmemnum("room.info")).text = AddTextToField("Room") && member("goingto_roomname").text & "\r" & AddTextToField("Owner") && gChosenFlatOwner
startLoading()
goContext("FLAT_LOADING", gPopUpContext2)
else
if ln1 contains "DOORBELL_RINGING" then
openRingbellAlert(Data.line[2])
else
if ln1 contains "FLATPROPERTY" then
ln2 = Data.line[2]
oldDelim = the itemDelimiter
the itemDelimiter = "/"
parType = ln2.item[1]
parValue = ln2.item[2]
the itemDelimiter = oldDelim
put(parType, parValue)
if parType = "wallpaper" then
setWallPaper(integer(parValue))
else
if parType = "floor" then
setFloor(integer(parValue))
end if
end if
else
if ln1 contains "STUFFTYPES" then
s = ""
oldDelim = the itemDelimiter
the itemDelimiter = "/"
gpStuffTypes = []
i = 2
repeat while i <= the number of line in Data
ln = Data.line[i]
addProp(gpStuffTypes, ln.item[2], [ln.item[1], ln.item[4], ln.item[5], 0])
i = 1 + i
end repeat
the itemDelimiter = oldDelim
else
if ln1 contains "ACTIVE_OBJECTS" or ln1 contains "ACTIVEOBJECT_ADD" then
i = 2
repeat while i <= the number of line in Data
ln = Data.line[i]
if ln.length > 4 then
createActiveObject(ln)
end if
i = 1 + i
end repeat
else
if ln1 contains "STUFFDATAUPDATE" then
tSaveDelim = the itemDelimiter
the itemDelimiter = "/"
tid = Data.getPropRef(#line, 2).getProp(#item, 1)
ttype = Data.getPropRef(#line, 2).getProp(#item, 2)
tProp = Data.getPropRef(#line, 2).getProp(#item, 3)
tValue = Data.getPropRef(#line, 2).getProp(#item, 4)
the itemDelimiter = tSaveDelim
tObj = sprite(getaProp(gpObjects, ttype & tid)).getProp(#scriptInstanceList, 1)
tObj.updateStuffdata(tProp, tValue)
else
if ln1 contains "ACTIVEOBJECT_UPDATE" then
oldDelim = the itemDelimiter
the itemDelimiter = ","
objectName = Data.word[1].item[1]
if offset("*", objectName) > 0 then
objectName = objectName.char[1..offset("*", objectName) - 1] & objectName.char[offset("*", objectName) + 2..objectName.length]
end if
spr = getaProp(gpObjects, objectName)
if spr > 0 then
sendSprite(spr, #die)
end if
createActiveObject(Data.line[2], 1)
the itemDelimiter = oldDelim
gChosenStuffSprite = getObjectSprite(objectName)
else
if ln1 contains "ACTIVEOBJECT_REMOVE" then
objectName = Data.line[2]
if offset("*", objectName) > 0 then
objectName = objectName.char[1..offset("*", objectName) - 1] & objectName.char[offset("*", objectName) + 2..objectName.length]
end if
put("rem:", objectName)
spr = getaProp(gpObjects, objectName)
if spr > 0 then
sendSprite(spr, #die)
end if
else
if ln1 contains "ITEMMSG" then
itemId = integer(ln1.word[2])
o = getaProp(gpInteractiveItems, itemId)
if objectp(o) then
processItemMessage(o, Data)
end if
else
if ln1 contains "OPEN_GAMEBOARD" then
openGameBoard(Data.line[2..the number of line in Data])
else
if ln1 contains "CLOSE_GAMEBOARD" then
closeGameBoard(Data.line[2..the number of line in Data])
else
if ln1 contains "STRIPUPDATED" or ln1 contains "ADDSTRIPITEM" then
if not the movieName contains "private" then
exit
end if
sendFuseMsg("GETSTRIP new")
gChosenStripLevel = "new"
else
if ln1 contains "TRADE_ITEMS" then
if not objectp(gTraderWindow) then
gConfirmPopUp = new(script("PopUp Context Class"), 2000000000, 871, 887, point(0, 0))
displayFrame(gConfirmPopUp, "tradeItem_dialog")
sprite(882).initTrade()
sendFuseMsg("GETSTRIP new")
end if
if objectp(gTraderWindow) then
if gTraderWindow.pClosing then
sprite(882).initTrade()
sendFuseMsg("GETSTRIP new")
else
tradeItems(gTraderWindow, Data)
end if
end if
else
if ln1 contains "TRADE_ACCEPT" then
if objectp(gTraderWindow) then
tradeAccept(gTraderWindow, Data)
end if
else
if ln1 contains "TRADE_CLOSE" then
if objectp(gTraderWindow) then
tradeClose(gTraderWindow, Data)
end if
else
if ln1 contains "TRADE_COMPLETED" then
if objectp(gTraderWindow) then
tradeCompleted(gTraderWindow, Data)
end if
else
if ln1 contains "CATALOGURL" then
gWaitCatStart = the ticks
loadCatalog(Data.line[2])
gWaitCatalog = 1
else
if ln1 contains "ITEMS" then
handleAddItems(Data.line[2..the number of line in Data])
else
if ln1 contains "ADDITEM" then
oldDelim = the itemDelimiter
createItem(Data.line[2..the number of line in Data])
the itemDelimiter = oldDelim
else
if ln1 contains "UPDATEITEM" then
oldDelim = the itemDelimiter
createItem(Data.line[2..the number of line in Data], 1)
the itemDelimiter = oldDelim
else
if ln1 contains "STRIPINFO" then
if goUserStrip = void() then
goUserStrip = new(script("UserStrip Class"))
end if
handleStripData(goUserStrip, Data.line[2..the number of line in Data])
if label(gWorldType & "_hand_open") > the frame then
goToFrame(gWorldType & "_hand_open")
else
if label(gWorldType & "_hand_open") < the frame and label(gWorldType & "_hand_open_b") > the frame then
goToFrame(gWorldType & "_hand_open_b")
else
prepareHandItems(goUserStrip)
end if
end if
else
if ln1 contains "FLATCREATED" then
put("FLATCREATED")
id = Data.word[1]
gChosenFlatId = id
gFloorHost = Data.word[2]
gFloorPort = Data.word[3]
if getmemnum("roomkiosk.roomname") > 0 then
s = "roomkiosk.description" & field(0)
s = "room_password" & field(0)
s = s & "\r" & "allsuperuser=" & getaProp(gProps, #superuser)
sendEPFuseMsg("SETFLATINFO /" & id & "/" & s)
roomName = Data.line[3]
if roomName.length < 2 then
roomName = field(0)
end if
member("goingto_roomname").text = Data.line[3]
NowinUnit = "Private Room:" && member("goingto_roomname").text
member(getmemnum("room.info")).text = AddTextToField("Room") && member("goingto_roomname").text & "\r" & AddTextToField("Owner") && gMyName
s = member("roomkiosk.confirmtext").text
-- UNK_5A 21
-- UNK_5A 21
member("roomkiosk.confirmtext").text = s
goContext("confirm")
end if
else
if ln1 contains "ALLUNITS" then
UnitsIDNum = 0
the itemDelimiter = ","
gUnits = []
sort(gUnits)
num = 1
put(Data)
i = 2
repeat while i <= the number of line in Data
unit = Data.line[i]
if unit.length > 5 and not unit contains "Floor1" then
newUnit(unit, num)
num = num + 1
else
if unit contains "Floor1" then
member("privaterooms.load").text = unit.item[2]
end if
end if
i = 1 + i
end repeat
else
if ln1 contains "UNITUPDATED" then
the itemDelimiter = ","
unit = Data.line[2]
name = unit.item[1]
l = getaProp(gUnits, name)
if name contains "Floor1" then
if the movieName contains "entry" then
member("privaterooms.load").text = unit.item[2]
end if
else
if l = void() then
nothing()
else
num = l.getAt(5)
activeUsers = integer(unit.item[2])
maxUsers = integer(unit.item[3])
host = unit.item[4]
port = integer(unit.item[5])
description = unit.item[6]
UnitPropL = getaProp(gUnits, name)
UnitPropL.activeUsers = activeUsers
UnitPropL.maxUsers = maxUsers
UnitPropL.host = host
UnitPropL.port = port
UnitPropL.description = description
setProp(gUnits, name, UnitPropL)
if not name contains "Floor" then
setUnitActiveUsers(name)
else
member("privaterooms.load").text = unit.item[2]
end if
end if
end if
else
if ln1 contains "UNITMEMBERS" then
s = Data.line[2..the number of line in Data]
s2 = ""
i = 1
repeat while i <= the number of line in s
i = 1 + i
end repeat
if getmemnum("publicroom_peoplelist") > 0 then
end if
if the movieName contains "cr_entry" then
-- UNK_5A 22
end if
else
if ln1 contains "REMOVEITEM" then
itemId = integer(Data.line[2])
sendAllSprites(#itemDie, itemId)
else
if ln1 contains "FLATINFO" then
the itemDelimiter = "="
i = 2
repeat while i <= the number of line in Data
ln = Data.line[i]
sfield = ln.item[1]
sdata = ln.item[2]
if getmemnum("flatinfoshow." & sfield) > 0 then
member("flatinfoshow." & sfield).text = sdata
end if
put(sfield, sdata)
if sfield = "image" then
pictureUrl = sdata
put(pictureUrl)
end if
if sfield = "isOpen" then
if sdata = "true" then
member("flatinfoshow.open_info").text = "Door is open"
sprite(20).visible = 1
else
member("flatinfoshow.open_info").text = "Door is closed"
sprite(20).visible = 0
end if
end if
if sfield = "host" then
gFloorHost = sdata.char[offset("/", sdata) + 1..sdata.length]
end if
if sfield = "port" then
gFloorPort = sdata
end if
i = 1 + i
end repeat
the itemDelimiter = ","
else
if ln1 contains "ADVERTISEMENT" then
put("GOT AD", Data)
gAd = new(script("FUSE Advertisement Class"), Data.line[2..the number of line in Data])
else
if ln1 contains "OPLOGO" then
handleOpLogoMessage(Data)
else
if ln1 contains "SYSTEMBROADCAST" then
ShowAlert("MessageFromAdmin", Data.line[2])
else
if ln1 contains "PURCHASE_NOBALANCE" then
ShowAlert("nobalance", "You don't have enough credits!")
else
if ln1 contains "PURCHASE_OK" then
ShowAlert("BuyingOK")
else
if ln1 contains "PURCHASE_ERROR" then
ShowAlert("purchasingerror", "Purchasing error")
else
if ln1 contains "ORDERINFO_ERROR" then
put(Data)
else
if ln1 contains "ORDERINFO" then
gPurchaseCode = Data.line[2]
price = integer(value(Data.line[3]))
description = Data.line[5]
gConfirmPopUp = new(script("PopUp Context Class"), 2000020000, 851, 870, point(0, 0))
if price > gCredits then
displayFrame(gConfirmPopUp, "purchase_confirm_nocredits")
else
displayFrame(gConfirmPopUp, "purchase_confirm")
end if
else
if ln1 contains "WALLETBALANCE" then
if the movieName contains "entry" and the frame < 100 or the movieName contains "cr_entry" then
nothing()
else
puppetSound(1, "cash1")
end if
gCredits = integer(value(Data.line[2]))
member("habbo_credits").text = integer(value(Data.line[2])) && AddTextToField("Credit(s)")
member("credits_amount_e").text = "You have" && integer(value(Data.line[2])) && "Habbo Credits in your purse."
else
if ln1 contains "DOORFLAT" then
gChosenTeleport.startTeleport(Data)
else
if ln1 contains "DOORNOTINSTALLED" then
gChosenTeleport.error(Data)
else
if ln1 contains "DOORDELETED" then
gChosenTeleport.error(Data)
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
exit
end
Code:
on createPoster(me)
if leftOrRight contains "left" then
s = "PLACEITEMFROMSTRIP" && pID && "leftwall " & y & "," & h & "," & myLocZ & "/" & pType
else
s = "PLACEITEMFROMSTRIP" && pID && "frontwall " & y & "," & h & "," & myLocZ & "/" & pType
end if
sendFuseMsg(s)
s = "GETSTRIP" && "new"
sendFuseMsg(s)
exit
end
Code:
on reserveRoom()
if getaProp(gProps, #showOwnerName) = 0 then
showName = 0
else
showName = 1
end if
put(field(0) & ":" && gProps)
fuseP = "roomkiosk.roomname" & field(0) & "/" & getaProp(gProps, #roomModel) & "/" & string(getaProp(gProps, #doorMode)) & "/" & showName
sendEPFuseMsg("CREATEFLAT /" & fuseP)
exit
end
on updateFlatInfo()
if getaProp(gProps, #showOwnerName) = 0 then
showName = 0
else
showName = 1
end if
fuseP = "navigator.roomname" & field(0)
fuseP = fuseP & "/" & string(getaProp(gProps, #doorMode))
fuseP = fuseP & "/" & showName
sendEPFuseMsg("UPDATEFLAT /" & fuseP)
s = "navigator.description" & field(0)
s = "roompassword" & field(0)
s = s & "\r" & "allsuperuser=" & getaProp(gProps, #superuser)
s = s & "\r" & "wordfilter_disable=" & getaProp(gProps, #wordfilter_disable)
put(s)
sendEPFuseMsg("SETFLATINFO /" & gChosenFlatId & "/" & s)
exit
end
-
Re: Habbo V1 CSTs w/ Bytecode
I don't really get how we can convert such weird code to actual Lingo. I do find this interesting. Now my question is, is the method used to unpack this from the V``1 DCRs able to do the same with V7 for example? Also, can we edit the files currently and convert them back into .cct/.dcr?
Good release nonetheless.
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
Glaceon
I don't really get how we can convert such weird code to actual Lingo. I do find this interesting. Now my question is, is the method used to unpack this from the V``1 DCRs able to do the same with V7 for example? Also, can we edit the files currently and convert them back into .cct/.dcr?
Good release nonetheless.
The person who converted the CCT to CST while still maintaining bytecode is a complete mystery. No one publically knows what this person did.
It's very possible to decompile DCR's back into bytecode (by first turning it into a .dir which is easy) but not .cct to .cst without destroying the scripts.
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
Quackster
The person who converted the CCT to CST while still maintaining bytecode is a complete mystery. No one publically knows what this person did.
It's very possible to decompile DCR's back into bytecode (by first turning it into a .dir which is easy) but not .cct to .cst without destroying the scripts.
Yeah and no offense to anyone.. but I answered these questions in the OP :glare:
Quote:
AND AGAIN I SAY: SO WHAT? We can't do SHIT with bytecode.
Up until a few weeks ago, this would be the appropriate, annoyed question to ask.
But a GitHub project (PM me for the name; the developers do not want to draw too much attention, and Sulake prowls this board like the animals their employees are) has been performing strong work to unpack the Lingo bytecode and guess the Lingo scripts. It does a really good job of this, and I've seen DIRs and CSTs be completely read in full from other games.
How 2 get moar unprotected CSTs? V5? V18? R26?
Not sure. A lot of these came from @Cecer's generous donations, so he may have a clue. But there are some reverse-engineering wizards among us, who secretly practice their magic on Shockwave files, whose names I shall not utter here (lurk moar :wink:)
But no worries. Because that next question is important to answer, eventually, because the work can be replicated on further files and later versions.
-
Re: Habbo V1 CSTs w/ Bytecode
Pretty safe to post the github ptoject if it isnt about Habbo or other Sulake IP.
Plenty of emulator repos out there that have never been taken down.
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
The General
Pretty safe to post the github ptoject if it isnt about Habbo or other Sulake IP.
Plenty of emulator repos out there that have never been taken down.
I'm going to do it because I agree with you.
Here it is:
https://github.com/Brian151/OpenShockwave
Here's the tool that allows you turn Shockwave bytecode back into readable Lingo (found in the GitHub project):
ProjectorRays
We are so close to fully decompiling Shockwave files. People told me it was impossible, just like PS3 emulation, yet here we are today (see RPCS3).
-
Re: Habbo V1 CSTs w/ Bytecode
Updating the post to add the link to the project. I know Sulake isn't directly affected by the project's existence, but if they have a compelling interest in proprietary secrecy, they may raise the alarm to Adobe.
I'm not sure. But I'm cautious about disclosing the project's name. That said, maybe they can recruit a few contributors from this section.
-
Re: Habbo V1 CSTs w/ Bytecode
I'm not worried about sulake. More worried about Adobe taking down that repository.
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
The General
I'm not worried about sulake. More worried about Adobe taking down that repository.
It'd be stupid; shockwave is so old and outdated so it would be stupid if they'd still take it down.
-
Re: Habbo V1 CSTs w/ Bytecode
I'm neither concerned for the safety of the project from Sulake nor Adobe. If it were my project, I wouldn't be.
But it's not my project, and the developers have expressed anxiety about C&D's for Shockwave games on certain Lego archives. And seeing as they're using a specific Lego game, Spybotics: The Nightfall Incident (great game, by the way) for most of their work, I felt it wouldn't be respectful to draw a swarm of unnecessary, more public attention to it. I thought, perhaps this would create some anxiety in the developers, who are knowingly and actively exploring a specific piece of intellectual property.
A wise member of this forum, one whose superior judgement I regularly choose to defer to, has previously advised me that he and the other Shockwave reverse-engineers in this forum choose to be quiet about their work. That's why I haven't called out any specific reverse engineers, as helpful as their unique expertise might be.
That said. I have updated the original post to reflect the community's general interest in knowing the identity of the project, and the ability to make use of it.
-
Re: Habbo V1 CSTs w/ Bytecode
Doesn't seem to work with V5:
PHP Code:
C:\Users\Josh\Documents\Blah\blahos\tools>python cst_python.py "fuse_client.cct"
RIFX_SIGN: XFIR
SIZE: 83319 (81kb)
SIGN: b'CDGF'
File num: 1853772146
--- READ POINTERS ---
Traceback (most recent call last):
File "cst_python.py", line 901, in <module>
main(sys.argv[1:])
File "cst_python.py", line 881, in main
readCST(f)
File "cst_python.py", line 242, in readCST
entryType = f.read(4).decode("utf-8")[::-1] # 4
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa6 in position 1: invalid
start byte
Or I'm doing something wrong?
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
Glaceon
It'd be stupid; shockwave is so old and outdated so it would be stupid if they'd still take it down.
Doesn't matter. Shockwave is still Adobes' IP. Regardless of it being outdated or not.
Quote:
Originally Posted by
FullmetalPride
A wise member of this forum, one whose superior judgement I regularly choose to defer to, has previously advised me that he and the other Shockwave reverse-engineers in this forum choose to be quiet about their work. That's why I haven't called out any specific reverse engineers, as helpful as their unique expertise might be.
If they wanted to hide it they wouldn't have put it in a publicly available repository.
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
Glaceon
Doesn't seem to work with V5:
PHP Code:
C:\Users\Josh\Documents\Blah\blahos\tools>python cst_python.py "fuse_client.cct"
RIFX_SIGN: XFIR
SIZE: 83319 (81kb)
SIGN: b'CDGF'
File num: 1853772146
--- READ POINTERS ---
Traceback (most recent call last):
File "cst_python.py", line 901, in <module>
main(sys.argv[1:])
File "cst_python.py", line 881, in main
readCST(f)
File "cst_python.py", line 242, in readCST
entryType = f.read(4).decode("utf-8")[::-1] # 4
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa6 in position 1: invalid
start byte
Or I'm doing something wrong?
You're trying to read a .cct when the function calls for a CST file?
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
Quackster
You're trying to read a .cct when the function calls for a CST file?
Oops. But I tried with .cst too (which - and correct me if I'm wrong - is just an unprotected .cct file, or is it gotten through a special method?)
Quote:
Originally Posted by
The General
Doesn't matter. Shockwave is still Adobes' IP. Regardless of it being outdated or not.
Got your point, and I agree, partly. It's my opinion I'd think it's stupid if they cared. Like when Nintendo would care about people using a GB emulator. It's not the same principe, but I think you get my point.
But yeah, you definitely got a point.
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
Glaceon
Oops. But I tried with .cst too (which - and correct me if I'm wrong - is just an unprotected .cct file, or is it gotten through a special method?)
Got your point, and I agree, partly. It's my opinion I'd think it's stupid if they cared. Like when Nintendo would care about people using a GB emulator. It's not the same principe, but I think you get my point.
But yeah, you definitely got a point.
I'm not sure what that part of the project does but it doesn't look so important. You should just use the lscrtoscript project.
If you'd rather not upload anything to your site, just use mine: ProjectorRays
-
Re: Habbo V1 CSTs w/ Bytecode
hi babe @Cecer they're mentioning you again, are you here? :love:
- @FullmetalPride
Shiet, never thought I'd see this. Thanks for releasing!
What I've never understood though, is, why'd we need the Lingo code?
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
Dominic
hi babe @
Cecer they're mentioning you again, are you here? :love:
- @
FullmetalPride
Shiet, never thought I'd see this. Thanks for releasing!
What I've never understood though, is, why'd we need the Lingo code?
In order to reach completion, such as adding Snowstorm to v26 etc...
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
FullmetalPride
I'm not sure what that part of the project does but it doesn't look so important. You should just use the lscrtoscript project.
If you'd rather not upload anything to your site, just use mine:
ProjectorRays
Do i put unprotected CCTs there? (Like with recover_cct) or something else? Sorry if i sound dumb but i tried v7 which didnt work for me but mustve done smth wrong
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
Glaceon
Do i put unprotected CCTs there? (Like with recover_cct) or something else? Sorry if i sound dumb but i tried v7 which didnt work for me but mustve done smth wrong
recover-cct destroys the bytecode when you use it.
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
FullmetalPride
How 2 get moar unprotected CSTs? V5? V18? R26?
Not sure. A lot of these came from @
Cecer's generous donations, so he may have a clue.
Sadly I have nothing I can offer in terms of advice. I acquired those files back when there was only really releases for incomplete V1. This was long before I did any real programming or had any real understanding about how Habbo worked internally. I probably got them while trying to set up ThuGie's H-Retro (or whatever the project name was xD)
I might have some other files but I'll have to dig about my archives.
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
Quackster
recover-cct destroys the bytecode when you use it.
Yes, what I was thinking. So how can I "convert" the .cct to a .cst while still having the bytecode?
-
Re: Habbo V1 CSTs w/ Bytecode
That's the thing we're trying to solve..
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
Glaceon
Yes, what I was thinking. So how can I "convert" the .cct to a .cst while still having the bytecode?
CCT = compressed / compiled
CST = source
CXT = encrypted, compressed and compiled.
Lingo bytecode - Just Solve the File Format Problem
You decompress it, most "dcr decompilers" only reverse the image data, they don't "get rid of" the code, they just don't know how to deserialize it to code. If you deserialize (or decompile if you will) the bytecode you can get a pretty damn close representation of the original source that's almost haunting enough. There's been numerous people who've gotten work done on it before including Matthew Parlane and others. There's more "secrets" on my discord if anyone's interested. I'll be taking everything I can find and putting it all under one of my domains when I get the chance.
You can do the same to a Director .exe it just packs it all in the EXE / DMG. Then the embedded interpreter decompresses / interprets the internal contents at runtime from itself.
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
Moogly
CCT = compressed / compiled
CST = source
CXT = encrypted, compressed and compiled.
Lingo bytecode - Just Solve the File Format Problem
You decompress it, most "dcr decompilers" only reverse the image data, they don't "get rid of" the code, they just don't know how to deserialize it to code. If you deserialize (or decompile if you will) the bytecode you can get a pretty damn close representation of the original source that's almost haunting enough. There's been numerous people who've gotten work done on it before including Matthew Parlane and others. There's more "secrets" on my discord if anyone's interested. I'll be taking everything I can find and putting it all under one of my domains when I get the chance.
You can do the same to a Director .exe it just packs it all in the EXE / DMG. Then the embedded interpreter decompresses / interprets the internal contents at runtime from itself.
Hmm. I guess I kind of understand. Also, can you send a link to the discord? I have a new account.
I just can't seem to understand how to decompress it. From what I understand, something like recover_cct and recover_dir or w/e the .dcr version is called only gets the images but don't decompress it? Or am I wrong?
Sorry if I sound noob I have 0% experience with this stuff.
-
Re: Habbo V1 CSTs w/ Bytecode
Quote:
Originally Posted by
Quackster
In order to reach completion, such as adding Snowstorm to v26 etc...
There's another problem: it seems every single DCR v26 pack has incomplete SnowStorm files.
Yesterday I started working on the map (.ROOM) files (you know, there're 7 arenas and in every single pack there's only one empty and incomplete arena), such as adding map items and collisions.
SnowStorm's files are this:
v26
hh_game_snowwar: recover-cct crashes when tries to convert this file in CST. So I tried with Offzip and I saw a lot of text (perhaps Lingo scripts?) in .dat files with an Hex Viewer.
hh_game_snowwar_ui: SnowStorm UI is stored here with its field settings (game-bar coords, time windows coords etc.)
hh_game_snowwar_room: this file has just one map (pretty empty) and map's items. Fortunately the other map's items are stored here.
Unfortunately, v28+ packs don't have any single new file, only BB files.