Sunday, December 19, 2010

Changes in Chaos 1.4

I've uploaded another version of Chaos to the Market. This adds the oft-requested "Quit" feature. Now you can leave a game at any time by selecting the option from the game menu. Once on the splash screen, if you press "back" the game will exit and you'll be returned to the home screen, or wherever you were when you started the game.

The second change reduces the size of the frame width around the board. In the GBA version I had increased this to 16 pixels (2 GBA hardware tiles) so that scrolling was less pointless. When the whole game fits on a single screen with space to spare, having such a large border doesn't make sense. This decrease in the total game board size means the graphics are slightly bigger than before once they've been scaled up. Here is a screen shot showing the before and after versions of the game screen so you can compare:

You can just about see the extra pixels used on the left and right of the screen. Now the game reaches to the ! on the "USB attached" icon and to the 2 of the 22:00 on the clock. We're only talking a few pixels here, but it's better than nothing.

I fixed a minor bug that caused the game to show the meditate spell incorrectly on the "examine spell" screen. No biggie there.

The last change I've made is to reduce the size of the APK file. What can I say? I was using uncompressed sound files, and now they are MP3-compressed. The APK size went from 512K to 160K, and the installed size went from around 800K to 380K. This was such a simple change that it reminded me of the Daily WTF article about the software company that added a pointless loop in the code that they reduced by an order of magnitude every now and again for an "amazing speedup".

Finally, I've released the GBA and Nintendo DS versions based on this same code base. I had a C++ semi-rewrite that ran on the DS, the old C code for the GBA, and then this version of the GBA C code tidied up for Android. The Android version also incorporated the bug fixes and improvements from the DS version, including the new spells. Now that I've finally figured out how to write cross platform code without too many hacks, all of these are based off of the same common C core.

I've created a new site with the Nintendo DS and Game Boy Advance downloads as well as some instructions on how to play on Android.

The hardest part about testing the GBA version was dusting off my old Windows 98 laptop, finding the "Flash Advance" adapter (the drivers came on floppy disk!) and copying the GBA file onto the aging flash cartridge. My current laptop doesn't have a printer port, so there was no other way to get the GBA files onto the flash cartridge. Here's a photo of my workshop set up on the dining room table.
My own computer museum

The photo was taken using a DSi of course :-) Suffice to say my dear wife was not impressed. I was accused of being like Jean Michel Jarre, surrounded by gadgets.

Sunday, December 05, 2010

Chaos 1.3

 I've uploaded a new version of Chaos to the Android Market. The only bug fix is the missing attack sound, but there are a couple of Android-specific cleanups in there. First off, I've now forced the game to run in landscape mode. Swapping between landscape and portrait was more of a tech demo than an actual useful feature. In addition, maybe people didn't realise you can rotate the screen to get a better view. I never used portrait mode anyway, it was too small. The second change is that you can now install the game to the SD card if you are running Android 2.2. I only have Android 1.6, so let me know if this works or fails spectacularly for you.

Spell select screen
For this release I upgraded my tools to the latest Android SDK, which is designed for Android 2.2. Prior to this upgrade I had assumed that I needed to use the old toolkits to compile for old versions of Android, I didn't realise that I could compile for 1.6 using the latest tools too. The explanation on the developers' documentation page is pretty confusing. As usual, looking for the API strings on Google Code Search turns up real world uses of the features and the correct implementation.

Speaking of confusing versioning, how about this tongue twister: the Android SDK is currently at API 8, revision 2. This is for Android 2.2. The SDK tools are at revision 7. These SDK tools are not tied to a version of Android, but API 7 is compatible with Android 2.1 in other places. In order to run on Android 1.6, you have to use "minSdkVersion=4", which corresponds to API 4. The latest version of the Android NDK is revision 4b. But the 4 here doesn't mean it only works with Android 1.6. In fact the NDK includes the libraries and header files for API versions 3, 4, 5 and 8, which correspond to Androids 1.5, 1.6, 2.0 and 2.2. Note that it doesn't include different headers, etc. for API levels 6 or 7.

And then you wonder why it took me so long to figure out how to use the latest SDK to compile for older versions of Android! :-P

Wednesday, December 01, 2010

Responding to Android Market Comments

The Android Market lets anyone comment on any of the applications available. Sadly there is no way to respond to a comment on the Market itself, so here is my feedback to your comments on Chaos...

