Dev Blog

Shellrazer Dev-Blog 27: More Waanderful tech

08/22/2012

Welcome back followers of the fearsome!

Since Jesse’s still a bit hung over from his birthday party last night, I (Nick) will be typing this weeks dev-blog. It’ll be programmer talk, but since Jesse can draw the turtle with his eyes closed now, he did manage to spruce up this post with an awesome turtle drawing.

I’ll be talking about loading screens. There are many games on iOS that have long loading screens, and every time I see them I wonder why. Some people I’ve met at the Full Indie meetup have  told me that the iPhone is very slow to load data from. In my experience this couldn’t be further from the truth. It’s one of the fastest loading devices I’ve ever worked with! So, in order to possibly help out a few fellow developers remove those long-ass loading screens, I’ll give you some information on how I load data into our game. Note that this information is totally useless if you use Unity, but if you have your own engine (yea! rock on!), this info could make things a lot easier and faster!

There are different ways to load data from a disk. The most common method is to fopen a file on disk, and use fread to get the data from it. On consoles with DVD drives a common trick to speed up loading is to compress the data on the disk, and unpack it at load time in a separate thread. When loading compressed data, you often end up with a memory buffer to load the compressed data into, and another memory buffer to unpack the data to, and then possibly another memory buffer to store the data after you’ve loaded it. (The last step depends on if you load in place and fix up pointers, another common trick, but that’s for another time). In my experience, allocating extra memory, or using extra CPU to load the data is quite undesirable on mobile devices. I tried using our console engine approach of loading and unzipping data, but it was extremely slow. Then I read a post by Carmack (which I can’t seem to find in my bookmarks.. argh) about how he uses a function called mmap in Rage for iOS. You should learn everything you can about this function as soon as possible. Here’s a wiki page to get you started: http://en.wikipedia.org/wiki/Mmap

So what does mmap do? mmap can map an entire file into a virtual memory address. It doesn’t load any data, it just reserves a memory address that you can access, at which point it will load the data on demand. So all you do is access the data through a pointer and data will get loaded behind the scenes (without having to go outside the kernel, speeding up thing considerably!). The trick is that no memory is actually allocated for this, except for possibly a bit of cache memory. Doesn’t that sound pretty weird and magical? That’s because it is.

So how do we use this in Shellrazer? We pack all of our data files (thousands of them) into one large archive file at compile time. The archive file is nothing other than a list of file-names with their offsets in the archive, and the data for each file. All the data is uncompressed so that I don’t need to uncompress data when I want to access it. (By the way, if your game is a gigabyte in size, this may not be desirable for your users, but that’s another story) When I need to get some data from a file, I simply look in the list of files, get the offset inside the archive, and return a pointer to the mmapped archive plus the offset. Then I can just start using the pointer and read from it as if you’re reading from any memory location. If I have texture data I just pass this pointer straight to OpenGL, so it can do it’s thing to load the texture. It’s super easy to use, it works all the time, and it’s crazy fast.

In fact, when I first put this method in, I was shocked at how fast it was. According to a few tests I did I was streaming in data at a rate of 300Mb per second. The data in our game loaded so fast that the loading screen I added was barely visible. In fact, I had to make the loading screen stay on screen artificially for at least 0.3 seconds, otherwise it looked like a bug.

After these tests I altered the way our game handles data. I keep a few things in memory at all times, such as the main font bitmap, and a few other commonly used bitmaps. Everything else gets swapped in and out of memory, depending on the currently active UI-screen. When the game switches to a new UI screen, the old screen first transitions  to our little loading indicator for about 0.2 seconds, then all the data gets flushed from memory, all the required data for the new screen gets loaded into memory, and the new screen transitions in for about 0.2 seconds. If you take a look at Shellrazer, every time you see a black screen with a little white rotating icon in the bottom right, that’s our loading screen, and in almost all of those cases, over 30Mb of data is loaded between two screens, plus it has about 0.4 seconds of artificial delay. Also, when our game goes into the background, I flush out all of the resources we use, and we reload these when the app goes to the foreground again, all of which takes less than half a second. Pretty speedy!

Now, as for application size, Apple has the 50Mb restriction on downloadable over 3G vs Wifi. Our archive file is 60Mb though. Well, the good news is that all data files get compressed by the Apple installer, so our download size for Shellrazer is only 31Mb. Problem solved. :)

Alright, I think that’s all I have to say about how to speed up your loading times. I probably missed a bunch of things, so if you have any questions about this stuff, I’ll be happy to help out!

tl;dr: use mmap to load, it’s awesome.

Cheers!

Nick

Posted by: Under: Shellrazer,ShellRazer Dev-blog

Comments:

Comment by: Gabor Furedi

August 22nd, 2012 at 2:36 pm

