06-24-2022, 11:35 PM
Hi,
I independently worked on reverse engineering Sky on Android since June 2020, though by October 2020 I had put the project off due to lack of time. I discovered a number of details, but I had stopped short of publishing anything as I did not want TGC to begin obfuscating the builds while they still had their core Android developers on it. I think it's fair to say that three years on, the core team has likely moved on to other projects (and so have I), so I would be happy to share anything I have to help you renew the endeavor. Sky's highly immersive artistry was emotionally moving for me, and my aspiration was to create a map of my own and to publish videos on it.
As you know, Sky uses an in-house engine written in C++ targeting ARM64. The music uses FMOD; there are about 6 hours of music present in the game, encoded in Ogg Vorbis at 64 kbps. In the sound banks, you'll see a number of tracks that appear to have been unused in the game.
I performed about 16 hours' worth of analysis under Ghidra on version 0.10.0 (build 151406). A number of findings:
With some work, I was able to intercept some, but not all, of the network traffic. It's part HTTP, part WebSockets, and a lot peer-to-peer ENet UDP.
Textures use ETC2 with RGBA, but I couldn't find tooling for it. Seems like you found it
Levels seem to use a novel format that is based on the concept of metaballs. Apparently, designers used an in-house Maya plugin to create the levels - refer to "Gnomon - Art of Sky: Children of the Light" on YouTube, which describes the game's art pipeline in great detail (start at 46:20 for details on map design). Like everything, the lighting has to be baked into the level data, which produces the "BstBaked.meshes" file that you see. I once speculated that "BST" refers to "Blue Sky Thinking" which was referred to by one of the Lua files, but it probably refers to a binary search tree/BSP. It's not an important detail. There's a level compiler intact in the game binary.
The renderer was also created in-house due to the desire at the time to accommodate for as many devices as possible and minimize memory footprint. More info is available in the video above.
Meshes also seemed to use a novel format, which I concentrated most of my time on but didn't make much progress. There were a number of branches in the decompilation output due to support for older mesh versions. There was also a lot of optimized NEON math that Ghidra refused to display in an intelligible format. Thankfully things only get better with Ghidra.
This is an interesting (and potentially helpful) finding, considering that I had never encountered any indication that any part of the engine was actually based on Ogre3d. Since Ogre3d is MIT-licensed, I wonder why they haven't posted any open-source licenses anywhere. Not sure why I didn't ask them earlier, considering they use some other basic OSS libraries as well (like ENet and OpenSSL).
Still, I've been looking for strings and symbols present in ogre-next and can't find any in Sky. They must have written an Ogre-compatible mesh loader, but it's hard to tell because the Ogre binary spec is undocumented. The Ogre format also assumes that each file is comprised of a stream of chunks, much like PNG. But I see in Sky that the mesh loader goes straight to iterating through a predefined number of LODs and loading mesh and occlusion data for each one.
I hope Cunningham's law works in our favor if I posted something wrong. Feel free to PM me for my Discord username if you're interested in even more details. Hope this helps.
I independently worked on reverse engineering Sky on Android since June 2020, though by October 2020 I had put the project off due to lack of time. I discovered a number of details, but I had stopped short of publishing anything as I did not want TGC to begin obfuscating the builds while they still had their core Android developers on it. I think it's fair to say that three years on, the core team has likely moved on to other projects (and so have I), so I would be happy to share anything I have to help you renew the endeavor. Sky's highly immersive artistry was emotionally moving for me, and my aspiration was to create a map of my own and to publish videos on it.
As you know, Sky uses an in-house engine written in C++ targeting ARM64. The music uses FMOD; there are about 6 hours of music present in the game, encoded in Ogg Vorbis at 64 kbps. In the sound banks, you'll see a number of tracks that appear to have been unused in the game.
I performed about 16 hours' worth of analysis under Ghidra on version 0.10.0 (build 151406). A number of findings:
- Device compatibility is hardcoded into a table. Every device has a predefined "rating" that determines the max graphics preset that the game can run at. Only devices with a rating of >=10,000 can run Sky at 60 fps. I constructed a CSV for this and even joined it at some point with the Google Play official device table, but I'll paste a link later as posting a link on my first post would probably get my account autoflagged for spam.
At the time, the highest-rated devices were the iPhone 11, the 2018 iPad Pro, the OnePlus 7T, the Meizu 6s Pro, the Samsung Galaxy Flip (which is actually my phone today), and the ZTE Axon 10 Pro.
- There is some DRM present. Sky uses the Google Play License Verification Library (LVL) to ensure that players didn't download the APK from somewhere else. There are some other rudimentary DRM schemes as well.
- Lootboxes were once in development, as their classes were present in the code.
- The game was originally intended to have throne guards and turrets with projectiles, as their classes were also present in the code.
- Game functions are heavily integrated with the Lua runtime for fast prototyping. You can dump pretty much any game object and call most native functions from Lua.
With some work, I was able to intercept some, but not all, of the network traffic. It's part HTTP, part WebSockets, and a lot peer-to-peer ENet UDP.
Textures use ETC2 with RGBA, but I couldn't find tooling for it. Seems like you found it
Levels seem to use a novel format that is based on the concept of metaballs. Apparently, designers used an in-house Maya plugin to create the levels - refer to "Gnomon - Art of Sky: Children of the Light" on YouTube, which describes the game's art pipeline in great detail (start at 46:20 for details on map design). Like everything, the lighting has to be baked into the level data, which produces the "BstBaked.meshes" file that you see. I once speculated that "BST" refers to "Blue Sky Thinking" which was referred to by one of the Lua files, but it probably refers to a binary search tree/BSP. It's not an important detail. There's a level compiler intact in the game binary.
The renderer was also created in-house due to the desire at the time to accommodate for as many devices as possible and minimize memory footprint. More info is available in the video above.
Meshes also seemed to use a novel format, which I concentrated most of my time on but didn't make much progress. There were a number of branches in the decompilation output due to support for older mesh versions. There was also a lot of optimized NEON math that Ghidra refused to display in an intelligible format. Thankfully things only get better with Ghidra.
(04-04-2022, 03:23 AM)ether0x1 Wrote:(01-17-2022, 02:24 PM)DancingTwix Wrote: No worries!!
Yeah the issue with getting product keys and the like are why I put looking into the switch one hold, and afraid to say I think I deleted it from my pc. Sorry!
Getting into the android files it's a lot easier.
Could I ask what are you loading the meshes into the level with??
Are you actually able to see and render things on the screen or something??
I must admit I'm a tad loat, more of web dev then anything so this is still all pretty new to me haha
Mesh files are compiled Ogre meshes. Sky runs on the ogre2 (ogre-next) engine, and the level.object.bins are their own format.
They have tgcl magic headers and are most likely ports from Journey with slight modifications. Due to the fact that the meshes are compiled it is quite tricky to load them into any modelling software or edit them in any ways. What is possible however is designing your own meshes and then compiling them into ogre2 meshes to get the game to load them. This is my discord tag: Lukas#8962. Hit me up if you feel like it.
This is an interesting (and potentially helpful) finding, considering that I had never encountered any indication that any part of the engine was actually based on Ogre3d. Since Ogre3d is MIT-licensed, I wonder why they haven't posted any open-source licenses anywhere. Not sure why I didn't ask them earlier, considering they use some other basic OSS libraries as well (like ENet and OpenSSL).
Still, I've been looking for strings and symbols present in ogre-next and can't find any in Sky. They must have written an Ogre-compatible mesh loader, but it's hard to tell because the Ogre binary spec is undocumented. The Ogre format also assumes that each file is comprised of a stream of chunks, much like PNG. But I see in Sky that the mesh loader goes straight to iterating through a predefined number of LODs and loading mesh and occlusion data for each one.
I hope Cunningham's law works in our favor if I posted something wrong. Feel free to PM me for my Discord username if you're interested in even more details. Hope this helps.