by Neko_Noskire (November 28, 2010) ★★★★
This is what trading card games should have been like. A way to get out of the game would be nice.
Seems this comment was later deleted, but it still shows up on AppBrain. Adding a way to quit is actually quite tricky given the way the Android Activity lifecycle works with applications using native code. At the moment you can just press the Home button to go back to the home screen. This pauses the game and, assuming the OS does not kill the Chaos process, you can restart the game by pressing its icon again. This can lead to some surprising resets, though the alternative (always hard reset when you hit the Home button) is worse, I think. I don't particularly like games that do the forced hard reset anyway, it seems to go against the spirit of multi tasking. Or maybe Neko wanted a way to completely abandon a game that you'd already started? Hmm, that might be it and that would be doable. One for the list of things to do.

by Peter (November 21, 2010) ★★★☆☆
Pretty good, but needs landscape mode & speeding up; missing "attack" sound
I wonder if Peter uses an EVO 4G? Rumour has it that the frame rate is capped at 30 frames per second, which would cause Chaos to run slower than it should do. I use the frame redraw to sync the timers in the game, you see. As for the attack sound missing, I'll have to check that. Disclaimer: I often play with the sound switched off. Heh heh. The landscape mode comment is strange - just rotate your phone, the screen adjusts. Maybe I should lock the game to landscape only? The portrait mode version is not very useful as you end up with a tiny area to play on and big black borders at the top and bottom.

by Jon (November 20, 2010) ★★★★★
I now no longer need any other game. Awesome retro fun!
Thanks Jon! :-)