pretty amazing stuff! i was thinking about using some magic to speed up our texture loading in Soctics as it takes around 2-3 seconds to load the atlases, looks like exactly what we need. ever thought of posting something on github? ;)

Comment by: slick

August 22nd, 2012 at 2:49 pm

Awesome, this should be exactly what you need then! How big are your texture atlasses? I load a few 2048x2048x32 bit uncompressed atlasses between screens, and they are 16Mb each. It still takes only a split second. It’s magic I tell you! :)

Comment by: FuzzYspo0N

August 22nd, 2012 at 3:21 pm

I am glad others are talking about this approach too, it seems like secret knowledge at times :)

Have you tried this on Android? Since the (mess) of the APK and file access there can be quite painful compared to other platforms.

Comment by: slick

August 22nd, 2012 at 3:33 pm

Ha, that’s a good point. I actually just started on the port to Android, so I’ll probably be running into that real soon.

Comment by: FuzzYspo0N

August 22nd, 2012 at 3:36 pm

Ah, that could work well for SD card files (i.e App is a bootloader for the data files, which the bootloader downloads to the SD card). Once on the SD card regular fopen works as expected so mmap would too.

You could also obviously unpack data from the APK to the sd card (using NDK AAssetManager functions that read the data and uncompress it for you), but there is little reason for that unless the game is much bigger (APK has a weird limit of 30 or 50mb depending on device memory and..the moon phase).

Comment by: slick

August 22nd, 2012 at 3:49 pm

Awesome, thanks for the tips! It sounds like there may be a bit of work required there. Maybe I’ll update the devblog post in the future when it works on Android ;)

Comment by: Jesse Chounard

August 22nd, 2012 at 8:12 pm

Well, that’s just awesome!

The only game I have on the app store (I ported Hypership to iOS) doesn’t spend much time loading, but I’ll definitely be using this in the future. Thanks!

Comment by: krangGAMES

August 23rd, 2012 at 12:44 am

Your comment at the top should read, “Note that this information is totally useless if you use Unity. If you’re using Flash, god help you.” ;)

Anyway, nice article! I really appreciate that you go very in-depth with the technical theory but don’t really get bogged down with jargon. Well written for a professional, but still accessible by a layman. Thanks.

Comment by: bilal

August 23rd, 2012 at 6:38 am

which game engine did you use for the game? was it unity?

Comment by: bilal

August 23rd, 2012 at 8:23 am

apologies, i typed before i read the whole thing.

Comment by: Ruben Garat

August 23rd, 2012 at 9:21 am

I am really loving your tech posts.

What format are you storing your textures in with this? I assume that you need to use something that can be directly pushed to the gpu so that means either PVR textures or just the raw RGBA data.

We would love to use this on android, but in that case the problems we see is that compressed textures are not standard over all devices(they support different formats, only ETC1 is standard but it doesn’t have alpha support) and storing the raw uncompressed RGBA data would make our game huge like going from 15 to 90 megs (before apk compression which is zip)

Comment by: slick

August 23rd, 2012 at 10:20 am

Hi all. :) Thanks for the comments!

We’re storing some textures in RGBA format (huge!), and some in PVRTC format. For android we have 4 different compressed texture formats we support, as well as all the uncompressed formats of course, and we select the one we need at load time.

Comment by: Karl Schmidt

August 23rd, 2012 at 1:34 pm

The original article from Carmack you were likely thinking of: http://www.bethblog.com/2010/10/29/john-carmack-discusses-rage-on-iphoneipadipod-touch/

Nice article BTW! I’m hoping to play with some of this stuff soon :)

Comment by: Magnus Osterlind

August 23rd, 2012 at 10:36 pm

I recently added something like this to my own code, and a cool thing I realized was that because I beforehand knew the names of all the files I was going to be looking up, I could create a perfect minimal hash table of the file names, so that I didn’t need to store the actual file names in my lookup table, but only the keys in the hashtable.

Comment by: Lee Wright

August 31st, 2012 at 3:56 am

RSK brings you mobile application development services including Iphone Application development, Android Application development, Blackberry Application development, Window phone development and many more latest technologies….

Comment by: Cookie

September 19th, 2012 at 6:13 pm

Hey I’m just a player of your game and I love it… I downloaded it not more than 2 days ago and already completed it :/ what’s happening with this second island? Cheers x

Follow us!

titlebutton_twitter titlebutton_facebook titlebutton_youtube titlebutton_twitch

Join our mailing list!

/ /

Dev Blog

October 22 2014

Welcome back followers of the fearsome! This week we’ll be taking a quick look at some of the very cool equipment customization in Viking Squad. We really want players to be able to choose gear that reflects their play style so we’ll be sure to give them a whole bunch of options.  Below is an image […]