by Martin (November 1, 2010) ☆☆☆☆
Naja, schwaches Game. Keine gescheite Steuerung :(
Translation: Well, weak game. No intelligent control. Er, okay. I think an '80s videogame magazine tautology will do here: If you don't like games like Chaos, then this game is not for you.

by Kieron (October 31, 2010) ★★★★★
YES! 1 of my fav Spectrum games that I still play on emus, Marvin works well but the keyboard mapping isn't great for phone. This port solves it! Thanks
This is why I wrote the GBA version originally too - I could play Chaos on FooN, but the controls were unwieldy. Almost a remake of a remake then.

by darren (October 31, 2010) ★★★★★
Amazing cool sexy fun ! Hint ! Kill the warlock on level seven by using your blood diamond in his water
Right... Not sure what darren has been imbibing (blood-diamond tainted water perhaps?) but at least he rated the game 5 stars. This may have been an odd sort of spam actually, it appeared almost immediately after uploading the game to the Market. I can't see what the spam is trying to achieve though. Very strange.

So there we go. Keep the feedback coming - Chaos is in maintenance mode while I hack on my next Android game, but I'll still add features if they sound good and aren't too tricky.

Sunday, November 07, 2010

Changes in Chaos 1.1

I've updated version 1.1 of Chaos in the Android Market. This version contains 2 bug fixes:

  • Computer opponents could never move again after casting Meditate
  • 2 sources of random crashes fixed

The first bug was a silly one, easy to fix. The other one, well, I didn't want to believe the random crashes. I was hoping it was caused by cosmic rays or something. After it happened to me again when I was finally about to win I decided to get to the bottom of things.

I added a "stress mode" to the PC test version I have, and left 8 computer controlled wizards to battle it out all day watched by valgrind. The results were that there are 2 places were I ended up reading well outside the memory I had allocated. I haven't seen a repeat of the error since then, so hopefully the problem is fixed now.

Sunday, October 31, 2010

Chaos on Android!

I've just uploaded my remake of Chaos to the Android Market. It's free to download and is advert free. Hopefully this link will work market://search? or you can download via here.

Spell selection screen
Movement round screen

This is pretty much a straight port of the GBA version of Chaos I wrote a few years back. I've added in some features from the Nintendo DS version I also did, such as the "Meditate" spell (new spells at the cost of no movement for the wizard that round) and finishing off the sleep and blind spells that almost existed in the Spectrum classic. The effects of Sleep are obvious, but Blind reduces movement, attack and defence to minimum. There's a random chance of either wearing off at the end of each cast round.

It has touch screen controls or can be controlled using the trackball or control pad if you have them. I've been testing this on my HTC Magic with Android 1.6. I hope it runs okay on newer phones with bigger screens, but let me know if you have issues.

Wednesday, October 13, 2010

Android Native Coding in C

When I read questions like "How to do code sharing between Android and iOS" on, and the answers are variations on the theme: "the NDK is not for creating cross platform apps", it makes me sad. The NDK is an excellent way to write cross platform games. Here is a little insight into the approach I've taken with my so-far unreleased Chaos port.

Chaos running on the HTC Magic

To code a game in C on Android you have to first write a Java Activity with a View. This can be either a regular View or one that is OpenGL-ified, this explanation uses the GLSurfaceView. Then you use the Java Native Interface (JNI) to call from Java into your C code. You compile your C code using the Android Native Development Kit. The remaining problem is then: how can I draw pixels?

You have 2 options (3 if you are willing to target Android 2.2+): drawing pixels to a Canvas, drawing to an OpenGL ES texture, or drawing directly to the pixel buffer of a Bitmap. This last option is similar to option 1, but is faster and available on Android 2.2 "Froyo" only.

Assuming you want to draw a screen that is smaller than the Android native screen size and scale this up, the OpenGL version is the fastest and most compatible of the 3 choices. Using OpenGL from C code is actually cleaner than from Java, as you do not need to worry about adding gl. to all the GL function calls (gl.glActiveTexture for example, where gl is an instance of javax.microedition.khronos.opengles.GL10). You also don't have to worry about the arrays you pass to GL functions being on the Java heap rather than being the required native arrays. This means you don't have to deal with all the ByteBuffer calls that clog up the Java OpenGL examples.

You will need at least 3 native functions to draw in OpenGL: the "main loop" that runs your game's code, the "screen resized" and the "screen rendered".

The main loop can be the classic while (1) { update_state(); wait_vsync();}. The screen resized function is called when the Android device is rotated or otherwise needs a new screen setting up. The screen rendered function is called once per frame.

The main loop and the render functions both accept no arguments. The screen resized or set up code accepts a width and height argument. The Java native declarations for these calls will look like this:

private static native void native_start();
private static native void native_gl_resize(int w, int h);
private static native void native_gl_render();

static {

Now you have to write these in C and somehow register them with the Dalvik VM (or "Dalek VM" as I often misread it. Exterminate!) Dalvik uses the same approach to binding native methods as the Java VM does; it opens a native library with dlopen() and looks for the symbol JNI_OnLoad and functions with "mangled" names that match the native declarations. The library loaded here will be "". You can either implement your functions with the mangled names or using a call to "RegisterNatives" in the JNI_OnLoad function. There are many JNI tutorials on the net, I won't rewrite how to do that here. Whichever way you choose, you still need to have the native declarations in your Java source code. My examples are using RegisterNatives, as it gives cleaner C function names.

In the constructor of your Java GLSurfaceView, you should call the main loop (in C) from a separate thread - this way the loop does not block the main thread of your Android application and the Android OS won't kill it for being non-responsive. It is important that the main C code does not do OpenGL manipulation as that can also crash the application. All GL manipulation is done in the renderer call. The main-loop thread can change whatever C state it likes; the render call later reads this state to create the final rendered screen.

public GlBufferView(Context context, AttributeSet attrs) {
super(context, attrs);
(new Thread() {
public void run() {
setRenderer(new MyRenderer());

The implementation of your GLSurfaceView.Renderer class simply delegates to the native functions and should look like this:

class MyRenderer implements GLSurfaceView.Renderer {
public void onSurfaceCreated(GL10 gl, EGLConfig c) { /* do nothing */ }

public void onSurfaceChanged(GL10 gl, int w, int h) {
native_gl_resize(w, h);

public void onDrawFrame(GL10 gl) {

The onSurfaceCreated method is not used, the onSurfaceChanged method is what the OpenGL implementation really uses to indicate a screen should be set up properly. The method onDrawFrame is called once per frame, at a rate of between 30-60 FPS (if you're lucky).

Now you can forget about Java until you need to do input, but that's another story, and write the rest of your game in C. The native_gl_resize method should grab a texture and set up the simplest rendering scenario it can. Experimentation has shown that this is not too shabby:

#define TEXTURE_WIDTH 512
#define TEXTURE_HEIGHT 256
#define MY_SCREEN_WIDTH 272
#define MY_SCREEN_HEIGHT 208
static int s_w;
static int s_h;
static GLuint s_texture;

void JNICALL native_gl_resize(JNIEnv *env, jclass clazz, jint w, jint h)
glGenTextures(1, &s_texture);
glBindTexture(GL_TEXTURE_2D, s_texture);
glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, rect);
glTexImage2D(GL_TEXTURE_2D, /* target */
0, /* level */
GL_RGB, /* internal format */
TEXTURE_WIDTH, /* width */
TEXTURE_HEIGHT, /* height */
0, /* border */
GL_RGB, /* format */
GL_UNSIGNED_SHORT_5_6_5,/* type */
NULL); /* pixels */
/* store the actual width of the screen */
s_w = w;
s_h = h;

You can also call glDisable to turn off fog, depth, and other 3D functions, but it doesn't seem to make too much difference. The glEnable(GL_TEXTURE_2D); call enables textures. You need this as you'll be drawing your pixels into a texture. glGenTextures and glBindTexture get a handle to a texture and set it as the currently used one. The 2 glTexParameterf calls are needed to make the texture actually show up on hardware. Cargo cult coding here. Without these the texture is just a white square. Similarly, the glShadeModel and glColor4x are needed to have any chance of your texture showing up either on hardware or on the emulator. Presumably if the screen has no color it is not drawn at all.

The rect[4] array and associated glTexParameteriv call will crop the texture to the rectangle size given. The MY_SCREEN_XX values depend on your "emulated" screen size, but should be smaller than the texture. The TEXTURE_XXX sizes should be power-of-2 (256, 512, 1024) to work on hardware. Anything else may work on the emulator, but will fail miserably on the real thing. The rectangle is inverted here to get the final texture to show the right way round. The call to glTexImage2D allocates the texture memory in video ram, passing NULL means nothing is copied there yet. The native Android pixel type is RGB565, which means 5 bits of red, 6 of green and 5 of blue. How close to the Nintendo DS or GBA pixel format, just 1 bit different! Using this colour type speeds ups the frame rate from less than 30 FPS to a more respectable 50-60 FPS.

Now the render code. This uses the glDrawTexiOES function call, which is an OpenGLES extension to render a texture straight to the screen. It is the fastest way to do things as there is no real 3D going on, it is just drawing your texture straight to screen.

void JNICALL native_gl_render(JNIEnv *env UNUSED, jclass clazz UNUSED)
memset(s_pixels, 0, S_PIXELS_SIZE);
glTexSubImage2D(GL_TEXTURE_2D, /* target */
0, /* level */
0, /* xoffset */
0, /* yoffset */
MY_SCREEN_WIDTH, /* width */
MY_SCREEN_HEIGHT, /* height */
GL_RGB, /* format */
GL_UNSIGNED_SHORT_5_6_5, /* type */
s_pixels); /* pixels */
glDrawTexiOES(0, 0, 0, s_w, s_h);
/* tell the other thread to carry on */

The memset clears out old pixel values. If you were careful and kept track of dirty areas, only refreshing those, this could be omitted. I'm keeping things simple here though and clearing the screen each time. The render_pixels routine does whatever it takes to draw your game's pixels into the s_pixels array in the RGB565 format. The glClear call is not strictly necessary, but it may help to speed up the pipeline as the hardware knows not to worry about keeping any old values. Experimentation shows that leaving it in doesn't harm the framerate at least. The glTexSubImage2D call will copy the s_pixels data into video memory, only updating the area indicated rather than the whole thing. If you do update the whole texture it is actually faster to call glTexImage2D. Finally, glDrawTexiOES will draw the texture to the screen, scaled to the screen size.

The final pthread_cond_signal is to tell our vsync call to wake up. I haven't mentioned this yet, but in order to have a GBA or DS-like coding experience, it is vital to wait on the screen refresh. The implementation of this is simple, as Android lets you play with all the usual pthread calls from the world of Linux. You create a mutex and condition at the start of the main, and have the implementation of waitvblank lock the mutex and wait for a signal on the pthread condition.

#define UNUSED __attribute__((unused))

static void wait_vsync()
pthread_cond_wait(&s_vsync_cond, &s_vsync_mutex);

void JNICALL native_start(JNIEnv *env UNUSED, jclass clazz UNUSED)
/* init conditions */
pthread_cond_init(&s_vsync_cond, NULL);
pthread_mutex_init(&s_vsync_mutex, NULL);

while (1) {
/* game code goes here */

That ensures that main loop can wait on screen redraws, which avoids tearing.

Obviously if you want to write code from scratch that will only ever run on Android, there is no point jumping through these hoops. Just use Java and forget about the NDK. However, if you want to port existing code to Android, or you don't want to write new code that is tied to a single platform, this approach is IMO the best way to go about it. It makes Android an almost decent platform for writing old-skool games on :-)

I've made a compilable example of this code available on github here.

Friday, October 01, 2010

A new era?

TL;DL I've bought an Android phone and will probably stop writing DS stuff.

As you can probably guess by the lack of updates, I haven't been particularly active writing code for the DS during the last year. The main reason for this is a complete lack of free time lately. Or perhaps it's just bad time management. The second reason is my dodgy SD card randomly failing to connect via USB. It gets frustrating having to plug in and unplug the card multiple time just to get it to register. Either way, I think I've reached the end of DS development for me. Never say never, but I don't have the enthusiasm I once did for the platform.

Want some more reasons? How about Nintendo's action against flash cards in the UK? I don't doubt that Nintendo is going to try and extend the ban in the rest of Europe during the next year, until the release of the 3DS. Because of this, the number of people able to run programs will remain constant or even decrease.

Speaking of unauthorized copying... I've always known that many flash card owners are into downloading and playing games that they ought to have paid for, but this means that if you write for the DS you're competing with commercial games directly. If you can get Zelda for free, why bother trying out some free homebrew? In other words, the homebrew scene is too tightly coupled to the scene that likes downloading and sharing commercial games, with the negatives that this brings. You can see this when homebrew games are released for download in the RAR file format, shared on rapidshare-type sites, without source code, or in a way that violates the GPL.

Many users don't care about the nuances of running homebrew games, improving the state of things, or doing it the "right way". As an example, I have an RSS feed for alerts about Bunjalloo. I get tired of reading about torrents and rapidshare downloads for really old versions of it, especially when you could download the latest release Free from the googlecode site anyway!

I bought a DSi when it came out in Europe. I think it is a pretty good console. The freebies from the Nintendo store are top notch, and the DSiWare titles are not too shabby. Nevertheless Nintendo has not really moved with the times. If you compare the price of DSiWare titles to Android or iPhone paid applications, the differences are laughable. Eurogamer does a semi-regular review roundup of downloadable games where you can see the disparity. A DSiWare title typically costs 7-9€, whereas the iPhone equivalent is 2-4€. Sometimes the difference is 30€ to 4€ (Ace Attorney). Anyone can write an iPhone or Android title, but no system is in place that lets the general public write for Nintendo's platform. On the DSi we have 2 free titles. There are thousands of free games and applications on the major phone platforms. Granted a lot of them are crap, but hey! it's free crap.

Maybe I could live with this state of affairs if the DSi hardware were homebrew programmable, but it isn't. Dave Murphy continues his efforts to hack on the DSi, but it is fairly obvious that Nintendo want their hardware locked down. The latest exploit does look promising. It rewrites part of the DSi's wifi module flash chip to "jailbreak" into DSi mode from an exploitable DSi-only game. Sadly the error that permits this exploit has already been fixed on newer DSi models (including the DSiXL). With Nintendo dead set against us, why bother anymore? It's getting tedious. Outside of the excellent devkitARM, the development tools are not as good as in the GBA era. There's still no developer-friendly emulator on par with Visual Boy Advance.

Perhaps if there were more DSi-only cartridge titles around, the companies creating flash cards would have found a way to run games in DSi mode. As it is, there's no need. This highlights the sad symbiosis of the homebrew hackers and the folks into unauthorized copying. We need flashcards to run our homebrew, they need us to make their flashcards "legitimate" in the eyes of the law (and even that wasn't enough in the UK).

Where now then? I don't think the DSi situation is going to change. I've moved with the times (2009 times...) and have bought a 2nd hand Android phone to do embedded stuff. I'll miss writing for Nintendo hardware though. As far as 2D games go, the DS is superior in every way, Nintendo designed it for gaming after all.

On the DS you have layered backgrounds with multiple modes, hardware sprites, and vblank power saving between frames. Android has a generic screen buffer type display that is not ideal for writing old skool 2D games. You have to do pixel pushing yourself, and it sends the CPU skyrocketing, while the battery flatlines. The emulator spins at 100% CPU even on the samples from Google, which is not good.

Apart from that, coding for Android feels like cheating. The emulator is highly accurate, you have a visual debugger, can connect to the running platform and kill runaway processes, there's a CPU usage monitor, unit testing is part of the SDK, the API is huge and you can use all of the standard Java libraries... what's not to like? Well, Java is a bit tedious, but the NDK leaves the door open for writing good old C or even ARM assembly.

I was starting to get a bit tired of the DS scene. Seeing my own code up and running on the Android emulator has reignited my enthusiasm again. Let's see how long it lasts (I give it a week).

Monday, January 04, 2010

Wi-Fi on the Nintendo DS

I've had a couple of people ask me about which Wi-Fi settings work with Bunjalloo. That means there are probably more folk out there who haven't asked but are not sure either. So here's the lowdown.

The original Nintendo DS or DS lite has 3 different ways to connect to a wireless network:

The Nintendo DSi adds an Advanced Settings with the following feature:

  • Connect to a Wi-Fi access point encrypted with WPA

Bunjalloo will only work with unencrypted or WEP encrypted Wi-Fi settings. It does not work with the DSi Advanced Settings options (WPA), nor does it work with the Nintendo USB Wi-Fi Connection.

These limitations are partly due to the dswifi library, which sgstair created by reverse engineering the original DS Wi-Fi hardware. It's remarkable that it works at all, let alone that it works so well while being easy to use. But the price of being unofficial is that it does not support all the hardware features that official titles do, notable it's missing support for the USB Wi-Fi device. The lack of DSi/WPA support is simply because applications booted from the current generation of DS flash cards cannot access any DSi features at all, Wi-Fi or otherwise.

As for the Nintendo USB Wi-Fi Connection... well, that's a bit of a white elephant really. The advantage is that you can use your network with WPA and still have your DS connect via the USB dongle that's plugged in to your regular PC. For me though having to turn on my PC to use the DS with Wi-Fi defeats the object of a low overhead, quick-to-boot-and-connect gizmo. The final straw is that the USB Wi-Fi program is only available for Windows.

On a regular DS system you need a Wi-Fi-enabled game in order to change the Wi-Fi settings. Mario Kart or Animal Crossing will do, for example. The DSi fixes this shortcoming by including a way to configure the Wi-Fi straight from its system menu. From the DSi's main menu you tap System Settings, then the Internet option. It looks something like this (if your screens are covered in lint, as mine appear to be here):

System Settings Internet

From the internet screen, tap Connection Settings then tap a connection to configure it:

Connection Settings Configure Connection

This is more or less the same deal as on a regular DS, but built in to the DSi's firmware. You don't need to start a game to alter the settings.

Open access points show the signal strength and SSID name. Encrypted connections also show a padlock icon. Gold padlocks are for WEP encrypted access points, which you can use with regular DS games (if you have the WEP keys). If the padlock is grey though, well that means the access point uses WPA encryption and you will only be able to connect using the DSi's "advanced settings".

WPA Connection

Here's what it says if you click on a grey padlock from the regular DSi Internet settings screen:

Unable To Connect

"Unable to connect to this access point using the current settings. To connect to this access point, use Advanced Setup"

For all you old-skool DS owners who might be curious, here is what the DSi says about the WPA connection. These are found in the "Advanced Settings" option of the DSi's Internet settings:

Advanced Connection

"Allows use of high-security proxy settings. Cannot be used with Nintendo DS-compatible functions."

In other words, you can't expect to use Mario Kart's online mode directly with your WPA protected network. This type of connection will only work with the DSi's built-in browser, the Nintendo DSiWare store, and other DSi-only titles.

So there you have it. The DSi's WPA Wi-Fi settings are not backwards compatible with regular DS titles, so they cannot be used by homebrew applications either. If you want to use the DS to its full potential, you will have to run an access point with the security set to "dubious" (WEP). It'll probably be enough to stop your neighbours accidentally nicking your broadband, but won't keep determined Wi-Fi thieves out. The official help for all this can be found on the Nintendo Customer Service site.